From 1bbcd71cd403da843e8a4a67926a4394b31a63fd Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 4 Jan 2017 15:31:25 +0100 Subject: [PATCH 001/175] Fix #390 - fix redirect after sign-up (to login page instead of homepage) --- app/controllers/auth/registrations_controller.rb | 4 ++++ spec/controllers/auth/registrations_controller_spec.rb | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 60eb9905a3..6ce4984bb3 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -23,6 +23,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController new_user_session_path end + def after_inactive_sign_up_path_for(_resource) + new_user_session_path + end + def check_single_user_mode redirect_to root_path if Rails.configuration.x.single_user_mode end diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb index f7ebebbcb8..27ad6cbde5 100644 --- a/spec/controllers/auth/registrations_controller_spec.rb +++ b/spec/controllers/auth/registrations_controller_spec.rb @@ -20,8 +20,8 @@ RSpec.describe Auth::RegistrationsController, type: :controller do post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678' } } end - it 'redirects to home page' do - expect(response).to redirect_to root_path + it 'redirects to login page' do + expect(response).to redirect_to new_user_session_path end it 'creates user' do From 2b0b7ff1b8b134e97c8827721a59cac21897932c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 4 Jan 2017 15:35:36 +0100 Subject: [PATCH 002/175] Fix #385 - /web now loads a page --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 18c239c48a..e46b27f1f4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -136,7 +136,7 @@ Rails.application.routes.draw do end end - get '/web/*any', to: 'home#index', as: :web + get '/web/(*any)', to: 'home#index', as: :web get :about, to: 'about#index' get :terms, to: 'about#terms' From 98b83aca372fabdfc32b05c1eb72c80a79102e53 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 4 Jan 2017 15:43:28 +0100 Subject: [PATCH 003/175] Fix #391 - relative timestamps now contain an exact datetime in title --- .../components/relative_timestamp.jsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/components/components/relative_timestamp.jsx b/app/assets/javascripts/components/components/relative_timestamp.jsx index 3a5b885236..3b012b184b 100644 --- a/app/assets/javascripts/components/components/relative_timestamp.jsx +++ b/app/assets/javascripts/components/components/relative_timestamp.jsx @@ -1,15 +1,18 @@ -import { - FormattedMessage, - FormattedDate, - FormattedRelative -} from 'react-intl'; +import { injectIntl, FormattedRelative } from 'react-intl'; -const RelativeTimestamp = ({ timestamp }) => { - return ; +const RelativeTimestamp = ({ intl, timestamp }) => { + const date = new Date(timestamp); + + return ( + + ); }; RelativeTimestamp.propTypes = { + intl: React.PropTypes.object.isRequired, timestamp: React.PropTypes.string.isRequired }; -export default RelativeTimestamp; +export default injectIntl(RelativeTimestamp); From 3807b0b171d588ccccfc6210c823e5ce87b9b90f Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 17:25:48 -0800 Subject: [PATCH 004/175] Improve quality of life for 4-inch phones Removes extra UI margins < 360px, and allows the tab bar to scroll. Also slightly improves horizontal scrolling behaviour on desktop. --- .../features/ui/components/tabs_bar.jsx | 3 +-- app/assets/stylesheets/components.scss | 27 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx index 219979522b..499c9e287b 100644 --- a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx +++ b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx @@ -3,9 +3,8 @@ import { FormattedMessage } from 'react-intl'; const outerStyle = { background: '#373b4a', - margin: '10px', flex: '0 0 auto', - marginBottom: '0' + overflowY: 'auto' }; const tabStyle = { diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index acfa85c6bd..2996fa92e4 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -331,11 +331,15 @@ } .columns-area { - margin: 10px; - margin-left: 0; flex-direction: row; } +@media screen and (min-width: 360px) { + .columns-area { + margin: 10px; + } +} + .column { width: 330px; position: relative; @@ -346,11 +350,20 @@ } .column, .drawer { - margin-left: 10px; + margin-left: 5px; + margin-right: 5px; flex: 0 0 auto; overflow: hidden; } +.column:first-child, .drawer:first-child { + margin-left: 0; +} + +.column:last-child, .drawer:last-child { + margin-right: 0; +} + @media screen and (max-width: 1024px) { .column, .drawer { width: 100%; @@ -359,7 +372,6 @@ } .columns-area { - margin: 10px; flex-direction: column; } } @@ -368,6 +380,13 @@ display: flex; } +@media screen and (min-width: 360px) { + .tabs-bar { + margin: 10px; + margin-bottom: 0; + } +} + @media screen and (min-width: 1025px) { .tabs-bar { display: none; From 5b75f6d0f36940f40db9f1064f37b0069068b691 Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 17:32:11 -0800 Subject: [PATCH 005/175] Make tabs bar take up less room on 4-inch phones --- .../javascripts/components/features/ui/components/tabs_bar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx index 499c9e287b..dbfdc3f852 100644 --- a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx +++ b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx @@ -10,7 +10,7 @@ const outerStyle = { const tabStyle = { display: 'block', flex: '1 1 auto', - padding: '10px', + padding: '10px 5px', color: '#fff', textDecoration: 'none', textAlign: 'center', From 312736cd1baaea12935e7decbb457c06299cc7d4 Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 17:33:05 -0800 Subject: [PATCH 006/175] =?UTF-8?q?Stop=20Mastodon=20friend=20from=20overl?= =?UTF-8?q?apping=20text=20=F0=9F=90=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/features/getting_started/index.jsx | 4 +--- app/assets/stylesheets/components.scss | 12 ++++-------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/components/features/getting_started/index.jsx b/app/assets/javascripts/components/features/getting_started/index.jsx index 157bdf8f2f..77253dd731 100644 --- a/app/assets/javascripts/components/features/getting_started/index.jsx +++ b/app/assets/javascripts/components/features/getting_started/index.jsx @@ -43,13 +43,11 @@ const GettingStarted = ({ intl, me }) => { {followRequests} -
+

- -
); }; diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index 2996fa92e4..c644192432 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -608,12 +608,8 @@ } } -.getting-started__illustration { - width: 330px; - height: 235px; - background: image-url('mastodon-getting-started.png') no-repeat 0 0; - position: absolute; - pointer-events: none; - bottom: 0; - left: 0; +.getting-started { + overflow-y: auto; + padding-bottom: 235px; + background: image-url('mastodon-getting-started.png') no-repeat 0 100% local; } From aaee8c9b5d935143cf749fbea78f8cfee74ee37f Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 17:44:41 -0800 Subject: [PATCH 007/175] Disallow compose navbar from being shrunk --- .../components/features/compose/components/navigation_bar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx index df94c30d22..23d695f132 100644 --- a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx +++ b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx @@ -16,7 +16,7 @@ const NavigationBar = React.createClass({ render () { return ( -
+
From bb033c1d37db11a871011ac8cdf6737721fbc13e Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 18:00:50 -0800 Subject: [PATCH 008/175] "Reblog" -> "boost" in more places A couple of places were using "reblog" rather than "boost" - this updates them to match the web UI --- .../features/notifications/components/notification.jsx | 2 +- config/locales/en.yml | 4 ++-- spec/mailers/notification_mailer_spec.rb | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/components/features/notifications/components/notification.jsx b/app/assets/javascripts/components/features/notifications/components/notification.jsx index 9f4cf9e4df..37715dd05b 100644 --- a/app/assets/javascripts/components/features/notifications/components/notification.jsx +++ b/app/assets/javascripts/components/features/notifications/components/notification.jsx @@ -71,7 +71,7 @@ const Notification = React.createClass({
- +
diff --git a/config/locales/en.yml b/config/locales/en.yml index e166fc7170..dd2ae3aac0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -67,8 +67,8 @@ en: body: 'You were mentioned by %{name} in:' subject: You were mentioned by %{name} reblog: - body: 'Your status was reblogged by %{name}:' - subject: "%{name} reblogged your status" + body: 'Your status was boosted by %{name}:' + subject: "%{name} boosted your status" pagination: next: Next prev: Prev diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index d4baca5aaa..3beaebeb1c 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -53,12 +53,12 @@ RSpec.describe NotificationMailer, type: :mailer do let(:mail) { NotificationMailer.reblog(own_status.account, Notification.create!(account: receiver.account, activity: reblog)) } it "renders the headers" do - expect(mail.subject).to eq("bob reblogged your status") + expect(mail.subject).to eq("bob boosted your status") expect(mail.to).to eq([receiver.email]) end it "renders the body" do - expect(mail.body.encoded).to match("Your status was reblogged by bob") + expect(mail.body.encoded).to match("Your status was boosted by bob") end end From cbcb7e1241c4d0655ca7c6ad0840585d61e23e03 Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 18:10:45 -0800 Subject: [PATCH 009/175] Don't render the media list when there's no media This stops the empty compose view from scrolling on 4-inch devices. --- .../features/compose/components/upload_form.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/components/features/compose/components/upload_form.jsx b/app/assets/javascripts/components/features/compose/components/upload_form.jsx index ac548033cb..8a14dda695 100644 --- a/app/assets/javascripts/components/features/compose/components/upload_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/upload_form.jsx @@ -18,9 +18,13 @@ const UploadForm = React.createClass({ mixins: [PureRenderMixin], render () { - const { intl } = this.props; + const { intl, media } = this.props; - const uploads = this.props.media.map(attachment => ( + if (!media.size) { + return null; + } + + const uploads = media.map(attachment => (
@@ -29,7 +33,7 @@ const UploadForm = React.createClass({ )); return ( -
+
{uploads}
); From 98729d50c80760e076607ecf625a95caea817aed Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Jan 2017 03:14:33 +0100 Subject: [PATCH 010/175] Make shortcode emojis work, make getting started area scrollable --- app/assets/javascripts/components/emoji.jsx | 2 +- .../components/features/getting_started/index.jsx | 10 ++++++---- app/assets/javascripts/extras.jsx | 2 -- app/assets/stylesheets/components.scss | 6 ++++++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/components/emoji.jsx b/app/assets/javascripts/components/emoji.jsx index a06c759531..c93c07c74b 100644 --- a/app/assets/javascripts/components/emoji.jsx +++ b/app/assets/javascripts/components/emoji.jsx @@ -5,5 +5,5 @@ emojione.sprites = false; emojione.imagePathPNG = '/emoji/'; export default function emojify(text) { - return emojione.unicodeToImage(text); + return emojione.toImage(text); }; diff --git a/app/assets/javascripts/components/features/getting_started/index.jsx b/app/assets/javascripts/components/features/getting_started/index.jsx index 77253dd731..51f165f9e2 100644 --- a/app/assets/javascripts/components/features/getting_started/index.jsx +++ b/app/assets/javascripts/components/features/getting_started/index.jsx @@ -43,10 +43,12 @@ const GettingStarted = ({ intl, me }) => { {followRequests}
-
-

-

-

+
+
+

+

+

+
); diff --git a/app/assets/javascripts/extras.jsx b/app/assets/javascripts/extras.jsx index b9f8e6842c..c1df182dea 100644 --- a/app/assets/javascripts/extras.jsx +++ b/app/assets/javascripts/extras.jsx @@ -19,8 +19,6 @@ $(() => { }); $('.webapp-btn').on('click', e => { - console.log(e); - if (e.button === 0) { e.preventDefault(); window.location.href = $(e.target).attr('href'); diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index c644192432..4f03f94e54 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -436,6 +436,10 @@ overflow-x: hidden; flex: 1 1 auto; -webkit-overflow-scrolling: touch; + + &.optionally-scrollable { + overflow-y: auto; + } } .column-back-button { @@ -609,7 +613,9 @@ } .getting-started { + box-sizing: border-box; overflow-y: auto; padding-bottom: 235px; background: image-url('mastodon-getting-started.png') no-repeat 0 100% local; + height: 100%; } From 251b04298e826818ecb48c2fdf96a83649e14e93 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Jan 2017 03:17:23 +0100 Subject: [PATCH 011/175] Fix undesired delivering of private toot to remote accounts that follow author --- app/services/process_mentions_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index ee42a5df24..72568e702d 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -28,7 +28,7 @@ class ProcessMentionsService < BaseService status.mentions.each do |mention| mentioned_account = mention.account - next if status.private_visibility? && !mentioned_account.following?(status.account) + next if status.private_visibility? && (!mentioned_account.following?(status.account) || !mentioned_account.local?) if mentioned_account.local? NotifyService.new.call(mentioned_account, mention) From 6c28886317bdf837e7e3f399115af91ac282735e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Jan 2017 03:28:21 +0100 Subject: [PATCH 012/175] Improve background jobs params and error handling --- app/workers/notification_worker.rb | 2 ++ app/workers/pubsubhubbub/confirmation_worker.rb | 2 +- app/workers/pubsubhubbub/delivery_worker.rb | 6 +++++- app/workers/thread_resolve_worker.rb | 2 ++ app/workers/unfavourite_worker.rb | 2 ++ 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/workers/notification_worker.rb b/app/workers/notification_worker.rb index 386e94111f..e4c38d3844 100644 --- a/app/workers/notification_worker.rb +++ b/app/workers/notification_worker.rb @@ -3,6 +3,8 @@ class NotificationWorker include Sidekiq::Worker + sidekiq_options retry: 5 + def perform(stream_entry_id, target_account_id) SendInteractionService.new.call(StreamEntry.find(stream_entry_id), Account.find(target_account_id)) end diff --git a/app/workers/pubsubhubbub/confirmation_worker.rb b/app/workers/pubsubhubbub/confirmation_worker.rb index 489bd83590..868fd9f972 100644 --- a/app/workers/pubsubhubbub/confirmation_worker.rb +++ b/app/workers/pubsubhubbub/confirmation_worker.rb @@ -4,7 +4,7 @@ class Pubsubhubbub::ConfirmationWorker include Sidekiq::Worker include RoutingHelper - sidekiq_options queue: 'push' + sidekiq_options queue: 'push', retry: false def perform(subscription_id, mode, secret = nil, lease_seconds = nil) subscription = Subscription.find(subscription_id) diff --git a/app/workers/pubsubhubbub/delivery_worker.rb b/app/workers/pubsubhubbub/delivery_worker.rb index 35bf7b2f07..15005bc802 100644 --- a/app/workers/pubsubhubbub/delivery_worker.rb +++ b/app/workers/pubsubhubbub/delivery_worker.rb @@ -4,7 +4,11 @@ class Pubsubhubbub::DeliveryWorker include Sidekiq::Worker include RoutingHelper - sidekiq_options queue: 'push', retry: 5 + sidekiq_options queue: 'push', retry: 3, dead: false + + sidekiq_retry_in do |count| + 5 * (count + 1) + end def perform(subscription_id, payload) subscription = Subscription.find(subscription_id) diff --git a/app/workers/thread_resolve_worker.rb b/app/workers/thread_resolve_worker.rb index 84eae73bef..593edd032f 100644 --- a/app/workers/thread_resolve_worker.rb +++ b/app/workers/thread_resolve_worker.rb @@ -3,6 +3,8 @@ class ThreadResolveWorker include Sidekiq::Worker + sidekiq_options retry: false + def perform(child_status_id, parent_url) child_status = Status.find(child_status_id) parent_status = FetchRemoteStatusService.new.call(parent_url) diff --git a/app/workers/unfavourite_worker.rb b/app/workers/unfavourite_worker.rb index a14c82d6fc..cce07e486c 100644 --- a/app/workers/unfavourite_worker.rb +++ b/app/workers/unfavourite_worker.rb @@ -5,5 +5,7 @@ class UnfavouriteWorker def perform(account_id, status_id) UnfavouriteService.new.call(Account.find(account_id), Status.find(status_id)) + rescue ActiveRecord::RecordNotFound + true end end From 1da73ecadedf26c5f04dc2de3bb65349ffc52ab9 Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 18:29:43 -0800 Subject: [PATCH 013/175] Fix Command-enter tooting metaKey is only set correctly on keyDown, not keyUp, so this swaps to using that --- .../components/components/autosuggest_textarea.jsx | 9 ++++++++- .../features/compose/components/compose_form.jsx | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/components/components/autosuggest_textarea.jsx b/app/assets/javascripts/components/components/autosuggest_textarea.jsx index 39ccbcaf96..57352be902 100644 --- a/app/assets/javascripts/components/components/autosuggest_textarea.jsx +++ b/app/assets/javascripts/components/components/autosuggest_textarea.jsx @@ -38,7 +38,8 @@ const AutosuggestTextarea = React.createClass({ onSuggestionsClearRequested: React.PropTypes.func.isRequired, onSuggestionsFetchRequested: React.PropTypes.func.isRequired, onChange: React.PropTypes.func.isRequired, - onKeyUp: React.PropTypes.func + onKeyUp: React.PropTypes.func, + onKeyDown: React.PropTypes.func }, getInitialState () { @@ -108,6 +109,12 @@ const AutosuggestTextarea = React.createClass({ break; } + + if (e.defaultPrevented || !this.props.onKeyDown) { + return; + } + + this.props.onKeyDown(e); }, onBlur () { diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index 55f361b0b7..412c293107 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -49,7 +49,7 @@ const ComposeForm = React.createClass({ this.props.onChange(e.target.value); }, - handleKeyUp (e) { + handleKeyDown (e) { if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { this.props.onSubmit(); } @@ -115,7 +115,7 @@ const ComposeForm = React.createClass({ value={this.props.text} onChange={this.handleChange} suggestions={this.props.suggestions} - onKeyUp={this.handleKeyUp} + onKeyDown={this.handleKeyDown} onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} onSuggestionsClearRequested={this.onSuggestionsClearRequested} onSuggestionSelected={this.onSuggestionSelected} From cc46c6b4936a3dbe1c38b97ab77a3fcfd3f22f03 Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 18:31:45 -0800 Subject: [PATCH 014/175] Friendlier unknown errors Don't ask users to check the console - if they're on mobile, they probably can't anyway ;) --- app/assets/javascripts/components/middleware/errors.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/middleware/errors.jsx b/app/assets/javascripts/components/middleware/errors.jsx index 3a1473bc14..74d77f0f9a 100644 --- a/app/assets/javascripts/components/middleware/errors.jsx +++ b/app/assets/javascripts/components/middleware/errors.jsx @@ -23,7 +23,7 @@ export default function errorsMiddleware() { dispatch(showAlert(title, message)); } else { console.error(action.error); - dispatch(showAlert('Oops!', 'An unexpected error occurred. Inspect the console for more details')); + dispatch(showAlert('Oops!', 'An unexpected error occurred.')); } } } From 0c600e9db6f343cdf8068554e27590e126035229 Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 19:30:02 -0800 Subject: [PATCH 015/175] Move "getting started" to its own route --- app/assets/javascripts/components/containers/mastodon.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/containers/mastodon.jsx b/app/assets/javascripts/components/containers/mastodon.jsx index 6704553765..026daeb065 100644 --- a/app/assets/javascripts/components/containers/mastodon.jsx +++ b/app/assets/javascripts/components/containers/mastodon.jsx @@ -16,6 +16,7 @@ import { useRouterHistory, Router, Route, + IndexRedirect, IndexRoute } from 'react-router'; import { useScroll } from 'react-router-scroll'; @@ -107,8 +108,9 @@ const Mastodon = React.createClass({ - + + From 9c493b1ea28ac3d36be367c019236394b6bd341d Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 19:30:22 -0800 Subject: [PATCH 016/175] Replace "Public" in tab bar with "More" hamburger --- .../javascripts/components/features/ui/components/tabs_bar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx index dbfdc3f852..aa40a488f3 100644 --- a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx +++ b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx @@ -30,7 +30,7 @@ const TabsBar = () => { - +
); }; From 05cc5636d8d56f95e1428408f6fce87ffb7c1a42 Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 19:30:39 -0800 Subject: [PATCH 017/175] Remove hamburger from "getting started" --- .../components/features/getting_started/index.jsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/assets/javascripts/components/features/getting_started/index.jsx b/app/assets/javascripts/components/features/getting_started/index.jsx index 51f165f9e2..9f47e7ab47 100644 --- a/app/assets/javascripts/components/features/getting_started/index.jsx +++ b/app/assets/javascripts/components/features/getting_started/index.jsx @@ -16,17 +16,6 @@ const mapStateToProps = state => ({ me: state.getIn(['accounts', state.getIn(['meta', 'me'])]) }); -const hamburgerStyle = { - background: '#373b4a', - color: '#fff', - fontSize: '16px', - padding: '15px', - position: 'absolute', - right: '0', - top: '-48px', - cursor: 'default' -}; - const GettingStarted = ({ intl, me }) => { let followRequests = ''; @@ -37,7 +26,6 @@ const GettingStarted = ({ intl, me }) => { return (
-
{followRequests} From 7ac55d2674b65bae78e6559a51ce97d859074bba Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 19:47:02 -0800 Subject: [PATCH 018/175] Differentiate settings links The "settings" links in the Getting Started section (or, if #399 were to happen, "more" menu) and compose sections are now different; the "compose" link is "Edit profile," while the one in the Getting Started section is now "Preferences." All languages have been updated to accommodate this, based on the existing usages of these phrases in language files in the Rails part of the app! addresses part of #384 --- .../components/features/compose/components/navigation_bar.jsx | 2 +- .../javascripts/components/features/getting_started/index.jsx | 4 ++-- app/assets/javascripts/components/locales/de.jsx | 3 ++- app/assets/javascripts/components/locales/en.jsx | 3 ++- app/assets/javascripts/components/locales/es.jsx | 3 ++- app/assets/javascripts/components/locales/fr.jsx | 3 ++- app/assets/javascripts/components/locales/hu.jsx | 3 ++- app/assets/javascripts/components/locales/pt.jsx | 3 ++- app/assets/javascripts/components/locales/uk.jsx | 3 ++- 9 files changed, 17 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx index 23d695f132..71b50fc3a3 100644 --- a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx +++ b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx @@ -21,7 +21,7 @@ const NavigationBar = React.createClass({
{this.props.account.get('acct')} - · · + ·
); diff --git a/app/assets/javascripts/components/features/getting_started/index.jsx b/app/assets/javascripts/components/features/getting_started/index.jsx index 51f165f9e2..ae850c3f9a 100644 --- a/app/assets/javascripts/components/features/getting_started/index.jsx +++ b/app/assets/javascripts/components/features/getting_started/index.jsx @@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; const messages = defineMessages({ heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, public_timeline: { id: 'navigation_bar.public_timeline', defaultMessage: 'Public timeline' }, - settings: { id: 'navigation_bar.settings', defaultMessage: 'Settings' }, + preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' } }); @@ -39,7 +39,7 @@ const GettingStarted = ({ intl, me }) => {
- + {followRequests}
diff --git a/app/assets/javascripts/components/locales/de.jsx b/app/assets/javascripts/components/locales/de.jsx index 17b74e15d6..97df674802 100644 --- a/app/assets/javascripts/components/locales/de.jsx +++ b/app/assets/javascripts/components/locales/de.jsx @@ -36,7 +36,8 @@ const en = { "compose_form.publish": "Veröffentlichen", "compose_form.sensitive": "Medien als sensitiv markieren", "compose_form.unlisted": "Öffentlich nicht auflisten", - "navigation_bar.settings": "Einstellungen", + "navigation_bar.edit_profile": "Profil bearbeiten", + "navigation_bar.preferences": "Einstellungen", "navigation_bar.public_timeline": "Öffentlich", "navigation_bar.logout": "Abmelden", "reply_indicator.cancel": "Abbrechen", diff --git a/app/assets/javascripts/components/locales/en.jsx b/app/assets/javascripts/components/locales/en.jsx index 3d4a389196..05fb0243c3 100644 --- a/app/assets/javascripts/components/locales/en.jsx +++ b/app/assets/javascripts/components/locales/en.jsx @@ -40,7 +40,8 @@ const en = { "compose_form.publish": "Toot", "compose_form.sensitive": "Mark media as sensitive", "compose_form.private": "Mark as private", - "navigation_bar.settings": "Settings", + "navigation_bar.edit_profile": "Edit profile", + "navigation_bar.preferences": "Preferences", "navigation_bar.public_timeline": "Public timeline", "navigation_bar.logout": "Logout", "reply_indicator.cancel": "Cancel", diff --git a/app/assets/javascripts/components/locales/es.jsx b/app/assets/javascripts/components/locales/es.jsx index 6bd9b18edf..b75fb57d92 100644 --- a/app/assets/javascripts/components/locales/es.jsx +++ b/app/assets/javascripts/components/locales/es.jsx @@ -37,7 +37,8 @@ const es = { "compose_form.publish": "Publicar", "compose_form.sensitive": "Marcar el contenido como sensible", "compose_form.unlisted": "Privado", - "navigation_bar.settings": "Ajustes", + "navigation_bar.edit_profile": "Editar perfil", + "navigation_bar.preferences": "Preferencias", "navigation_bar.public_timeline": "Público", "navigation_bar.logout": "Cerrar sesión", "reply_indicator.cancel": "Cancelar", diff --git a/app/assets/javascripts/components/locales/fr.jsx b/app/assets/javascripts/components/locales/fr.jsx index 968c3f8c39..183e5d5b52 100644 --- a/app/assets/javascripts/components/locales/fr.jsx +++ b/app/assets/javascripts/components/locales/fr.jsx @@ -38,7 +38,8 @@ const fr = { "compose_form.publish": "Pouet", "compose_form.sensitive": "Marquer le contenu comme délicat", "compose_form.unlisted": "Ne pas apparaître dans le fil public", - "navigation_bar.settings": "Paramètres", + "navigation_bar.edit_profile": "Modifier le profil", + "navigation_bar.preferences": "Préférences", "navigation_bar.public_timeline": "Public", "navigation_bar.logout": "Déconnexion", "reply_indicator.cancel": "Annuler", diff --git a/app/assets/javascripts/components/locales/hu.jsx b/app/assets/javascripts/components/locales/hu.jsx index 606fc830fe..9a2d14d87a 100644 --- a/app/assets/javascripts/components/locales/hu.jsx +++ b/app/assets/javascripts/components/locales/hu.jsx @@ -38,7 +38,8 @@ const hu = { "compose_form.publish": "Tülk!", "compose_form.sensitive": "Tartalom érzékenynek jelölése", "compose_form.unlisted": "Listázatlan mód", - "navigation_bar.settings": "Beállítások", + "navigation_bar.edit_profile": "Profil szerkesztése", + "navigation_bar.preferences": "Beállítások", "navigation_bar.public_timeline": "Nyilvános időfolyam", "navigation_bar.logout": "Kijelentkezés", "reply_indicator.cancel": "Mégsem", diff --git a/app/assets/javascripts/components/locales/pt.jsx b/app/assets/javascripts/components/locales/pt.jsx index 57cbcd31be..d68724b13b 100644 --- a/app/assets/javascripts/components/locales/pt.jsx +++ b/app/assets/javascripts/components/locales/pt.jsx @@ -36,7 +36,8 @@ const pt = { "compose_form.publish": "Publicar", "compose_form.sensitive": "Marcar conteúdo como sensível", "compose_form.unlisted": "Modo não-listado", - "navigation_bar.settings": "Configurações", + "navigation_bar.edit_profile": "Editar perfil", + "navigation_bar.preferences": "Preferências", "navigation_bar.public_timeline": "Timeline Pública", "navigation_bar.logout": "Logout", "reply_indicator.cancel": "Cancelar", diff --git a/app/assets/javascripts/components/locales/uk.jsx b/app/assets/javascripts/components/locales/uk.jsx index 53535c25ac..84a348c210 100644 --- a/app/assets/javascripts/components/locales/uk.jsx +++ b/app/assets/javascripts/components/locales/uk.jsx @@ -38,7 +38,8 @@ const uk = { "compose_form.publish": "Дмухнути", "compose_form.sensitive": "Непристойний зміст", "compose_form.unlisted": "Таємний режим", - "navigation_bar.settings": "Налаштування", + "navigation_bar.edit_profile": "Редагувати профіль", + "navigation_bar.preferences": "Налаштування", "navigation_bar.public_timeline": "Публічна стіна", "navigation_bar.logout": "Вийти", "reply_indicator.cancel": "Відмінити", From c100b83b98b8a6ce24d7f0d9140f47e722b17a06 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Wed, 4 Jan 2017 20:04:14 -0800 Subject: [PATCH 019/175] Automatically position cursor when writing a reply toot --- .../features/compose/components/compose_form.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index 412c293107..44c44bcb0e 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -86,6 +86,13 @@ const ComposeForm = React.createClass({ componentDidUpdate (prevProps) { if (prevProps.in_reply_to !== this.props.in_reply_to) { + // If replying to zero or one users, places the cursor at the end of the textbox. + // If replying to more than one user, selects any usernames past the first; + // this provides a convenient shortcut to drop everyone else from the conversation. + let selectionStart = this.props.text.search(/\s/) + 1; + let selectionEnd = this.props.text.length; + this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd); + this.autosuggestTextarea.textarea.focus(); } }, From 1f3c895ffb320c188b77b0036603b40a22733902 Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Wed, 4 Jan 2017 20:24:27 -0800 Subject: [PATCH 020/175] Use system fonts on more platforms This allows other platforms such as Windows, macOS and iOS to use their system fonts rather than downloading a copy of Roboto. It also makes the app feel a little closer to native on those platforms! --- app/assets/javascripts/components/components/button.jsx | 2 +- .../components/features/compose/components/search.jsx | 2 +- app/assets/stylesheets/about.scss | 2 +- app/assets/stylesheets/application.scss | 2 +- app/assets/stylesheets/components.scss | 4 ++-- app/assets/stylesheets/forms.scss | 6 +++--- public/404.html | 4 ++-- public/500.html | 4 ++-- storybook/storybook.scss | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/components/components/button.jsx b/app/assets/javascripts/components/components/button.jsx index d631290131..19c52550a8 100644 --- a/app/assets/javascripts/components/components/button.jsx +++ b/app/assets/javascripts/components/components/button.jsx @@ -27,7 +27,7 @@ const Button = React.createClass({ render () { const style = { - fontFamily: 'Roboto', + fontFamily: 'inherit', display: this.props.block ? 'block' : 'inline-block', width: this.props.block ? '100%' : 'auto', position: 'relative', diff --git a/app/assets/javascripts/components/features/compose/components/search.jsx b/app/assets/javascripts/components/features/compose/components/search.jsx index b4e618820e..e4672216b4 100644 --- a/app/assets/javascripts/components/features/compose/components/search.jsx +++ b/app/assets/javascripts/components/features/compose/components/search.jsx @@ -38,7 +38,7 @@ const inputStyle = { border: 'none', padding: '10px', paddingRight: '30px', - fontFamily: 'Roboto', + fontFamily: 'inherit', background: '#282c37', color: '#9baec8', fontSize: '14px', diff --git a/app/assets/stylesheets/about.scss b/app/assets/stylesheets/about.scss index 3681672d8c..620c86a677 100644 --- a/app/assets/stylesheets/about.scss +++ b/app/assets/stylesheets/about.scss @@ -11,7 +11,7 @@ } h1 { - font: 46px/52px 'Roboto', sans-serif; + font: 46px/52px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-weight: 600; margin-bottom: 20px; color: #2b90d9; diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index e4c550b818..1e571385f4 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -95,7 +95,7 @@ table { } body { - font-family: 'Roboto', sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #282c37 image-url('background-photo.jpeg'); background-size: cover; background-attachment: fixed; diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index 4f03f94e54..c2fcd76b3c 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -1,6 +1,6 @@ .button { background-color: #2b90d9; - font-family: 'Roboto'; + font-family: inherit; display: inline-block; position: relative; box-sizing: border-box; @@ -574,7 +574,7 @@ resize: none; color: #282c37; padding: 7px; - font-family: 'Roboto'; + font-family: inherit; font-size: 14px; margin: 0; resize: vertical; diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss index e6d2e85a2f..b3b71b412b 100644 --- a/app/assets/stylesheets/forms.scss +++ b/app/assets/stylesheets/forms.scss @@ -26,7 +26,7 @@ code { display: flex; label { - font-family: 'Roboto'; + font-family: inherit; font-size: 16px; color: #fff; width: 100px; @@ -48,7 +48,7 @@ code { margin-bottom: 5px; label { - font-family: 'Roboto'; + font-family: inherit; font-size: 14px; color: white; display: block; @@ -83,7 +83,7 @@ code { display: block; width: 100%; outline: 0; - font-family: 'Roboto'; + font-family: inherit; &:invalid { box-shadow: none; diff --git a/public/404.html b/public/404.html index eecfd67438..fc75c78be4 100644 --- a/public/404.html +++ b/public/404.html @@ -7,7 +7,7 @@ diff --git a/public/500.html b/public/500.html index 915b890f15..d085d490b0 100644 --- a/public/500.html +++ b/public/500.html @@ -7,7 +7,7 @@ diff --git a/storybook/storybook.scss b/storybook/storybook.scss index b0145f9bda..31f11b5adf 100644 --- a/storybook/storybook.scss +++ b/storybook/storybook.scss @@ -2,7 +2,7 @@ @import url(https://fonts.googleapis.com/css?family=Roboto+Mono:400,500); #root { - font-family: 'Roboto', sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #282c37; font-size: 13px; line-height: 18px; From c318e6e42e2903af90be205760a5a2ba00e378b8 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Wed, 4 Jan 2017 22:23:02 -0800 Subject: [PATCH 021/175] Display native emoji on browsers which support it --- app/assets/javascripts/components/emoji.jsx | 11 ++++++++++- package.json | 1 + yarn.lock | 8 ++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/components/emoji.jsx b/app/assets/javascripts/components/emoji.jsx index c93c07c74b..82b82b7196 100644 --- a/app/assets/javascripts/components/emoji.jsx +++ b/app/assets/javascripts/components/emoji.jsx @@ -1,9 +1,18 @@ import emojione from 'emojione'; +import detectVersion from 'mojibaka'; emojione.imageType = 'png'; emojione.sprites = false; emojione.imagePathPNG = '/emoji/'; +let emoji_version = detectVersion(); + export default function emojify(text) { - return emojione.toImage(text); + // Browser too old to support native emoji + if (emoji_version < 6.1) { + return emojione.toImage(text); + // Convert short codes into native emoji + } else { + return emojione.shortnameToUnicode(text); + } }; diff --git a/package.json b/package.json index 05663a729e..13b0484ecc 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "intl": "^1.2.5", "jsdom": "^9.6.0", "mocha": "^3.1.1", + "mojibaka": "^0.0.1", "node-sass": "^4.0.0", "react": "^15.3.2", "react-addons-perf": "^15.3.2", diff --git a/yarn.lock b/yarn.lock index f71a8ae104..b79c468983 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2368,7 +2368,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@7.0.5, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: +glob@7.0.5, glob@^7.0.0, glob@^7.0.3: version "7.0.5" resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" dependencies: @@ -2389,7 +2389,7 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@~7.1.1: +glob@^7.0.5, glob@~7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -3392,6 +3392,10 @@ module-deps@^4.0.2: through2 "^2.0.0" xtend "^4.0.0" +mojibaka@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/mojibaka/-/mojibaka-0.0.1.tgz#54b0690d9149bbdf97f13b909f2417c53b8d52e5" + ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" From 53b765f4b150d7671d697eed7333c948622045cf Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Wed, 4 Jan 2017 22:47:51 -0800 Subject: [PATCH 022/175] Bump emoji requirement to Unicode 9 --- app/assets/javascripts/components/emoji.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/emoji.jsx b/app/assets/javascripts/components/emoji.jsx index 82b82b7196..990aea5be5 100644 --- a/app/assets/javascripts/components/emoji.jsx +++ b/app/assets/javascripts/components/emoji.jsx @@ -9,7 +9,7 @@ let emoji_version = detectVersion(); export default function emojify(text) { // Browser too old to support native emoji - if (emoji_version < 6.1) { + if (emoji_version < 9.0) { return emojione.toImage(text); // Convert short codes into native emoji } else { From 9e6ceb3201a2737e676decf3df9605714632a300 Mon Sep 17 00:00:00 2001 From: Eugen Date: Thu, 5 Jan 2017 13:45:21 +0100 Subject: [PATCH 023/175] Revert "Display native emoji on browsers which support it" --- app/assets/javascripts/components/emoji.jsx | 11 +---------- package.json | 1 - yarn.lock | 8 ++------ 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/components/emoji.jsx b/app/assets/javascripts/components/emoji.jsx index 990aea5be5..c93c07c74b 100644 --- a/app/assets/javascripts/components/emoji.jsx +++ b/app/assets/javascripts/components/emoji.jsx @@ -1,18 +1,9 @@ import emojione from 'emojione'; -import detectVersion from 'mojibaka'; emojione.imageType = 'png'; emojione.sprites = false; emojione.imagePathPNG = '/emoji/'; -let emoji_version = detectVersion(); - export default function emojify(text) { - // Browser too old to support native emoji - if (emoji_version < 9.0) { - return emojione.toImage(text); - // Convert short codes into native emoji - } else { - return emojione.shortnameToUnicode(text); - } + return emojione.toImage(text); }; diff --git a/package.json b/package.json index 13b0484ecc..05663a729e 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "intl": "^1.2.5", "jsdom": "^9.6.0", "mocha": "^3.1.1", - "mojibaka": "^0.0.1", "node-sass": "^4.0.0", "react": "^15.3.2", "react-addons-perf": "^15.3.2", diff --git a/yarn.lock b/yarn.lock index b79c468983..f71a8ae104 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2368,7 +2368,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@7.0.5, glob@^7.0.0, glob@^7.0.3: +glob@7.0.5, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: version "7.0.5" resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" dependencies: @@ -2389,7 +2389,7 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.5, glob@~7.1.1: +glob@~7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -3392,10 +3392,6 @@ module-deps@^4.0.2: through2 "^2.0.0" xtend "^4.0.0" -mojibaka@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/mojibaka/-/mojibaka-0.0.1.tgz#54b0690d9149bbdf97f13b909f2417c53b8d52e5" - ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" From 10e6288444567106570baf317801d99989e2df83 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Jan 2017 13:59:58 +0100 Subject: [PATCH 024/175] Revert to Roboto for all --- app/assets/stylesheets/application.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 1e571385f4..e4c550b818 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -95,7 +95,7 @@ table { } body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + font-family: 'Roboto', sans-serif; background: #282c37 image-url('background-photo.jpeg'); background-size: cover; background-attachment: fixed; From ca7dce4a5a0234461fee554153d9328bc246ee55 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Jan 2017 14:06:09 +0100 Subject: [PATCH 025/175] Fix selection resetting in compose form after unrelated data updates --- .../features/compose/components/compose_form.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index 44c44bcb0e..8128bb382a 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -85,14 +85,14 @@ const ComposeForm = React.createClass({ }, componentDidUpdate (prevProps) { - if (prevProps.in_reply_to !== this.props.in_reply_to) { + if (!prevProps.in_reply_to || !this.props.in_reply_to || prevProps.in_reply_to.get('id') !== this.props.in_reply_to.get('id')) { // If replying to zero or one users, places the cursor at the end of the textbox. // If replying to more than one user, selects any usernames past the first; // this provides a convenient shortcut to drop everyone else from the conversation. - let selectionStart = this.props.text.search(/\s/) + 1; - let selectionEnd = this.props.text.length; - this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd); + const selectionStart = this.props.text.search(/\s/) + 1; + const selectionEnd = this.props.text.length; + this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd); this.autosuggestTextarea.textarea.focus(); } }, From a1de2e332d4406eb0d5934aa22fb96958d291a5f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Jan 2017 14:18:38 +0100 Subject: [PATCH 026/175] Fix compose form bug --- .../components/features/compose/components/compose_form.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index 8128bb382a..5a76b177b6 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -85,7 +85,7 @@ const ComposeForm = React.createClass({ }, componentDidUpdate (prevProps) { - if (!prevProps.in_reply_to || !this.props.in_reply_to || prevProps.in_reply_to.get('id') !== this.props.in_reply_to.get('id')) { + if ((!prevProps.in_reply_to && this.props.in_reply_to) || prevProps.in_reply_to.get('id') !== this.props.in_reply_to.get('id')) { // If replying to zero or one users, places the cursor at the end of the textbox. // If replying to more than one user, selects any usernames past the first; // this provides a convenient shortcut to drop everyone else from the conversation. From 00b9ba64c92715ba86d45209215694497eecefce Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Jan 2017 14:23:59 +0100 Subject: [PATCH 027/175] Fixed unexpected error --- .../components/features/compose/components/compose_form.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index 5a76b177b6..078bfbdc62 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -85,12 +85,12 @@ const ComposeForm = React.createClass({ }, componentDidUpdate (prevProps) { - if ((!prevProps.in_reply_to && this.props.in_reply_to) || prevProps.in_reply_to.get('id') !== this.props.in_reply_to.get('id')) { + if ((prevProps.in_reply_to === null && this.props.in_reply_to !== null) || (prevProps.in_reply_to !== null && this.props.in_reply_to !== null && prevProps.in_reply_to.get('id') !== this.props.in_reply_to.get('id'))) { // If replying to zero or one users, places the cursor at the end of the textbox. // If replying to more than one user, selects any usernames past the first; // this provides a convenient shortcut to drop everyone else from the conversation. const selectionStart = this.props.text.search(/\s/) + 1; - const selectionEnd = this.props.text.length; + const selectionEnd = this.props.text.length; this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd); this.autosuggestTextarea.textarea.focus(); From 10a9ebae3b2fc0addb4604798a62d6c4e066d491 Mon Sep 17 00:00:00 2001 From: Effy Elden Date: Fri, 6 Jan 2017 08:26:45 +1100 Subject: [PATCH 028/175] Add tag property to desktop notifications, preventing duplicates (i.e. when multiple Mastodon tabs are open) --- app/assets/javascripts/components/actions/notifications.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/actions/notifications.jsx b/app/assets/javascripts/components/actions/notifications.jsx index 8bd8354063..182b598aa5 100644 --- a/app/assets/javascripts/components/actions/notifications.jsx +++ b/app/assets/javascripts/components/actions/notifications.jsx @@ -40,7 +40,7 @@ export function updateNotifications(notification, intlMessages, intlLocale) { const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username }); const body = $('

').html(notification.status ? notification.status.content : '').text(); - new Notification(title, { body, icon: notification.account.avatar }); + new Notification(title, { body, icon: notification.account.avatar, tag: notification.id }); } }; }; From 819bfb75c6135d7acd4d5473f47c4e10497dec2b Mon Sep 17 00:00:00 2001 From: Effy Elden Date: Fri, 6 Jan 2017 09:47:40 +1100 Subject: [PATCH 029/175] Add twitter:card metatag to enable Twitter Cards support --- app/views/about/index.html.haml | 1 + app/views/accounts/show.html.haml | 1 + app/views/stream_entries/show.html.haml | 2 ++ 3 files changed, 4 insertions(+) diff --git a/app/views/about/index.html.haml b/app/views/about/index.html.haml index 6dd1822059..b0260dc516 100644 --- a/app/views/about/index.html.haml +++ b/app/views/about/index.html.haml @@ -9,6 +9,7 @@ %meta{ property: 'og:image', content: asset_url('mastodon_small.jpg') }/ %meta{ property: 'og:image:width', content: '400' }/ %meta{ property: 'og:image:height', content: '400' }/ + %meta{ property: 'twitter:card', content: 'summary' }/ .wrapper %h1 diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index 7afeb68a97..bc0f08a798 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -12,6 +12,7 @@ %meta{ property: 'og:image', content: full_asset_url(@account.avatar.url(:original)) }/ %meta{ property: 'og:image:width', content: '120' }/ %meta{ property: 'og:image:height', content: '120' }/ + %meta{ property: 'twitter:card', content: 'summary' }/ = render partial: 'header' diff --git a/app/views/stream_entries/show.html.haml b/app/views/stream_entries/show.html.haml index 43935da60f..d106173d2e 100644 --- a/app/views/stream_entries/show.html.haml +++ b/app/views/stream_entries/show.html.haml @@ -14,5 +14,7 @@ %meta{ property: 'og:image:width', content: '120' }/ %meta{ property: 'og:image:height', content: '120' }/ + %meta{ property: 'twitter:card', content: 'summary' }/ + .activity-stream.activity-stream-headless = render partial: @type, locals: { @type.to_sym => @stream_entry.activity, include_threads: true } From 28a2f79dff04c8593e4228d8a3fa38dabafe3dbe Mon Sep 17 00:00:00 2001 From: Jessica Stokes Date: Thu, 5 Jan 2017 15:16:13 -0800 Subject: [PATCH 030/175] Upgrade EmojiOne to 2.2.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for, among other things, 🏳️‍🌈 --- package.json | 3 +++ yarn.lock | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 05663a729e..3a9365d3e3 100644 --- a/package.json +++ b/package.json @@ -53,5 +53,8 @@ "sass-loader": "^4.0.2", "sinon": "^1.17.6", "style-loader": "^0.13.1" + }, + "dependencies": { + "emojione": "latest" } } diff --git a/yarn.lock b/yarn.lock index f71a8ae104..db5f7d408c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1935,9 +1935,9 @@ elliptic@^6.0.0: hash.js "^1.0.0" inherits "^2.0.1" -emojione: - version "2.2.6" - resolved "https://registry.yarnpkg.com/emojione/-/emojione-2.2.6.tgz#67dec452937d5b14ee669207ea41cdb1f69fb8f6" +emojione@latest: + version "2.2.7" + resolved "https://registry.yarnpkg.com/emojione/-/emojione-2.2.7.tgz#46457cf6b9b2f8da13ae8a2e4e547de06ee15e96" emojis-list@^2.0.0: version "2.1.0" @@ -2368,7 +2368,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@7.0.5, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: +glob@7.0.5, glob@^7.0.0, glob@^7.0.3: version "7.0.5" resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" dependencies: @@ -2389,7 +2389,7 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@~7.1.1: +glob@^7.0.5, glob@~7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: From 7b9f8766e88dceb9519085deada3fa673e4c015b Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 6 Jan 2017 00:21:12 +0100 Subject: [PATCH 031/175] Fix #416 - Generate random unique 14-byte (19 characters) shortcodes for local attachments, use them in URLs. Check status privacy before redirecting to actual file. --- app/controllers/media_controller.rb | 3 ++- app/models/media_attachment.rb | 18 ++++++++++++++++++ ...24407_add_shortcode_to_media_attachments.rb | 14 ++++++++++++++ db/schema.rb | 4 +++- 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20170105224407_add_shortcode_to_media_attachments.rb diff --git a/app/controllers/media_controller.rb b/app/controllers/media_controller.rb index 6f1f7ec482..488c4f944f 100644 --- a/app/controllers/media_controller.rb +++ b/app/controllers/media_controller.rb @@ -10,6 +10,7 @@ class MediaController < ApplicationController private def set_media_attachment - @media_attachment = MediaAttachment.where.not(status_id: nil).find(params[:id]) + @media_attachment = MediaAttachment.where.not(status_id: nil).find_by!(shortcode: params[:id]) + raise ActiveRecord::RecordNotFound unless @media_attachment.status.permitted?(current_account) end end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 2a5d23739a..ecbed03e33 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -16,6 +16,7 @@ class MediaAttachment < ApplicationRecord validates :account, presence: true + scope :local, -> { where(remote_url: '') } default_scope { order('id asc') } def local? @@ -38,6 +39,12 @@ class MediaAttachment < ApplicationRecord image? ? 'image' : 'video' end + def to_param + shortcode + end + + before_create :set_shortcode + class << self private @@ -62,4 +69,15 @@ class MediaAttachment < ApplicationRecord end end end + + private + + def set_shortcode + return unless local? + + loop do + self.shortcode = SecureRandom.urlsafe_base64(14) + break if MediaAttachment.find_by(shortcode: shortcode).nil? + end + end end diff --git a/db/migrate/20170105224407_add_shortcode_to_media_attachments.rb b/db/migrate/20170105224407_add_shortcode_to_media_attachments.rb new file mode 100644 index 0000000000..2685ae150e --- /dev/null +++ b/db/migrate/20170105224407_add_shortcode_to_media_attachments.rb @@ -0,0 +1,14 @@ +class AddShortcodeToMediaAttachments < ActiveRecord::Migration[5.0] + def up + add_column :media_attachments, :shortcode, :string, null: true, default: nil + add_index :media_attachments, :shortcode, unique: true + + # Migrate old links + MediaAttachment.local.update_all('shortcode = id') + end + + def down + remove_index :media_attachments, :shortcode + remove_column :media_attachments, :shortcode + end +end diff --git a/db/schema.rb b/db/schema.rb index b9236d42fd..a535c5fdb1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161222204147) do +ActiveRecord::Schema.define(version: 20170105224407) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -95,6 +95,8 @@ ActiveRecord::Schema.define(version: 20161222204147) do t.integer "account_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "shortcode" + t.index ["shortcode"], name: "index_media_attachments_on_shortcode", unique: true, using: :btree t.index ["status_id"], name: "index_media_attachments_on_status_id", using: :btree end From 18deeb9db58391ed9ecb4d4d48ae47acb3e7fb46 Mon Sep 17 00:00:00 2001 From: Greg V Date: Fri, 6 Jan 2017 18:08:40 +0300 Subject: [PATCH 032/175] Add Microformats2 markup h-feed, h-card and h-entry --- app/views/accounts/_header.html.haml | 12 ++++---- app/views/accounts/show.html.haml | 22 +++++++------- .../stream_entries/_detailed_status.html.haml | 17 ++++++----- .../stream_entries/_simple_status.html.haml | 17 ++++++----- app/views/stream_entries/_status.html.haml | 30 ++++++++++--------- app/views/tags/show.html.haml | 2 +- 6 files changed, 53 insertions(+), 47 deletions(-) diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index 1c6b5f0f67..e410ff72cb 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -1,4 +1,4 @@ -.card{ style: "background-image: url(#{@account.header.url( :original)})" } +.card.h-card{ class: [local_assigns[:in_feed] && 'p-author'], style: "background-image: url(#{@account.header.url( :original)})" } - if user_signed_in? && current_account.id != @account.id && !current_account.requested?(@account) .controls - if current_account.following?(@account) @@ -9,19 +9,19 @@ .controls .remote-follow = link_to t('accounts.remote_follow'), account_remote_follow_path(@account), class: 'button' - .avatar= image_tag @account.avatar.url(:original) + .avatar= image_tag @account.avatar.url(:original), class: 'u-photo' %h1.name - = display_name(@account) + %span.p-name= display_name(@account) %small - = "@#{@account.username}" + %span.p-nickname= "@#{@account.username}" = fa_icon('lock') if @account.locked? .details .bio - .account__header__content= Formatter.instance.simplified_format(@account) + .account__header__content.p-note= Formatter.instance.simplified_format(@account) .details-counters .counter{ class: active_nav_class(account_url(@account)) } - = link_to account_url(@account) do + = link_to account_url(@account), class: 'u-url u-uid' do %span.counter-label= t('accounts.posts') %span.counter-number= number_with_delimiter @account.statuses.count .counter{ class: active_nav_class(following_account_url(@account)) } diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index bc0f08a798..8840b5503d 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -14,15 +14,17 @@ %meta{ property: 'og:image:height', content: '120' }/ %meta{ property: 'twitter:card', content: 'summary' }/ -= render partial: 'header' +.h-feed + %data.p-name{ value: "#{@account.username} on #{Rails.configuration.x.local_domain}" } + = render partial: 'header', locals: {in_feed: true} -- if @statuses.empty? - .accounts-grid - = render partial: 'nothing_here' -- else - .activity-stream - = render partial: 'stream_entries/status', collection: @statuses, as: :status + - if @statuses.empty? + .accounts-grid + = render partial: 'nothing_here' + - else + .activity-stream + = render partial: 'stream_entries/status', collection: @statuses, as: :status -.pagination - - if @statuses.size == 20 - = link_to safe_join([t('pagination.next'), fa_icon('chevron-right')], ' '), account_url(@account, max_id: @statuses.last.id), class: 'next_page', rel: 'next' + .pagination + - if @statuses.size == 20 + = link_to safe_join([t('pagination.next'), fa_icon('chevron-right')], ' '), account_url(@account, max_id: @statuses.last.id), class: 'next_page', rel: 'next' diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index 94451d3bda..b0d36872cf 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -1,30 +1,31 @@ .detailed-status.light - = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name', target: @external_links ? '_blank' : nil, rel: 'noopener' do + = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: @external_links ? '_blank' : nil, rel: 'noopener' do %div %div.avatar - = image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '' + = image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'u-photo' %span.display-name - %strong= display_name(status.account) - %span= acct(status.account) + %strong.p-name= display_name(status.account) + %span.p-nickname= acct(status.account) - .status__content= Formatter.instance.format(status) + .status__content.e-content.p-name= Formatter.instance.format(status) - unless status.media_attachments.empty? - if status.media_attachments.first.video? .video-player - if status.sensitive? = render partial: 'stream_entries/content_spoiler' - %video{ src: status.media_attachments.first.file.url(:original), loop: true } + %video{ src: status.media_attachments.first.file.url(:original), loop: true, class: 'u-video' } - else .detailed-status__attachments - if status.sensitive? = render partial: 'stream_entries/content_spoiler' - status.media_attachments.each do |media| .media-item - = link_to '', (media.remote_url.blank? ? media.file.url(:original) : media.remote_url), style: "background-image: url(#{media.file.url(:original)})", target: '_blank', rel: 'noopener' + = link_to '', (media.remote_url.blank? ? media.file.url(:original) : media.remote_url), style: "background-image: url(#{media.file.url(:original)})", target: '_blank', rel: 'noopener', class: "u-#{media.video? ? 'video' : 'photo'}" %div.detailed-status__meta - = link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: @external_links ? '_blank' : nil, rel: 'noopener' do + %data.dt-published{ value: status.created_at.to_time.iso8601 } + = link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: @external_links ? '_blank' : nil, rel: 'noopener' do %span= l(status.created_at) · %span diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index da3bc0ccb9..b08cf5dab9 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -1,17 +1,18 @@ .status.light .status__header .status__meta - = link_to time_ago_in_words(status.created_at), TagManager.instance.url_for(status), class: 'status__relative-time', title: l(status.created_at), target: @external_links ? '_blank' : nil, rel: 'noopener' + = link_to time_ago_in_words(status.created_at), TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', title: l(status.created_at), target: @external_links ? '_blank' : nil, rel: 'noopener' + %data.dt-published{ value: status.created_at.to_time.iso8601 } - = link_to TagManager.instance.url_for(status.account), class: 'status__display-name', target: @external_links ? '_blank' : nil, rel: 'noopener' do + = link_to TagManager.instance.url_for(status.account), class: 'status__display-name p-author h-card', target: @external_links ? '_blank' : nil, rel: 'noopener' do .status__avatar %div - = image_tag status.account.avatar(:original), width: 48, height: 48, alt: '' + = image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo' %span.display-name - %strong= display_name(status.account) - %span= acct(status.account) + %strong.p-name= display_name(status.account) + %span.p-nickname= acct(status.account) - .status__content= Formatter.instance.format(status) + .status__content.e-content.p-name= Formatter.instance.format(status) - unless status.media_attachments.empty? .status__attachments @@ -19,10 +20,10 @@ = render partial: 'stream_entries/content_spoiler' - if status.media_attachments.first.video? .video-item - = link_to (status.media_attachments.first.remote_url.blank? ? status.media_attachments.first.file.url(:original) : status.media_attachments.first.remote_url), style: "background-image: url(#{status.media_attachments.first.file.url(:small)})", target: '_blank', rel: 'noopener' do + = link_to (status.media_attachments.first.remote_url.blank? ? status.media_attachments.first.file.url(:original) : status.media_attachments.first.remote_url), style: "background-image: url(#{status.media_attachments.first.file.url(:small)})", target: '_blank', rel: 'noopener', class: 'u-video' do .video-item__play = fa_icon('play') - else - status.media_attachments.each do |media| .media-item - = link_to '', (media.remote_url.blank? ? media.file.url(:original) : media.remote_url), style: "background-image: url(#{media.file.url(:original)})", target: '_blank', rel: 'noopener' + = link_to '', (media.remote_url.blank? ? media.file.url(:original) : media.remote_url), style: "background-image: url(#{media.file.url(:original)})", target: '_blank', rel: 'noopener', class: "u-#{media.video? ? 'video' : 'photo'}" diff --git a/app/views/stream_entries/_status.html.haml b/app/views/stream_entries/_status.html.haml index f70e2c8902..eeb2fec00a 100644 --- a/app/views/stream_entries/_status.html.haml +++ b/app/views/stream_entries/_status.html.haml @@ -3,20 +3,22 @@ - is_successor ||= false - centered ||= include_threads && !is_predecessor && !is_successor -- if status.reply? && include_threads - = render partial: 'status', collection: @ancestors, as: :status, locals: { is_predecessor: true } +%div{ class: [is_predecessor && 'u-in-reply-to h-cite', is_successor && 'u-comment h-cite', !is_predecessor && !is_successor && 'h-entry'] } + - if status.reply? && include_threads + = render partial: 'status', collection: @ancestors, as: :status, locals: { is_predecessor: true } -.entry{ class: entry_classes(status, is_predecessor, is_successor, include_threads) } - - if status.reblog? - .pre-header - %div.pre-header__icon - = fa_icon('retweet fw') - %span - = link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do - %strong= display_name(status.account) - = t('stream_entries.reblogged') + .entry{ class: entry_classes(status, is_predecessor, is_successor, include_threads) } + - if status.reblog? + .pre-header + %div.pre-header__icon + = fa_icon('retweet fw') + %span + = link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do + %strong= display_name(status.account) + = t('stream_entries.reblogged') - = render partial: centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status', locals: { status: proper_status(status) } + %div{ class: [status.reblog? && 'u-repost-of h-cite'] } + = render partial: centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status', locals: { status: proper_status(status) } -- if include_threads - = render partial: 'status', collection: @descendants, as: :status, locals: { is_successor: true } + - if include_threads + = render partial: 'status', collection: @descendants, as: :status, locals: { is_successor: true } diff --git a/app/views/tags/show.html.haml b/app/views/tags/show.html.haml index dd42fe22c5..412ec4fa5d 100644 --- a/app/views/tags/show.html.haml +++ b/app/views/tags/show.html.haml @@ -2,7 +2,7 @@ .accounts-grid = render partial: 'accounts/nothing_here' - else - .activity-stream + .activity-stream.h-feed = render partial: 'stream_entries/status', collection: @statuses, as: :status, cached: true .pagination From 72c3a41befb6407f21068ef4cb9e34187e3515f0 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 6 Jan 2017 20:15:24 +0100 Subject: [PATCH 033/175] Fix h-card classes and remote follow button appearing when it shouldn't --- app/views/accounts/_header.html.haml | 4 ++-- app/views/accounts/show.html.haml | 5 +++-- app/views/stream_entries/_status.html.haml | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index e410ff72cb..7a5cea7abc 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -1,11 +1,11 @@ -.card.h-card{ class: [local_assigns[:in_feed] && 'p-author'], style: "background-image: url(#{@account.header.url( :original)})" } +.card.h-card.p-author{ style: "background-image: url(#{@account.header.url( :original)})" } - if user_signed_in? && current_account.id != @account.id && !current_account.requested?(@account) .controls - if current_account.following?(@account) = link_to t('accounts.unfollow'), unfollow_account_path(@account), data: { method: :post }, class: 'button' - else = link_to t('accounts.follow'), follow_account_path(@account), data: { method: :post }, class: 'button' - - else + - elsif !user_signed_in? .controls .remote-follow = link_to t('accounts.remote_follow'), account_remote_follow_path(@account), class: 'button' diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index 8840b5503d..c194ce33dd 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -15,8 +15,9 @@ %meta{ property: 'twitter:card', content: 'summary' }/ .h-feed - %data.p-name{ value: "#{@account.username} on #{Rails.configuration.x.local_domain}" } - = render partial: 'header', locals: {in_feed: true} + %data.p-name{ value: "#{@account.username} on #{Rails.configuration.x.local_domain}" }/ + + = render partial: 'header' - if @statuses.empty? .accounts-grid diff --git a/app/views/stream_entries/_status.html.haml b/app/views/stream_entries/_status.html.haml index eeb2fec00a..29dcd6081c 100644 --- a/app/views/stream_entries/_status.html.haml +++ b/app/views/stream_entries/_status.html.haml @@ -3,7 +3,7 @@ - is_successor ||= false - centered ||= include_threads && !is_predecessor && !is_successor -%div{ class: [is_predecessor && 'u-in-reply-to h-cite', is_successor && 'u-comment h-cite', !is_predecessor && !is_successor && 'h-entry'] } +%div{ class: [is_predecessor ? 'u-in-reply-to h-cite' : nil, is_successor ? 'u-comment h-cite' : nil, !is_predecessor && !is_successor ? 'h-entry' : nil].compact } - if status.reply? && include_threads = render partial: 'status', collection: @ancestors, as: :status, locals: { is_predecessor: true } @@ -17,7 +17,7 @@ %strong= display_name(status.account) = t('stream_entries.reblogged') - %div{ class: [status.reblog? && 'u-repost-of h-cite'] } + %div{ class: status.reblog? ? 'u-repost-of h-cite' : nil } = render partial: centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status', locals: { status: proper_status(status) } - if include_threads From 1bfbce7b4542739a3601e0722a975b450e86bfb2 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 6 Jan 2017 20:24:51 +0100 Subject: [PATCH 034/175] Clean up h-card mess of divs --- app/helpers/stream_entries_helper.rb | 8 +++--- app/views/stream_entries/_status.html.haml | 30 ++++++++++------------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb index ae2f575b51..15601a0796 100644 --- a/app/helpers/stream_entries_helper.rb +++ b/app/helpers/stream_entries_helper.rb @@ -15,10 +15,10 @@ module StreamEntriesHelper def entry_classes(status, is_predecessor, is_successor, include_threads) classes = ['entry'] - classes << 'entry-reblog' if status.reblog? - classes << 'entry-predecessor' if is_predecessor - classes << 'entry-successor' if is_successor - classes << 'entry-center' if include_threads + classes << 'entry-reblog u-repost-of h-cite' if status.reblog? + classes << 'entry-predecessor u-in-reply-to h-cite' if is_predecessor + classes << 'entry-successor u-comment h-cite' if is_successor + classes << 'entry-center h-entry' if include_threads classes.join(' ') end diff --git a/app/views/stream_entries/_status.html.haml b/app/views/stream_entries/_status.html.haml index 29dcd6081c..f70e2c8902 100644 --- a/app/views/stream_entries/_status.html.haml +++ b/app/views/stream_entries/_status.html.haml @@ -3,22 +3,20 @@ - is_successor ||= false - centered ||= include_threads && !is_predecessor && !is_successor -%div{ class: [is_predecessor ? 'u-in-reply-to h-cite' : nil, is_successor ? 'u-comment h-cite' : nil, !is_predecessor && !is_successor ? 'h-entry' : nil].compact } - - if status.reply? && include_threads - = render partial: 'status', collection: @ancestors, as: :status, locals: { is_predecessor: true } +- if status.reply? && include_threads + = render partial: 'status', collection: @ancestors, as: :status, locals: { is_predecessor: true } - .entry{ class: entry_classes(status, is_predecessor, is_successor, include_threads) } - - if status.reblog? - .pre-header - %div.pre-header__icon - = fa_icon('retweet fw') - %span - = link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do - %strong= display_name(status.account) - = t('stream_entries.reblogged') +.entry{ class: entry_classes(status, is_predecessor, is_successor, include_threads) } + - if status.reblog? + .pre-header + %div.pre-header__icon + = fa_icon('retweet fw') + %span + = link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do + %strong= display_name(status.account) + = t('stream_entries.reblogged') - %div{ class: status.reblog? ? 'u-repost-of h-cite' : nil } - = render partial: centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status', locals: { status: proper_status(status) } + = render partial: centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status', locals: { status: proper_status(status) } - - if include_threads - = render partial: 'status', collection: @descendants, as: :status, locals: { is_successor: true } +- if include_threads + = render partial: 'status', collection: @descendants, as: :status, locals: { is_successor: true } From 989c3f40022bc65d69915be597acda3c4d58de60 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 6 Jan 2017 22:09:55 +0100 Subject: [PATCH 035/175] Add tab bar alternative to desktop UI, upgrade react & react-redux --- .../components/containers/mastodon.jsx | 7 +- .../features/compose/components/drawer.jsx | 73 ++++++++++++++++--- .../compose/components/navigation_bar.jsx | 2 +- .../components/features/compose/index.jsx | 5 +- .../features/ui/components/tabs_bar.jsx | 2 +- .../components/features/ui/index.jsx | 9 ++- app/assets/stylesheets/components.scss | 22 ++++++ package.json | 9 +-- yarn.lock | 6 +- 9 files changed, 103 insertions(+), 32 deletions(-) diff --git a/app/assets/javascripts/components/containers/mastodon.jsx b/app/assets/javascripts/components/containers/mastodon.jsx index 026daeb065..6c0d280536 100644 --- a/app/assets/javascripts/components/containers/mastodon.jsx +++ b/app/assets/javascripts/components/containers/mastodon.jsx @@ -9,7 +9,6 @@ import { import { updateNotifications } from '../actions/notifications'; import { setAccessToken } from '../actions/meta'; import { setAccountSelf } from '../actions/accounts'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; import createBrowserHistory from 'history/lib/createBrowserHistory'; import { applyRouterMiddleware, @@ -63,8 +62,6 @@ const Mastodon = React.createClass({ locale: React.PropTypes.string.isRequired }, - mixins: [PureRenderMixin], - componentWillMount() { const { token, account, locale } = this.props; @@ -108,9 +105,9 @@ const Mastodon = React.createClass({ - + - + diff --git a/app/assets/javascripts/components/features/compose/components/drawer.jsx b/app/assets/javascripts/components/features/compose/components/drawer.jsx index d31d0e4535..b694cdd2a2 100644 --- a/app/assets/javascripts/components/features/compose/components/drawer.jsx +++ b/app/assets/javascripts/components/features/compose/components/drawer.jsx @@ -1,26 +1,75 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; +import { Link } from 'react-router'; +import { injectIntl, defineMessages } from 'react-intl'; -const style = { +const messages = defineMessages({ + start: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, + public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Public timeline' }, + preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, + logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' } +}); + +const outerStyle = { + boxSizing: 'border-box', + display: 'flex', + flexDirection: 'column', + overflowY: 'hidden' +}; + +const innerStyle = { boxSizing: 'border-box', - background: '#454b5e', padding: '0', display: 'flex', flexDirection: 'column', - overflowY: 'auto' + overflowY: 'auto', + flexGrow: '1' }; -const Drawer = React.createClass({ +const tabStyle = { + display: 'block', + flex: '1 1 auto', + padding: '15px', + paddingBottom: '13px', + color: '#9baec8', + textDecoration: 'none', + textAlign: 'center', + fontSize: '16px', + borderBottom: '2px solid transparent' +}; - mixins: [PureRenderMixin], +const tabActiveStyle = { + color: '#2b90d9', + borderBottom: '2px solid #2b90d9' +}; - render () { - return ( -

- {this.props.children} +const Drawer = ({ children, withHeader, intl }) => { + let header = ''; + + if (withHeader) { + header = ( +
+ + + +
); } -}); + return ( +
+ {header} -export default Drawer; +
+ {children} +
+
+ ); +}; + +Drawer.propTypes = { + withHeader: React.PropTypes.bool, + children: React.PropTypes.node, + intl: React.PropTypes.object +}; + +export default injectIntl(Drawer); diff --git a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx index 71b50fc3a3..289e2dddf1 100644 --- a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx +++ b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx @@ -21,7 +21,7 @@ const NavigationBar = React.createClass({
{this.props.account.get('acct')} - · +
); diff --git a/app/assets/javascripts/components/features/compose/index.jsx b/app/assets/javascripts/components/features/compose/index.jsx index 4017c8949f..f6095c0c6d 100644 --- a/app/assets/javascripts/components/features/compose/index.jsx +++ b/app/assets/javascripts/components/features/compose/index.jsx @@ -10,7 +10,8 @@ import { mountCompose, unmountCompose } from '../../actions/compose'; const Compose = React.createClass({ propTypes: { - dispatch: React.PropTypes.func.isRequired + dispatch: React.PropTypes.func.isRequired, + withHeader: React.PropTypes.bool }, mixins: [PureRenderMixin], @@ -25,7 +26,7 @@ const Compose = React.createClass({ render () { return ( - + diff --git a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx index aa40a488f3..2f8a28fadc 100644 --- a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx +++ b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx @@ -30,7 +30,7 @@ const TabsBar = () => { - +
); }; diff --git a/app/assets/javascripts/components/features/ui/index.jsx b/app/assets/javascripts/components/features/ui/index.jsx index 76e3dd9402..db793f945e 100644 --- a/app/assets/javascripts/components/features/ui/index.jsx +++ b/app/assets/javascripts/components/features/ui/index.jsx @@ -14,6 +14,11 @@ import { connect } from 'react-redux'; const UI = React.createClass({ + propTypes: { + dispatch: React.PropTypes.func.isRequired, + children: React.PropTypes.node + }, + getInitialState () { return { width: window.innerWidth @@ -41,7 +46,7 @@ const UI = React.createClass({ handleDrop (e) { e.preventDefault(); - if (e.dataTransfer) { + if (e.dataTransfer && e.dataTransfer.files.length === 1) { this.props.dispatch(uploadCompose(e.dataTransfer.files)); } }, @@ -72,7 +77,7 @@ const UI = React.createClass({ } else { mountedColumns = ( - + {this.props.children} diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index c2fcd76b3c..69595995c1 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -349,6 +349,28 @@ width: 280px; } +.drawer__inner { + background: linear-gradient(rgba(69, 75, 94, 1), rgba(69, 75, 94, 0.65)); +} + +.drawer__header { + flex: 0 0 auto; + font-size: 16px; + background: darken(#454b5e, 5%); + margin-bottom: 10px; + display: flex; + flex-direction: row; + + a { + transition: all 100ms ease-in; + + &:hover { + background: darken(#454b5e, 10%); + transition: all 200ms ease-out; + } + } +} + .column, .drawer { margin-left: 5px; margin-right: 5px; diff --git a/package.json b/package.json index 3a9365d3e3..6a072ca064 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "chai": "^3.5.0", "chai-enzyme": "^0.5.2", "css-loader": "^0.26.1", - "emojione": "^2.2.6", + "emojione": "latest", "enzyme": "^2.4.1", "es6-promise": "^3.2.1", "http-link-header": "^0.5.0", @@ -39,22 +39,19 @@ "react-motion": "^0.4.5", "react-notification": "^6.4.0", "react-proxy": "^1.1.8", - "react-redux": "^5.0.0-beta.3", + "react-redux": "^5.0.1", "react-redux-loading-bar": "^2.4.1", "react-router": "^2.8.0", "react-router-scroll": "^0.3.2", "react-simple-dropdown": "^1.1.4", "react-storybook-addon-intl": "^0.1.0", "react-toggle": "^2.1.1", - "redux": "^3.5.2", + "redux": "^3.6.0", "redux-immutable": "^3.0.8", "redux-thunk": "^2.1.0", "reselect": "^2.5.4", "sass-loader": "^4.0.2", "sinon": "^1.17.6", "style-loader": "^0.13.1" - }, - "dependencies": { - "emojione": "latest" } } diff --git a/yarn.lock b/yarn.lock index db5f7d408c..948de9ba82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4301,9 +4301,9 @@ react-redux@^4.4.5: lodash "^4.2.0" loose-envify "^1.1.0" -react-redux@^5.0.0-beta.3: - version "5.0.0-beta.3" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.0-beta.3.tgz#d50bfb00799cf7d2a9fd55fe34d6b3ecc24d3072" +react-redux@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.1.tgz#84a41bd4cdd180452bb6922bc79ad25bd5abb7c4" dependencies: hoist-non-react-statics "^1.0.3" invariant "^2.0.0" From f1289ca3c0b0a785b47d569e919a345b08136d28 Mon Sep 17 00:00:00 2001 From: Effy Elden Date: Sat, 7 Jan 2017 23:22:24 +1100 Subject: [PATCH 036/175] Add Vagrant development environment support --- .gitignore | 3 ++ README.md | 30 +++++++++++++++++++ Vagrantfile | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 Vagrantfile diff --git a/.gitignore b/.gitignore index a60603c7d4..7f51045aa0 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ public/assets .env.production node_modules/ neo4j/ + +# Ignore Vagrant files +.vagrant/ diff --git a/README.md b/README.md index 2d84062a75..59aa409d5a 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,36 @@ Which will re-create the updated containers, leaving databases and data as is. D Docker is great for quickly trying out software, but it has its drawbacks too. If you prefer to run Mastodon without using Docker, refer to the [production guide](https://github.com/Gargron/mastodon/wiki/Production-guide) for examples, configuration and instructions. +## Development with Vagrant + +A quick way to get a development environment up and running is with Vagrant. You will need recent versions of [Vagrant](https://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/) installed. + +Install the latest version for your operating systems, and then run: + + vagrant plugin install vagrant-hostsupdater + +This is optional, but will update your 'hosts' file when you start the virtual machine, allowing you to access the site at http://mastodon.dev (instead of http://localhost:3000). + +To create and provision a new virtual machine for Mastodon development: + + git clone git@github.com:Gargron/mastodon.git + cd mastodon + vagrant up + +Running `vagrant up` for the first time will run provisioning, which will: + +- Download the Ubuntu 14.04 base image, if there isn't already a copy on your machine +- Create a new VirtualBox virtual machine from that image +- Run the provisioning script (located inside the Vagrantfile), which installs the system packages, Ruby gems, and JS modules required for Mastodon + +Once this has completed, the virtual machine will start a rails process. You can then access your development site at http://mastodon.dev (or at http://localhost:3000 if you haven't installed vagrants-hostupdater). Any changes you make should be reflected on the server instantly. + +When you are finished with your session, run `vagrant halt` to stop the VM. Next time, running `vagrant up` should boot the VM, and skip provsioning. + +If you no longer need your environment, or if things have gone terribly wrong, running `vagrant destroy` will delete the virtual machine (after which, running `vagrant up` will create a new one, and run provisioning). + + + ## Contributing You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository. This section may be updated with more details in the future. diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000000..dabfd70c82 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,86 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +$script = <