about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2016-09-04 14:04:26 +0200
committerEugen Rochko <eugen@zeonfederated.com>2016-09-04 14:04:26 +0200
commit1022d682dc915bcbf3076c0280f29472068830bb (patch)
tree6ede8a3c1cb66e175efcd56af347dc2931806284
parent7939a216ff5cc7ac6bb30e850a21355f04fdebe5 (diff)
Normalized data in Redux, fix for asset URLs when rendered outside request
-rw-r--r--app/assets/javascripts/components/components/display_name.jsx8
-rw-r--r--app/assets/javascripts/components/containers/status_list_container.jsx14
-rw-r--r--app/assets/javascripts/components/reducers/timelines.jsx58
-rw-r--r--app/helpers/atom_builder_helper.rb2
-rw-r--r--app/helpers/routing_helper.rb6
-rw-r--r--app/views/accounts/show.atom.ruby2
-rw-r--r--app/views/api/accounts/show.rabl2
-rw-r--r--config/initializers/ostatus.rb4
-rw-r--r--spec/helpers/application_helper_spec.rb6
9 files changed, 73 insertions, 29 deletions
diff --git a/app/assets/javascripts/components/components/display_name.jsx b/app/assets/javascripts/components/components/display_name.jsx
index 1d579731b..f8d821bce 100644
--- a/app/assets/javascripts/components/components/display_name.jsx
+++ b/app/assets/javascripts/components/components/display_name.jsx
@@ -7,9 +7,15 @@ const DisplayName = React.createClass({
   },
 
   render () {
+    let displayName = this.props.account.get('display_name');
+
+    if (displayName.length === 0) {
+      displayName = this.props.account.get('username');
+    }
+
     return (
       <span style={{ display: 'block', maxWidth: '100%', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}>
-        <strong style={{ fontWeight: 'bold' }}>{this.props.account.get('display_name')}</strong> <span style={{ fontSize: '14px' }}>@{this.props.account.get('acct')}</span>
+        <strong style={{ fontWeight: 'bold' }}>{displayName}</strong> <span style={{ fontSize: '14px' }}>@{this.props.account.get('acct')}</span>
       </span>
     );
   }
diff --git a/app/assets/javascripts/components/containers/status_list_container.jsx b/app/assets/javascripts/components/containers/status_list_container.jsx
index cc6333a81..743e56c67 100644
--- a/app/assets/javascripts/components/containers/status_list_container.jsx
+++ b/app/assets/javascripts/components/containers/status_list_container.jsx
@@ -3,9 +3,21 @@ import StatusList            from '../components/status_list';
 import { replyCompose }      from '../actions/compose';
 import { reblog, favourite } from '../actions/interactions';
 
+function selectStatus(state, id) {
+  let status = state.getIn(['timelines', 'statuses', id]);
+
+  status = status.set('account', state.getIn(['timelines', 'accounts', status.get('account')]));
+
+  if (status.get('reblog') !== null) {
+    status = status.set('reblog', selectStatus(state, status.get('reblog')));
+  }
+
+  return status;
+};
+
 const mapStateToProps = function (state, props) {
   return {
-    statuses: state.getIn(['timelines', props.type])
+    statuses: state.getIn(['timelines', props.type]).map(id => selectStatus(state, id))
   };
 };
 
diff --git a/app/assets/javascripts/components/reducers/timelines.jsx b/app/assets/javascripts/components/reducers/timelines.jsx
index 616411186..9900489df 100644
--- a/app/assets/javascripts/components/reducers/timelines.jsx
+++ b/app/assets/javascripts/components/reducers/timelines.jsx
@@ -2,31 +2,57 @@ import { TIMELINE_SET, TIMELINE_UPDATE }    from '../actions/timelines';
 import { REBLOG_SUCCESS, FAVOURITE_SUCCESS } from '../actions/interactions';
 import Immutable                            from 'immutable';
 
-const initialState = Immutable.Map();
-
-function updateMatchingStatuses(state, needle, callback) {
-  return state.map(function (list) {
-    return list.map(function (status) {
-      if (status.get('id') === needle.get('id')) {
-        return callback(status);
-      } else if (status.getIn(['reblog', 'id'], null) === needle.get('id')) {
-        return status.set('reblog', callback(status.get('reblog')));
-      }
-
-      return status;
-    });
+const initialState = Immutable.Map({
+  home: Immutable.List(),
+  mentions: Immutable.List(),
+  statuses: Immutable.Map(),
+  accounts: Immutable.Map()
+});
+
+function statusToMaps(state, status) {
+  // Separate account
+  let account = status.get('account');
+  status = status.set('account', account.get('id'));
+
+  // Separate reblog, repeat for reblog
+  let reblog = status.get('reblog');
+
+  if (reblog !== null) {
+    status = status.set('reblog', reblog.get('id'));
+    state  = statusToMaps(state, reblog);
+  }
+
+  return state.withMutations(map => {
+    map.setIn(['accounts', account.get('id')], account);
+    map.setIn(['statuses', status.get('id')], status);
+  });
+};
+
+function timelineToMaps(state, timeline, statuses) {
+  statuses.forEach((status, i) => {
+    state = statusToMaps(state, status);
+    state = state.setIn([timeline, i], status.get('id'));
   });
+
+  return state;
+};
+
+function updateTimelineWithMaps(state, timeline, status) {
+  state = statusToMaps(state, status);
+  state = state.update(timeline, list => list.unshift(status.get('id')));
+
+  return state;
 };
 
 export default function timelines(state = initialState, action) {
   switch(action.type) {
     case TIMELINE_SET:
-      return state.set(action.timeline, Immutable.fromJS(action.statuses));
+      return timelineToMaps(state, action.timeline, Immutable.fromJS(action.statuses));
     case TIMELINE_UPDATE:
-      return state.update(action.timeline, list => list.unshift(Immutable.fromJS(action.status)));
+      return updateTimelineWithMaps(state, action.timeline,Immutable.fromJS(action.status));
     case REBLOG_SUCCESS:
     case FAVOURITE_SUCCESS:
-      return updateMatchingStatuses(state, action.status, () => Immutable.fromJS(action.response));
+      return statusToMaps(state, Immutable.fromJS(action.response));
     default:
       return state;
   }
diff --git a/app/helpers/atom_builder_helper.rb b/app/helpers/atom_builder_helper.rb
index f71f0e83e..a98cb7b3b 100644
--- a/app/helpers/atom_builder_helper.rb
+++ b/app/helpers/atom_builder_helper.rb
@@ -214,6 +214,6 @@ module AtomBuilderHelper
   end
 
   def single_link_avatar(xml, account, size, px)
-    xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => px, 'media:height' =>px, 'href' => asset_url(account.avatar.url(size, false)))
+    xml.link('rel' => 'avatar', 'type' => account.avatar_content_type, 'media:width' => px, 'media:height' =>px, 'href' => full_asset_url(account.avatar.url(size, false)))
   end
 end
diff --git a/app/helpers/routing_helper.rb b/app/helpers/routing_helper.rb
index cd8132f07..101382604 100644
--- a/app/helpers/routing_helper.rb
+++ b/app/helpers/routing_helper.rb
@@ -1,11 +1,15 @@
 module RoutingHelper
   extend ActiveSupport::Concern
   include Rails.application.routes.url_helpers
-  include ActionView::Helpers::AssetUrlHelper
+  include ActionView::Helpers::AssetTagHelper
 
   included do
     def default_url_options
       ActionMailer::Base.default_url_options
     end
   end
+
+  def full_asset_url(source)
+    File.join(root_url, ActionController::Base.helpers.asset_url(source))
+  end
 end
diff --git a/app/views/accounts/show.atom.ruby b/app/views/accounts/show.atom.ruby
index b7e3d2590..8a7bc1b92 100644
--- a/app/views/accounts/show.atom.ruby
+++ b/app/views/accounts/show.atom.ruby
@@ -4,7 +4,7 @@ Nokogiri::XML::Builder.new do |xml|
     title      xml, @account.display_name
     subtitle   xml, @account.note
     updated_at xml, stream_updated_at
-    logo       xml, asset_url(@account.avatar.url(:medium, false))
+    logo       xml, full_asset_url(@account.avatar.url(:medium, false))
 
     author(xml) do
       include_author xml, @account
diff --git a/app/views/api/accounts/show.rabl b/app/views/api/accounts/show.rabl
index 05c92c99d..4f7cee680 100644
--- a/app/views/api/accounts/show.rabl
+++ b/app/views/api/accounts/show.rabl
@@ -3,7 +3,7 @@ object @account
 attributes :id, :username, :acct, :display_name, :note
 
 node(:url)             { |account| url_for_target(account) }
-node(:avatar)          { |account| asset_url(account.avatar.url(:large, false)) }
+node(:avatar)          { |account| full_asset_url(account.avatar.url(:large, false)) }
 node(:followers_count) { |account| account.followers.count }
 node(:following_count) { |account| account.following.count }
 node(:statuses_count)  { |account| account.statuses.count  }
diff --git a/config/initializers/ostatus.rb b/config/initializers/ostatus.rb
index 6aada2c32..72009334f 100644
--- a/config/initializers/ostatus.rb
+++ b/config/initializers/ostatus.rb
@@ -1,9 +1,9 @@
 Rails.application.configure do
-  config.x.local_domain = ENV['LOCAL_DOMAIN'] || 'localhost'
+  config.x.local_domain = ENV['LOCAL_DOMAIN'] || "localhost:#{ENV['PORT'] || 3000}"
   config.x.hub_url      = ENV['HUB_URL']      || 'https://pubsubhubbub.superfeedr.com'
   config.x.use_https    = ENV['LOCAL_HTTPS'] == 'true'
 
-  config.action_mailer.default_url_options = { host: config.x.local_domain, protocol: config.x.use_https ? 'https://' : 'http://' }
+  config.action_mailer.default_url_options = { host: config.x.local_domain, protocol: config.x.use_https ? 'https://' : 'http://', trailing_slash: false }
 
   if Rails.env.production?
     config.action_cable.allowed_request_origins = ["http#{config.x.use_https ? 's' : ''}://#{config.x.local_domain}"]
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index d294b9587..9f68a504a 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -1,11 +1,7 @@
 require 'rails_helper'
 
 RSpec.describe ApplicationHelper, type: :helper do
-  let(:local_domain) { 'local.tld' }
-
-  before do
-    Rails.configuration.x.local_domain = local_domain
-  end
+  let(:local_domain) { Rails.configuration.x.local_domain }
 
   describe '#unique_tag' do
     it 'returns a string' do