-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce React, TypeScript, TSLint and React-StyleGuidist #2219
Conversation
npm run transpile Works on files under js/react/ Outputs files right next to the .tsx file This is part of our `grunt dev` task, as well as the default grunt task, which does everything else necessary to get a raw git checkout ready to run.
Due to a number of hacks, the style guide can be used to show Backbone views. This will allow a smooth path from the old way of doing things to the new.
We also fully set up i18n and put it on util as well as making it available on windows.i18n for Backbone views.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First batch of comments. Super excited about this — nice work!!
Happy to discuss any details / style questions in person during standup 😄
.eslintignore
Outdated
js/views/**/*.js | ||
test/*.js | ||
test/models/*.js | ||
test/views/*.js | ||
/*.js | ||
|
||
# typescript-generated files | ||
js/react/**/*.js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏
.eslintignore
Outdated
# ES2015+ files | ||
!js/background.js | ||
!js/backup.js | ||
!js/database.js | ||
!js/logging.js | ||
!js/i18n.js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
Gruntfile.js
Outdated
'!js/modules/**/*.js', | ||
'!js/views/conversation_search_view.js', | ||
'!js/react/**/*.js', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Could we try and keep 🔡 order in such lists to make them easier to scan and avoid duplicates? I often use Sublime Text‘s Sort Lines command 😄
return content; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎆
tasks: ['jshint'] | ||
}, | ||
style: { | ||
files: ['<%= jscs.all.src %>', './js/**/*.js'], | ||
files: ['<%= jscs.all.src %>'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the past, I’ve liked using git ls-files
to only target files we are actually tracking but I know this can break down in places where we don’t have Git. In our case, we even have Git on CI though, right? Would you be open to that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you're suggesting here. We've already specified, in detail, what the jscs
task applies to, so we'll be using that for the watch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies if I wasn’t clear. I meant that we often reference js/**/*.js
but that includes all files in the repo, regardless of whether they’re tracked in Git or not. When working on a new feature, one can have JS files in the project that haven’t been checked in but still trigger lint errors, etc.
js/react/conversation/Message.tsx
Outdated
</li> | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
js/react/conversation/Message.tsx
Outdated
<div className="bubble"> | ||
<div className="sender" dir="auto" /> | ||
<div className="attachments" /> | ||
<p className="content" dir="auto"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious: What’s our guideline for setting dir
attribute? The following article suggests setting it where user enter data: https://www.w3.org/International/questions/qa-html-dir Do we set it here because our app is localized and the templates may be filled with either LTR or RTL text? I don’t have a lot of experience with bidi compatibility 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pure history. Not really sure what the reasoning is there. I just copied what messages are generating today!
js/react/util/BackboneWrapper.tsx
Outdated
@@ -0,0 +1,78 @@ | |||
import React from 'react'; | |||
|
|||
interface IProps { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, this might be contentious but the TypeScript community has a convention not to use I
prefixes for interfaces:
- https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines#names
- Prohibition against prefixing interfaces with "I" microsoft/TypeScript-Handbook#121
Since we seem to agree to prefer not using classes, this shouldn’t be a big issue for us. Let’s discuss this in person 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed! I only did it because tslint
defaulted that way.
js/react/util/BackboneWrapper.tsx
Outdated
this.el = element; | ||
this.setup(); | ||
}; | ||
this.setup = this.setup.bind(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: If we use static initializers, we can avoid the manual binds (note the =
assignment), e.g.
private handleClick = () => {
this.handleUserLogin({isNew: false})
}
We used this extensively on previous team with great success! (we might have to enable some TSC option for it though, IIRC)
js/react/util/MessageParents.tsx
Outdated
/** | ||
* Corresponds to the theme setting in the app, and the class added to the root element. | ||
*/ | ||
theme: 'ios' | 'android' | 'android-dark'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, loving these union types!! http://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Really excited about this — nice work and thanks for starting this 🎉
js/react/util/BackboneWrapper.tsx
Outdated
super(props); | ||
|
||
this.el = null; | ||
this.view = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: You can initialize instance properties inline using static initializers:
protected el: Element | null = null;
protected view: IBackboneView | null = null;
js/react/util/index.ts
Outdated
|
||
// TypeScript wants two things when you import: | ||
// 1) a normal typescript file | ||
// 2) a javascript file with type definiitions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor typo: definiitions
--> definitions
js/react/util/MessageParents.tsx
Outdated
/** | ||
* Provides the parent elements necessary to allow the main Signal Desktop stylesheet to | ||
* apply (with no changes) to messages in this context. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love this! Thanks for documenting.
js/react/util/MessageParents.tsx
Outdated
* Provides the parent elements necessary to allow the main Signal Desktop stylesheet to | ||
* apply (with no changes) to messages in this context. | ||
*/ | ||
export class MessageParents extends React.Component<IProps, {}> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: How about *Container
or *Provider
to align with Redux concepts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
js/react/util/index.ts
Outdated
|
||
|
||
// Required, or TypeScript complains about adding keys to window | ||
const parent = window as any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grr, I hate when that happens. I think there are ways to define the new props but I’d have to do some research.
{ | ||
// To test handling of attachments, we need arraybuffers in memory | ||
test: /\.(gif|mp3|mp4|txt)$/, | ||
loader: 'arraybuffer-loader', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice find! 👀
(we were getting crashes in the initial setup of a backbone view)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍 Just found one typo (I think)
js/react/util/BackboneWrapper.md
Outdated
@@ -1,4 +1,4 @@ | |||
Rendering a real `Whisper.MessageView` using `<util.MessageParents />` and | |||
Rendering a real `Whisper.MessageView` using `<util.ConversationContextProvider />` and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: ConversationContextProvider
--> ConversationContext
(I think)
Last two commits LGTM 👍 |
Split out test-specific and general utility react components too. And moved our test/legacy* files for the Style Guide into a styleguide/ subdirectory of test/. I think we'll be able to live in this directory structure for a while.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good 🚢
<!-- When making changes to these templates, be sure to update these two places: | ||
1) test/styleguide/legacy_templates.js | ||
2) test/index.html | ||
--> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 👏 👏 Super helpful!
test/styleguide/legacy_bridge.js
Outdated
@@ -17,14 +18,14 @@ window.Signal.Migrations = { | |||
getPlaceholderMigrations: () => {}, | |||
}; | |||
|
|||
window.Signal.React = window.Signal.React = {}; | |||
window.Signal.React = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reminds me - perhaps this should be window.Signal.Components
?
test/styleguide/legacy_templates.js
Outdated
|
||
window.Whisper.View.Templates = { | ||
hasRetry: ` | ||
{{ messageNotSent }} | ||
<span href='#' class='retry'>{{ resend }}</span> | ||
{{ messageNotSent }} <span href='#' class='retry'>{{ resend }}</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, one thing you might notice is that since React doesn’t output spaces in the HTML, we might have to tweak certain paddings and margins in places! 😄 See: https://github.com/gasi/Signal-Desktop/pull/1/files#r165859574
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These aren't rendered with React... yet. Duly noted, however!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
ts/test/StyleGuideUtil.ts
Outdated
SignalReact.Message = Message; | ||
SignalReact.Reply = Reply; | ||
SignalComponents.Message = Message; | ||
SignalComponents.Reply = Reply; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: What if we did the following?
parent.Signal.Components = {
Message,
Reply,
};
Receive quoted replies (#2244) iOS theme: one bubble for both attachment and message contents (#2244) Improve URL Auto-Linking In Messages (#2240) Redact More Variants Of Paths In Stack Traces (#2229) Fixed: Conversation message preview would sometimes continue to show after message disappeared (1206b3c) Dev: Introduce React, TypeScript, TSLint and React-StyleGuidist (#2219 and #2232)
Quite a bit of change here.
First, the basics:
react
,typescript
,tslint
, andreact-styleguidist
npm
script:transpile
. It usestypescript
to process.tsx
files injs/react
, putting.js
files next to the original file. It's part of the watch functionality ofgrunt dev
as well as the default task run with justgrunt
(used to build the app prior to release). A lighter-weight to get watch behavior when just working on React components is to runyarn transpile --watch
.yarn run clean-transpile
will remove generated.js
filesStyle guide via
react-styleguidist
. Example site: https://react-styleguidist.js.org/examples/basic/yarn styleguide
Component.md
files right next to the.tsx
fileA bit of dependency cleanup to enable use in React components:
moment
was moved from our Bower dependencies to ournpm
dependencies, so it can be used in React components not running in a browser window.i18n
was moved into the newcommonjs
format, so it can be used in React components even ifwindow
is not available.Lastly, a bit of Gruntfile cleanup:
background.js
jshint
/jscs
watch more targeted, since more and more we'll be using other tools