Summary:
- Rename DraftStoreExtension to ComposerExtension
- Rename MessageStoreExtension to MessageViewExtension
- Rename ContenteditablePlugin to ContenteditableExtension
- Update Contenteditable to use new naming convention
- Adds support for extension handlers as props
- Add ExtensionRegistry to register extensions:
- ContenteditableExtensions will not be registered through the
ExtensionRegistry. They are meant for internal use, or if anyone wants
to use our Contenteditable component directly in their plugins.
- Adds specs
- Refactors internal_packages and src to use new names and new ExtensionRegistry api
- Adds deprecation util function and deprecation notices for old api methods:
- DraftStore.{registerExtension, unregisterExtension}
- MessageStore.{registerExtension, unregisterExtension}
- DraftStoreExtension.{onMouseUp, onTabDown}
- MessageStoreExtension
- Adds and updates docs
Test Plan: - Unit tests
Reviewers: bengotow, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2293
Summary:
reduce scope of changes
more changes
Test Plan: Run 1 new test
Reviewers: juan
Reviewed By: juan
Differential Revision: https://phab.nylas.com/D2290
Electron 0.35.1 includes the tray fixes we contributed last week but also includes API restructuring and improvements. Most importantly, modules from electron are now imported via `require('electron')`
Summary:
- Refactors account-sidebar internal package:
- Separates into smaller react components
- Makes DisclosureTriangle its own independent component
- Adds data to AccountSidebarStore to allow removal or addition of items for a
specific section of the sidebar
- Adds button and input and css styles to create categories
- Adds context menu to destroy a category
- Adds new method to CategoryStore to get the icon name for the categories of
the current account
- Removes some unused code
Test Plan: Manual
Reviewers: evan, bengotow
Reviewed By: bengotow
Differential Revision: https://phab.nylas.com/D2283
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
Summary:
- Fixes T5819 issues
- Adds ContenteditbalePlugin mechanism to allow extension of Contenteditable
functionality, and completely removes lifecycleCallbacks from Contenteditable
- Refactors list functionality outside of Contenteditable and into a plugin
- Updates ComposerView to apply DraftStoreExtensions through a ContentEditablePlugin
- Moves spell checking logic outside of Contenteditable into the spellcheck package
Fixes T5824 (atom.assert)
Fixes T5951 (shift-tabbing) bullets
Test Plan: - Unit tests and manual
Reviewers: evan, bengotow
Reviewed By: bengotow
Maniphest Tasks: T5951, T5824, T5819
Differential Revision: https://phab.nylas.com/D2261
Summary:
- Include ES6 files in spec-suite
- Fix template store specs
- Refactors TemplateStore a little bit to adjust to specs
- Convert coffe .cjsx files to ES6 .jsx files
- Fix TemplateDraftStoreExtension functions
- Update ComposerTemplates example README
Test Plan: - Plugin unit tests
Reviewers: bengotow, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2250
This fixes#393.
The name "Olivia" was being caught in our parser designed to shorten "Mike Kaylor via LinkedIn" to "Mike Kaylor". We now check that "via" is it's own distinct word in the phrase.
Summary:
Can select all, deselect-all, read, unread, starred, unstarred.
Yes, it's not REALLY select "all", but it uses the items in the current
`retainedRange`. This is actually similar to what gmail does (only selects
on the first page of a 100).
Test Plan: new test
Reviewers: juan, bengotow
Reviewed By: bengotow
Differential Revision: https://phab.nylas.com/D2241
Summary:
Refactor keymaps to wrap components with a <KeymapHandlers /> component.
This more Reactful way of declaring keyback handlers prevents us from
needing to subscribe to `atom.commands`
Test Plan: new tests
Reviewers: bengotow, juan
Reviewed By: bengotow
Differential Revision: https://phab.nylas.com/D2226
Summary:
We send database `trigger()` events through the ActionBrige to all windows of the app. This means that during initial sync, we're serializing, IPCing and unserializing thousands of models a minute x "N" windows.
This diff converts the payload of the trigger method into an actual class that implements a custom toJSON. It converts the impacted `objects` into a string, and doesn't deserialize them until it's asked.
Bottom line: this means that in many scenarios, we can avoid creating Contact models, etc. in composer windows only to broadcast them and then gc them.
Test Plan: No new tests yet, but this should definitel be tested. #willfix.
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2236
Summary:
ignores composition event commands until they're done. We then simply
update the new state after that happens.
Some additional refactoring:
- The <Contenteditable /> prop is 'value' instead of 'html' to make it
look more like a standard React controlled input
- Removed `filters` prop and `footerElements` prop from Contenteditable.
These could easily be moved into the composer (where they belong).
- Moved contenteditable and a few of its helper classes into their own
folder.
- Moved `UndoManager` up out of the `flux` folder into `src`. Currently
undo/redo is only in the composer when all contenteditables should have
the basic funcionality. Will refactor this later.
- Fix tests
Test Plan: manual
Reviewers: bengotow
Reviewed By: bengotow
Differential Revision: https://phab.nylas.com/D2211
Summary:
Adding signature support in preferences
Extracting out DraftStore extensions from the Contenteditable component
Moved Contenteditable to the nylas component kit
Build react remote window selection synchronization.
Test Plan: todo
Reviewers: bengotow
Reviewed By: bengotow
Differential Revision: https://phab.nylas.com/D2204
Summary:
The Promise chain we were creating was never cleared and created a memory
leak. We instead use a `PromiseQueue` to cleanup finished promises.
Also added several more tests and verified that the memory leak is gone
with the Chrome profiler
Test Plan: new tests
Reviewers: bengotow
Reviewed By: bengotow
Differential Revision: https://phab.nylas.com/D2184
Summary:
The EventStore was really doing nothing, except caching hundreds of MB of
event data unnecessarily in each and every window :(
Test Plan: manual
Reviewers: bengotow
Reviewed By: bengotow
Differential Revision: https://phab.nylas.com/D2187
Summary:
This diff centralizes logic for creating common tasks for things like moving to trash, archive, etc. TaskFactory exposes a set of convenience methods and hides the whole "and also remove the current label" business from the user.
This diff also formally separates the concept of "moving to trash" and "archiving" so that "remove" isn't used in an unclear way.
I also refactored where selection is managed. Previously you'd fire some action like archiveSelection and it'd clear the selection, but if you selected some items and used another method to archive a few, they were still selected. The selection is now bound to the ModelView as intended, so if items are removed from the modelView, they are removed from it's attached selection. This means that it shouldn't /technically/ be possible to have selected items which are not in view.
I haven't refactored the tests yet. They are likely broken...
Fix next/prev logic
Test Plan: Run tests
Reviewers: evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2157
Summary:
Fixes T4291
If I made a final edit to a pre-existing draft and sent, we'd queue a
`SyncbackDraftTask` before a `SendDraftTask`. This is important because
since we have a valid draft `server_id`, the `SendDraftTask` will send by
server_id, not by POSTing the whole body.
If the `SyncbackDraftTask` fails, then we had a very serious issue whereby
the `SendDraftTask` would keep on sending. Unfortunately the server never
got the latest changes and sent the wrong version of the draft. This
incorrect version would show up later when the `/send` endpoint returned
the message that got actually sent.
The solution was to make any queued `SendDraftTask` fail if a dependent
`SyncbackDraftTask` failed.
This meant we needed to make the requirements for `shouldWaitForTask`
stricter, and block if tasks failed.
Unfortunatley there was no infrastructure in place to do this.
The first change was to change `shouldWaitForTask` to `isDependentTask`.
If we're going to fail when a dependent task fails, I wanted the method
name to reflect this.
Now, if a dependent task fails, we recursively check the dependency tree
(and check for cycles) and `dequeue` anything that needed that to succeed.
I chose `dequeue` as the default action because it seemed as though all
current uses of `shouldWaitForTask` really should bail if their
dependencies fail. It's possible you don't want your task dequeued in this
dependency case. You can return the special `Task.DO_NOT_DEQUEUE_ME`
constant from the `onDependentTaskError` method.
When a task gets dequeued because of the reason above, the
`onDependentTaskError` callback gets fired. This gives tasks like the
`SendDraftTask` a chance to notify the user that it bailed. Not all tasks
need to notify.
The next big issue was a better way to determine if a task truely errored
to the point that we need to dequeue dependencies. In the Developer Status
area we were showing tasks that had errored as "Green" because we caught
the error and resolved with `Task.Status.Finished`. This used to be fine
since nothing life-or-death cared if a task errored or not. Now that it
might cause abortions down the line, we needed a more robust method then
this.
For one I changed `Task.Status.Finished` to a variety of finish types
including `Task.Status.Success`. The way you "error" out is to `throw` or
`Promise.reject` an `Error` object from the `performRemote` method. This
allows us to propagate API errors up, and acts as a safety net that can
catch any malformed code or unexpected responses.
The developer bar now shows a much richer set of statuses instead of a
binary one, which was REALLY helpful in debugging this. We also record
when a Task got dequeued because of the conditions introduced here.
Once all this was working we still had an issue of sending old drafts.
If after a `SyncbackDraftTask` failed, now we'd block the send and notify
the users as such. However, if we tried to send again, there was a
separate issue whereby we wouldn't queue another `SyncbackDraftTask` to
update the server with the latest information. Since our changes were
persisted to the DB, we thought we had no changes, and therefore didn't
need to queue a `SyncbackDraftTask`.
The fix to this is to always force the creation of a `SyncbackDraftTask`
before send regardless of the state of the `DraftStoreProxy`.
Test Plan: new tests. Lots of manual testing
Reviewers: bengotow
Reviewed By: bengotow
Subscribers: mg
Maniphest Tasks: T4291
Differential Revision: https://phab.nylas.com/D2156
Summary:
Also added tests to catch the case
Fixes T4290
Test Plan: new tests
Reviewers: bengotow
Reviewed By: bengotow
Maniphest Tasks: T4290
Differential Revision: https://phab.nylas.com/D2153
An absolute ContactStore spec was causing the listener leak by
re-initializing the store and not cleaning it up.
Intermittent theme manager failing spec might be caused due to timing of
the theme activation
Summary:
Contact ranking is now tested.
There was a bug whereby the RankingsJSONCache would only update in the
workerwindow. This regressed when Contact ranking moved exclusively into
the main window and separate composer windws requested rankings via ipc
Test Plan: New tests
Reviewers: drew, bengotow
Reviewed By: bengotow
Differential Revision: https://phab.nylas.com/D2134
Summary: Fixes Sentry 3319 and 3303
Test Plan: Run three new tests
Reviewers: dillon, evan
Reviewed By: dillon, evan
Differential Revision: https://phab.nylas.com/D2118