-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
166 lines (166 loc) · 7.03 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var immer_1 = __importStar(require("immer"));
var defaultOptions = {
namespace: 'timeline',
include: [],
limit: 1024,
};
var initialState = {
canUndo: false,
canRedo: false,
undoCount: 0,
redoCount: 0,
};
exports.default = (function (options) {
var _a;
if (options === void 0) { options = defaultOptions; }
var newOptions = __assign(__assign({}, defaultOptions), options);
var namespace = newOptions.namespace;
var stack = [];
var inverseStack = [];
return {
/**
* Make sure that every reducer is wrapped by immer.
* At the same time, we collect patches
*
* @param {Function} reducer
* @return {Function}
*/
_handleActions: function (handlers, defaultState) {
return function (state, action) {
if (state === void 0) { state = defaultState; }
var type = action.type;
var result = immer_1.default(state, function (draft) {
var handler = handlers[type];
if (typeof handler === 'function') {
var compatiableRet = handler(draft, action);
if (compatiableRet !== undefined) {
return compatiableRet;
}
}
}, function (patches, inversePatches) {
// Only record the action whose namespace is in the include array.
if (patches.length) {
var namespace_1 = type.split('/')[0];
// Namespace with '@@' will be filtered because of some dva's plugin(dva-loading)
if (newOptions.include.includes(namespace_1) && !namespace_1.includes('@@')) {
// Clear the redo stack when a new change comes.
inverseStack = [];
if (action.clear === true) {
stack = [];
}
else if (action.replace === true) {
var stackItem = stack.pop();
if (stackItem) {
var itemPatches = stackItem.patches, itemInversePatches = stackItem.inversePatches;
patches = __spreadArrays(itemPatches, patches);
inversePatches = __spreadArrays(inversePatches, itemInversePatches);
}
}
if (action.clear !== true) {
stack.push({ namespace: namespace_1, patches: patches, inversePatches: inversePatches });
}
// Make sure the length of changes is less than options.limit
stack = stack.slice(-newOptions.limit);
}
}
});
return result === undefined ? {} : result;
};
},
/**
* High-Order reducer to undo or redo
*
* @param {Function} redux's reducer
* @return {Function} redux's reducer
*/
onReducer: function (reducer) {
return function (state, action) {
var newState = state;
// Execute undo operation
if (action.type === namespace + "/undo") {
var stackItem_1 = stack.pop();
if (stackItem_1) {
inverseStack.push(stackItem_1);
newState = immer_1.default(state, function (draft) {
var nsp = stackItem_1.namespace, inversePatches = stackItem_1.inversePatches;
draft[nsp] = immer_1.applyPatches(draft[nsp], inversePatches);
});
}
}
else if (action.type === namespace + "/redo") {
// Execute redo operation
var stackItem_2 = inverseStack.pop();
if (stackItem_2) {
stack.push(stackItem_2);
newState = immer_1.default(state, function (draft) {
var nsp = stackItem_2.namespace, patches = stackItem_2.patches;
draft[nsp] = immer_1.applyPatches(draft[nsp], patches);
});
}
}
else if (action.type === namespace + "/clear") {
// Execute clear operation
stack = [];
inverseStack = [];
}
else {
newState = reducer(state, action);
}
// When the state is changed,
// determine whether it is canUndo(canRedo) or not.
return immer_1.default(newState, function (draft) {
var canUndo = stack.length > 0;
var canRedo = inverseStack.length > 0;
if (draft[namespace].canUndo !== canUndo) {
draft[namespace].canUndo = canUndo;
}
if (draft[namespace].canRedo !== canRedo) {
draft[namespace].canRedo = canRedo;
}
if (draft[namespace].undoCount !== stack.length) {
draft[namespace].undoCount = stack.length;
}
if (draft[namespace].redoCount !== inverseStack.length) {
draft[namespace].redoCount = inverseStack.length;
}
});
};
},
/**
* The reducer to set initial state
*/
extraReducers: (_a = {},
_a[namespace] = function (state) {
if (state === void 0) { state = initialState; }
return state;
},
_a),
};
});