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 60eb9905a3767..6ce4984bb31ee 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 f7ebebbcb8dec..27ad6cbde5c0d 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 18c239c48a509..e46b27f1f4e69 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 3a5b88523617c..3b012b184b434 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 219979522b30d..499c9e287b56d 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 acfa85c6bdcd0..2996fa92e449d 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 499c9e287b56d..dbfdc3f852961 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 157bdf8f2ff1f..77253dd731cc8 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 2996fa92e449d..c6441924321cb 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 df94c30d22900..23d695f132deb 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 9f4cf9e4df3d8..37715dd05b91b 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 e166fc7170ac9..dd2ae3aac0710 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 d4baca5aaada0..3beaebeb1c5ed 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 ac548033cb48c..8a14dda695cd7 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 a06c759531347..c93c07c74b283 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 77253dd731cc8..51f165f9e2d0b 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 b9f8e6842cd43..c1df182deafe2 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 c6441924321cb..4f03f94e542fa 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 ee42a5df24e69..72568e702da48 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 386e94111f543..e4c38d3844bb6 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 489bd835904a6..868fd9f972c80 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 35bf7b2f07e7f..15005bc80200a 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 84eae73befa99..593edd032f2e6 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 a14c82d6fcec4..cce07e486c710 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 39ccbcaf96763..57352be902ce8 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 55f361b0b775a..412c29310723b 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 3a1473bc14c4b..74d77f0f9a1f7 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 67045537651bb..026daeb0656d9 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 dbfdc3f852961..aa40a488f3e86 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 51f165f9e2d0b..9f47e7ab47f87 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 23d695f132deb..71b50fc3a3e31 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 51f165f9e2d0b..ae850c3f9a7cd 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 17b74e15d610d..97df6748021a9 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 3d4a389196ddc..05fb0243c38c7 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 6bd9b18edfac4..b75fb57d9233e 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 968c3f8c394a9..183e5d5b524cc 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 606fc830fe83c..9a2d14d87af4f 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 57cbcd31be09e..d68724b13b08d 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 53535c25acc83..84a348c210a29 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 412c29310723b..44c44bcb0ece4 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 d631290131f4b..19c52550a8230 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 b4e618820e12a..e4672216b4aff 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 3681672d8ca1e..620c86a677c9f 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 e4c550b818553..1e571385f4ef4 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 4f03f94e542fa..c2fcd76b3c24c 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 e6d2e85a2f2c1..b3b71b412bc16 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 eecfd67438208..fc75c78be4679 100644 --- a/public/404.html +++ b/public/404.html @@ -7,7 +7,7 @@ diff --git a/public/500.html b/public/500.html index 915b890f15ce2..d085d490b0c1e 100644 --- a/public/500.html +++ b/public/500.html @@ -7,7 +7,7 @@ diff --git a/storybook/storybook.scss b/storybook/storybook.scss index b0145f9bda7a6..31f11b5adfadf 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 c93c07c74b283..82b82b7196ca6 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 05663a729ef22..13b0484eccc1c 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 f71a8ae104df6..b79c46898357a 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 82b82b7196ca6..990aea5be5109 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 990aea5be5109..c93c07c74b283 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 13b0484eccc1c..05663a729ef22 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 b79c46898357a..f71a8ae104df6 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 1e571385f4ef4..e4c550b818553 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 44c44bcb0ece4..8128bb382afbf 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 8128bb382afbf..5a76b177b689d 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 5a76b177b689d..078bfbdc62b7d 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 8bd83540631a4..182b598aa5372 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 6dd1822059bcf..b0260dc516ab3 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 7afeb68a97f21..bc0f08a7989ad 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 43935da60ff7e..d106173d2e553 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 05663a729ef22..3a9365d3e35b4 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 f71a8ae104df6..db5f7d408ccb4 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 6f1f7ec482f1e..488c4f944f6f7 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 2a5d23739ae9d..ecbed03e33402 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 0000000000000..2685ae150ec62 --- /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 b9236d42fdced..a535c5fdb1217 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 1c6b5f0f67640..e410ff72cbfd9 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 bc0f08a7989ad..8840b5503de92 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 94451d3bda032..b0d36872cfcbf 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 da3bc0ccb9e11..b08cf5dab97d3 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 f70e2c8902943..eeb2fec00a19e 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 dd42fe22c5441..412ec4fa5da5a 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 e410ff72cbfd9..7a5cea7abc481 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 8840b5503de92..c194ce33dd3a2 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 eeb2fec00a19e..29dcd6081c83a 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 ae2f575b51114..15601a0796bde 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 29dcd6081c83a..f70e2c8902943 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 026daeb0656d9..6c0d280536c8e 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 d31d0e45356aa..b694cdd2a270d 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 71b50fc3a3e31..289e2dddf155c 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 4017c8949f2f8..f6095c0c6d7b7 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 aa40a488f3e86..2f8a28fadcda3 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 76e3dd940268c..db793f945e130 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 c2fcd76b3c24c..69595995c12c7 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 3a9365d3e35b4..6a072ca064075 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 db5f7d408ccb4..948de9ba82177 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 a60603c7d42af..7f51045aa0bbc 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 2d84062a75944..59aa409d5a272 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 0000000000000..dabfd70c82632 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,86 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +$script = <