index.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import { createSelector } from 'reselect';
  2. import { List as ImmutableList, Map as ImmutableMap, is } from 'immutable';
  3. import { me } from '../initial_state';
  4. const getAccountBase = (state, id) => state.getIn(['accounts', id], null);
  5. const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null);
  6. const getAccountRelationship = (state, id) => state.getIn(['relationships', id], null);
  7. const getAccountMoved = (state, id) => state.getIn(['accounts', state.getIn(['accounts', id, 'moved'])]);
  8. export const makeGetAccount = () => {
  9. return createSelector([getAccountBase, getAccountCounters, getAccountRelationship, getAccountMoved], (base, counters, relationship, moved) => {
  10. if (base === null) {
  11. return null;
  12. }
  13. return base.merge(counters).withMutations(map => {
  14. map.set('relationship', relationship);
  15. map.set('moved', moved);
  16. });
  17. });
  18. };
  19. const toServerSideType = columnType => {
  20. switch (columnType) {
  21. case 'home':
  22. case 'notifications':
  23. case 'public':
  24. case 'thread':
  25. case 'account':
  26. return columnType;
  27. default:
  28. if (columnType.indexOf('list:') > -1) {
  29. return 'home';
  30. } else {
  31. return 'public'; // community, account, hashtag
  32. }
  33. }
  34. };
  35. const escapeRegExp = string =>
  36. string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
  37. const regexFromKeywords = keywords => {
  38. if (keywords.size === 0) {
  39. return null;
  40. }
  41. return new RegExp(keywords.map(keyword_filter => {
  42. let expr = escapeRegExp(keyword_filter.get('keyword'));
  43. if (keyword_filter.get('whole_word')) {
  44. if (/^[\w]/.test(expr)) {
  45. expr = `\\b${expr}`;
  46. }
  47. if (/[\w]$/.test(expr)) {
  48. expr = `${expr}\\b`;
  49. }
  50. }
  51. return expr;
  52. }).join('|'), 'i');
  53. };
  54. const getFilters = (state, { contextType }) => {
  55. if (!contextType) return null;
  56. const serverSideType = toServerSideType(contextType);
  57. const now = new Date();
  58. return state.get('filters').filter((filter) => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || filter.get('expires_at') > now));
  59. };
  60. export const makeGetStatus = () => {
  61. return createSelector(
  62. [
  63. (state, { id }) => state.getIn(['statuses', id]),
  64. (state, { id }) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]),
  65. (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]),
  66. (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]),
  67. getFilters,
  68. ],
  69. (statusBase, statusReblog, accountBase, accountReblog, filters) => {
  70. if (!statusBase) {
  71. return null;
  72. }
  73. if (statusReblog) {
  74. statusReblog = statusReblog.set('account', accountReblog);
  75. } else {
  76. statusReblog = null;
  77. }
  78. let filtered = false;
  79. if ((accountReblog || accountBase).get('id') !== me && filters) {
  80. let filterResults = statusReblog?.get('filtered') || statusBase.get('filtered') || ImmutableList();
  81. if (filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action']) === 'hide')) {
  82. return null;
  83. }
  84. if (!filterResults.isEmpty()) {
  85. filtered = filterResults.map(result => filters.getIn([result.get('filter'), 'title']));
  86. }
  87. }
  88. return statusBase.withMutations(map => {
  89. map.set('reblog', statusReblog);
  90. map.set('account', accountBase);
  91. map.set('filtered', filtered);
  92. });
  93. },
  94. );
  95. };
  96. export const makeGetPictureInPicture = () => {
  97. return createSelector([
  98. (state, { id }) => state.get('picture_in_picture').statusId === id,
  99. (state) => state.getIn(['meta', 'layout']) !== 'mobile',
  100. ], (inUse, available) => ImmutableMap({
  101. inUse: inUse && available,
  102. available,
  103. }));
  104. };
  105. const getAlertsBase = state => state.get('alerts');
  106. export const getAlerts = createSelector([getAlertsBase], (base) => {
  107. let arr = [];
  108. base.forEach(item => {
  109. arr.push({
  110. message: item.get('message'),
  111. message_values: item.get('message_values'),
  112. title: item.get('title'),
  113. key: item.get('key'),
  114. dismissAfter: 5000,
  115. barStyle: {
  116. zIndex: 200,
  117. },
  118. });
  119. });
  120. return arr;
  121. });
  122. export const makeGetNotification = () => createSelector([
  123. (_, base) => base,
  124. (state, _, accountId) => state.getIn(['accounts', accountId]),
  125. ], (base, account) => base.set('account', account));
  126. export const makeGetReport = () => createSelector([
  127. (_, base) => base,
  128. (state, _, targetAccountId) => state.getIn(['accounts', targetAccountId]),
  129. ], (base, targetAccount) => base.set('target_account', targetAccount));
  130. export const getAccountGallery = createSelector([
  131. (state, id) => state.getIn(['timelines', `account:${id}:media`, 'items'], ImmutableList()),
  132. state => state.get('statuses'),
  133. (state, id) => state.getIn(['accounts', id]),
  134. ], (statusIds, statuses, account) => {
  135. let medias = ImmutableList();
  136. statusIds.forEach(statusId => {
  137. const status = statuses.get(statusId);
  138. medias = medias.concat(status.get('media_attachments').map(media => media.set('status', status).set('account', account)));
  139. });
  140. return medias;
  141. });
  142. export const getAccountHidden = createSelector([
  143. (state, id) => state.getIn(['accounts', id, 'hidden']),
  144. (state, id) => state.getIn(['relationships', id, 'following']) || state.getIn(['relationships', id, 'requested']),
  145. (state, id) => id === me,
  146. ], (hidden, followingOrRequested, isSelf) => {
  147. return hidden && !(isSelf || followingOrRequested);
  148. });