mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-05 04:04:38 +08:00
perf(autolinker): Use requestIdleCallback to fix hanging on large bodies
This commit is contained in:
parent
75c9b116bb
commit
75ff8282a8
4 changed files with 28 additions and 8 deletions
|
@ -28,7 +28,7 @@ function _runOnTextNode(node, matchers) {
|
|||
}
|
||||
}
|
||||
|
||||
export function autolink(doc) {
|
||||
export function autolink(doc, {async} = {}) {
|
||||
// Traverse the new DOM tree and make things that look like links clickable,
|
||||
// and ensure anything with an href has a title attribute.
|
||||
const textWalker = document.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
|
||||
|
@ -38,8 +38,21 @@ export function autolink(doc) {
|
|||
['', RegExpUtils.urlRegex({matchEntireString: false})],
|
||||
];
|
||||
|
||||
while (textWalker.nextNode()) {
|
||||
_runOnTextNode(textWalker.currentNode, matchers);
|
||||
if (async) {
|
||||
const fn = (deadline) => {
|
||||
while (textWalker.nextNode()) {
|
||||
_runOnTextNode(textWalker.currentNode, matchers);
|
||||
if (deadline.timeRemaining() <= 0) {
|
||||
window.requestIdleCallback(fn, {timeout: 500});
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
window.requestIdleCallback(fn, {timeout: 500});
|
||||
} else {
|
||||
while (textWalker.nextNode()) {
|
||||
_runOnTextNode(textWalker.currentNode, matchers);
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse the new DOM tree and make sure everything with an href has a title.
|
||||
|
|
|
@ -65,7 +65,7 @@ export default class EmailFrame extends React.Component {
|
|||
doc.write(`<div id='inbox-html-wrapper'>${this._emailContent()}</div>`);
|
||||
doc.close();
|
||||
|
||||
autolink(doc);
|
||||
autolink(doc, {async: true});
|
||||
|
||||
// Notify the EventedIFrame that we've replaced it's document (with `open`)
|
||||
// so it can attach event listeners again.
|
||||
|
|
|
@ -55,7 +55,7 @@ describe "AccountStore", ->
|
|||
(new Account).fromJSON(@configAccounts[1])
|
||||
])
|
||||
|
||||
it "should initialize tokens from config, if present, save them to keytar, and remove them from config", ->
|
||||
it "should initialize tokens from config, if present, and save them to keytar", ->
|
||||
@configTokens = {'A': 'A-TOKEN'}
|
||||
@instance = new @constructor
|
||||
expect(@instance.tokenForAccountId('A')).toEqual('A-TOKEN')
|
||||
|
|
|
@ -35,6 +35,9 @@ class MessageBodyProcessor {
|
|||
return;
|
||||
}
|
||||
|
||||
// grab the old value
|
||||
const oldOutput = this._recentlyProcessedD[changedKey].body;
|
||||
|
||||
// remove the message from the cache
|
||||
delete this._recentlyProcessedD[changedKey];
|
||||
this._recentlyProcessedA = this._recentlyProcessedA.filter(({key}) =>
|
||||
|
@ -52,9 +55,13 @@ class MessageBodyProcessor {
|
|||
const updatedMessage = changedMessage.clone();
|
||||
updatedMessage.body = updatedMessage.body || subscriptions[0].message.body;
|
||||
const output = this.retrieve(updatedMessage);
|
||||
for (const subscription of subscriptions) {
|
||||
subscription.callback(output);
|
||||
subscription.message = updatedMessage;
|
||||
|
||||
// only trigger if the output has really changed
|
||||
if (output !== oldOutput) {
|
||||
for (const subscription of subscriptions) {
|
||||
subscription.callback(output);
|
||||
subscription.message = updatedMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue