about summary refs log tree commit diff
path: root/app/javascript/mastodon/reducers
diff options
context:
space:
mode:
authorSorin Davidoi <sorin.davidoi@gmail.com>2017-08-07 20:32:03 +0200
committerEugen Rochko <eugen@zeonfederated.com>2017-08-07 20:32:03 +0200
commit8eb6d171e690e013eb2881478cfa1fd50b4ba705 (patch)
treec0b2305a4bbe66298771699c42d6ce74c2373365 /app/javascript/mastodon/reducers
parent594234740788a51fa528152343eb50dc1c6ca093 (diff)
feat: Cache status height to avoid expensive renders (#4439)
* feat: Cache status height to avoid expensive renders

* feat: Escape content and emojify in reducers

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

* fix(statuses): Avoid creating DOMParses inside a loop
Diffstat (limited to 'app/javascript/mastodon/reducers')
-rw-r--r--app/javascript/mastodon/reducers/accounts.js6
-rw-r--r--app/javascript/mastodon/reducers/statuses.js26
2 files changed, 31 insertions, 1 deletions
diff --git a/app/javascript/mastodon/reducers/accounts.js b/app/javascript/mastodon/reducers/accounts.js
index 4d7c3adc9..6442d13be 100644
--- a/app/javascript/mastodon/reducers/accounts.js
+++ b/app/javascript/mastodon/reducers/accounts.js
@@ -44,7 +44,9 @@ import {
   FAVOURITED_STATUSES_EXPAND_SUCCESS,
 } from '../actions/favourites';
 import { STORE_HYDRATE } from '../actions/store';
+import emojify from '../emoji';
 import { Map as ImmutableMap, fromJS } from 'immutable';
+import escapeTextContentForBrowser from 'escape-html';
 
 const normalizeAccount = (state, account) => {
   account = { ...account };
@@ -53,6 +55,10 @@ const normalizeAccount = (state, account) => {
   delete account.following_count;
   delete account.statuses_count;
 
+  const displayName = account.display_name.length === 0 ? account.username : account.display_name;
+  account.display_name_html = emojify(escapeTextContentForBrowser(displayName));
+  account.note_emojified = emojify(account.note);
+
   return state.set(account.id, fromJS(account));
 };
 
diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js
index b1b1d0988..3e40b0b42 100644
--- a/app/javascript/mastodon/reducers/statuses.js
+++ b/app/javascript/mastodon/reducers/statuses.js
@@ -13,6 +13,8 @@ import {
   CONTEXT_FETCH_SUCCESS,
   STATUS_MUTE_SUCCESS,
   STATUS_UNMUTE_SUCCESS,
+  STATUS_SET_HEIGHT,
+  STATUSES_CLEAR_HEIGHT,
 } from '../actions/statuses';
 import {
   TIMELINE_REFRESH_SUCCESS,
@@ -33,7 +35,11 @@ import {
   FAVOURITED_STATUSES_EXPAND_SUCCESS,
 } from '../actions/favourites';
 import { SEARCH_FETCH_SUCCESS } from '../actions/search';
+import emojify from '../emoji';
 import { Map as ImmutableMap, fromJS } from 'immutable';
+import escapeTextContentForBrowser from 'escape-html';
+
+const domParser = new DOMParser();
 
 const normalizeStatus = (state, status) => {
   if (!status) {
@@ -49,7 +55,9 @@ const normalizeStatus = (state, status) => {
   }
 
   const searchContent = [status.spoiler_text, status.content].join(' ').replace(/<br \/>/g, '\n').replace(/<\/p><p>/g, '\n\n');
-  normalStatus.search_index = new DOMParser().parseFromString(searchContent, 'text/html').documentElement.textContent;
+  normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
+  normalStatus.contentHtml = emojify(normalStatus.content);
+  normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(normalStatus.spoiler_text || ''));
 
   return state.update(status.id, ImmutableMap(), map => map.mergeDeep(fromJS(normalStatus)));
 };
@@ -82,6 +90,18 @@ const filterStatuses = (state, relationship) => {
   return state;
 };
 
+const setHeight = (state, id, height) => {
+  return state.update(id, ImmutableMap(), map => map.set('height', height));
+};
+
+const clearHeights = (state) => {
+  state.forEach(status => {
+    state = state.deleteIn([status.get('id'), 'height']);
+  });
+
+  return state;
+};
+
 const initialState = ImmutableMap();
 
 export default function statuses(state = initialState, action) {
@@ -120,6 +140,10 @@ export default function statuses(state = initialState, action) {
     return deleteStatus(state, action.id, action.references);
   case ACCOUNT_BLOCK_SUCCESS:
     return filterStatuses(state, action.relationship);
+  case STATUS_SET_HEIGHT:
+    return setHeight(state, action.id, action.height);
+  case STATUSES_CLEAR_HEIGHT:
+    return clearHeights(state);
   default:
     return state;
   }