Turn on prettier support for markdown files, update all files

This commit is contained in:
Scott Nonnenberg 2018-05-01 15:37:21 -07:00
parent 47468ee3db
commit 322d307655
13 changed files with 782 additions and 971 deletions

View file

@ -12,34 +12,34 @@ locations if you have a question or comment:
Lastly, be sure to preview your issue before saving. Thanks! Lastly, be sure to preview your issue before saving. Thanks!
--> -->
- [ ] I have searched open and closed issues for duplicates * [ ] I have searched open and closed issues for duplicates
<!-- <!--
You can search all issues here: You can search all issues here:
https://github.com/WhisperSystems/Signal-Desktop/issues?utf8=%E2%9C%93&q=is%3Aissue https://github.com/WhisperSystems/Signal-Desktop/issues?utf8=%E2%9C%93&q=is%3Aissue
Replace [ ] with [X] once you've searched Replace [ ] with [X] once you've searched
--> -->
---------------------------------------- ---
### Bug description ### Bug description
<!-- Give an overall summary of the issue. --> <!-- Give an overall summary of the issue. -->
### Steps to reproduce ### Steps to reproduce
<!-- Using bullet points, list the steps that reproduce the bug. --> <!-- Using bullet points, list the steps that reproduce the bug. -->
1. 1. step one
2. 2. step two
3. 3. step three
Actual result: Actual result:
<!-- Describe the details of the buggy behaviour. --> <!-- Describe the details of the buggy behaviour. -->
Expected result: Expected result:
<!-- Describe in detail what the correct behavior should be. -->
<!-- Describe in detail what the correct behavior should be. -->
### Screenshots ### Screenshots
@ -48,19 +48,19 @@ How to take screenshots on all OSes: https://www.take-a-screenshot.org/
You can drag and drop images into this text box. You can drag and drop images into this text box.
--> -->
### Platform info ### Platform info
Signal version: Signal version:
<!-- You can see Signal's version number at Help -> About or File -> About Signal Desktop --> <!-- You can see Signal's version number at Help -> About or File -> About Signal Desktop -->
Operating System: Operating System:
<!-- Instructions for finding your OS version are here: http://whatsmyos.com/ --> <!-- Instructions for finding your OS version are here: http://whatsmyos.com/ -->
Linked device version: Linked device version:
<!-- Android: Settings -> Advanced, iOS: Settings -> General -> About -->
<!-- Android: Settings -> Advanced, iOS: Settings -> General -> About -->
### Link to debug log ### Link to debug log

View file

@ -8,17 +8,17 @@ Remember, you can preview this before saving it.
<!-- You can remove this first section if you have contributed before --> <!-- You can remove this first section if you have contributed before -->
### First time contributor checklist: ### First time contributor checklist:
- [ ] I have read the [README](https://github.com/WhisperSystems/Signal-Desktop/blob/master/README.md) and [Contributor Guidelines](https://github.com/WhisperSystems/Signal-Desktop/blob/master/CONTRIBUTING.md)
- [ ] I have signed the [Contributor Licence Agreement](https://whispersystems.org/cla/)
* [ ] I have read the [README](https://github.com/WhisperSystems/Signal-Desktop/blob/master/README.md) and [Contributor Guidelines](https://github.com/WhisperSystems/Signal-Desktop/blob/master/CONTRIBUTING.md)
* [ ] I have signed the [Contributor Licence Agreement](https://whispersystems.org/cla/)
### Contributor checklist: ### Contributor checklist:
- [ ] My contribution is **not** related to translations. _Please submit translation changes via our [Signal Desktop Transifex project](https://www.transifex.com/liliakai/signal-desktop/)._
- [ ] My commits are in nice logical chunks with [good commit messages](http://chris.beams.io/posts/git-commit/)
- [ ] My changes are [rebased](https://medium.freecodecamp.org/git-rebase-and-the-golden-rule-explained-70715eccc372) on the latest [`development`](https://github.com/WhisperSystems/Signal-Desktop/tree/development) branch
- [ ] My changes pass 100% of [local tests](https://github.com/WhisperSystems/Signal-Desktop/blob/master/CONTRIBUTING.md#tests)
- [ ] My changes are ready to be shipped to users
* [ ] My contribution is **not** related to translations. _Please submit translation changes via our [Signal Desktop Transifex project](https://www.transifex.com/liliakai/signal-desktop/)._
* [ ] My commits are in nice logical chunks with [good commit messages](http://chris.beams.io/posts/git-commit/)
* [ ] My changes are [rebased](https://medium.freecodecamp.org/git-rebase-and-the-golden-rule-explained-70715eccc372) on the latest [`development`](https://github.com/WhisperSystems/Signal-Desktop/tree/development) branch
* [ ] My changes pass 100% of [local tests](https://github.com/WhisperSystems/Signal-Desktop/blob/master/CONTRIBUTING.md#tests)
* [ ] My changes are ready to be shipped to users
### Description ### Description

View file

@ -1,5 +1,4 @@
Contributor Guidelines # Contributor Guidelines
======================
## Advice for new contributors ## Advice for new contributors
@ -20,7 +19,6 @@ Once you've spent a little bit of time planning your solution, it's a good idea
back to the issue and talk about your approach. We'd be happy to provide feedback. [An back to the issue and talk about your approach. We'd be happy to provide feedback. [An
ounce of prevention, as they say!](https://www.goodreads.com/quotes/247269-an-ounce-of-prevention-is-worth-a-pound-of-cure) ounce of prevention, as they say!](https://www.goodreads.com/quotes/247269-an-ounce-of-prevention-is-worth-a-pound-of-cure)
## Developer Setup ## Developer Setup
First, you'll need [Node.js](https://nodejs.org/) which matches our current version. First, you'll need [Node.js](https://nodejs.org/) which matches our current version.
@ -33,7 +31,7 @@ Then you need `git`, if you don't have that yet: https://git-scm.com/
And for the final step before we actually get started, you'll need build tools to install And for the final step before we actually get started, you'll need build tools to install
the native modules used by the application. On Windows, it's easiest to open the [Command the native modules used by the application. On Windows, it's easiest to open the [Command
Prompt (`cmd.exe`) as Administrator](https://technet.microsoft.com/en-us/library/cc947813(v=ws.10).aspx) Prompt (`cmd.exe`) as Administrator](<https://technet.microsoft.com/en-us/library/cc947813(v=ws.10).aspx>)
and run this: and run this:
``` ```
@ -78,7 +76,6 @@ Fear not! You don't have to link the app with your phone. During setup in develo
mode, you'll be presented with a 'Standalone' button which goes through the registration mode, you'll be presented with a 'Standalone' button which goes through the registration
process like you would on a phone. But you won't be linked to any other devices. process like you would on a phone. But you won't be linked to any other devices.
## The staging environment ## The staging environment
Sadly, this default setup results in no contacts and no message history, an entirely Sadly, this default setup results in no contacts and no message history, an entirely
@ -86,9 +83,10 @@ empty application. But you can use the information from your production install
Desktop to populate your testing application! Desktop to populate your testing application!
First, find your application data: First, find your application data:
- OSX: `~/Library/Application Support/Signal`
- Linux: `~/.config/Signal` * OSX: `~/Library/Application Support/Signal`
- Windows 10: `C:\Users\<YourName>\AppData\Roaming\Signal` * Linux: `~/.config/Signal`
* Windows 10: `C:\Users\<YourName>\AppData\Roaming\Signal`
Now make a copy of this production data directory in the same place, and call it Now make a copy of this production data directory in the same place, and call it
`Signal-development`. Now start up the development version of the app as normal, `Signal-development`. Now start up the development version of the app as normal,
@ -105,7 +103,6 @@ message history and contact list.
Here's the catch: you can't message any of these contacts, since they haven't done the Here's the catch: you can't message any of these contacts, since they haven't done the
same thing. Who can you message for testing? same thing. Who can you message for testing?
## Additional storage profiles ## Additional storage profiles
What you need for proper testing is additional phone numbers, to register additional What you need for proper testing is additional phone numbers, to register additional
@ -134,13 +131,11 @@ NODE_APP_INSTANCE=alice yarn run start
This changes the [userData](https://electron.atom.io/docs/all/#appgetpathname) This changes the [userData](https://electron.atom.io/docs/all/#appgetpathname)
directory from `%appData%/Signal` to `%appData%/Signal-aliceProfile`. directory from `%appData%/Signal` to `%appData%/Signal-aliceProfile`.
# Making changes # Making changes
So you're in the process of preparing that pull request. Here's how to make that go So you're in the process of preparing that pull request. Here's how to make that go
smoothly. smoothly.
## Tests ## Tests
Please write tests! Our testing framework is Please write tests! Our testing framework is
@ -163,44 +158,43 @@ the report with `yarn open-coverage`.
So you wanna make a pull request? Please observe the following guidelines. So you wanna make a pull request? Please observe the following guidelines.
* Please do not submit pull requests for translation fixes. Anyone can update * Please do not submit pull requests for translation fixes. Anyone can update
the translations in the translations in
[Transifex](https://www.transifex.com/projects/p/signal-desktop). [Transifex](https://www.transifex.com/projects/p/signal-desktop).
* Never use plain strings right in the source code - pull them from `messages.json`! * Never use plain strings right in the source code - pull them from `messages.json`!
You **only** need to modify the default locale You **only** need to modify the default locale
[`_locales/en/messages.json`](_locales/en/messages.json). Other locales are generated [`_locales/en/messages.json`](_locales/en/messages.json). Other locales are generated
automatically based on that file and then periodically uploaded to Transifex for automatically based on that file and then periodically uploaded to Transifex for
translation. translation.
* [Rebase](https://nathanleclaire.com/blog/2014/09/14/dont-be-scared-of-git-rebase/) your * [Rebase](https://nathanleclaire.com/blog/2014/09/14/dont-be-scared-of-git-rebase/) your
changes on the latest `development` branch, resolving any conflicts. changes on the latest `development` branch, resolving any conflicts.
This ensures that your changes will merge cleanly when you open your PR. This ensures that your changes will merge cleanly when you open your PR.
* Be sure to add and run tests! * Be sure to add and run tests!
* Make sure the diff between our master and your branch contains only the * Make sure the diff between our master and your branch contains only the
minimal set of changes needed to implement your feature or bugfix. This will minimal set of changes needed to implement your feature or bugfix. This will
make it easier for the person reviewing your code to approve the changes. make it easier for the person reviewing your code to approve the changes.
Please do not submit a PR with commented out code or unfinished features. Please do not submit a PR with commented out code or unfinished features.
* Avoid meaningless or too-granular commits. If your branch contains commits like * Avoid meaningless or too-granular commits. If your branch contains commits like
the lines of "Oops, reverted this change" or "Just experimenting, will the lines of "Oops, reverted this change" or "Just experimenting, will
delete this later", please [squash or rebase those changes away](https://robots.thoughtbot.com/git-interactive-rebase-squash-amend-rewriting-history). delete this later", please [squash or rebase those changes away](https://robots.thoughtbot.com/git-interactive-rebase-squash-amend-rewriting-history).
* Don't have too few commits. If you have a complicated or long lived feature * Don't have too few commits. If you have a complicated or long lived feature
branch, it may make sense to break the changes up into logical atomic chunks branch, it may make sense to break the changes up into logical atomic chunks
to aid in the review process. to aid in the review process.
* Provide a well written and nicely formatted commit message. See [this * Provide a well written and nicely formatted commit message. See [this
link](http://chris.beams.io/posts/git-commit/) link](http://chris.beams.io/posts/git-commit/)
for some tips on formatting. As far as content, try to include in your for some tips on formatting. As far as content, try to include in your
summary summary
1. What you changed 1. What you changed
2. Why this change was made (including git issue # if appropriate) 2. Why this change was made (including git issue # if appropriate)
3. Any relevant technical details or motivations for your implementation 3. Any relevant technical details or motivations for your implementation
choices that may be helpful to someone reviewing or auditing the commit choices that may be helpful to someone reviewing or auditing the commit
history in the future. When in doubt, err on the side of a longer history in the future. When in doubt, err on the side of a longer
commit message. commit message.
Above all, spend some time with the repository. Follow the pull request template added to Above all, spend some time with the repository. Follow the pull request template added to
your pull request description automatically. Take a look at recent approved pull requests, your pull request description automatically. Take a look at recent approved pull requests,
see how they did things. see how they did things.
## Linking to a staging mobile device ## Linking to a staging mobile device
Multiple standalone desktop devices are great for testing of a lot of scenarios. But a lot Multiple standalone desktop devices are great for testing of a lot of scenarios. But a lot
@ -226,7 +220,6 @@ Then you can set up your development build of Signal Desktop as normal. If you'v
set up as a standalone install, you can switch by opening the DevTools (View -> Toggle set up as a standalone install, you can switch by opening the DevTools (View -> Toggle
Developer Tools) and entering this into the Console and pressing enter: `window.owsDesktopApp.appView.openInstaller();` Developer Tools) and entering this into the Console and pressing enter: `window.owsDesktopApp.appView.openInstaller();`
## Changing to production ## Changing to production
If you're completely sure that your changes will have no impact to the production servers, If you're completely sure that your changes will have no impact to the production servers,
@ -244,16 +237,16 @@ you can connect your development build to the production server by putting a fil
production servers will _unregister_ your mobile device! All messages from your contacts production servers will _unregister_ your mobile device! All messages from your contacts
will go to your new development desktop app instead of your phone. will go to your new development desktop app instead of your phone.
## Testing Production Builds ## Testing Production Builds
To test changes to the build system, build a release using To test changes to the build system, build a release using
``` ```
yarn generate yarn generate
yarn build-release yarn build-release
``` ```
Then, run the tests using `grunt test-release:osx --dir=release`, replacing `osx` with `linux` or `win` depending on your platform.
Then, run the tests using `grunt test-release:osx --dir=release`, replacing `osx` with `linux` or `win` depending on your platform.
## Dependencies ## Dependencies
@ -265,11 +258,11 @@ npm, then run `npm install` to install bower, grunt, and related plugins.
### Adding a bower component ### Adding a bower component
Add the package name and version to bower.json under 'dependencies' or `bower Add the package name and version to bower.json under 'dependencies' or `bower install package-name --save`
install package-name --save`
Next update the "preen" config in bower.json with the list of files we will Next update the "preen" config in bower.json with the list of files we will
actually use from the new package, e.g.: actually use from the new package, e.g.:
``` ```
"preen": { "preen": {
"package-name": [ "package-name": [
@ -279,6 +272,7 @@ actually use from the new package, e.g.:
... ...
} }
``` ```
If you'd like to add the new dependency to js/components.js to be included on If you'd like to add the new dependency to js/components.js to be included on
all html pages, simply append the package name to the concat.app list in all html pages, simply append the package name to the concat.app list in
`bower.json`. Take care to insert it in the order you would like it `bower.json`. Take care to insert it in the order you would like it

View file

@ -4,7 +4,7 @@ Signal Desktop
Signal Desktop is an Electron application that links with your Signal Desktop is an Electron application that links with your
[Signal Android](https://github.com/signalapp/Signal-Android) [Signal Android](https://github.com/signalapp/Signal-Android)
or [Signal iOS](https://github.com/signalapp/Signal-iOS) app. or [Signal iOS](https://github.com/signalapp/Signal-iOS) app.
## Install production version: https://signal.org/download/ ## Install production version: https://signal.org/download/
@ -12,40 +12,36 @@ Signal Desktop is an Electron application that links with your
You can install it on a computer which already has the production version installed. It uses different data and install locations. You can install it on a computer which already has the production version installed. It uses different data and install locations.
- _Windows:_ You can find the most recent build here: https://updates.signal.org/desktop/beta.yml * _Windows:_ You can find the most recent build here: https://updates.signal.org/desktop/beta.yml
- _Mac:_ You can find the most recent build here: https://updates.signal.org/desktop/beta-mac.yml * _Mac:_ You can find the most recent build here: https://updates.signal.org/desktop/beta-mac.yml
- _Linux:_ same instructions as the production install steps linked above, but run `apt-get install signal-desktop-beta` instead * _Linux:_ same instructions as the production install steps linked above, but run `apt-get install signal-desktop-beta` instead
## Got a question? ## Got a question?
You can find answers to a number of frequently asked questions on our support site: https://support.signal.org/. You can find answers to a number of frequently asked questions on our support site: https://support.signal.org/.
The community forum is another good place for questions: https://community.signalusers.org/. The community forum is another good place for questions: https://community.signalusers.org/.
## Found a Bug? Have a feature request? ## Found a Bug? Have a feature request?
Please search the existing issues for your bug and create a new one if the issue is not yet tracked! Please search the existing issues for your bug and create a new one if the issue is not yet tracked!
https://github.com/signalapp/Signal-Desktop/issues https://github.com/signalapp/Signal-Desktop/issues
## Contributing Translations ## Contributing Translations
Interested in helping to translate Signal? Contribute here: Interested in helping to translate Signal? Contribute here:
https://www.transifex.com/projects/p/signal-desktop https://www.transifex.com/projects/p/signal-desktop
## Contributing Code ## Contributing Code
Please see [CONTRIBUTING.md](https://github.com/signalapp/Signal-Desktop/blob/master/CONTRIBUTING.md) Please see [CONTRIBUTING.md](https://github.com/signalapp/Signal-Desktop/blob/master/CONTRIBUTING.md)
for setup instructions and contributor guidelines. And don't forget to sign the for setup instructions and contributor guidelines. And don't forget to sign the
[CLA](https://signal.org/cla/). [CLA](https://signal.org/cla/).
## Contributing Funds ## Contributing Funds
You can donate to Signal development through the [Freedom of the Press Foundation](https://freedom.press/crowdfunding/signal/).
You can donate to Signal development through the [Freedom of the Press Foundation](https://freedom.press/crowdfunding/signal/).
## Cryptography Notice ## Cryptography Notice

View file

@ -31,7 +31,7 @@
"lint": "yarn format --list-different && yarn lint-windows", "lint": "yarn format --list-different && yarn lint-windows",
"lint-windows": "yarn eslint && yarn grunt lint && yarn tslint", "lint-windows": "yarn eslint && yarn grunt lint && yarn tslint",
"tslint": "tslint --config tslint.json --format stylish --project .", "tslint": "tslint --config tslint.json --format stylish --project .",
"format": "prettier --write \"*.js\" \"js/**/*.js\" \"ts/**/*.{ts,tsx}\" \"test/**/*.js\"", "format": "prettier --write \"*.js\" \"js/**/*.js\" \"ts/**/*.{ts,tsx}\" \"test/**/*.js\" \"*.md\" \"./**/*.md\"",
"transpile": "tsc", "transpile": "tsc",
"clean-transpile": "rimraf ts/**/*.js ts/*.js", "clean-transpile": "rimraf ts/**/*.js ts/*.js",
"open-coverage": "open coverage/lcov-report/index.html", "open-coverage": "open coverage/lcov-report/index.html",

View file

@ -1,7 +1,7 @@
```js ```js
const noop = () => {}; const noop = () => {};
<div style={{position: 'relative', width: '100%', height: 500}}> <div style={{ position: 'relative', width: '100%', height: 500 }}>
<Lightbox <Lightbox
objectURL="https://placekitten.com/800/600" objectURL="https://placekitten.com/800/600"
contentType="image/jpeg" contentType="image/jpeg"
@ -9,5 +9,5 @@ const noop = () => {};
onPrevious={noop} onPrevious={noop}
onSave={noop} onSave={noop}
/> />
</div> </div>;
``` ```

View file

@ -10,10 +10,7 @@ const items = [
{ objectURL: 'https://placekitten.com/920/620', contentType: 'image/jpeg' }, { objectURL: 'https://placekitten.com/920/620', contentType: 'image/jpeg' },
]; ];
<div style={{position: 'relative', width: '100%', height: 500}}> <div style={{ position: 'relative', width: '100%', height: 500 }}>
<LightboxGallery <LightboxGallery items={items} onSave={noop} />
items={items} </div>;
onSave={noop}
/>
</div>
``` ```

View file

@ -1,4 +1,3 @@
Placeholder component: Placeholder component:
```jsx ```jsx
@ -17,21 +16,17 @@ const outgoing = new Whisper.Message({
body: 'How are you doing this fine day?', body: 'How are you doing this fine day?',
sent_at: Date.now() - 18000, sent_at: Date.now() - 18000,
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
### In a group conversation ### In a group conversation
@ -42,21 +37,17 @@ const outgoing = new Whisper.Message({
body: 'How are you doing this fine day?', body: 'How are you doing this fine day?',
sent_at: Date.now() - 200000, sent_at: Date.now() - 200000,
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme} type="group" > <util.ConversationContext theme={util.theme} type="group">
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
### With an error ### With an error
@ -72,22 +63,18 @@ const outgoing = new Whisper.Message({
sent_at: Date.now() - 200000, sent_at: Date.now() - 200000,
errors: [error], errors: [error],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
body: null, type: 'incoming',
})); body: null,
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Network error (outgoing only) #### Network error (outgoing only)
@ -103,12 +90,9 @@ const outgoing = new Whisper.Message({
body: "This message won't get through...", body: "This message won't get through...",
}); });
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme} type="group" > <util.ConversationContext theme={util.theme} type="group">
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: outgoing }} />
View={View} </util.ConversationContext>;
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Network error, partial send in group (outgoing only) #### Network error, partial send in group (outgoing only)
@ -125,12 +109,9 @@ const outgoing = new Whisper.Message({
body: "This message won't get through...", body: "This message won't get through...",
}); });
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme} type="group" > <util.ConversationContext theme={util.theme} type="group">
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: outgoing }} />
View={View} </util.ConversationContext>;
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### No message contents #### No message contents
@ -140,22 +121,18 @@ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 200000, sent_at: Date.now() - 200000,
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme} > <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
### Disappearing ### Disappearing
@ -168,22 +145,18 @@ const outgoing = new Whisper.Message({
expirationStartTimestamp: Date.now() - 1000, expirationStartTimestamp: Date.now() - 1000,
body: 'This message will self-destruct in two minutes', body: 'This message will self-destruct in two minutes',
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme} > <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
### Notfications ### Notfications
@ -200,7 +173,7 @@ const fromOther = new Whisper.Message({
expirationStartTimestamp: Date.now() - 1000, expirationStartTimestamp: Date.now() - 1000,
expirationTimerUpdate: { expirationTimerUpdate: {
source: '+12025550003', source: '+12025550003',
} },
}); });
const fromUpdate = new Whisper.Message({ const fromUpdate = new Whisper.Message({
type: 'incoming', type: 'incoming',
@ -212,7 +185,7 @@ const fromUpdate = new Whisper.Message({
expirationTimerUpdate: { expirationTimerUpdate: {
fromSync: true, fromSync: true,
source: util.ourNumber, source: util.ourNumber,
} },
}); });
const fromMe = new Whisper.Message({ const fromMe = new Whisper.Message({
type: 'incoming', type: 'incoming',
@ -223,23 +196,14 @@ const fromMe = new Whisper.Message({
expirationStartTimestamp: Date.now() - 1000, expirationStartTimestamp: Date.now() - 1000,
expirationTimerUpdate: { expirationTimerUpdate: {
source: util.ourNumber, source: util.ourNumber,
} },
}); });
const View = Whisper.ExpirationTimerUpdateView; const View = Whisper.ExpirationTimerUpdateView;
<util.ConversationContext theme={util.theme} > <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: fromOther }} />
View={View} <util.BackboneWrapper View={View} options={{ model: fromUpdate }} />
options={{ model: fromOther }} <util.BackboneWrapper View={View} options={{ model: fromMe }} />
/> </util.ConversationContext>;
<util.BackboneWrapper
View={View}
options={{ model: fromUpdate }}
/>
<util.BackboneWrapper
View={View}
options={{ model: fromMe }}
/>
</util.ConversationContext>
``` ```
#### Safety number change #### Safety number change
@ -251,12 +215,9 @@ const incoming = new Whisper.Message({
key_changed: '+12025550003', key_changed: '+12025550003',
}); });
const View = Whisper.KeyChangeView; const View = Whisper.KeyChangeView;
<util.ConversationContext theme={util.theme} > <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} </util.ConversationContext>;
options={{ model: incoming }}
/>
</util.ConversationContext>
``` ```
#### Marking as verified #### Marking as verified
@ -277,16 +238,10 @@ const local = new Whisper.Message({
}); });
const View = Whisper.VerifiedChangeView; const View = Whisper.VerifiedChangeView;
<util.ConversationContext theme={util.theme} > <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: fromPrimary }} />
View={View} <util.BackboneWrapper View={View} options={{ model: local }} />
options={{ model: fromPrimary }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: local }}
/>
</util.ConversationContext>
``` ```
#### Marking as not verified #### Marking as not verified
@ -305,16 +260,10 @@ const local = new Whisper.Message({
}); });
const View = Whisper.VerifiedChangeView; const View = Whisper.VerifiedChangeView;
<util.ConversationContext theme={util.theme} > <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: fromPrimary }} />
View={View} <util.BackboneWrapper View={View} options={{ model: local }} />
options={{ model: fromPrimary }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: local }}
/>
</util.ConversationContext>
``` ```
#### Group update #### Group update
@ -324,29 +273,21 @@ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 200000, sent_at: Date.now() - 200000,
group_update: { group_update: {
joined: [ joined: ['+12025550007', '+12025550008', '+12025550009'],
'+12025550007',
'+12025550008',
'+12025550009',
],
}, },
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme} > <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### End session #### End session
@ -357,22 +298,18 @@ const outgoing = new Whisper.Message({
sent_at: Date.now() - 200000, sent_at: Date.now() - 200000,
flags: textsecure.protobuf.DataMessage.Flags.END_SESSION, flags: textsecure.protobuf.DataMessage.Flags.END_SESSION,
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme} > <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
### With an attachment ### With an attachment
@ -384,27 +321,25 @@ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
body: 'I am pretty confused about Pi.', body: 'I am pretty confused about Pi.',
sent_at: Date.now() - 18000000, sent_at: Date.now() - 18000000,
attachments: [{ attachments: [
data: util.gif, {
fileName: 'pi.gif', data: util.gif,
contentType: 'image/gif', fileName: 'pi.gif',
}], contentType: 'image/gif',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Image #### Image
@ -413,27 +348,25 @@ const View = Whisper.MessageView;
const outgoing = new Whisper.Message({ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 18000000, sent_at: Date.now() - 18000000,
attachments: [{ attachments: [
data: util.gif, {
fileName: 'pi.gif', data: util.gif,
contentType: 'image/gif', fileName: 'pi.gif',
}], contentType: 'image/gif',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Image with portrait aspect ratio #### Image with portrait aspect ratio
@ -442,30 +375,27 @@ const View = Whisper.MessageView;
const outgoing = new Whisper.Message({ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 18000000, sent_at: Date.now() - 18000000,
attachments: [{ attachments: [
data: util.portraitYellow, {
fileName: 'portraitYellow.png', data: util.portraitYellow,
contentType: 'image/png', fileName: 'portraitYellow.png',
}], contentType: 'image/png',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Image with portrait aspect ratio and caption #### Image with portrait aspect ratio and caption
```jsx ```jsx
@ -473,27 +403,25 @@ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
body: 'This is an odd yellow bar. Cool, huh?', body: 'This is an odd yellow bar. Cool, huh?',
sent_at: Date.now() - 18000000, sent_at: Date.now() - 18000000,
attachments: [{ attachments: [
data: util.portraitYellow, {
fileName: 'portraitYellow.png', data: util.portraitYellow,
contentType: 'image/png', fileName: 'portraitYellow.png',
}], contentType: 'image/png',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Image with landscape aspect ratio #### Image with landscape aspect ratio
@ -502,27 +430,25 @@ const View = Whisper.MessageView;
const outgoing = new Whisper.Message({ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 18000000, sent_at: Date.now() - 18000000,
attachments: [{ attachments: [
data: util.landscapePurple, {
fileName: 'landscapePurple.jpg', data: util.landscapePurple,
contentType: 'image/jpeg', fileName: 'landscapePurple.jpg',
}], contentType: 'image/jpeg',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Image with landscape aspect ratio and caption #### Image with landscape aspect ratio and caption
@ -532,27 +458,25 @@ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
body: "An interesting horizontal bar. It's art.", body: "An interesting horizontal bar. It's art.",
sent_at: Date.now() - 18000000, sent_at: Date.now() - 18000000,
attachments: [{ attachments: [
data: util.landscapePurple, {
fileName: 'landscapePurple.jpg', data: util.landscapePurple,
contentType: 'image/jpeg', fileName: 'landscapePurple.jpg',
}], contentType: 'image/jpeg',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Video with caption #### Video with caption
@ -562,27 +486,25 @@ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
body: "Beautiful, isn't it?", body: "Beautiful, isn't it?",
sent_at: Date.now() - 10000, sent_at: Date.now() - 10000,
attachments: [{ attachments: [
data: util.mp4, {
fileName: 'freezing_bubble.mp4', data: util.mp4,
contentType: 'video/mp4', fileName: 'freezing_bubble.mp4',
}], contentType: 'video/mp4',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Video #### Video
@ -591,27 +513,25 @@ const View = Whisper.MessageView;
const outgoing = new Whisper.Message({ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 10000, sent_at: Date.now() - 10000,
attachments: [{ attachments: [
data: util.mp4, {
fileName: 'freezing_bubble.mp4', data: util.mp4,
contentType: 'video/mp4', fileName: 'freezing_bubble.mp4',
}], contentType: 'video/mp4',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Audio with caption #### Audio with caption
@ -621,27 +541,25 @@ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
body: 'This is a nice song', body: 'This is a nice song',
sent_at: Date.now() - 15000, sent_at: Date.now() - 15000,
attachments: [{ attachments: [
data: util.mp3, {
fileName: 'agnus_dei.mp3', data: util.mp3,
contentType: 'audio/mp3', fileName: 'agnus_dei.mp3',
}], contentType: 'audio/mp3',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Audio #### Audio
@ -650,27 +568,25 @@ const View = Whisper.MessageView;
const outgoing = new Whisper.Message({ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 15000, sent_at: Date.now() - 15000,
attachments: [{ attachments: [
data: util.mp3, {
fileName: 'agnus_dei.mp3', data: util.mp3,
contentType: 'audio/mp3', fileName: 'agnus_dei.mp3',
}], contentType: 'audio/mp3',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Voice message #### Voice message
@ -679,28 +595,26 @@ const View = Whisper.MessageView;
const outgoing = new Whisper.Message({ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 15000, sent_at: Date.now() - 15000,
attachments: [{ attachments: [
flags: textsecure.protobuf.AttachmentPointer.Flags.VOICE_MESSAGE, {
data: util.mp3, flags: textsecure.protobuf.AttachmentPointer.Flags.VOICE_MESSAGE,
fileName: 'agnus_dei.mp3', data: util.mp3,
contentType: 'audio/mp3', fileName: 'agnus_dei.mp3',
}], contentType: 'audio/mp3',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Other file type with caption #### Other file type with caption
@ -710,27 +624,25 @@ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
body: 'My manifesto is now complete!', body: 'My manifesto is now complete!',
sent_at: Date.now() - 15000, sent_at: Date.now() - 15000,
attachments: [{ attachments: [
data: util.txt, {
fileName: 'lorum_ipsum.txt', data: util.txt,
contentType: 'text/plain', fileName: 'lorum_ipsum.txt',
}], contentType: 'text/plain',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```
#### Other file type #### Other file type
@ -739,25 +651,23 @@ const View = Whisper.MessageView;
const outgoing = new Whisper.Message({ const outgoing = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
sent_at: Date.now() - 15000, sent_at: Date.now() - 15000,
attachments: [{ attachments: [
data: util.txt, {
fileName: 'lorum_ipsum.txt', data: util.txt,
contentType: 'text/plain', fileName: 'lorum_ipsum.txt',
}], contentType: 'text/plain',
},
],
}); });
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { const incoming = new Whisper.Message(
source: '+12025550003', Object.assign({}, outgoing.attributes, {
type: 'incoming', source: '+12025550003',
})); type: 'incoming',
})
);
const View = Whisper.MessageView; const View = Whisper.MessageView;
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={{ model: incoming }} />
View={View} <util.BackboneWrapper View={View} options={{ model: outgoing }} />
options={{ model: incoming }} </util.ConversationContext>;
/>
<util.BackboneWrapper
View={View}
options={{ model: outgoing }}
/>
</util.ConversationContext>
``` ```

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,11 @@
```js ```js
<div style={{ position: "relative", width: "100%", height: 300 }}> <div style={{ position: 'relative', width: '100%', height: 300 }}>
<EmptyState label="You have no attachments with media" /> <EmptyState label="You have no attachments with media" />
</div> </div>
``` ```
```js ```js
<div style={{ position: "relative", width: "100%", height: 500 }}> <div style={{ position: 'relative', width: '100%', height: 500 }}>
<EmptyState label="You have no documents with media" /> <EmptyState label="You have no documents with media" />
</div> </div>
``` ```

View file

@ -18,27 +18,32 @@ const MONTH_MS = 30 * DAY_MS;
const YEAR_MS = 12 * MONTH_MS; const YEAR_MS = 12 * MONTH_MS;
const tokens = ['foo', 'bar', 'baz', 'qux', 'quux']; const tokens = ['foo', 'bar', 'baz', 'qux', 'quux'];
const fileExtensions = ['docx', 'pdf', 'txt', 'mp3', 'wmv', 'tiff']; const fileExtensions = ['docx', 'pdf', 'txt', 'mp3', 'wmv', 'tiff'];
const createRandomMessage = ({startTime, timeWindow} = {}) => (props) => { const createRandomMessage = ({ startTime, timeWindow } = {}) => props => {
const now = Date.now(); const now = Date.now();
const fileName = const fileName = `${_.sample(tokens)}${_.sample(tokens)}.${_.sample(
`${_.sample(tokens)}${_.sample(tokens)}.${_.sample(fileExtensions)}`; fileExtensions
)}`;
return { return {
id: _.random(now).toString(), id: _.random(now).toString(),
received_at: _.random(startTime, startTime + timeWindow), received_at: _.random(startTime, startTime + timeWindow),
attachments: [{ attachments: [
data: null, {
fileName, data: null,
size: _.random(1000, 1000 * 1000 * 50), fileName,
}], size: _.random(1000, 1000 * 1000 * 50),
},
],
objectURL: `https://placekitten.com/${_.random(50, 150)}/${_.random(50, 150)}`, objectURL: `https://placekitten.com/${_.random(50, 150)}/${_.random(
50,
150
)}`,
...props, ...props,
}; };
}; };
const createRandomMessages = ({startTime, timeWindow}) => const createRandomMessages = ({ startTime, timeWindow }) =>
_.range(_.random(5, 10)).map(createRandomMessage({startTime, timeWindow})); _.range(_.random(5, 10)).map(createRandomMessage({ startTime, timeWindow }));
const startTime = Date.now(); const startTime = Date.now();
const messages = _.sortBy( const messages = _.sortBy(
@ -67,9 +72,5 @@ const messages = _.sortBy(
message => -message.received_at message => -message.received_at
); );
<MediaGallery <MediaGallery i18n={window.i18n} media={messages} documents={messages} />;
i18n={window.i18n}
media={messages}
documents={messages}
/>
``` ```

View file

@ -6,15 +6,12 @@ const model = new Whisper.Message({
type: 'outgoing', type: 'outgoing',
body: 'text', body: 'text',
sent_at: Date.now() - 5000, sent_at: Date.now() - 5000,
}) });
const View = Whisper.MessageView; const View = Whisper.MessageView;
const options = { const options = {
model, model,
}; };
<util.ConversationContext theme={util.theme}> <util.ConversationContext theme={util.theme}>
<util.BackboneWrapper <util.BackboneWrapper View={View} options={options} />
View={View} </util.ConversationContext>;
options={options}
/>
</util.ConversationContext>
``` ```

View file

@ -1,4 +1,3 @@
The simplest example of using the `<ConversationContext />` component: The simplest example of using the `<ConversationContext />` component:
```jsx ```jsx