Commit Graph

121 Commits (2fd2666eea571737fa689a2808b3e5f8786701f0)

Author SHA1 Message Date
Eugen Rochko 795f0107d2
Include preview cards in status entity in REST API (#9120)
* Include preview cards in status entity in REST API

* Display preview card in-stream

* Improve in-stream display of preview cards
2018-10-28 06:35:03 +01:00
Eugen Rochko eb1b9903a6
Redesign direct messages column (#9022) 2018-10-20 02:23:58 +02:00
Eugen Rochko 3d7f68c273
Revert Font Awesome 5 upgrade (#8810)
* Revert "Fix some icon names changed by the Font Awesome 5. (#8796)"

This reverts commit 3f9ec3de82.

* Revert "Migrate to font-awesome 5.0. (#8799)"

This reverts commit 8bae14591b.

* Revert "Fix some icons names, unavailable in fontawesome5 (free license). (#8792)"

This reverts commit b9c727a945.

* Revert "Update the icon name changed by the Font Awesome 5. (#8776)"

This reverts commit 17af4d27da.

* Revert "Add bot icon to bot avatars and migrate to newer version of Font Awesome (#8484)"

This reverts commit 4b794e134d.
2018-09-28 02:11:14 +02:00
Naoki Kosaka 8bae14591b Migrate to font-awesome 5.0. (#8799) 2018-09-27 17:08:56 +02:00
Haelwenn Monnier 15fc2b76f9 Show "read more" link on overly long in-stream statuses (#8205)
Show "read more" link on overly long in-stream statuses
2018-09-27 17:04:33 +02:00
Yamagishi Kazutoshi 0ddbccf7e6 Upgrade Babel to version 7.0.0 (#5925) 2018-09-14 17:59:48 +02:00
Maciek Baron 2bbec9f4da Add CSS class to replies (#8473) 2018-08-27 13:07:47 -04:00
Eugen Rochko a791bac153
Add aria-label to notifications (#8460)
Fix #8192
2018-08-26 17:53:26 +02:00
M Somerville ac092d03e7 Add missing video descriptions (#8416)
* Pass through video description as necessary.

* Add title to video, matching aria-label.
2018-08-24 23:55:41 +02:00
Eugen Rochko 248df68c36
Give focused status a sensible aria-label for screen readers (#8387)
* Give focused status a sensible aria-label for screen readers

Fix #8192

* Use content warning in aria-label unless expanded
2018-08-23 20:56:57 +02:00
M Somerville 298ee84488 Fix #8264 - Do not override ctrl/cmd+click. (#8265)
This includes clicks on hashtags, mentions, display names and media in the
timeline; and usernames in reply-indicator, detailed status, and the boost
modal.
2018-08-18 12:50:32 +02:00
Eugen Rochko cdb101340a
Keyword/phrase filtering (#7905)
* Add keyword filtering

    GET|POST       /api/v1/filters
    GET|PUT|DELETE /api/v1/filters/:id

- Irreversible filters can drop toots from home or notifications
- Other filters can hide toots through the client app
- Filters use a phrase valid in particular contexts, expiration

* Make sure expired filters don't get applied client-side

* Add missing API methods

* Remove "regex filter" from column settings

* Add tests

* Add test for FeedManager

* Add CustomFilter test

* Add UI for managing filters

* Add streaming API event to allow syncing filters

* Fix tests
2018-06-29 15:34:36 +02:00
Yamagishi Kazutoshi d9b2f84c92 Open video modal on public UI (#7469) 2018-05-13 13:48:14 +02:00
Yamagishi Kazutoshi e0b1e17bd0 Show media modal on public timeline (#7413) 2018-05-08 13:33:09 +02:00
TakesxiSximada 23106844a1 Fix the hot key (j, k) does not function correctly when there is a pinned toot in account timeline. (#7202)
* Fix the hot key (j, k) does not function correctly when there is a pinned toot in account timeline.

* Fix typo

* Add custom attribute prefix
2018-04-20 18:14:21 +02:00
Neil Moore fad7b9f5f2 Adds keyboard hotkey for revealing/hiding statuses (#7173)
Resolves #5550
2018-04-18 03:33:59 +02:00
Emelia Smith 904a2479dd Feature: Direct message from Statuses (#7089)
* Fix: Switching between composing direct message and mention from menus

Previously clicking "direct message" followed by "mention" resulted in the composed status staying as "direct", along with weird spacing of items in the text area. This attempts to fix that.

* Fix: Add missing proptype check for onMention in Status component

* Add the ability to send a direct message to a user from the menu on Statuses

* Add space between "Embed" and "Mention" on expanded statuses menu
2018-04-09 17:09:11 +02:00
Eugen Rochko b6003afcdb
Add show more/less toggle for entire threads in web UI (#6733)
Fix #1258
2018-03-11 09:52:59 +01:00
Eugen Rochko 77406d3a09
Display AttachmentList in notifications (#6693) 2018-03-08 08:22:04 +01:00
Eugen Rochko 86a9de6753
Display AttachmentList in timelines in compact style when media missing (#6680) 2018-03-08 04:54:26 +01:00
Eugen Rochko 9110db41c5
Federate pinned statuses over ActivityPub (#6610)
* Federate pinned statuses over ActivityPub

* Display pinned toots in web UI

Fix #6117

* Fix migration

* Fix tests

* Update outbox_serializer.rb

* Update remove_serializer.rb

* Update add_serializer.rb

* Update fetch_featured_collection_service.rb
2018-03-04 09:19:11 +01:00
Eugen Rochko 036dd98abb
Responsively enforce 16:9 ratio on all media thumbnails in web UI (#6590)
* Responsively enforce 16:9 ratio on all media thumbnails in web UI

Also change video player behaviour to "contain" rather than
"cover" videos that don't fit the ratio, unlike images and GIFs,
it's expected that a video is shown fully.

* Fix spacing issues and remove floor

* Remove floor
2018-03-02 07:00:04 +01:00
Yamagishi Kazutoshi 0a103c7749 Upgrade ESLint to version 4.x (#6276) 2018-01-17 16:57:15 +01:00
Eugen Rochko 7861c5f108
Surround mid-text display names with bdi tags (#6257)
* Fix #1095 - Surround mid-text display names with bdi tags

* Update jest snapshot
2018-01-15 18:55:10 +01:00
Nolan Lawson b254e6ca5f Refactor initial state: "me" (#5563)
* Refactor initial state: "me"

* remove "me" from reducers/meta.js
2017-10-31 11:27:48 +09:00
Nolan Lawson 5e111ce16d Reactor unfollow_modal, boost_modal, delete_modal (#5505) 2017-10-30 00:10:15 +09:00
Nolan Lawson 3de22a82bf Refactor initial state: reduce_motion and auto_play_gif (#5501) 2017-10-28 00:04:44 +09:00
Eugen Rochko 7db0f8dcb2 Implement hotkeys for web UI (#5164)
* Fix #2102 - Implement hotkeys

Hotkeys on status list:

- r to reply
- m to mention author
- f to favourite
- b to boost
- enter to open status
- p to open author's profile
- up or k to move up in the list
- down or j to move down in the list
- 1-9 to focus a status in one of the columns
- n to focus the compose textarea
- alt+n to start a brand new toot
- backspace to navigate back

* Add navigational hotkeys

The key g followed by:

- s: start
- h: home
- n: notifications
- l: local timeline
- t: federated timeline
- f: favourites
- u: own profile
- p: pinned toots
- b: blocked users
- m: muted users

* Add hotkey for focusing search, make escape un-focus compose/search

* Fix focusing notifications column, fix hotkeys in compose textarea
2017-10-06 01:07:59 +02:00
Eugen Rochko 632178d754 Use own, shorter relative timestamps (#5171)
* Use own, shorter relative timestamps

* Add acct to title tooltip of display name in statuses

* Improve i18n of the relative times
2017-10-04 01:23:52 +02:00
aschmitz 669fe9ee06 Change IDs to strings rather than numbers in API JSON output (#5019)
* Fix JavaScript interface with long IDs

Somewhat predictably, the JS interface handled IDs as numbers, which in
JS are IEEE double-precision floats. This loses some precision when
working with numbers as large as those generated by the new ID scheme,
so we instead handle them here as strings. This is relatively simple,
and doesn't appear to have caused any problems, but should definitely
be tested more thoroughly than the built-in tests. Several days of use
appear to support this working properly.

BREAKING CHANGE:

The major(!) change here is that IDs are now returned as strings by the
REST endpoints, rather than as integers. In practice, relatively few
changes were required to make the existing JS UI work with this change,
but it will likely hit API clients pretty hard: it's an entirely
different type to consume. (The one API client I tested, Tusky, handles
this with no problems, however.)

Twitter ran into this issue when introducing Snowflake IDs, and decided
to instead introduce an `id_str` field in JSON responses. I have opted
to *not* do that, and instead force all IDs to 64-bit integers
represented by strings in one go. (I believe Twitter exacerbated their
problem by rolling out the changes three times: once for statuses, once
for DMs, and once for user IDs, as well as by leaving an integer ID
value in JSON. As they said, "If you’re using the `id` field with JSON
in a Javascript-related language, there is a very high likelihood that
the integers will be silently munged by Javascript interpreters. In most
cases, this will result in behavior such as being unable to load or
delete a specific direct message, because the ID you're sending to the
API is different than the actual identifier associated with the
message." [1]) However, given that this is a significant change for API
users, alternatives or a transition time may be appropriate.

1: https://blog.twitter.com/developer/en_us/a/2011/direct-messages-going-snowflake-on-sep-30-2011.html

* Additional fixes for stringified IDs in JSON

These should be the last two. These were identified using eslint to try
to identify any plain casts to JavaScript numbers. (Some such casts are
legitimate, but these were not.)

Adding the following to .eslintrc.yml will identify casts to numbers:

~~~
  no-restricted-syntax:
  - warn
  - selector: UnaryExpression[operator='+'] > :not(Literal)
    message: Avoid the use of unary +
  - selector: CallExpression[callee.name='Number']
    message: Casting with Number() may coerce string IDs to numbers
~~~

The remaining three casts appear legitimate: two casts to array indices,
one in a server to turn an environment variable into a number.

* Back out RelationshipsController Change

This was made to make a test a bit less flakey, but has nothing to
do with this branch.

* Change internal streaming payloads to stringified IDs as well

Per
https://github.com/tootsuite/mastodon/pull/5019#issuecomment-330736452
we need these changes to send deleted status IDs as strings, not
integers.
2017-09-20 14:53:48 +02:00
Eugen Rochko 2bbf987a0a Redesign video player (#4911)
* Redesign video player

* Use new video player on static public pages too

* Use media gallery component on static public pages too

* Pause video when hiding it

* Full-screen sizing on WebKit

* Add aria labels to video player buttons

* Display link card on public status page

* Fix fullscreen from modal sizing issue

* Remove contain: strict property to fix fullscreen from columns
2017-09-14 03:39:10 +02:00
Eugen Rochko 9c04fadec9 Finish up embed modal feature (#4759)
* Add embed button to dropdowns of in-timeline statuses

* yarn run manage:translations
2017-09-01 21:30:13 +02:00
abcang 0827c09c44 Generalized the infinite scrollable list (#4697) 2017-08-28 22:23:44 +02:00
Eugen Rochko 9caa90025f Pinned statuses (#4675)
* Pinned statuses

* yarn manage:translations
2017-08-25 01:41:18 +02:00
Sorin Davidoi 8eb6d171e6 feat: Cache status height to avoid expensive renders (#4439)
* feat: Cache status height to avoid expensive renders

* feat: Escape content and emojify in reducers

* fix(css): Remove backface-visibility: hidden from .scrollable

* fix(statuses): Avoid creating DOMParses inside a loop
2017-08-07 20:32:03 +02:00
Ondřej Hruška 5942347407 Refactor Avatar and AvatarOverlay to have 'account' as prop instead of src and staticSrc (#4526)
* Refactored Avatar and AvatarOverlay (DRY) to have 'account' as prop.
Also removed animate attribute from compose navigation bar, which should
have never been there. Added test for avatar overlay.

* fix broken tests

* god dammit another bug in tests! travis please let this pass

* formatting in avatar overlay
2017-08-07 19:44:55 +02:00
unarist a5e0cf2450 fix(status): Don't add tabIndex to wrapped status (#4437) 2017-07-29 14:20:05 +02:00
Sorin Davidoi 534da4f24f Improve accessibility (part 5) (#4417)
* fix(status): Add tabIndex=0

* fix(status_list): Make keyboard navigable
2017-07-28 13:33:40 +02:00
Yamagishi Kazutoshi 58eea59864 Fix broken PropTypes (#4413) 2017-07-28 13:32:05 +02:00
Sorin Davidoi b7d47c2aef Improve accessibility (part 4) (#4408)
* fix(dropdown_menu): Keyboard navigation

* fix(icon_button): Add aria-pressed attribute

* fix(privacy_dropdown): Make accessible

* fix(emoji_picker_dropdown): Make accessible

* fix(icon_button): Support tabIndex

* fix(actions_modal): Remove icon from tab order

* fix(dropdown_menu): Add role=group

* fix(setting_toggle): Toggle via space key

* fix(dropdown_menu): Remove redundant handling of Space key

* fix(emoji_picker_dropdown): Remove redundant Space key handling

* fix(privacy_dropdown): Remove redundant Space key handling

* fix(status): Switch to article and add aria-posinset, aria-setsize

* fix(status_list): Use role=feed and pass more ARIA props to Status

* chore(eslint): jsx-a11y/role-supports-aria-props
2017-07-28 04:37:30 +02:00
Yamagishi Kazutoshi f2233c3e25 Update intersection-observer to version 0.4.0 (#4398) 2017-07-27 16:20:48 +02:00
Eugen Rochko e19eefe219 Redesign the landing page, mount public timeline on it (#4122)
* Redesign the landing page, mount public timeline on it

* Adjust the standalone mounted component to the lacking of router

* Adjust auth layout pages to new design

* Fix tests

* Standalone public timeline polling every 5 seconds

* Remove now obsolete translations

* Add responsive design for new landing page

* Address reviews

* Add floating clouds behind frontpage form

* Use access token from public page when available

* Fix mentions and hashtags links, cursor on status content in standalone mode

* Add footer link to source code

* Fix errors on pages that don't embed the component, use classnames

* Fix tests

* Change anonymous autoPlayGif default to false

* When gif autoplay is disabled, hover to play

* Add option to hide the timeline preview

* Slightly improve alt layout

* Add elephant friend to new frontpage

* Display "back to mastodon" in place of "login" when logged in on frontpage

* Change polling time to 3s
2017-07-11 15:27:59 +02:00
Nolan Lawson 63b77f2320 Avoid using getBoundingClientRect to calculate height (#4001) 2017-07-08 01:57:22 +02:00
Sorin Davidoi 348d6f5e75 Lazy load components (#3879)
* feat: Lazy-load routes

* feat: Lazy-load modals

* feat: Lazy-load columns

* refactor: Simplify Bundle API

* feat: Optimize bundles

* feat: Prevent flashing the waiting state

* feat: Preload commonly used bundles

* feat: Lazy load Compose reducers

* feat: Lazy load Notifications reducer

* refactor: Move all dynamic imports into one file

* fix: Minor bugs

* fix: Manually hydrate the lazy-loaded reducers

* refactor: Move all dynamic imports to async-components

* fix: Loading modal style

* refactor: Avoid converting the raw state for each lazy hydration

* refactor: Remove unused component

* refactor: Maintain modal name

* fix: Add as=script to preload link

* chore: Fix lint error

* fix(components/bundle): Check if timestamp is set when computing elapsed

* fix: Load compose reducers for the onboarding modal
2017-07-08 00:06:02 +02:00
unarist 9c03fd9cae Unobserve status on unmount (#4013)
This fixes a warning on status unmounting (e.g. deletion).

This also resets IntersectionObserverWrapper on disconnect to avoid `unobserve()` calls
which has bug in Edge.
2017-07-06 21:26:21 +02:00
Sorin Davidoi 64d9c016bd fix(components/status): Up & down jump due to content being added to the DOM (#3972) 2017-06-27 18:43:53 +02:00
Yamagishi Kazutoshi c1a8e3d1eb Use Class and Property Decorators (#3730)
ref https://tc39.github.io/proposal-decorators/
2017-06-23 19:36:54 +02:00
Yamagishi Kazutoshi eff9416469 Remove unused variables (#3906) 2017-06-23 16:05:04 +02:00
unarist cc382c5006 Don't attach IntersectionObserver for wrapped statuses (#3883)
(This patch has been merged as bugfix and reverted, but still valuable as
improvement)

Previously, we've attached IntersectionObserver twice for boosted statuses:
wrapper Status and wrapped Status. but wrapped Status don't need to manage
intersection and visibility by itself, because it's a part of wrapper Status.
2017-06-21 06:47:36 +02:00
Eugen Rochko 946a166791 Revert #3851 (#3878) 2017-06-21 01:37:15 +02:00
Eugen Rochko 31cd649041 Revert "Don't attach IntersectionObserver for wrapped statuses" (#3877)
* Revert "Bump version to 1.4.4"

This reverts commit 1585b0c6cc.

* Revert "Fix conversations (fixes #3869) (#3870)"

This reverts commit 15b43f555d.

* Revert "Fix streaming server. Redis connection subscribe for each channel. (#3828)"

This reverts commit d8ec832806.

* Revert "Filter direct statuses in Status.as_home_timeline (#3842)"

This reverts commit bab5a18232.

* Revert "Fix RemoteFollow behavior (#3868)"

This reverts commit a20cf3b64e.

* Revert "Update fabricator for MediaAttachment to attach a file according to type (#3862)"

This reverts commit 356df7ae6b.

* Revert "Upgrade React Router (#3677)"

This reverts commit 8f03fdce7f.

* Revert "Do not call setState from unmounted component (#3853)"

This reverts commit 1fc6cb4997.

* Revert "Replace TextIconButton for SensitiveButton to IconButton (#3759)"

This reverts commit eb832e88f4.

* Revert "Fix RTL detection on Ruby side (#3867)"

This reverts commit b16b69350e.

* Revert "i18n: Fixed typo in Polish translation (#3864)"

This reverts commit da6fa029f6.

* Revert "Don't attach IntersectionObserver for wrapped statuses (#3863)"

This reverts commit 94ad0706f5.
2017-06-21 01:33:14 +02:00
Sorin Davidoi 8f03fdce7f Upgrade React Router (#3677)
* chore(yarn): Remove react-router

* chore(yarn): Remove react-router-scroll

* chore(yarn): Remove history

* chore(yarn): Add react-router-dom

* chore: Remove usages of react-router-scroll

* refactor: Upgrade to react-router-web

* refactor: Use fork of react-router-scroll

This reverts commit 2ddea9a6c8d39fc64b7d0b587f3fbda7a45a7fa2.

* fix: Issues mentions in the PR feedback
2017-06-20 20:40:03 +02:00
alpaca-tc 1fc6cb4997 Do not call setState from unmounted component (#3853)
Stop an executing task if the component already unmounted.
2017-06-20 20:37:09 +02:00
unarist 94ad0706f5 Don't attach IntersectionObserver for wrapped statuses (#3863)
This fixes a bug that sometimes boosted statuses being hidden on scrolling.

Previously, we've attached IntersectionObserver twice for boosted statuses:
wrapper Status and wrapped Status. This will call intersection handler twice,
so this may results race condition...probably.
2017-06-20 04:12:51 +02:00
alpaca-tc cf6fe4f8cb Unobserve status on unmount (#3851) 2017-06-19 11:29:57 +02:00
Sorin Davidoi 0f52e42c2d fix(status): Content jump due to height changes (#3734) 2017-06-13 20:46:21 +02:00
Yamagishi Kazutoshi d8ae3efec3 Improve ESLint rules for JSX (#3608)
* Add react/no-string-refs ESLint rule

* Add react/jsx-boolean-value ESLint rule

* Add react/jsx-closing-bracket-location ESLint rule

* Add react/jsx-indent ESLint rule

* Add react/jsx-curly-spacing ESLint rule

* Add react/jsx-equals-spacing ESLint rule

* Add react/jsx-first-prop-new-line ESLint rule

* Add react/jsx-no-duplicate-props ESLint rule

* Add react/jsx-tag-spacing ESLint rule
2017-06-06 13:20:07 +02:00
Nolan Lawson 3363f2f4d6 Fix isIntersecting in Chrome (#3525) 2017-06-03 14:43:10 +02:00
Nolan Lawson 0e12a8dab9 Improve scheduling of requestIdleCallback tasks (#3477) 2017-05-31 15:11:33 +02:00
Nolan Lawson 34a93ccf57 Add IntersectionObserverWrapper to cut down on re-renders (#3406) 2017-05-29 18:17:51 +02:00
unarist c6db416ff7 Fix "Cannot read property" on missing status (#3322)
I've found this issue when I clicked replies to muted user on the timeline.

Properties I've removed in here were added with lazy loading using
IntersectionObserver (8e4d1cba), but those statuses are not need to be
tracked anyway because it will be rendered as only empty div.
2017-05-26 14:07:48 +02:00
Nolan Lawson b00cb2aed3 Improve shouldComponentUpdate for status and status_action_bar (#3323) 2017-05-26 14:05:52 +02:00
unarist 9f69aa3cb1 Prevent contents of the status placeholder from overflowing (#3287)
Since long lines may overflow and cause the status-list horizontally scrollable,
I added `overflow: hidden` to placeholder contents to prevent it.
2017-05-25 02:23:54 +02:00
Sorin Davidoi 8e4d1cba00 Lazy load toots using IntersectionObserver (#3191)
* refactor(components/status_list): Lazy load using IntersectionObserver

* refactor(components/status_list): Avoid setState bottleneck

* refactor(components/status_list): Update state correctly

* fix(components/status): Render if isIntersecting is undefined

* refactor(components/status): Recycle timeout

* refactor(components/status): Reduce animation duration

* refactor(components/status): Use requestIdleCallback

* chore: Split polyfill bundles

* refactor(components/status_list): Increase rootMargin to 300%

* fix(components/status): Check if onRef is not defined

* chore: Add note about polyfill bundle splitting

* fix(components/status): Reduce animation duration to 0.3 seconds
2017-05-24 17:55:00 +02:00
Yamagishi Kazutoshi 2e112e2406 Improve eslint rules (#3147)
* Add semi to ESLint rules

* Add padded-blocks to ESLint rules

* Add comma-dangle to ESLint rules

* add config/webpack and storyboard

* add streaming/

* yarn test:lint -- --fix
2017-05-20 17:31:47 +02:00
Nolan Lawson 419226d1f6 Remove unnecessary status__info-time div (#3172) 2017-05-20 16:48:49 +02:00
Sorin Davidoi 1548695c83 Avoid useless renders (#3141)
* feat(eslint): Set react/jsx-no-bind: error

* refactor(notifications/setting_toggle): Do not use bind

* refactor(components/dropdown_menu): Do not use bind

* refactor(components/autosuggest_textarea): Do not use bind

* refactor(compose/privacy_dropdown): Do not use bind

* refactor(compose/upload_form): Do not use bind

* refactor(components/status): Do not use bind

* refactor(components/onboarding_modal): Do not use bind

* refactor: PR feedback

* chore(notifications/setting_toggle): Lint

* refactor: PR feedback
2017-05-19 20:58:12 +02:00
Eugen Rochko 1d5dcfcd46 Make direct statuses stand out more (#3025)
Resolves #2515
2017-05-13 01:38:51 +02:00
Yamagishi Kazutoshi 2991a7cfe6 Use ES Class Fields & Static Properties (#3008)
Use ES Class Fields & Static Properties (currently stage 2) for improve class outlook.

Added babel-plugin-transform-class-properties as a Babel plugin.
2017-05-12 14:44:10 +02:00
kawax 383c0b7802 Show boosted user's avatar (#2518)
* Show boosted user's avatar

* add .status__avatar-boost

* margin

* apply to notifications too.

* account__avatar-boost

* Add inline prop to Avatar component

* Add AvatarOverlay component

* rename mixins.scss

* move files for latest master

* fixed for webpack
2017-05-03 11:43:37 +02:00
Eugen Rochko f5bf5ebb82 Replace sprockets/browserify with Webpack (#2617)
* Replace browserify with webpack

* Add react-intl-translations-manager

* Do not minify in development, add offline-plugin for ServiceWorker background cache updates

* Adjust tests and dependencies

* Fix production deployments

* Fix tests

* More optimizations

* Improve travis cache for npm stuff

* Re-run travis

* Add back support for custom.scss as before

* Remove offline-plugin and babili

* Fix issue with Immutable.List().unshift(...values) not working as expected

* Make travis load schema instead of running all migrations in sequence

* Fix missing React import in WarningContainer. Optimize rendering performance by using ImmutablePureComponent instead of
React.PureComponent. ImmutablePureComponent uses Immutable.is() to compare props. Replace dynamic callback bindings in
<UI />

* Add react definitions to places that use JSX

* Add Procfile.dev for running rails, webpack and streaming API at the same time
2017-05-03 02:04:16 +02:00