Commit graph

116 commits

Author SHA1 Message Date
Evan Morikawa e90735ed6e feat(win): faster popout windows
Summary:
This diff is designed to dramatically speed up new window load time for
all window types and reduce memory consumption of our hot windows.

Before this diff, windows loaded in ~3 seconds. They now boot in a couple
hundred milliseconds without requiring to keep hot windows around for
each and every type of popout window we want to load quickly.

One of the largest bottlenecks was the `require`ing and initializing of
everything in `NylasExports`.

I changed `NylasExports` to be entirely lazily-loaded. Drafts and tasks
now register their constructors with a `StoreRegistry` and the
`TaskRegistry`. This lets us explicitly choose a time to activate these
stores in the window initalization instead of whenever nylas-exports
happens to be required first.

Before, NylasExports was required first when components were first
rendering. This made initial render extremely slow and made the proposed
time picker popout slow.

By moving require into the very initial window boot, we can create a new
scheme of hot windows that are "half loaded". All of the expensive
require-ing and store initialization is done. All we need to do is
activate the packages for just the one window.

This means that the hot window scheme needs to fundamentally change from
have fully pre-loaded windows, to having half-loaded empty hot windows
that can get their window props overridden again.

This led to a major refactor of the WindowManager to support this new
window scheme.

Along the way the API of WindowManager was significantly simplifed.
Instead of a bunch of special-cased windows, there are now consistent
interfaces to get and `ensure` windows are created and displayed. This
DRYed up a lot of repeated logic around showing or creating core windows.

This also allowed the consolidation of the core window configurations into
one place for much easier reasoning about what's getting booted up.

When a hot window goes "live" and gets populated, we simply change the
`windowType`. This now re-triggers the loading of all of the packages for
the window. All of the loading time is now just for the packages that
window requires since core Nylas is there thanks to the hot window
mechanism.

Unfortunately loading all of the packages for the composer was still
unnaceptably slow. The major issue was that all of the composer plugins
were taking a long time to process and initialize. The solution was to
have the main composer load first, then trigger another window load
settings change to change the `windowType` that loads in all of the
plugins.

Another major bottleneck was the `RetinaImg` name lookup on disk. This
requires traversing the entire static folder synchronously on boot. This
is now done once when the main window loads and saved in a cache in the
browser process. Any secondary windows simply ask the backend for this
cache and save the filesystem access time.

The Paper Doc below is the current set of manual tests I'm doing to make
sure no window interactions (there are a lot of them!) regressed.

Test Plan: https://paper.dropbox.com/doc/Window-Refactor-UYsgvjgdXgVlTw8nXTr9h

Reviewers: juan, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2916
2016-04-22 13:30:42 -07:00
Ben Gotow ca24fc31e9 rename(drafts) DraftStoreProxy => DraftEditingSession 2016-04-19 16:08:58 -07:00
Ben Gotow 585dab7cdf refactor(composer): Make session, draft available everywhere
Summary:
Up until now, we've been requiring that every plugin control in the composer take the draftClientId, retreive the session, listen to it, build state from the draft, etc. This is a huge pain and is hard to explain to newcomers becaus it frankly makes no sense.

In 0.3.45 we made it so that the ComposerView always has a non-null draft and session. (It isn't rendered until they're available). In this diff, I just pass those through to all the plugins and remove all the session retrieval cruft.

Almost none of the buttons have state of their own, which I think is appropriate.

They do render on every keystroke, but they were already running code (to recompute their state) on each keystroke and profiling suggests this has no impact.

Prepare for immutable

In preparation for Immutable models, make the draft store proxy returns a !== draft if any changes have been made. This means you can safely know that a draft has changed if `props.draft !== nextProps.draft`

Test Plan: Run tests

Reviewers: juan, evan

Reviewed By: juan, evan

Differential Revision: https://phab.nylas.com/D2902
2016-04-19 16:05:15 -07:00
Ben Gotow b75ed6f920 perf(db): Use subselect to improve thread list query perf (53%!)
Summary:
- Use a sub-select query with much better performance to display the thread list
- Perform analyze on tables after launch

The new query is:

```
SELECT `Thread`.`data` FROM `Thread` WHERE `Thread`.`id` IN (SELECT `id` FROM `ThreadCategory` AS `M26` WHERE `M26`.`value` IN ('9m9ks71k06n5rmx82kgues09p','9s9k25q6j1krjgpkovbcjm7d','13b7ufruoymvih07ki0uahlto','dtmhlzz6phr47zp512knhjgf8','16dvjb84bszfh15kgfrjj37i3','aclwmgncdqjfibp51bvgbeik','17qad7jhbp6tozog3klm5zagt','4x4bkbawiq825u4eu3aus8tll','7axr9f5f1lzpwm2rw2ghkirhq','dsnn660af0pmou2gg3nstga8a','361qr5rva1ieby2r0ec3sn0bm','10fyvba7pjyjgeyr5i65i1zri') AND `M26`.`in_all_mail` = 1  ORDER BY `M26`.`last_message_received_timestamp` DESC LIMIT 200 OFFSET 0) ORDER BY `Thread`.`last_message_received_timestamp` DESC;
`
0|0|0|SEARCH TABLE Thread USING INDEX Thread_id (id=?)
0|0|0|EXECUTE LIST SUBQUERY 1
1|0|0|SCAN TABLE Thread-Category AS M26 USING COVERING INDEX ThreadFancyIndex
1|0|0|EXECUTE LIST SUBQUERY 2
0|0|0|USE TEMP B-TREE FOR (only on 200 result items)
```

Which is twice as performant as:
```
SELECT `Thread`.`data` FROM `Thread` INNER JOIN `ThreadCategory` AS `M26` ON `M26`.`id` = `Thread`.`id` WHERE `M26`.`value` IN ('9m9ks71k06n5rmx82kgues09p','9s9k25q6j1krjgpkovbcjm7d','13b7ufruoymvih07ki0uahlto','dtmhlzz6phr47zp512knhjgf8','16dvjb84bszfh15kgfrjj37i3','aclwmgncdqjfibp51bvgbeik','17qad7jhbp6tozog3klm5zagt','4x4bkbawiq825u4eu3aus8tll','7axr9f5f1lzpwm2rw2ghkirhq','361qr5rva1ieby2r0ec3sn0bm','10fyvba7pjyjgeyr5i65i1zri') AND `M26`.`in_all_mail` = 1  ORDER BY `M26`.`last_message_received_timestamp` DESC LIMIT 200 OFFSET 0;

0|0|1|SCAN TABLE Thread-Category AS M26 USING COVERING INDEX ThreadFancyIndex
0|0|0|EXECUTE LIST SUBQUERY 1
0|1|0|SEARCH TABLE Thread USING INDEX Thread_id (id=?)
```

Test Plan: Broken!

Reviewers: evan, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D2869
2016-04-11 13:29:05 -07:00
Juan Tejada d9517101d5 fix(perspective): Fix specs for FocusedPerspectiveStore 2016-04-11 07:59:40 -07:00
Ben Gotow 4329f53ce8 fix(fwd): Do not mention Bcc'd recipeints in forward headers #1873 2016-04-06 14:51:17 -07:00
Ben Gotow 0b4127bc4b fix(composer): Show when rendered, send draft JSON to composer windows 2016-04-04 18:30:50 -07:00
Ben Gotow 227f3345a0 fix(db): Remove - from table names, which was a bad idea 2016-04-04 17:44:45 -07:00
Ben Gotow a3ede94423 feat(offline-status): Show a bar when not connected to the API
Summary:
The TaskQueue does it's own throttling and has it's own processQueue retry timeout, no need for longPollConnected

Remove dead code (OfflineError)

Rename long connection state to status so we don't ask for `state.state`

Remove long poll actions related to online/offline in favor of exposing connection state through NylasSyncStatusStore

Consoliate notifications and account-error-heaer into a single package and organize files into sidebar vs. header.

Update the DeveloperBarStore to query the sync status store for long poll statuses

Test Plan: All existing tests pass

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D2835
2016-04-04 17:11:09 -07:00
Ben Gotow 324296eb1c fix(drafts): Use the appropriate account and alias 2016-03-24 19:35:24 -07:00
Ben Gotow 52e8e57e4a perf(autolinker): Use requestIdleCallback to fix hanging on large bodies 2016-03-23 19:03:21 -07:00
Juan Tejada 2e860f97ec fix(specs): Fix specs for account store token initialization 2016-03-23 18:10:15 -07:00
Ben Gotow c265cf0dfa fix(drafts): Formalize draft factory, add reply "behaviors" #1722
Summary:
This diff implements a behavior change described in https://github.com/nylas/N1/issues/1722.

Reply buttons should prefer to focus an existing draft in reply to the same message, if one is pristine, altering it as necessary to switch between reply / reply-all. If no pristine reply is already there, it creates one.

Reply keyboard shortcuts should do the same, but more strictly - the shortcuts should switch between reply / reply-all for an existing draft regardless of whether it's pristine.

This diff also cleans up the DraftStore and moves all the draft creation itself to a new DraftFactory object. This makes it much easier to see what's going on in the DraftStore, and I also refactored away the "newMessageWithContext" method, which was breaking the logic for Reply vs Forward between a bunch of different helper methods and was hard to follow.

Test Plan: They're all wrecked. Will fix after concept is greenlighted

Reviewers: evan, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D2776
2016-03-22 15:47:51 -07:00
Ben Gotow 510e417cb3 fix(tray): Use total count, not unread count, for tray icon 2016-03-21 17:36:18 -07:00
Ben Gotow a88c7db3a5 Merge pull request #1783 from mbilker/change-dialog-call
Use `remote` exports instead of `remote.require` for dialog
2016-03-18 17:42:31 -07:00
Ben Gotow 47a8823242 fix(queue): Delay retries up to 30s when tasks request a retry
Summary:
This is a critical patch that fixes two problems with the task queue:

1. Tasks in Status: Retry are retried the next time processQueue is run,
   which could be pretty much immediately. Certain scenarios lead to tasks
   running in a hard loop forever.

2. Returning Task.Status.Retry set the retry flags on the task but did not
   schedule the queue to be processed again. So if only a single item in the
   queue was present, it might never be retried again until the user performed
   another action.

Test Plan: Where did the specs for TaskQueue go? There aren't many... need to write more.

Reviewers: evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D2762
2016-03-18 13:25:30 -07:00
mbilker ea540ebf18 fix(specs): change to use electron.remote.dialog 2016-03-18 01:27:13 -04:00
Ben Gotow fe5b75b32a fix(counts): Switch to simpler SQL-based counters, introduce total counts
Summary:
The old approach we were using to track unread counts by category was really complicated because it involved computing changes to counts in javascript and then syncing them back to the database, from each process that was making queries. Rather than try to fix that, this diff moves us to a new approach where the counts are maintained by executing a query before and after threads are modified to unapply / reapply them from the counters. Doing this in the database in the same transactions as the thread modifications themselves ensures the counts are internally consistent with the Threads table.

This SQL approach is also able to compute initial counts way faster - initializing totals and unreads in a 1GB edgehill.db in about 1 second on my machine.

Test Plan: All old tests removed, new tests coming

Reviewers: evan, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D2757
2016-03-17 18:24:27 -07:00
Ben Gotow b515a5e0e2 feat(dock-icon): Drop files to attach them to new msg
Summary:
Fix specs

Fix responding to mailto, files at launch

It's super important that `window:loaded` is /not/ sent from index.js because `loadSettings.bootstrapScript` is async and nothing is actually loaded yet. This was causing the app to dispatch the mailto:// links into the main window before a DraftStore existed.

I think this was necessary at one point because we had NylasWindows not using a bootstrapScript? Should not be here anymore...

Test Plan: Run a few new tests

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D2737
2016-03-17 13:14:55 -07:00
Ben Gotow 2e2ecf0647 fix(quoted-text): div vs blockquote, signature cleanup #1746
Summary:
Previously we always created <blockquote class="gmail_quote"> to wrap quoted text. This is not correct.
Gmail uses blockquotes only when it wants visual indentation, and <div>s to wrap other quoted text, like forwarded
messages which are not displayed indented.

This diff updates N1 to match Gmail exactly. Note that for replies, Gmail actually nests a blockquote.gmail_quote
inside a div.gmail_quote.

I also updated signature handling because it turns out the regexp that was removing existing signatures would blow
away any and all divs until it reached a <blockquote> tag.

Test Plan: See updated specs. Manually tested by creating a thread in Google Inbox and then performing fwd and reply in both N1 and Inbox. Results match.

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D2750
2016-03-17 13:11:00 -07:00
Ben Gotow 552b66fbaf fix(syncback): Bidirectional transforms, ready-to-send saved state
Summary:
This diff replaces "finalizeSessionBeforeSending" with a
plugin hook that is bidirectional and allows us to put the draft in
the "ready to send" state every time we save it, and restore it to
the "ready to edit" state every time a draft session is created to
edit it.

This diff also significantly restructures the draft tasks:

1. SyncbackDraftUploadsTask:
   - ensures that `uploads` are converted to `files` and that any
     existing files on the draft are part of the correct account.

1. SyncbackDraftTask:
   - saves the draft, nothing else.

3. SendDraftTask
   - sends the draft, nothing else.
   - deletes the entire uploads directory for the draft

Test Plan: WIP

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D2753
2016-03-16 19:27:12 -07:00
Ben Gotow b75843bbc0 fix(unread): counts should exclude items outside all mail
#1726, #1718
2016-03-14 18:33:04 -07:00
Juan Tejada 0b2d7043d7 fix(specs): Remove fdescribe 2016-03-14 15:39:42 -07:00
Juan Tejada cfbbcd23d3 fix(snooze): Correctly query and create snooze categories per account
Summary:
- Was not properly updating the references to snoozed categories when
  accounts were added or removed
- Update whenCategoriesReady to make sure we listen until category syncing has concluded (Move inside CategoryStore)
- #1676, #1658

Test Plan: - TODO

Reviewers: evan, drew, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2723
2016-03-14 15:36:39 -07:00
Ben Gotow 734a52aa6a fix(config): Move account tokens to system keychain
Summary:
This diff also adds an account version number to the config so that the AccountStore can tell whether it should reload accounts (depending on whether it was the instance making tthe changes.)

This diff also fixes a tiny issue where un-opened composers threw an exception if you changed accounts.

Test Plan: New tests

Reviewers: evan, drew, juan

Reviewed By: juan

Subscribers: juan

Differential Revision: https://phab.nylas.com/D2726
2016-03-14 15:14:08 -07:00
Ben Gotow 041817c589 patch(save): Only save drafts when necessary, avoid sync-engine issues
Summary:
Previously, we have saved drafts back to the user's provider through the sync engine. There are a handful of very serious edge case issues we're working to solve that are creating a bad user experience. (#933, #1175, #1504, #1237)

For now, we're going to change the behavior of N1 to mitagate these issues.

- If you create a draft in N1, we will not sync it to other mail clients while you're working on it.
- If you enable send later, we'll start syncing the draft to the server as before.
- If you created the draft in another client, we'll sync the draft to the server as before.

Fix specs

Test Plan: Run specs

Reviewers: evan, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D2706
2016-03-10 11:03:38 -08:00
Ben Gotow b1ab520d0e fix(bodies): Move loading into component, add retry, loading spinner 2016-03-09 19:14:54 -08:00
Ben Gotow 3e8f7fbfd7 fix(downloads): Properly handle network errors, retries of downloads 2016-03-08 18:32:47 -08:00
Drew Regitsky f1d3959591 fix(send): make send/syncback draft tasks cooperate, fix task ordering tracking
Summary:
Fixes an issue with sending where certain conditions could result in a
duplicated message.

Fixes task dependency logic for draft syncback and send. Changes `createdAt`
on tasks to instead be `sequentialId`, assigned when the task is queued, to
track order of enqueueing. Renames `isDependentTask` => `isDependentOnTask`
and adds comments for clarity.

Test Plan:
Specs updated. Might be good to add some later to test this particular
edge case.

Reviewers: juan, evan, bengotow

Reviewed By: evan, bengotow

Differential Revision: https://phab.nylas.com/D2681
2016-03-07 20:14:58 -08:00
Juan Tejada 248467894e fix(lint) 2016-03-04 10:28:48 -08:00
Ben Gotow 7219dd91d7 fix(downloads): Replace stripped extensions, remember folder 2016-03-03 18:00:43 -08:00
Ben Gotow f1cd1056cc fix(attachments): fixes + specs for download on-receive option 2016-02-19 18:54:20 -08:00
Juan Tejada ae2f03ac96 fix(focused-persepective): Init saved perspective correctly
- When accounts changed and the saved perspective could reference
  accounts that no longer exist and cause all sorts of errors. This is
  fixed.
- Add specs
- Fixes some sentry errors
2016-02-09 20:10:33 -08:00
Juan Tejada 58725b98ef fix(account-store): Correctly check alias email inside accountForAlias
- Add spec
2016-02-07 00:39:11 -08:00
Ben Gotow 91240f8979 feat(outbox): Sending status now appears beside drafts
Summary:
This diff adds an "OutboxStore" which reflects the TaskQueue and
adds a progress bar / cancel button to drafts which are currently sending.

- Sending state is different from things like Send later because drafts
  which are sending shouldn't be editable. You should have to stop them
  from sending before editing. I think we can implement "Send Later"
  indicators, etc. with a simple InjectedComponentSet on the draft list
  rows, but the OutboxStore is woven into the DraftList query subscription
  so every draft has a `uploadTaskId`.

- The TaskQueue now saves periodically (every one second) when there are
  "Processing" tasks. This is not really necessary, but makes it super
  easy for tasks to expose "progress", because they're essentially
  serialized and propagated to all windows every one second with the
  current progress value. Kind of questionable, but super convenient.

- I also cleaned up ListTabular and MultiselectList a bit because they
  applied the className prop to an inner element and not the top one.

- If a DestroyDraft task is created for a draft without a server id, it
  ends with Task.Status.Continue and not Failed.

- The SendDraftTask doesn't delete uploads until the send actually goes
  through, in case the app crashes and it forgets the file IDs it created.

Test Plan: Tests coming soon

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D2524
2016-02-04 14:14:24 -08:00
Ben Gotow 3453cfecb5 fix(mailto): test case / parsing for url encoded To field 2016-02-01 11:22:23 -08:00
Ben Gotow 2027901deb fix(uploads): Consolidate logic, use Promisify, path.join 2016-01-29 14:45:53 -08:00
Juan Tejada a3b686e546 fix(electron): Update api usage to require('electron') 2016-01-29 14:24:33 -08:00
Ben Gotow a4e37c66f4 fix(specs): Re-enable draft-store specs 2016-01-28 15:48:08 -08:00
Ben Gotow 52a7a6625f fix(linter): Switching between Coffee + ES6 is hard... 2016-01-28 14:59:17 -08:00
Ben Gotow d1415585d5 fix(contact-search): Keep only ranked contacts, query for others. Massive perf boost. 2016-01-28 14:56:15 -08:00
Ben Gotow 63102ba732 fix(message-list): Spec fixes, all stubs need accountId 2016-01-28 11:14:04 -08:00
Juan Tejada 8be8bfcab2 Fix in upload store when deleting draft 2016-01-28 01:29:33 -08:00
Juan Tejada f74ee7b6c2 Fix specs 2016-01-28 00:48:45 -08:00
Juan Tejada 3343000f86 Update file uploads (see details):
- Add uploads field to Message and removes cache from FileUploadsStore
- Updates draft via session from DraftStore
  - This makes everything way cleaner
- This fixes bug when creating draft with uploads and the opening it in
  new window
- Updates specs
2016-01-28 00:33:22 -08:00
Juan Tejada ff3213f003 Rewrite tests for FileUploadStore 2016-01-27 12:33:27 -08:00
Ben Gotow 32ccaad1e7 More spec fixes 2016-01-27 10:31:54 -08:00
Ben Gotow 3b3b19a172 Spec fixes 2016-01-26 19:12:51 -08:00
Ben Gotow 820973cfa5 Fixes to the SendDraftTask 2016-01-26 16:41:49 -08:00
Ben Gotow c8bd09a260 Begin cleanup of Send Task 2016-01-26 15:44:44 -08:00