Progress
This commit is contained in:
parent
b5e3c2a94f
commit
bb4fcdf32d
10
.eslintrc.js
10
.eslintrc.js
|
@ -10,6 +10,13 @@ module.exports = {
|
||||||
|
|
||||||
globals: {
|
globals: {
|
||||||
ATTACHMENT_HOST: false,
|
ATTACHMENT_HOST: false,
|
||||||
|
_s: true,
|
||||||
|
PropTypes: true,
|
||||||
|
PureComponent: true,
|
||||||
|
React: {
|
||||||
|
Component: true,
|
||||||
|
},
|
||||||
|
connect: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
parser: 'babel-eslint',
|
parser: 'babel-eslint',
|
||||||
|
@ -98,8 +105,9 @@ module.exports = {
|
||||||
classes: 'always',
|
classes: 'always',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
'prefer-const': 'error',
|
||||||
quotes: ['error', 'single'],
|
quotes: ['error', 'single'],
|
||||||
semi: 'error',
|
semi: 'off',
|
||||||
strict: 'off',
|
strict: 'off',
|
||||||
'valid-typeof': 'error',
|
'valid-typeof': 'error',
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
import { CancelToken, isCancel } from 'axios';
|
import { CancelToken, isCancel } from 'axios';
|
||||||
import { throttle } from 'lodash';
|
import throttle from 'lodash.throttle'
|
||||||
import moment from 'moment';
|
|
||||||
import { search as emojiSearch } from '../components/emoji/emoji_mart_search_light';
|
import { search as emojiSearch } from '../components/emoji/emoji_mart_search_light';
|
||||||
import { urlRegex } from '../features/compose/util/url_regex'
|
import { urlRegex } from '../features/compose/util/url_regex'
|
||||||
import { tagHistory } from '../settings';
|
import { tagHistory } from '../settings';
|
||||||
|
@ -133,7 +132,7 @@ export function mentionCompose(account, routerHistory) {
|
||||||
export function handleComposeSubmit(dispatch, getState, response, status) {
|
export function handleComposeSubmit(dispatch, getState, response, status) {
|
||||||
if (!dispatch || !getState) return;
|
if (!dispatch || !getState) return;
|
||||||
|
|
||||||
const isScheduledStatus = response.data['scheduled_at'] !== undefined;
|
const isScheduledStatus = response.data.scheduled_at !== undefined;
|
||||||
if (isScheduledStatus) {
|
if (isScheduledStatus) {
|
||||||
// dispatch(showAlertForError({
|
// dispatch(showAlertForError({
|
||||||
// response: {
|
// response: {
|
||||||
|
@ -154,7 +153,7 @@ export function handleComposeSubmit(dispatch, getState, response, status) {
|
||||||
const timeline = getState().getIn(['timelines', timelineId]);
|
const timeline = getState().getIn(['timelines', timelineId]);
|
||||||
|
|
||||||
if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
|
if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
|
||||||
let dequeueArgs = {};
|
const dequeueArgs = {};
|
||||||
if (timelineId === 'community') dequeueArgs.onlyMedia = getState().getIn(['settings', 'community', 'other', 'onlyMedia']);
|
if (timelineId === 'community') dequeueArgs.onlyMedia = getState().getIn(['settings', 'community', 'other', 'onlyMedia']);
|
||||||
dispatch(dequeueTimeline(timelineId, null, dequeueArgs));
|
dispatch(dequeueTimeline(timelineId, null, dequeueArgs));
|
||||||
dispatch(updateTimeline(timelineId, { ...response.data }));
|
dispatch(updateTimeline(timelineId, { ...response.data }));
|
||||||
|
@ -174,7 +173,7 @@ export function submitCompose(routerHistory, group) {
|
||||||
if (!me) return;
|
if (!me) return;
|
||||||
|
|
||||||
let status = getState().getIn(['compose', 'text'], '');
|
let status = getState().getIn(['compose', 'text'], '');
|
||||||
let statusMarkdown = getState().getIn(['compose', 'text_markdown'], '');
|
const statusMarkdown = getState().getIn(['compose', 'text_markdown'], '');
|
||||||
const media = getState().getIn(['compose', 'media_attachments']);
|
const media = getState().getIn(['compose', 'media_attachments']);
|
||||||
|
|
||||||
// : hack :
|
// : hack :
|
||||||
|
@ -183,10 +182,10 @@ export function submitCompose(routerHistory, group) {
|
||||||
const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
||||||
return hasProtocol ? match : `http://${match}`
|
return hasProtocol ? match : `http://${match}`
|
||||||
})
|
})
|
||||||
statusMarkdown = statusMarkdown.replace(urlRegex, (match) =>{
|
// statusMarkdown = statusMarkdown.replace(urlRegex, (match) =>{
|
||||||
const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
// const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
||||||
return hasProtocol ? match : `http://${match}`
|
// return hasProtocol ? match : `http://${match}`
|
||||||
})
|
// })
|
||||||
|
|
||||||
dispatch(submitComposeRequest());
|
dispatch(submitComposeRequest());
|
||||||
dispatch(closeModal());
|
dispatch(closeModal());
|
||||||
|
@ -197,12 +196,13 @@ export function submitCompose(routerHistory, group) {
|
||||||
: `/api/v1/statuses/${id}`;
|
: `/api/v1/statuses/${id}`;
|
||||||
const method = id === null ? 'post' : 'put';
|
const method = id === null ? 'post' : 'put';
|
||||||
|
|
||||||
let scheduled_at = getState().getIn(['compose', 'scheduled_at'], null);
|
const scheduled_at = getState().getIn(['compose', 'scheduled_at'], null);
|
||||||
if (scheduled_at !== null) scheduled_at = moment.utc(scheduled_at).toDate();
|
// : todo :
|
||||||
|
// if (scheduled_at !== null) scheduled_at = moment.utc(scheduled_at).toDate();
|
||||||
|
|
||||||
api(getState)[method](endpoint, {
|
api(getState)[method](endpoint, {
|
||||||
status,
|
status,
|
||||||
statusMarkdown,
|
// statusMarkdown,
|
||||||
scheduled_at,
|
scheduled_at,
|
||||||
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
||||||
quote_of_id: getState().getIn(['compose', 'quote_of_id'], null),
|
quote_of_id: getState().getIn(['compose', 'quote_of_id'], null),
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { me } from '../initial_state';
|
||||||
|
|
||||||
export const NOTIFICATIONS_INITIALIZE = 'NOTIFICATIONS_INITIALIZE';
|
export const NOTIFICATIONS_INITIALIZE = 'NOTIFICATIONS_INITIALIZE';
|
||||||
export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
|
export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
|
||||||
export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP';
|
|
||||||
export const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE';
|
export const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE';
|
||||||
export const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE';
|
export const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE';
|
||||||
|
|
||||||
|
@ -76,7 +75,6 @@ export function updateNotificationsQueue(notification, intlMessages, intlLocale,
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true);
|
const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true);
|
||||||
const filters = getFilters(getState(), { contextType: 'notifications' });
|
const filters = getFilters(getState(), { contextType: 'notifications' });
|
||||||
const playSound = getState().getIn(['settings', 'notifications', 'sounds', notification.type], true);
|
|
||||||
|
|
||||||
let filtered = false;
|
let filtered = false;
|
||||||
|
|
||||||
|
@ -101,13 +99,6 @@ export function updateNotificationsQueue(notification, intlMessages, intlLocale,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playSound && !filtered) {
|
|
||||||
dispatch({
|
|
||||||
type: NOTIFICATIONS_UPDATE_NOOP,
|
|
||||||
meta: { sound: 'ribbit' },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isOnNotificationsPage) {
|
if (isOnNotificationsPage) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: NOTIFICATIONS_UPDATE_QUEUE,
|
type: NOTIFICATIONS_UPDATE_QUEUE,
|
||||||
|
@ -115,8 +106,7 @@ export function updateNotificationsQueue(notification, intlMessages, intlLocale,
|
||||||
intlMessages,
|
intlMessages,
|
||||||
intlLocale,
|
intlLocale,
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
dispatch(updateNotifications(notification, intlMessages, intlLocale));
|
dispatch(updateNotifications(notification, intlMessages, intlLocale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,15 +117,13 @@ export function dequeueNotifications() {
|
||||||
const queuedNotifications = getState().getIn(['notifications', 'queuedNotifications'], ImmutableList());
|
const queuedNotifications = getState().getIn(['notifications', 'queuedNotifications'], ImmutableList());
|
||||||
const totalQueuedNotificationsCount = getState().getIn(['notifications', 'totalQueuedNotificationsCount'], 0);
|
const totalQueuedNotificationsCount = getState().getIn(['notifications', 'totalQueuedNotificationsCount'], 0);
|
||||||
|
|
||||||
if (totalQueuedNotificationsCount == 0) {
|
if (totalQueuedNotificationsCount === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
} else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
|
||||||
else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
|
|
||||||
queuedNotifications.forEach(block => {
|
queuedNotifications.forEach(block => {
|
||||||
dispatch(updateNotifications(block.notification, block.intlMessages, block.intlLocale));
|
dispatch(updateNotifications(block.notification, block.intlMessages, block.intlLocale));
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
dispatch(expandNotifications());
|
dispatch(expandNotifications());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,9 +156,9 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("activeFilter:", activeFilter)
|
console.log('activeFilter:', activeFilter)
|
||||||
console.log("excludeTypesFromSettings(getState()):", excludeTypesFromSettings(getState()))
|
console.log('excludeTypesFromSettings(getState()):', excludeTypesFromSettings(getState()))
|
||||||
console.log("excludeTypesFromFilter(activeFilter):", excludeTypesFromFilter(activeFilter))
|
console.log('excludeTypesFromFilter(activeFilter):', excludeTypesFromFilter(activeFilter))
|
||||||
|
|
||||||
// : todo :
|
// : todo :
|
||||||
// filter verified and following here too
|
// filter verified and following here too
|
||||||
|
@ -268,7 +256,7 @@ export function markReadNotifications() {
|
||||||
const last_read = getState().getIn(['notifications', 'lastRead']);
|
const last_read = getState().getIn(['notifications', 'lastRead']);
|
||||||
|
|
||||||
if (top_notification && top_notification > last_read) {
|
if (top_notification && top_notification > last_read) {
|
||||||
api(getState).post('/api/v1/notifications/mark_read', {id: top_notification}).then(response => {
|
api(getState).post('/api/v1/notifications/mark_read', { id: top_notification }).then(response => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: NOTIFICATIONS_MARK_READ,
|
type: NOTIFICATIONS_MARK_READ,
|
||||||
notification: top_notification,
|
notification: top_notification,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash.debounce';
|
||||||
// import { showAlertForError } from './alerts';
|
// import { showAlertForError } from './alerts';
|
||||||
import { me } from '../initial_state';
|
import { me } from '../initial_state';
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ export const fetchGifCategories = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchGifResults = () => {
|
export const fetchGifResults = (maxId) => {
|
||||||
return function (dispatch, getState) {
|
return function (dispatch, getState) {
|
||||||
if (!me) return
|
if (!me) return
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ export const fetchGifResults = () => {
|
||||||
|
|
||||||
axios.get(`https://api.tenor.com/v1/search?q=${searchText}&media_filter=minimal&limit=30&key=${tenorkey}`)
|
axios.get(`https://api.tenor.com/v1/search?q=${searchText}&media_filter=minimal&limit=30&key=${tenorkey}`)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
console.log("response:", response)
|
console.log('response:', response)
|
||||||
dispatch(fetchGifResultsSuccess(response.data.results))
|
dispatch(fetchGifResultsSuccess(response.data.results))
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
dispatch(fetchGifResultsFail(error))
|
dispatch(fetchGifResultsFail(error))
|
||||||
|
|
|
@ -55,29 +55,24 @@ export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) {
|
||||||
|
|
||||||
let shouldDispatchDequeue = true;
|
let shouldDispatchDequeue = true;
|
||||||
|
|
||||||
if (totalQueuedItemsCount == 0) {
|
if (totalQueuedItemsCount === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
} else if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
|
||||||
else if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
|
|
||||||
queuedItems.forEach(status => {
|
queuedItems.forEach(status => {
|
||||||
dispatch(updateTimeline(timeline, status.toJS(), null));
|
dispatch(updateTimeline(timeline, status.toJS(), null));
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (typeof expandFunc === 'function') {
|
if (typeof expandFunc === 'function') {
|
||||||
dispatch(clearTimeline(timeline));
|
dispatch(clearTimeline(timeline));
|
||||||
expandFunc();
|
expandFunc();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (timeline === 'home') {
|
if (timeline === 'home') {
|
||||||
dispatch(clearTimeline(timeline));
|
dispatch(clearTimeline(timeline));
|
||||||
dispatch(expandHomeTimeline(optionalExpandArgs));
|
dispatch(expandHomeTimeline(optionalExpandArgs));
|
||||||
}
|
} else if (timeline === 'community') {
|
||||||
else if (timeline === 'community') {
|
|
||||||
dispatch(clearTimeline(timeline));
|
dispatch(clearTimeline(timeline));
|
||||||
dispatch(expandCommunityTimeline(optionalExpandArgs));
|
dispatch(expandCommunityTimeline(optionalExpandArgs));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
shouldDispatchDequeue = false;
|
shouldDispatchDequeue = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ export const getLinks = response => {
|
||||||
return LinkHeader.parse(value);
|
return LinkHeader.parse(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
let csrfHeader = {};
|
const csrfHeader = {};
|
||||||
|
|
||||||
function setCSRFHeader() {
|
function setCSRFHeader() {
|
||||||
const csrfToken = document.querySelector('meta[name=csrf-token]');
|
const csrfToken = document.querySelector('meta[name=csrf-token]');
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
const HiddenIcon = ({
|
||||||
|
className = '',
|
||||||
|
width = '16px',
|
||||||
|
height = '16px',
|
||||||
|
viewBox = '0 0 48 48',
|
||||||
|
title = 'Hidden',
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
version='1.1'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
x='0px'
|
||||||
|
y='0px'
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
xmlSpace='preserve'
|
||||||
|
aria-label={title}
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path d='M 23.632812 16.398438 L 30.503906 23.269531 L 30.539062 22.910156 C 30.539062 19.300781 27.605469 16.367188 23.996094 16.367188 Z M 23.632812 16.398438' />
|
||||||
|
<path d='M 23.996094 12.003906 C 30.015625 12.003906 34.902344 16.890625 34.902344 22.910156 C 34.902344 24.316406 34.617188 25.65625 34.125 26.890625 L 40.507812 33.269531 C 43.800781 30.523438 46.398438 26.964844 48 22.910156 C 44.214844 13.332031 34.914062 6.550781 23.996094 6.550781 C 20.941406 6.550781 18.019531 7.09375 15.300781 8.078125 L 20.015625 12.777344 C 21.246094 12.296875 22.585938 12.003906 23.996094 12.003906 Z M 23.996094 12.003906' />
|
||||||
|
<path d='M 2.179688 6.058594 L 7.15625 11.03125 L 8.148438 12.023438 C 4.546875 14.839844 1.703125 18.578125 0 22.910156 C 3.773438 32.484375 13.089844 39.269531 23.996094 39.269531 C 27.375 39.269531 30.605469 38.613281 33.558594 37.425781 L 34.488281 38.351562 L 40.84375 44.722656 L 43.625 41.953125 L 4.960938 3.277344 Z M 14.242188 18.109375 L 17.613281 21.480469 C 17.515625 21.949219 17.449219 22.417969 17.449219 22.910156 C 17.449219 26.519531 20.382812 29.453125 23.996094 29.453125 C 24.484375 29.453125 24.953125 29.386719 25.414062 29.289062 L 28.78125 32.660156 C 27.332031 33.378906 25.71875 33.816406 23.996094 33.816406 C 17.972656 33.816406 13.089844 28.929688 13.089844 22.910156 C 13.089844 21.1875 13.523438 19.570312 14.242188 18.109375 Z M 14.242188 18.109375' />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default HiddenIcon
|
|
@ -93,6 +93,7 @@ class Account extends ImmutablePureComponent {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// : todo : cleanup
|
||||||
let buttonOptions
|
let buttonOptions
|
||||||
let buttonText
|
let buttonText
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import unicodeMapping from '../emoji/emoji_unicode_mapping_light';
|
import unicodeMapping from '../emoji/emoji_unicode_mapping_light'
|
||||||
|
|
||||||
const assetHost = process.env.CDN_HOST || '';
|
const assetHost = process.env.CDN_HOST || ''
|
||||||
|
|
||||||
export default class AutosuggestEmoji extends PureComponent {
|
export default class AutosuggestEmoji extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
emoji: PropTypes.object.isRequired,
|
emoji: PropTypes.object.isRequired,
|
||||||
};
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { emoji } = this.props;
|
const { emoji } = this.props
|
||||||
let url;
|
let url
|
||||||
|
|
||||||
if (emoji.custom) {
|
if (emoji.custom) {
|
||||||
url = emoji.imageUrl;
|
url = emoji.imageUrl
|
||||||
} else {
|
} else {
|
||||||
const mapping = unicodeMapping[emoji.native] || unicodeMapping[emoji.native.replace(/\uFE0F$/, '')];
|
const mapping = unicodeMapping[emoji.native] || unicodeMapping[emoji.native.replace(/\uFE0F$/, '')]
|
||||||
|
|
||||||
if (!mapping) return null;
|
if (!mapping) return null
|
||||||
|
|
||||||
url = `${assetHost}/emoji/${mapping.filename}.svg`;
|
url = `${assetHost}/emoji/${mapping.filename}.svg`
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -27,7 +27,7 @@ export default class AutosuggestEmoji extends PureComponent {
|
||||||
<img className='emojione' src={url} alt={emoji.native || emoji.colons} />
|
<img className='emojione' src={url} alt={emoji.native || emoji.colons} />
|
||||||
{emoji.colons}
|
{emoji.colons}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { Fragment } from 'react'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import Textarea from 'react-textarea-autosize'
|
|
||||||
import ContentEditable from 'react-contenteditable'
|
|
||||||
import { isRtl } from '../../utils/rtl'
|
import { isRtl } from '../../utils/rtl'
|
||||||
import { textAtCursorMatchesToken } from '../../utils/cursor_token_match'
|
import { textAtCursorMatchesToken } from '../../utils/cursor_token_match'
|
||||||
import AutosuggestAccount from '../autosuggest_account'
|
import AutosuggestAccount from '../autosuggest_account'
|
||||||
|
@ -210,7 +208,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||||
id,
|
id,
|
||||||
maxLength,
|
maxLength,
|
||||||
textarea,
|
textarea,
|
||||||
prependIcon
|
prependIcon,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const { suggestionsHidden } = this.state
|
const { suggestionsHidden } = this.state
|
||||||
|
@ -307,6 +305,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
{ /* : todo : */ }
|
||||||
<div className='autosuggest-textarea__suggestions-wrapper'>
|
<div className='autosuggest-textarea__suggestions-wrapper'>
|
||||||
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
|
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
|
||||||
{suggestions.map(this.renderSuggestion)}
|
{suggestions.map(this.renderSuggestion)}
|
||||||
|
|
|
@ -47,6 +47,7 @@ class Avatar extends ImmutablePureComponent {
|
||||||
const shouldAnimate = animate || !sameImg
|
const shouldAnimate = animate || !sameImg
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
alt: !account ? 'Avatar' : account.get('display_name'),
|
||||||
className: [_s.default, _s.circle, _s.overflowHidden].join(' '),
|
className: [_s.default, _s.circle, _s.overflowHidden].join(' '),
|
||||||
onMouseEnter: shouldAnimate ? this.handleMouseEnter : undefined,
|
onMouseEnter: shouldAnimate ? this.handleMouseEnter : undefined,
|
||||||
onMouseLeave: shouldAnimate ? this.handleMouseLeave : undefined,
|
onMouseLeave: shouldAnimate ? this.handleMouseLeave : undefined,
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
export default class Block extends PureComponent {
|
export default class Block extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children } = this.props
|
const { children } = this.props
|
||||||
|
|
||||||
|
@ -8,4 +13,5 @@ export default class Block extends PureComponent {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -32,7 +32,7 @@ export default class ColumnHeader extends PureComponent {
|
||||||
title,
|
title,
|
||||||
showBackBtn,
|
showBackBtn,
|
||||||
tabs,
|
tabs,
|
||||||
actions
|
actions,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -68,15 +68,15 @@ export default class ColumnHeader extends PureComponent {
|
||||||
{
|
{
|
||||||
actions.map((action, i) => (
|
actions.map((action, i) => (
|
||||||
<Button
|
<Button
|
||||||
radiusSmall
|
backgroundColor='none'
|
||||||
backgroundColor='tertiary'
|
color='secondary'
|
||||||
onClick={() => action.onClick() }
|
onClick={() => action.onClick()}
|
||||||
key={`column-header-action-btn-${i}`}
|
key={`column-header-action-btn-${i}`}
|
||||||
className={[_s.ml5, _s.px10].join(' ')}
|
className={[_s.ml5, _s.fillColorBrand_onHover, _s.backgroundColorBrandLightOpaque_onHover, _s.px10].join(' ')}
|
||||||
iconClassName={_s.fillColorSecondary}
|
|
||||||
icon={action.icon}
|
icon={action.icon}
|
||||||
iconWidth='20px'
|
iconClassName={_s.inheritFill}
|
||||||
iconHeight='20px'
|
iconWidth='15px'
|
||||||
|
iconHeight='15px'
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,33 +22,9 @@ const makeMapStateToProps = () => {
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const status = getStatus(state, props)
|
const status = getStatus(state, props)
|
||||||
let descendantsIds = Immutable.List()
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
// ALL descendants
|
|
||||||
descendantsIds = descendantsIds.withMutations(mutable => {
|
|
||||||
const ids = [status.get('id')]
|
|
||||||
|
|
||||||
while (ids.length > 0) {
|
|
||||||
let id = ids.shift();
|
|
||||||
const replies = state.getIn(['contexts', 'replies', id])
|
|
||||||
|
|
||||||
if (status.get('id') !== id) {
|
|
||||||
mutable.push(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (replies) {
|
|
||||||
replies.reverse().forEach(reply => {
|
|
||||||
ids.unshift(reply)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
descendantsIds,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,30 +38,22 @@ class Comment extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: ImmutablePropTypes.map.isRequired,
|
status: ImmutablePropTypes.map.isRequired,
|
||||||
descendantsIds: ImmutablePropTypes.list,
|
indent: ImmutablePropTypes.number,
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = () => {
|
|
||||||
// if (this.props.onClick) {
|
|
||||||
// this.props.onClick();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!this.context.router) return;
|
|
||||||
|
|
||||||
// this.context.router.history.push(
|
|
||||||
// `/${this._properStatus().getIn(['account', 'acct'])}/posts/${this._properStatus().get('id')}`
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { status } = this.props
|
const { status, indent } = this.props
|
||||||
|
|
||||||
console.log("status:", status)
|
console.log("status:", status)
|
||||||
|
const style = {
|
||||||
|
paddingLeft: `${indent * 40}px`,
|
||||||
|
}
|
||||||
|
|
||||||
|
// : todo : add media
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.px10, _s.mb10, _s.py5].join(' ')} data-comment={status.get('id')}>
|
<div className={[_s.default, _s.px10, _s.mb10, _s.py5].join(' ')} data-comment={status.get('id')}>
|
||||||
<div className={[_s.default].join(' ')}>
|
<div className={[_s.default].join(' ')} style={style}>
|
||||||
|
|
||||||
<div className={[_s.default, _s.flexRow].join(' ')}>
|
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||||
<NavLink
|
<NavLink
|
||||||
|
|
|
@ -1,159 +1,27 @@
|
||||||
import { Fragment } from 'react'
|
|
||||||
import { NavLink } from 'react-router-dom'
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { makeGetStatus } from '../selectors';
|
import Comment from './comment'
|
||||||
import CommentHeader from './comment_header'
|
|
||||||
import Avatar from './avatar'
|
|
||||||
import Button from './button'
|
|
||||||
import DisplayName from './display_name'
|
|
||||||
import DotTextSeperator from './dot_text_seperator'
|
|
||||||
import RelativeTimestamp from './relative_timestamp'
|
|
||||||
import Text from './text'
|
|
||||||
import StatusContent from './status_content'
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
export default class CommentList extends ImmutablePureComponent {
|
||||||
follow: { id: 'follow', defaultMessage: 'Follow' },
|
|
||||||
})
|
|
||||||
|
|
||||||
const makeMapStateToProps = () => {
|
|
||||||
const getStatus = makeGetStatus()
|
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
|
||||||
const status = getStatus(state, props)
|
|
||||||
let descendantsIds = Immutable.List()
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
// ALL descendants
|
|
||||||
descendantsIds = descendantsIds.withMutations(mutable => {
|
|
||||||
const ids = [status.get('id')]
|
|
||||||
|
|
||||||
while (ids.length > 0) {
|
|
||||||
let id = ids.shift();
|
|
||||||
const replies = state.getIn(['contexts', 'replies', id])
|
|
||||||
|
|
||||||
if (status.get('id') !== id) {
|
|
||||||
mutable.push(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (replies) {
|
|
||||||
replies.reverse().forEach(reply => {
|
|
||||||
ids.unshift(reply)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
status,
|
|
||||||
descendantsIds,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapStateToProps
|
|
||||||
}
|
|
||||||
|
|
||||||
export default
|
|
||||||
@injectIntl
|
|
||||||
@connect(makeMapStateToProps)
|
|
||||||
class Comment extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: ImmutablePropTypes.map.isRequired,
|
descendants: ImmutablePropTypes.list,
|
||||||
descendantsIds: ImmutablePropTypes.list,
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = () => {
|
|
||||||
// if (this.props.onClick) {
|
|
||||||
// this.props.onClick();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!this.context.router) return;
|
|
||||||
|
|
||||||
// this.context.router.history.push(
|
|
||||||
// `/${this._properStatus().getIn(['account', 'acct'])}/posts/${this._properStatus().get('id')}`
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { status } = this.props
|
const { descendants } = this.props
|
||||||
|
|
||||||
console.log("status:", status)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.px10, _s.mb10, _s.py5].join(' ')} data-comment={status.get('id')}>
|
<div>
|
||||||
<div className={[_s.default].join(' ')}>
|
{
|
||||||
|
descendants.map((descendant, i) => (
|
||||||
<div className={[_s.default, _s.flexRow].join(' ')}>
|
<Comment
|
||||||
<NavLink
|
key={`comment-${descendant.get('statusId')}-${i}`}
|
||||||
to={`/${status.getIn(['account', 'acct'])}`}
|
id={descendant.get('statusId')}
|
||||||
title={status.getIn(['account', 'acct'])}
|
indent={descendant.get('indent')}
|
||||||
className={[_s.default, _s.mr10, _s.pt5].join(' ')}
|
|
||||||
>
|
|
||||||
<Avatar account={status.get('account')} size={32} />
|
|
||||||
</NavLink>
|
|
||||||
|
|
||||||
<div className={[_s.default, _s.flexGrow1].join(' ')}>
|
|
||||||
<div className={[_s.default, _s.px10, _s.py5, _s.radiusSmall, _s.backgroundSubtle].join(' ')}>
|
|
||||||
<div className={_s.pt2}>
|
|
||||||
<CommentHeader status={status} />
|
|
||||||
</div>
|
|
||||||
<div className={[_s.py5].join(' ')}>
|
|
||||||
<StatusContent
|
|
||||||
status={status}
|
|
||||||
onClick={this.handleClick}
|
|
||||||
isComment
|
|
||||||
collapsable
|
|
||||||
/>
|
/>
|
||||||
</div>
|
))
|
||||||
</div>
|
}
|
||||||
<div className={[_s.default, _s.flexRow, _s.mt5].join(' ')}>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
text
|
|
||||||
radiusSmall
|
|
||||||
backgroundColor='none'
|
|
||||||
color='tertiary'
|
|
||||||
className={[_s.px5, _s.backgroundSubtle_onHover, _s.py2, _s.mr5].join(' ')}
|
|
||||||
>
|
|
||||||
<Text size='extraSmall' color='inherit' weight='bold'>
|
|
||||||
Like
|
|
||||||
</Text>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
text
|
|
||||||
radiusSmall
|
|
||||||
backgroundColor='none'
|
|
||||||
color='tertiary'
|
|
||||||
className={[_s.px5, _s.backgroundSubtle_onHover, _s.py2, _s.mr5].join(' ')}
|
|
||||||
>
|
|
||||||
<Text size='extraSmall' color='inherit' weight='bold'>
|
|
||||||
Reply
|
|
||||||
</Text>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
text
|
|
||||||
radiusSmall
|
|
||||||
backgroundColor='none'
|
|
||||||
color='tertiary'
|
|
||||||
className={[_s.px5, _s.backgroundSubtle_onHover, _s.py2, _s.mr5].join(' ')}
|
|
||||||
>
|
|
||||||
<Text size='extraSmall' color='inherit' weight='bold'>
|
|
||||||
···
|
|
||||||
</Text>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { debounce } from 'lodash'
|
import debounce from 'lodash.debounce'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import { openPopover, closePopover } from '../actions/popover'
|
import { openPopover, closePopover } from '../actions/popover'
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { pick } from 'lodash';
|
import pick from 'lodash.pick'
|
||||||
import { emojiIndex } from 'emoji-mart';
|
import { emojiIndex } from 'emoji-mart';
|
||||||
import { search } from '../emoji_mart_search_light';
|
import { search } from '../emoji_mart_search_light';
|
||||||
|
|
||||||
|
|
|
@ -40,17 +40,6 @@ export default class FileInput extends PureComponent {
|
||||||
} = this.props
|
} = this.props
|
||||||
const { file } = this.state
|
const { file } = this.state
|
||||||
|
|
||||||
const imageClasses = cx({
|
|
||||||
border2PX: 1,
|
|
||||||
borderDashed: 1,
|
|
||||||
borderColorSecondary: 1,
|
|
||||||
backgroundColorPrimary: 1,
|
|
||||||
px10: 1,
|
|
||||||
py10: 1,
|
|
||||||
radiusSmall: 1,
|
|
||||||
cursorPointer: 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
|
@ -63,7 +52,7 @@ export default class FileInput extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className={[_s.default, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}
|
className={[_s.default, _s.alignItemsCenter, _s.radiusSmall, _s.cursorPointer, _s.px10, _s.py10, _s.justifyContentCenter, _s.border2PX, _s.borderColorSecondary, _s.borderDashed].join(' ')}
|
||||||
htmlFor={`file-input-${title}`}
|
htmlFor={`file-input-${title}`}
|
||||||
style={{
|
style={{
|
||||||
width,
|
width,
|
||||||
|
@ -71,9 +60,7 @@ export default class FileInput extends PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
className={imageClasses}
|
className={[_s.height100PC, _s.width100PC, _s.radiusSmall].join(' ')}
|
||||||
width={width}
|
|
||||||
height={height}
|
|
||||||
src={fileType === 'image' ? file : null}
|
src={fileType === 'image' ? file : null}
|
||||||
/>
|
/>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
import Button from './button'
|
import Button from './button'
|
||||||
|
|
||||||
export default class FloatingActionButton extends Component {
|
export default class FloatingActionButton extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
message: PropTypes.string.isRequired,
|
message: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -30,6 +30,7 @@ export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class GroupCollectionItem extends ImmutablePureComponent {
|
class GroupCollectionItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
group: ImmutablePropTypes.map,
|
group: ImmutablePropTypes.map,
|
||||||
relationships: ImmutablePropTypes.map,
|
relationships: ImmutablePropTypes.map,
|
||||||
|
@ -50,14 +51,9 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||||
</Fragment>
|
</Fragment>
|
||||||
) : intl.formatMessage(messages.no_recent_activity)
|
) : intl.formatMessage(messages.no_recent_activity)
|
||||||
|
|
||||||
const imageHeight = '180px'
|
|
||||||
|
|
||||||
const isMember = relationships.get('member')
|
const isMember = relationships.get('member')
|
||||||
|
const isAdmin = relationships.get('admin')
|
||||||
const outsideClasses = cx({
|
const coverSrc = group.get('cover')
|
||||||
default: 1,
|
|
||||||
width50PC: 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
const navLinkClasses = cx({
|
const navLinkClasses = cx({
|
||||||
default: 1,
|
default: 1,
|
||||||
|
@ -74,18 +70,30 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={outsideClasses}>
|
<div className={_s.default}>
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/groups/${group.get('id')}`}
|
to={`/groups/${group.get('id')}`}
|
||||||
className={navLinkClasses}
|
className={navLinkClasses}
|
||||||
>
|
>
|
||||||
|
{
|
||||||
|
!!coverSrc &&
|
||||||
<Image
|
<Image
|
||||||
src={group.get('cover')}
|
src={coverSrc}
|
||||||
alt={group.get('title')}
|
alt={group.get('title')}
|
||||||
height={imageHeight}
|
className={_s.height158PX}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
!coverSrc && (isMember || isAdmin) &&
|
||||||
|
<div className={[_s.default, _s.height40PX, _s.backgroundSubtle, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
(isMember || isAdmin) &&
|
||||||
<div className={[_s.default, _s.flexRow, _s.positionAbsolute, _s.top0, _s.right0, _s.pt10, _s.mr10].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.positionAbsolute, _s.top0, _s.right0, _s.pt10, _s.mr10].join(' ')}>
|
||||||
|
{
|
||||||
|
isMember &&
|
||||||
<Text
|
<Text
|
||||||
badge
|
badge
|
||||||
className={_s.backgroundColorWhite}
|
className={_s.backgroundColorWhite}
|
||||||
|
@ -94,6 +102,9 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.member)}
|
{intl.formatMessage(messages.member)}
|
||||||
</Text>
|
</Text>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
isAdmin &&
|
||||||
<Text
|
<Text
|
||||||
badge
|
badge
|
||||||
className={[_s.backgroundColorBlack, _s.ml5].join(' ')}
|
className={[_s.backgroundColorBlack, _s.ml5].join(' ')}
|
||||||
|
@ -102,7 +113,9 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.admin)}
|
{intl.formatMessage(messages.admin)}
|
||||||
</Text>
|
</Text>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div className={[_s.default, _s.px10, _s.my10].join(' ')}>
|
<div className={[_s.default, _s.px10, _s.my10].join(' ')}>
|
||||||
<Text color='primary' size='medium' weight='bold'>
|
<Text color='primary' size='medium' weight='bold'>
|
||||||
|
@ -119,8 +132,6 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||||
<Text color='secondary' size='small' className={_s.ml5}>
|
<Text color='secondary' size='small' className={_s.ml5}>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
</Text>
|
</Text>
|
||||||
<DotTextSeperator />
|
|
||||||
<Text color='secondary' size='small' className={_s.ml5}>→</Text>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -128,4 +139,5 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -25,6 +25,7 @@ export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class GroupListItem extends ImmutablePureComponent {
|
class GroupListItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
group: ImmutablePropTypes.map,
|
group: ImmutablePropTypes.map,
|
||||||
relationships: ImmutablePropTypes.map,
|
relationships: ImmutablePropTypes.map,
|
||||||
|
@ -82,16 +83,22 @@ class GroupListItem extends ImmutablePureComponent {
|
||||||
mb10: !slim,
|
mb10: !slim,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const coverSrc = group.get('cover')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/groups/${group.get('id')}`}
|
to={`/groups/${group.get('id')}`}
|
||||||
className={containerClasses}
|
className={containerClasses}
|
||||||
>
|
>
|
||||||
|
|
||||||
|
{
|
||||||
|
(!!coverSrc || slim) &&
|
||||||
<Image
|
<Image
|
||||||
src={group.get('cover')}
|
src={coverSrc}
|
||||||
alt={group.get('title')}
|
alt={group.get('title')}
|
||||||
className={imageClasses}
|
className={imageClasses}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
<div className={textContainerClasses}>
|
<div className={textContainerClasses}>
|
||||||
<Text color='brand' weight='bold'>
|
<Text color='brand' weight='bold'>
|
||||||
|
@ -115,4 +122,5 @@ class GroupListItem extends ImmutablePureComponent {
|
||||||
</NavLink>
|
</NavLink>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -45,6 +45,7 @@ export default class HashtagItem extends ImmutablePureComponent {
|
||||||
text
|
text
|
||||||
backgroundColor='none'
|
backgroundColor='none'
|
||||||
color='none'
|
color='none'
|
||||||
|
title='Remove'
|
||||||
icon='caret-down'
|
icon='caret-down'
|
||||||
iconWidth='8px'
|
iconWidth='8px'
|
||||||
iconHeight='8px'
|
iconHeight='8px'
|
||||||
|
|
|
@ -25,6 +25,7 @@ import GlobeIcon from '../assets/globe_icon'
|
||||||
import GroupIcon from '../assets/group_icon'
|
import GroupIcon from '../assets/group_icon'
|
||||||
import GroupAddIcon from '../assets/group_add_icon'
|
import GroupAddIcon from '../assets/group_add_icon'
|
||||||
import HappyIcon from '../assets/happy_icon'
|
import HappyIcon from '../assets/happy_icon'
|
||||||
|
import HiddenIcon from '../assets/hidden_icon'
|
||||||
import HomeIcon from '../assets/home_icon'
|
import HomeIcon from '../assets/home_icon'
|
||||||
import InvestorIcon from '../assets/investor_icon'
|
import InvestorIcon from '../assets/investor_icon'
|
||||||
import ItalicIcon from '../assets/italic_icon'
|
import ItalicIcon from '../assets/italic_icon'
|
||||||
|
@ -64,70 +65,71 @@ import VerifiedIcon from '../assets/verified_icon'
|
||||||
import WarningIcon from '../assets/warning_icon'
|
import WarningIcon from '../assets/warning_icon'
|
||||||
|
|
||||||
const ICONS = {
|
const ICONS = {
|
||||||
'add': AddIcon,
|
'add': AddIcon,
|
||||||
'angle-right': AngleRightIcon,
|
'angle-right': AngleRightIcon,
|
||||||
'apps': AppsIcon,
|
'apps': AppsIcon,
|
||||||
'audio': AudioIcon,
|
'audio': AudioIcon,
|
||||||
'audio-mute': AudioMuteIcon,
|
'audio-mute': AudioMuteIcon,
|
||||||
'back': BackIcon,
|
'back': BackIcon,
|
||||||
'blockquote': BlockquoteIcon,
|
'blockquote': BlockquoteIcon,
|
||||||
'bold': BoldIcon,
|
'bold': BoldIcon,
|
||||||
'calendar': CalendarIcon,
|
'calendar': CalendarIcon,
|
||||||
'chat': ChatIcon,
|
'chat': ChatIcon,
|
||||||
'close': CloseIcon,
|
'close': CloseIcon,
|
||||||
'code': CodeIcon,
|
'code': CodeIcon,
|
||||||
'comment': CommentIcon,
|
'comment': CommentIcon,
|
||||||
'copy': CopyIcon,
|
'copy': CopyIcon,
|
||||||
'dissenter': DissenterIcon,
|
'dissenter': DissenterIcon,
|
||||||
'donor': DonorIcon,
|
'donor': DonorIcon,
|
||||||
'ellipsis': EllipsisIcon,
|
'ellipsis': EllipsisIcon,
|
||||||
'email': EmailIcon,
|
'email': EmailIcon,
|
||||||
'error': ErrorIcon,
|
'error': ErrorIcon,
|
||||||
'fullscreen': FullscreenIcon,
|
'fullscreen': FullscreenIcon,
|
||||||
'gab-logo': GabLogoIcon,
|
'gab-logo': GabLogoIcon,
|
||||||
'gif': GifIcon,
|
'gif': GifIcon,
|
||||||
'globe': GlobeIcon,
|
'globe': GlobeIcon,
|
||||||
'group': GroupIcon,
|
'group': GroupIcon,
|
||||||
'group-add': GroupAddIcon,
|
'group-add': GroupAddIcon,
|
||||||
'happy': HappyIcon,
|
'hidden': HiddenIcon,
|
||||||
'home': HomeIcon,
|
'happy': HappyIcon,
|
||||||
'investor': InvestorIcon,
|
'home': HomeIcon,
|
||||||
'italic': ItalicIcon,
|
'investor': InvestorIcon,
|
||||||
'like': LikeIcon,
|
'italic': ItalicIcon,
|
||||||
'liked': LikedIcon,
|
'like': LikeIcon,
|
||||||
'link': LinkIcon,
|
'liked': LikedIcon,
|
||||||
'list': ListIcon,
|
'link': LinkIcon,
|
||||||
'list-add': ListAddIcon,
|
'list': ListIcon,
|
||||||
'loading': LoadingIcon,
|
'list-add': ListAddIcon,
|
||||||
'lock': LockIcon,
|
'loading': LoadingIcon,
|
||||||
'lock-filled': LockFilledIcon,
|
'lock': LockIcon,
|
||||||
'media': MediaIcon,
|
'lock-filled': LockFilledIcon,
|
||||||
'minimize-fullscreen': MinimizeFullscreenIcon,
|
'media': MediaIcon,
|
||||||
'missing': MissingIcon,
|
'minimize-fullscreen': MinimizeFullscreenIcon,
|
||||||
'more': MoreIcon,
|
'missing': MissingIcon,
|
||||||
'notifications': NotificationsIcon,
|
'more': MoreIcon,
|
||||||
'ol-list': OLListIcon,
|
'notifications': NotificationsIcon,
|
||||||
'pause': PauseIcon,
|
'ol-list': OLListIcon,
|
||||||
'pin': PinIcon,
|
'pause': PauseIcon,
|
||||||
'play': PlayIcon,
|
'pin': PinIcon,
|
||||||
'poll': PollIcon,
|
'play': PlayIcon,
|
||||||
'pro': ProIcon,
|
'poll': PollIcon,
|
||||||
'repost': RepostIcon,
|
'pro': ProIcon,
|
||||||
'rich-text': RichTextIcon,
|
'repost': RepostIcon,
|
||||||
'search': SearchIcon,
|
'rich-text': RichTextIcon,
|
||||||
'search-alt': SearchAltIcon,
|
'search': SearchIcon,
|
||||||
'share': ShareIcon,
|
'search-alt': SearchAltIcon,
|
||||||
'shop': ShopIcon,
|
'share': ShareIcon,
|
||||||
'strikethrough': StrikethroughIcon,
|
'shop': ShopIcon,
|
||||||
'subtract': SubtractIcon,
|
'strikethrough': StrikethroughIcon,
|
||||||
'text-size': TextSizeIcon,
|
'subtract': SubtractIcon,
|
||||||
'trends': TrendsIcon,
|
'text-size': TextSizeIcon,
|
||||||
'ul-list': ULListIcon,
|
'trends': TrendsIcon,
|
||||||
'underline': UnderlineIcon,
|
'ul-list': ULListIcon,
|
||||||
'unlock-filled': UnlockFilledIcon,
|
'underline': UnderlineIcon,
|
||||||
'verified': VerifiedIcon,
|
'unlock-filled': UnlockFilledIcon,
|
||||||
'warning': WarningIcon,
|
'verified': VerifiedIcon,
|
||||||
'': CircleIcon,
|
'warning': WarningIcon,
|
||||||
|
'': CircleIcon,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Icon extends PureComponent {
|
export default class Icon extends PureComponent {
|
||||||
|
@ -148,4 +150,5 @@ export default class Icon extends PureComponent {
|
||||||
return <Asset {...options} />
|
return <Asset {...options} />
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
|
|
||||||
// : testing :
|
|
||||||
// : todo :
|
|
||||||
const placeholderSource = 'https://source.unsplash.com/random'
|
|
||||||
const imageUnavailable = 'https://source.unsplash.com/random'
|
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
export default class Image extends PureComponent {
|
export default class Image extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
alt: PropTypes.string,
|
alt: PropTypes.string.isRequired,
|
||||||
src: PropTypes.string,
|
src: PropTypes.string,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
fit: PropTypes.oneOf(['contain', 'cover', 'tile', 'none']),
|
fit: PropTypes.oneOf(['contain', 'cover', 'tile', 'none']),
|
||||||
nullable: PropTypes.bool,
|
nullable: PropTypes.bool,
|
||||||
|
lazy: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -32,29 +29,41 @@ export default class Image extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { src, fit, className, nullable, ...otherProps } = this.props
|
const {
|
||||||
|
src,
|
||||||
|
fit,
|
||||||
|
className,
|
||||||
|
nullable,
|
||||||
|
lazy,
|
||||||
|
...otherProps
|
||||||
|
} = this.props
|
||||||
const { error } = this.state
|
const { error } = this.state
|
||||||
|
|
||||||
let source = src || placeholderSource
|
|
||||||
const classes = cx(className, {
|
const classes = cx(className, {
|
||||||
default: 1,
|
default: 1,
|
||||||
objectFitCover: fit === 'cover'
|
objectFitCover: !!src && fit === 'cover',
|
||||||
|
backgroundSubtle2: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
//If error and not our own image
|
//If error and not our own image
|
||||||
if (error && nullable) {
|
if (error && nullable) {
|
||||||
return null
|
return null
|
||||||
} else if (error) {
|
}
|
||||||
source = imageUnavailable
|
|
||||||
|
if (!src) {
|
||||||
|
return (
|
||||||
|
<div className={classes} />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
className={classes}
|
className={classes}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
src={source}
|
src={src}
|
||||||
onError={this.handleOnError}
|
onError={this.handleOnError}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(makeMapStateToProps, mapDispatchToProps)
|
@connect(makeMapStateToProps, mapDispatchToProps)
|
||||||
class IntersectionObserverArticle extends Component {
|
class IntersectionObserverArticle extends React.Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
intersectionObserverWrapper: PropTypes.object.isRequired,
|
intersectionObserverWrapper: PropTypes.object.isRequired,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import moment from 'moment'
|
|
||||||
import {
|
import {
|
||||||
FormattedMessage,
|
FormattedMessage,
|
||||||
defineMessages,
|
defineMessages,
|
||||||
|
@ -46,7 +45,7 @@ class LinkFooter extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { onOpenHotkeys, intl } = this.props
|
const { onOpenHotkeys, intl } = this.props
|
||||||
|
|
||||||
const currentYear = moment().format('YYYY')
|
const currentYear = new Date().getFullYear()
|
||||||
|
|
||||||
const linkFooterItems = [
|
const linkFooterItems = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,9 @@ import { decode } from 'blurhash';
|
||||||
import { autoPlayGif, displayMedia } from '../../initial_state';
|
import { autoPlayGif, displayMedia } from '../../initial_state';
|
||||||
import { isIOS } from '../../utils/is_mobile';
|
import { isIOS } from '../../utils/is_mobile';
|
||||||
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio';
|
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio';
|
||||||
import Button from '../button';
|
import Button from '../button'
|
||||||
|
import SensitiveMediaItem from '../../components/sensitive_media_item'
|
||||||
|
import Text from '../text'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
|
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
|
||||||
|
@ -16,6 +18,7 @@ const messages = defineMessages({
|
||||||
});
|
});
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
class Item extends ImmutablePureComponent {
|
class Item extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -58,7 +61,7 @@ class Item extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hoverToPlay () {
|
hoverToPlay() {
|
||||||
const { attachment } = this.props;
|
const { attachment } = this.props;
|
||||||
return autoPlayGif === false && attachment.get('type') === 'gifv';
|
return autoPlayGif === false && attachment.get('type') === 'gifv';
|
||||||
}
|
}
|
||||||
|
@ -79,23 +82,23 @@ class Item extends ImmutablePureComponent {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount() {
|
||||||
if (this.props.attachment.get('blurhash')) {
|
if (this.props.attachment.get('blurhash')) {
|
||||||
this._decode();
|
this._decode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (prevProps.attachment.get('blurhash') !== this.props.attachment.get('blurhash') && this.props.attachment.get('blurhash')) {
|
if (prevProps.attachment.get('blurhash') !== this.props.attachment.get('blurhash') && this.props.attachment.get('blurhash')) {
|
||||||
this._decode();
|
this._decode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_decode () {
|
_decode() {
|
||||||
const hash = this.props.attachment.get('blurhash');
|
const hash = this.props.attachment.get('blurhash');
|
||||||
const pixels = decode(hash, 32, 32);
|
const pixels = decode(hash, 32, 32);
|
||||||
|
|
||||||
if (pixels) {
|
if (pixels && this.canvas) {
|
||||||
const ctx = this.canvas.getContext('2d');
|
const ctx = this.canvas.getContext('2d');
|
||||||
const imageData = new ImageData(pixels, 32, 32);
|
const imageData = new ImageData(pixels, 32, 32);
|
||||||
|
|
||||||
|
@ -111,7 +114,7 @@ class Item extends ImmutablePureComponent {
|
||||||
this.setState({ loaded: true });
|
this.setState({ loaded: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render() {
|
||||||
const { attachment, index, size, standalone, displayWidth, visible, dimensions } = this.props;
|
const { attachment, index, size, standalone, displayWidth, visible, dimensions } = this.props;
|
||||||
|
|
||||||
const ar = attachment.getIn(['meta', 'small', 'aspect']);
|
const ar = attachment.getIn(['meta', 'small', 'aspect']);
|
||||||
|
@ -148,12 +151,12 @@ class Item extends ImmutablePureComponent {
|
||||||
|
|
||||||
if (attachment.get('type') === 'unknown') {
|
if (attachment.get('type') === 'unknown') {
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default].join(' ')} key={attachment.get('id')} style={{ position, float, left, top, right, bottom, height, borderRadius, width: `${width}%` }}>
|
<div className={[_s.default, _s.positionAbsolute].join(' ')} key={attachment.get('id')} style={{ position, float, left, top, right, bottom, height, borderRadius, width: `${width}%` }}>
|
||||||
<a className='media-gallery__item-thumbnail' href={attachment.get('remote_url')} target='_blank' style={{ cursor: 'pointer' }}>
|
<a className={[_s.default, _s.heigh100PC, _s.width100PC, _s.cursorPointer].join(' ')} href={attachment.get('remote_url')} target='_blank' rel='noreferrer noopener'>
|
||||||
<canvas width={32} height={32} ref={this.setCanvasRef} className='media-gallery__preview' />
|
<canvas width={32} height={32} ref={this.setCanvasRef} className={[_s.default, _s.heigh100PC, _s.width100PC].join(' ')} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
} else if (attachment.get('type') === 'image') {
|
} else if (attachment.get('type') === 'image') {
|
||||||
const previewUrl = attachment.get('preview_url');
|
const previewUrl = attachment.get('preview_url');
|
||||||
const previewWidth = attachment.getIn(['meta', 'small', 'width']);
|
const previewWidth = attachment.getIn(['meta', 'small', 'width']);
|
||||||
|
@ -213,14 +216,19 @@ class Item extends ImmutablePureComponent {
|
||||||
playsInline
|
playsInline
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span className='media-gallery__gifv__label'>GIF</span>
|
<div className={[_s.default, _s.positionAbsolute, _s.z2, _s.radiusSmall, _s.backgroundColorOpaque, _s.px5, _s.py5, _s.mr10, _s.mb10, _s.bottom0, _s.right0].join(' ')}>
|
||||||
|
<Text size='extraSmall' color='white' weight='medium'>GIF</Text>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.defeault, _s.positionAbsolute].join(' ')} key={attachment.get('id')} style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}>
|
<div className={[_s.defeault, _s.positionAbsolute].join(' ')} key={attachment.get('id')} style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}>
|
||||||
<canvas width={0} height={0} ref={this.setCanvasRef} className={_s.displayNone} />
|
{
|
||||||
|
!visible && !this.state.loaded &&
|
||||||
|
<canvas width={32} height={32} ref={this.setCanvasRef} className={[_s.default, _s.heigh100PC, _s.width100PC].join(' ')} />
|
||||||
|
}
|
||||||
{visible && thumbnail}
|
{visible && thumbnail}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -256,9 +264,11 @@ class MediaGallery extends PureComponent {
|
||||||
width: this.props.defaultWidth,
|
width: this.props.defaultWidth,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (!is(nextProps.media, this.props.media) && nextProps.visible === undefined) {
|
if (!is(nextProps.media, this.props.media) && nextProps.visible === undefined) {
|
||||||
this.setState({ visible: displayMedia !== 'hide_all' && !nextProps.sensitive || displayMedia === 'show_all' });
|
this.setState({
|
||||||
|
visible: displayMedia !== 'hide_all' && !nextProps.sensitive || displayMedia === 'show_all',
|
||||||
|
})
|
||||||
} else if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
|
} else if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
|
||||||
this.setState({ visible: nextProps.visible });
|
this.setState({ visible: nextProps.visible });
|
||||||
}
|
}
|
||||||
|
@ -287,21 +297,19 @@ class MediaGallery extends PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render() {
|
||||||
const {
|
const {
|
||||||
media,
|
media,
|
||||||
intl,
|
intl,
|
||||||
sensitive,
|
sensitive,
|
||||||
height,
|
height,
|
||||||
defaultWidth,
|
defaultWidth,
|
||||||
reduced
|
reduced,
|
||||||
} = this.props
|
} = this.props
|
||||||
const { visible } = this.state
|
const { visible } = this.state
|
||||||
|
|
||||||
const width = this.state.width || defaultWidth;
|
const width = this.state.width || defaultWidth;
|
||||||
|
|
||||||
let children, spoilerButton;
|
|
||||||
|
|
||||||
const style = {};
|
const style = {};
|
||||||
const size = media.take(4).size;
|
const size = media.take(4).size;
|
||||||
|
|
||||||
|
@ -312,7 +320,7 @@ class MediaGallery extends PureComponent {
|
||||||
const panoSize_px = `${Math.floor(width / maximumAspectRatio)}px`;
|
const panoSize_px = `${Math.floor(width / maximumAspectRatio)}px`;
|
||||||
let itemsDimensions = [];
|
let itemsDimensions = [];
|
||||||
|
|
||||||
if (size == 1 && width) {
|
if (size === 1 && width && visible) {
|
||||||
const aspectRatio = media.getIn([0, 'meta', 'small', 'aspect']);
|
const aspectRatio = media.getIn([0, 'meta', 'small', 'aspect']);
|
||||||
|
|
||||||
if (isPanoramic(aspectRatio)) {
|
if (isPanoramic(aspectRatio)) {
|
||||||
|
@ -322,13 +330,13 @@ class MediaGallery extends PureComponent {
|
||||||
} else {
|
} else {
|
||||||
style.height = Math.floor(width / aspectRatio);
|
style.height = Math.floor(width / aspectRatio);
|
||||||
}
|
}
|
||||||
} else if (size > 1 && width) {
|
} else if (size > 1 && width && visible) {
|
||||||
const ar1 = media.getIn([0, 'meta', 'small', 'aspect']);
|
const ar1 = media.getIn([0, 'meta', 'small', 'aspect']);
|
||||||
const ar2 = media.getIn([1, 'meta', 'small', 'aspect']);
|
const ar2 = media.getIn([1, 'meta', 'small', 'aspect']);
|
||||||
const ar3 = media.getIn([2, 'meta', 'small', 'aspect']);
|
const ar3 = media.getIn([2, 'meta', 'small', 'aspect']);
|
||||||
const ar4 = media.getIn([3, 'meta', 'small', 'aspect']);
|
const ar4 = media.getIn([3, 'meta', 'small', 'aspect']);
|
||||||
|
|
||||||
if (size == 2) {
|
if (size === 2) {
|
||||||
if (isPortrait(ar1) && isPortrait(ar2)) {
|
if (isPortrait(ar1) && isPortrait(ar2)) {
|
||||||
style.height = width - (width / maximumAspectRatio);
|
style.height = width - (width / maximumAspectRatio);
|
||||||
} else if (isPanoramic(ar1) && isPanoramic(ar2)) {
|
} else if (isPanoramic(ar1) && isPanoramic(ar2)) {
|
||||||
|
@ -378,7 +386,7 @@ class MediaGallery extends PureComponent {
|
||||||
{ w: 50, h: '100%', l: '2px', br: ['tr', 'br'] },
|
{ w: 50, h: '100%', l: '2px', br: ['tr', 'br'] },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} else if (size == 3) {
|
} else if (size === 3) {
|
||||||
if (isPanoramic(ar1) && isPanoramic(ar2) && isPanoramic(ar3)) {
|
if (isPanoramic(ar1) && isPanoramic(ar2) && isPanoramic(ar3)) {
|
||||||
style.height = panoSize * 3;
|
style.height = panoSize * 3;
|
||||||
} else if (isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3)) {
|
} else if (isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3)) {
|
||||||
|
@ -391,7 +399,7 @@ class MediaGallery extends PureComponent {
|
||||||
|
|
||||||
if (isPanoramic(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3)) {
|
if (isPanoramic(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3)) {
|
||||||
itemsDimensions = [
|
itemsDimensions = [
|
||||||
{ w: 100, h: `50%`, b: '2px', br: ['tl', 'tr'] },
|
{ w: 100, h: '50%', b: '2px', br: ['tl', 'tr'] },
|
||||||
{ w: 50, h: '50%', t: '2px', r: '2px', br: ['bl'] },
|
{ w: 50, h: '50%', t: '2px', r: '2px', br: ['bl'] },
|
||||||
{ w: 50, h: '50%', t: '2px', l: '2px', br: ['br'] },
|
{ w: 50, h: '50%', t: '2px', l: '2px', br: ['br'] },
|
||||||
];
|
];
|
||||||
|
@ -403,7 +411,7 @@ class MediaGallery extends PureComponent {
|
||||||
];
|
];
|
||||||
} else if (isPortrait(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3)) {
|
} else if (isPortrait(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3)) {
|
||||||
itemsDimensions = [
|
itemsDimensions = [
|
||||||
{ w: 50, h: `100%`, r: '2px', br: ['tl', 'bl'] },
|
{ w: 50, h: '100%', r: '2px', br: ['tl', 'bl'] },
|
||||||
{ w: 50, h: '50%', b: '2px', l: '2px', br: ['tr'] },
|
{ w: 50, h: '50%', b: '2px', l: '2px', br: ['tr'] },
|
||||||
{ w: 50, h: '50%', t: '2px', l: '2px', br: ['br'] },
|
{ w: 50, h: '50%', t: '2px', l: '2px', br: ['br'] },
|
||||||
];
|
];
|
||||||
|
@ -411,7 +419,7 @@ class MediaGallery extends PureComponent {
|
||||||
itemsDimensions = [
|
itemsDimensions = [
|
||||||
{ w: 50, h: '50%', b: '2px', r: '2px', br: ['tl'] },
|
{ w: 50, h: '50%', b: '2px', r: '2px', br: ['tl'] },
|
||||||
{ w: 50, h: '50%', l: '-2px', b: '-2px', pos: 'absolute', float: 'none', br: ['bl'] },
|
{ w: 50, h: '50%', l: '-2px', b: '-2px', pos: 'absolute', float: 'none', br: ['bl'] },
|
||||||
{ w: 50, h: `100%`, r: '-2px', t: '0px', b: '0px', pos: 'absolute', float: 'none', br: ['tr', 'br'] },
|
{ w: 50, h: '100%', r: '-2px', t: '0px', b: '0px', pos: 'absolute', float: 'none', br: ['tr', 'br'] },
|
||||||
];
|
];
|
||||||
} else if (
|
} else if (
|
||||||
(isNonConformingRatio(ar1) && isPortrait(ar2) && isNonConformingRatio(ar3)) ||
|
(isNonConformingRatio(ar1) && isPortrait(ar2) && isNonConformingRatio(ar3)) ||
|
||||||
|
@ -419,7 +427,7 @@ class MediaGallery extends PureComponent {
|
||||||
) {
|
) {
|
||||||
itemsDimensions = [
|
itemsDimensions = [
|
||||||
{ w: 50, h: '50%', b: '2px', r: '2px', br: ['tl'] },
|
{ w: 50, h: '50%', b: '2px', r: '2px', br: ['tl'] },
|
||||||
{ w: 50, h: `100%`, l: '2px', float: 'right', br: ['tr', 'br'] },
|
{ w: 50, h: '100%', l: '2px', float: 'right', br: ['tr', 'br'] },
|
||||||
{ w: 50, h: '50%', t: '2px', r: '2px', br: ['bl'] },
|
{ w: 50, h: '50%', t: '2px', r: '2px', br: ['bl'] },
|
||||||
];
|
];
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -444,10 +452,10 @@ class MediaGallery extends PureComponent {
|
||||||
itemsDimensions = [
|
itemsDimensions = [
|
||||||
{ w: 50, h: '50%', b: '2px', r: '2px', br: ['tl'] },
|
{ w: 50, h: '50%', b: '2px', r: '2px', br: ['tl'] },
|
||||||
{ w: 50, h: '50%', b: '2px', l: '2px', br: ['tr'] },
|
{ w: 50, h: '50%', b: '2px', l: '2px', br: ['tr'] },
|
||||||
{ w: 100, h: `50%`, t: '2px', br: ['bl', 'br'] },
|
{ w: 100, h: '50%', t: '2px', br: ['bl', 'br'] },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} else if (size == 4) {
|
} else if (size === 4) {
|
||||||
if (
|
if (
|
||||||
(isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3) && isPortrait(ar4)) ||
|
(isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3) && isPortrait(ar4)) ||
|
||||||
(isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3) && isNonConformingRatio(ar4)) ||
|
(isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3) && isNonConformingRatio(ar4)) ||
|
||||||
|
@ -491,7 +499,7 @@ class MediaGallery extends PureComponent {
|
||||||
{ w: 67, h: '100%', r: '2px' },
|
{ w: 67, h: '100%', r: '2px' },
|
||||||
{ w: 33, h: '33%', b: '4px', l: '2px' },
|
{ w: 33, h: '33%', b: '4px', l: '2px' },
|
||||||
{ w: 33, h: '33%', l: '2px' },
|
{ w: 33, h: '33%', l: '2px' },
|
||||||
{ w: 33, h: '33%', t: '4px', l: '2px' }
|
{ w: 33, h: '33%', t: '4px', l: '2px' },
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
itemsDimensions = [
|
itemsDimensions = [
|
||||||
|
@ -512,7 +520,11 @@ class MediaGallery extends PureComponent {
|
||||||
style.height = width / 2
|
style.height = width / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
children = media.take(4).map((attachment, i) => (
|
if (!visible) {
|
||||||
|
style.height = 'auto'
|
||||||
|
}
|
||||||
|
|
||||||
|
const children = media.take(4).map((attachment, i) => (
|
||||||
<Item
|
<Item
|
||||||
key={attachment.get('id')}
|
key={attachment.get('id')}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
|
@ -523,28 +535,16 @@ class MediaGallery extends PureComponent {
|
||||||
visible={visible}
|
visible={visible}
|
||||||
dimensions={itemsDimensions[i]}
|
dimensions={itemsDimensions[i]}
|
||||||
/>
|
/>
|
||||||
));
|
))
|
||||||
|
|
||||||
if (visible) {
|
|
||||||
spoilerButton = <Button title={intl.formatMessage(messages.toggle_visible)} icon='eye-slash' overlay onClick={this.handleOpen} />;
|
|
||||||
} else {
|
|
||||||
spoilerButton = (
|
|
||||||
<button type='button' onClick={this.handleOpen} className='spoiler-button__overlay'>
|
|
||||||
<span className='spoiler-button__overlay__label'>
|
|
||||||
{intl.formatMessage(sensitive ? messages.warning : messages.hidden)}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const containerClasses = cx({
|
const containerClasses = cx({
|
||||||
default: 1,
|
default: 1,
|
||||||
displayBlock: 1,
|
displayBlock: 1,
|
||||||
overflowHidden: 1,
|
overflowHidden: 1,
|
||||||
borderColorSecondary: size === 1,
|
borderColorSecondary: size === 1 && visible,
|
||||||
borderTop1PX: size === 1,
|
borderTop1PX: size === 1 && visible,
|
||||||
borderBottom1PX: size === 1,
|
borderBottom1PX: size === 1 && visible,
|
||||||
px5: size > 1,
|
px5: size > 1 && visible,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -554,14 +554,30 @@ class MediaGallery extends PureComponent {
|
||||||
ref={this.handleRef}
|
ref={this.handleRef}
|
||||||
>
|
>
|
||||||
|
|
||||||
{ /* : todo :
|
{
|
||||||
<div className={classNames('spoiler-button', { 'spoiler-button--minified': visible })}>
|
!visible && sensitive &&
|
||||||
{spoilerButton}
|
<SensitiveMediaItem onClick={this.handleOpen} />
|
||||||
</div> */ }
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
visible &&
|
||||||
<div className={[_s.default, _s.displayBlock, _s.width100PC, _s.height100PC, _s.overflowHidden].join(' ')}>
|
<div className={[_s.default, _s.displayBlock, _s.width100PC, _s.height100PC, _s.overflowHidden].join(' ')}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
visible && sensitive &&
|
||||||
|
<div className={[_s.positionAbsolute, _s.z2, _s.top0, _s.right0, _s.mt10, _s.mr10].join(' ')}>
|
||||||
|
<Button
|
||||||
|
title={intl.formatMessage(messages.toggle_visible)}
|
||||||
|
icon='hidden'
|
||||||
|
backgroundColor='none'
|
||||||
|
className={[_s.px10, _s.backgroundColorBlackOpaque_onHover].join(' ')}
|
||||||
|
onClick={this.handleOpen}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,11 +208,10 @@ class GifResultsCollection extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { results, handleSelectGifResult } = this.props
|
const { results, handleSelectGifResult } = this.props
|
||||||
|
|
||||||
|
// : todo :
|
||||||
const count = results.length
|
const count = results.length
|
||||||
const columnIndex = 10
|
const columnIndex = 10
|
||||||
|
|
||||||
console.log("results:", results)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.height100PC, _s.flexRow, _s.width100PC].join(' ')}>
|
<div className={[_s.default, _s.height100PC, _s.flexRow, _s.width100PC].join(' ')}>
|
||||||
<GifResultsCollectionColumn
|
<GifResultsCollectionColumn
|
||||||
|
|
|
@ -48,8 +48,7 @@ class ModalBase extends PureComponent {
|
||||||
activeElement = this.state.revealed ? document.activeElement : null
|
activeElement = this.state.revealed ? document.activeElement : null
|
||||||
|
|
||||||
handleKeyUp = (e) => {
|
handleKeyUp = (e) => {
|
||||||
if ((e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27)
|
if ((e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27) && !!this.props.children) {
|
||||||
&& !!this.props.children) {
|
|
||||||
this.handleOnClose()
|
this.handleOnClose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,9 +56,9 @@ class ModalBase extends PureComponent {
|
||||||
handleOnClose = (e) => {
|
handleOnClose = (e) => {
|
||||||
const { onOpenModal, composeText, composeId, onClose, intl, type, onCancelReplyCompose } = this.props
|
const { onOpenModal, composeText, composeId, onClose, intl, type, onCancelReplyCompose } = this.props
|
||||||
|
|
||||||
if (this.dialog !== e.target) return
|
if (!!e && this.dialog !== e.target) return
|
||||||
|
|
||||||
if (!composeId && composeText && type == 'COMPOSE') {
|
if (!composeId && composeText && type === 'COMPOSE') {
|
||||||
onOpenModal('CONFIRM', {
|
onOpenModal('CONFIRM', {
|
||||||
message: intl.formatMessage(messages.delete),
|
message: intl.formatMessage(messages.delete),
|
||||||
confirm: intl.formatMessage(messages.confirm),
|
confirm: intl.formatMessage(messages.confirm),
|
||||||
|
|
|
@ -69,8 +69,8 @@ const MODAL_COMPONENTS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
type: state.get('modal').modalType,
|
type: state.getIn(['modal', 'modalType']),
|
||||||
props: state.get('modal').modalProps,
|
props: state.getIn(['modal', 'modalProps'], {}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|
|
@ -61,4 +61,5 @@ class ProUpgradeModal extends ImmutablePureComponent {
|
||||||
</ModalLayout>
|
</ModalLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { Manager, Reference, Popper } from 'react-popper'
|
import { Manager, Reference, Popper } from 'react-popper'
|
||||||
import classnames from 'classnames/bind'
|
import classnames from 'classnames/bind'
|
||||||
import Overlay from 'react-overlays/lib/Overlay'
|
|
||||||
import spring from 'react-motion/lib/spring'
|
import spring from 'react-motion/lib/spring'
|
||||||
import Motion from '../../features/ui/util/optional_motion'
|
import Motion from '../../features/ui/util/optional_motion'
|
||||||
import { openPopover, closePopover } from '../../actions/popover'
|
import { openPopover, closePopover } from '../../actions/popover'
|
||||||
|
@ -14,7 +13,7 @@ const cx = classnames.bind(_s)
|
||||||
let id = 0
|
let id = 0
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
isModalOpen: state.get('modal').modalType === 'ACTIONS',
|
isModalOpen: state.getIn(['modal', 'modalType']) === 'ACTIONS',
|
||||||
popoverPlacement: state.getIn(['popover', 'placement']),
|
popoverPlacement: state.getIn(['popover', 'placement']),
|
||||||
openPopoverType: state.getIn(['popover', 'popoverType']),
|
openPopoverType: state.getIn(['popover', 'popoverType']),
|
||||||
})
|
})
|
||||||
|
@ -123,7 +122,7 @@ class PopoverBase extends ImmutablePureComponent {
|
||||||
displayNone: !visible,
|
displayNone: !visible,
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log("targetRef:", targetRef)
|
console.log('targetRef:', targetRef)
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -32,8 +32,8 @@ const POPOVER_COMPONENTS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
type: state.get('popover').popoverType,
|
type: state.getIn(['popover', 'popoverType']),
|
||||||
props: state.get('popover').popoverProps,
|
props: state.getIn(['popover', 'popoverProps'], {}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
@ -45,6 +45,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps, mapDispatchToProps)
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
class PopoverRoot extends PureComponent {
|
class PopoverRoot extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
props: PropTypes.object,
|
props: PropTypes.object,
|
||||||
|
@ -172,4 +173,5 @@ class PopoverRoot extends PureComponent {
|
||||||
</PopoverBase>
|
</PopoverBase>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -42,7 +42,7 @@ const mapStateToProps = state => {
|
||||||
const mapDispatchToProps = (dispatch, { intl }) => ({
|
const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
|
|
||||||
openProfileOptionsPopover(props) {
|
openProfileOptionsPopover(props) {
|
||||||
console.log("props:", props)
|
console.log('props:', props)
|
||||||
dispatch(openPopover('PROFILE_OPTIONS', props))
|
dispatch(openPopover('PROFILE_OPTIONS', props))
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -112,9 +112,9 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
|
|
||||||
// : todo :
|
// : todo :
|
||||||
makeInfo() {
|
makeInfo() {
|
||||||
const { account, intl } = this.props;
|
const { account, intl } = this.props
|
||||||
|
|
||||||
let info = [];
|
const info = []
|
||||||
|
|
||||||
if (!account || !me) return info;
|
if (!account || !me) return info;
|
||||||
|
|
||||||
|
@ -130,8 +130,8 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
info.push(<span key='domain_blocked' className='relationship-tag'>{intl.formatMessage(messages.domainBlocked)}</span>);
|
info.push(<span key='domain_blocked' className='relationship-tag'>{intl.formatMessage(messages.domainBlocked)}</span>);
|
||||||
}
|
}
|
||||||
|
|
||||||
return info;
|
return info
|
||||||
};
|
}
|
||||||
|
|
||||||
setOpenMoreNodeRef = (n) => {
|
setOpenMoreNodeRef = (n) => {
|
||||||
this.openMoreNode = n
|
this.openMoreNode = n
|
||||||
|
@ -175,11 +175,10 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
let buttonOptions = {}
|
let buttonOptions = {}
|
||||||
|
|
||||||
if (!account) {
|
if (!account) {
|
||||||
console.log("no account")
|
console.log('no account')
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (!account.get('relationship')) {
|
if (!account.get('relationship')) {
|
||||||
console.log("no relationship")
|
console.log('no relationship')
|
||||||
// Wait until the relationship is loaded
|
// Wait until the relationship is loaded
|
||||||
} else if (account.getIn(['relationship', 'requested'])) {
|
} else if (account.getIn(['relationship', 'requested'])) {
|
||||||
buttonText = intl.formatMessage(messages.requested)
|
buttonText = intl.formatMessage(messages.requested)
|
||||||
|
@ -209,7 +208,7 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
backgroundColor: 'tertiary',
|
backgroundColor: 'tertiary',
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("no nothin")
|
console.log('no nothin')
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (account.get('id') !== me && account.get('relationship', null) !== null) {
|
// if (account.get('id') !== me && account.get('relationship', null) !== null) {
|
||||||
|
@ -240,8 +239,8 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("buttonOptions:", buttonText, buttonOptions)
|
console.log('buttonOptions:', buttonText, buttonOptions)
|
||||||
console.log("account: ", account)
|
console.log('account: ', account)
|
||||||
|
|
||||||
|
|
||||||
// : todo : "follows you", "mutual follow"
|
// : todo : "follows you", "mutual follow"
|
||||||
|
@ -253,6 +252,7 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
!headerMissing &&
|
!headerMissing &&
|
||||||
<div className={[_s.default, _s.height350PX, _s.width100PC, _s.radiusSmall, _s.overflowHidden].join(' ')}>
|
<div className={[_s.default, _s.height350PX, _s.width100PC, _s.radiusSmall, _s.overflowHidden].join(' ')}>
|
||||||
<Image
|
<Image
|
||||||
|
alt='Cover Photo'
|
||||||
className={_s.height350PX}
|
className={_s.height350PX}
|
||||||
src={headerSrc}
|
src={headerSrc}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -30,7 +30,7 @@ const makeMapStateToProps = () => {
|
||||||
const ids = [status.get('id')]
|
const ids = [status.get('id')]
|
||||||
|
|
||||||
while (ids.length > 0) {
|
while (ids.length > 0) {
|
||||||
let id = ids.shift();
|
const id = ids.shift();
|
||||||
const replies = state.getIn(['contexts', 'replies', id])
|
const replies = state.getIn(['contexts', 'replies', id])
|
||||||
|
|
||||||
if (status.get('id') !== id) {
|
if (status.get('id') !== id) {
|
||||||
|
|
|
@ -66,52 +66,44 @@ const getUnitDelay = units => {
|
||||||
export const timeAgoString = (intl, date, now, year) => {
|
export const timeAgoString = (intl, date, now, year) => {
|
||||||
const delta = now - date.getTime()
|
const delta = now - date.getTime()
|
||||||
|
|
||||||
let relativeTime
|
|
||||||
|
|
||||||
if (delta < 10 * SECOND) {
|
if (delta < 10 * SECOND) {
|
||||||
relativeTime = intl.formatMessage(messages.just_now)
|
return intl.formatMessage(messages.just_now)
|
||||||
} else if (delta < 7 * DAY) {
|
} else if (delta < 7 * DAY) {
|
||||||
if (delta < MINUTE) {
|
if (delta < MINUTE) {
|
||||||
relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) })
|
return intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) })
|
||||||
} else if (delta < HOUR) {
|
} else if (delta < HOUR) {
|
||||||
relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) })
|
return intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) })
|
||||||
} else if (delta < DAY) {
|
} else if (delta < DAY) {
|
||||||
relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) })
|
return intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) })
|
||||||
} else {
|
} else {
|
||||||
relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) })
|
return intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) })
|
||||||
}
|
}
|
||||||
} else if (date.getFullYear() === year) {
|
} else if (date.getFullYear() === year) {
|
||||||
relativeTime = intl.formatDate(date, shortDateFormatOptions)
|
return intl.formatDate(date, shortDateFormatOptions)
|
||||||
} else {
|
|
||||||
relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return relativeTime
|
return intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' })
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeRemainingString = (intl, date, now) => {
|
const timeRemainingString = (intl, date, now) => {
|
||||||
const delta = date.getTime() - now
|
const delta = date.getTime() - now
|
||||||
|
|
||||||
let relativeTime
|
|
||||||
|
|
||||||
if (delta < 10 * SECOND) {
|
if (delta < 10 * SECOND) {
|
||||||
relativeTime = intl.formatMessage(messages.moments_remaining)
|
return intl.formatMessage(messages.moments_remaining)
|
||||||
} else if (delta < MINUTE) {
|
} else if (delta < MINUTE) {
|
||||||
relativeTime = intl.formatMessage(messages.seconds_remaining, { number: Math.floor(delta / SECOND) })
|
return intl.formatMessage(messages.seconds_remaining, { number: Math.floor(delta / SECOND) })
|
||||||
} else if (delta < HOUR) {
|
} else if (delta < HOUR) {
|
||||||
relativeTime = intl.formatMessage(messages.minutes_remaining, { number: Math.floor(delta / MINUTE) })
|
return intl.formatMessage(messages.minutes_remaining, { number: Math.floor(delta / MINUTE) })
|
||||||
} else if (delta < DAY) {
|
} else if (delta < DAY) {
|
||||||
relativeTime = intl.formatMessage(messages.hours_remaining, { number: Math.floor(delta / HOUR) })
|
return intl.formatMessage(messages.hours_remaining, { number: Math.floor(delta / HOUR) })
|
||||||
} else {
|
|
||||||
relativeTime = intl.formatMessage(messages.days_remaining, { number: Math.floor(delta / DAY) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return relativeTime
|
return intl.formatMessage(messages.days_remaining, { number: Math.floor(delta / DAY) })
|
||||||
}
|
}
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class RelativeTimestamp extends Component {
|
class RelativeTimestamp extends React.Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { throttle } from 'lodash'
|
import throttle from 'lodash.throttle'
|
||||||
import { List as ImmutableList } from 'immutable'
|
import { List as ImmutableList } from 'immutable'
|
||||||
import IntersectionObserverArticle from './intersection_observer_article'
|
import IntersectionObserverArticle from './intersection_observer_article'
|
||||||
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'
|
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'
|
||||||
|
@ -199,7 +199,15 @@ export default class ScrollableList extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children, scrollKey, showLoading, isLoading, hasMore, emptyMessage, onLoadMore } = this.props;
|
const {
|
||||||
|
children,
|
||||||
|
scrollKey,
|
||||||
|
showLoading,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
emptyMessage,
|
||||||
|
onLoadMore,
|
||||||
|
} = this.props
|
||||||
const childrenCount = React.Children.count(children);
|
const childrenCount = React.Children.count(children);
|
||||||
|
|
||||||
const trackScroll = true; //placeholder
|
const trackScroll = true; //placeholder
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import Button from './button'
|
||||||
|
import Text from './text'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
warning: { id: 'status.sensitive_warning_2', defaultMessage: 'The following media includes potentially sensitive content.' },
|
||||||
|
view: { id: 'view', defaultMessage: 'View' },
|
||||||
|
});
|
||||||
|
|
||||||
|
export default
|
||||||
|
@injectIntl
|
||||||
|
class SensitiveMediaItem extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
intl,
|
||||||
|
onClick,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.px15, _s.pt5].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.radiusSmall, _s.backgroundColorSecondary3, _s.py10, _s.px15, _s.height100PC, _s.width100PC].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.justifyContentCenter, _s.flexNormal].join(' ')}>
|
||||||
|
<Text color='secondary'>
|
||||||
|
{intl.formatMessage(messages.warning)}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<div className={[_s.default, _s.justifyContentCenter, _s.marginLeftAuto].join(' ')}>
|
||||||
|
<Button
|
||||||
|
onClick={onClick}
|
||||||
|
color='tertiary'
|
||||||
|
backgroundColor='none'
|
||||||
|
className={_s.backgroundSubtle2Dark_onHover}
|
||||||
|
>
|
||||||
|
<Text color='inherit' weight='bold' size='medium'>
|
||||||
|
{intl.formatMessage(messages.view)}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ const messages = defineMessages({
|
||||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
||||||
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
||||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||||
lists: { id: 'column.lists', defaultMessage: 'Lists', },
|
lists: { id: 'column.lists', defaultMessage: 'Lists' },
|
||||||
apps: { id: 'tabs_bar.apps', defaultMessage: 'Apps' },
|
apps: { id: 'tabs_bar.apps', defaultMessage: 'Apps' },
|
||||||
more: { id: 'sidebar.more', defaultMessage: 'More' },
|
more: { id: 'sidebar.more', defaultMessage: 'More' },
|
||||||
pro: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
|
pro: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
|
||||||
|
@ -37,7 +37,7 @@ const mapStateToProps = state => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account: getAccount(state, me),
|
account: getAccount(state, me),
|
||||||
moreOpen: state.get('popover').popoverType === 'SIDEBAR_MORE',
|
moreOpen: state.getIn(['popover', 'popoverType']) === 'SIDEBAR_MORE',
|
||||||
notificationCount: state.getIn(['notifications', 'unread']),
|
notificationCount: state.getIn(['notifications', 'unread']),
|
||||||
homeItemsQueueCount: state.getIn(['timelines', 'home', 'totalQueuedItemsCount']),
|
homeItemsQueueCount: state.getIn(['timelines', 'home', 'totalQueuedItemsCount']),
|
||||||
showCommunityTimeline: state.getIn(['settings', 'community', 'shows', 'inSidebar']),
|
showCommunityTimeline: state.getIn(['settings', 'community', 'shows', 'inSidebar']),
|
||||||
|
@ -95,7 +95,7 @@ class Sidebar extends ImmutablePureComponent {
|
||||||
notificationCount,
|
notificationCount,
|
||||||
homeItemsQueueCount,
|
homeItemsQueueCount,
|
||||||
showCommunityTimeline,
|
showCommunityTimeline,
|
||||||
moreOpen
|
moreOpen,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
// : todo :
|
// : todo :
|
||||||
|
@ -104,7 +104,7 @@ class Sidebar extends ImmutablePureComponent {
|
||||||
const acct = account.get('acct')
|
const acct = account.get('acct')
|
||||||
const isPro = account.get('is_pro')
|
const isPro = account.get('is_pro')
|
||||||
|
|
||||||
console.log("showCommunityTimeline:", showCommunityTimeline)
|
console.log('showCommunityTimeline:', showCommunityTimeline)
|
||||||
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import Button from './button'
|
import Button from './button'
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
|
import Image from './image'
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
export default class SidebarSectionItem extends PureComponent {
|
export default class SidebarSectionItem extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
router: PropTypes.object,
|
||||||
}
|
}
|
||||||
|
@ -45,7 +47,7 @@ export default class SidebarSectionItem extends PureComponent {
|
||||||
count,
|
count,
|
||||||
onClick,
|
onClick,
|
||||||
href,
|
href,
|
||||||
buttonRef
|
buttonRef,
|
||||||
} = this.props
|
} = this.props
|
||||||
const { hovering } = this.state
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
@ -65,6 +67,7 @@ export default class SidebarSectionItem extends PureComponent {
|
||||||
radiusSmall: 1,
|
radiusSmall: 1,
|
||||||
mt2: 1,
|
mt2: 1,
|
||||||
border1PX: 1,
|
border1PX: 1,
|
||||||
|
outlineNone: 1,
|
||||||
borderColorTransparent: !shouldShowActive,
|
borderColorTransparent: !shouldShowActive,
|
||||||
borderColorSecondary: shouldShowActive,
|
borderColorSecondary: shouldShowActive,
|
||||||
backgroundTransparent: !shouldShowActive,
|
backgroundTransparent: !shouldShowActive,
|
||||||
|
@ -77,7 +80,6 @@ export default class SidebarSectionItem extends PureComponent {
|
||||||
fontSize15PX: 1,
|
fontSize15PX: 1,
|
||||||
text: 1,
|
text: 1,
|
||||||
textOverflowEllipsis: 1,
|
textOverflowEllipsis: 1,
|
||||||
outlineNone: 1,
|
|
||||||
colorSecondary: !hovering && !active && !me && !shouldShowActive,
|
colorSecondary: !hovering && !active && !me && !shouldShowActive,
|
||||||
colorPrimary: shouldShowActive || me,
|
colorPrimary: shouldShowActive || me,
|
||||||
})
|
})
|
||||||
|
@ -111,14 +113,15 @@ export default class SidebarSectionItem extends PureComponent {
|
||||||
buttonRef={buttonRef}
|
buttonRef={buttonRef}
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
className={[_s.default, _s.noUnderline, _s.cursorPointer, _s.width100PC, _s.backgroundTransparent].join(' ')}
|
className={[_s.default, _s.noUnderline, _s.outlineNone, _s.cursorPointer, _s.width100PC, _s.backgroundTransparent].join(' ')}
|
||||||
>
|
>
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses}>
|
||||||
<div className={[_s.default]}>
|
<div className={[_s.default]}>
|
||||||
{ icon && <Icon id={icon} className={iconClasses} width={iconSize} height={iconSize} /> }
|
{ icon && <Icon id={icon} className={iconClasses} width={iconSize} height={iconSize} /> }
|
||||||
{ image &&
|
{ image &&
|
||||||
<img
|
<Image
|
||||||
className={[_s.default, _s.circle].join(' ')}
|
alt={title}
|
||||||
|
className={_s.circle}
|
||||||
width={iconSize}
|
width={iconSize}
|
||||||
height={iconSize}
|
height={iconSize}
|
||||||
src={image}
|
src={image}
|
||||||
|
@ -137,4 +140,5 @@ export default class SidebarSectionItem extends PureComponent {
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,7 +272,7 @@ class Status extends ImmutablePureComponent {
|
||||||
group,
|
group,
|
||||||
promoted,
|
promoted,
|
||||||
borderless,
|
borderless,
|
||||||
isChild
|
isChild,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
let media = null
|
let media = null
|
||||||
|
@ -287,7 +287,7 @@ class Status extends ImmutablePureComponent {
|
||||||
// status = status.get('reblog');
|
// status = status.get('reblog');
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let { status, ...other } = this.props;
|
const { status, ...other } = this.props;
|
||||||
|
|
||||||
// console.log("replies:", this.props.replies)
|
// console.log("replies:", this.props.replies)
|
||||||
|
|
||||||
|
|
|
@ -169,11 +169,12 @@ export default class Card extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// : todo : use <Image />
|
||||||
let embed = ''
|
let embed = ''
|
||||||
let thumbnail = interactive ?
|
const thumbnail = interactive ?
|
||||||
<img src={cardImg} className={[_s.default, _s.objectFitCover, _s.positionAbsolute, _s.width100PC, _s.height100PC, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')} />
|
<img alt={''} src={cardImg} className={[_s.default, _s.objectFitCover, _s.positionAbsolute, _s.width100PC, _s.height100PC, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')} />
|
||||||
:
|
:
|
||||||
<img src={cardImg} className={[_s.default, _s.objectFitCover, _s.width330PX, _s.height220PX].join(' ')} />
|
<img alt={''} src={cardImg} className={[_s.default, _s.objectFitCover, _s.width330PX, _s.height220PX].join(' ')} />
|
||||||
|
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
if (embedded) {
|
if (embedded) {
|
||||||
|
@ -199,7 +200,7 @@ export default class Card extends ImmutablePureComponent {
|
||||||
className={[_s.default, _s.cursorPointer, _s.backgroundColorOpaque, _s.radiusSmall, _s.py15, _s.px15].join(' ')}
|
className={[_s.default, _s.cursorPointer, _s.backgroundColorOpaque, _s.radiusSmall, _s.py15, _s.px15].join(' ')}
|
||||||
onClick={this.handleEmbedClick}
|
onClick={this.handleEmbedClick}
|
||||||
>
|
>
|
||||||
<Icon id={iconVariant} className={[_s.fillColorWhite].join(' ')}/>
|
<Icon id={iconVariant} className={[_s.fillColorWhite].join(' ')} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,12 +224,17 @@ class StatusContent extends ImmutablePureComponent {
|
||||||
displayNone: hidden,
|
displayNone: hidden,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const containerClasses = cx({
|
||||||
|
statusContent: 1,
|
||||||
|
px15: !isComment,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={[].join(' ')}
|
className={[].join(' ')}
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
className={[_s.px15, _s.statusContent].join(' ')}
|
className={containerClasses}
|
||||||
style={directionStyle}
|
style={directionStyle}
|
||||||
onMouseDown={this.handleMouseDown}
|
onMouseDown={this.handleMouseDown}
|
||||||
onMouseUp={this.handleMouseUp}
|
onMouseUp={this.handleMouseUp}
|
||||||
|
@ -317,11 +322,18 @@ class StatusContent extends ImmutablePureComponent {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const containerClasses = cx({
|
||||||
|
statusContent: 1,
|
||||||
|
px15: !isComment,
|
||||||
|
mb15: !isComment,
|
||||||
|
mt5: isComment,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
className={[_s.px15, _s.mb15, _s.statusContent].join(' ')}
|
className={containerClasses}
|
||||||
style={directionStyle}
|
style={directionStyle}
|
||||||
dangerouslySetInnerHTML={content}
|
dangerouslySetInnerHTML={content}
|
||||||
lang={status.get('language')}
|
lang={status.get('language')}
|
||||||
|
|
|
@ -10,7 +10,7 @@ export default class TimelineQueueButtonHeader extends PureComponent {
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
count: PropTypes.number,
|
count: PropTypes.number,
|
||||||
itemType: PropTypes.string,
|
itemType: PropTypes.string,
|
||||||
floating: PropTypes.bool
|
floating: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default class TrendingItem extends PureComponent {
|
||||||
author,
|
author,
|
||||||
publishDate,
|
publishDate,
|
||||||
isLast,
|
isLast,
|
||||||
wide
|
wide,
|
||||||
} = this.props
|
} = this.props
|
||||||
const { hovering } = this.state
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
@ -70,13 +70,14 @@ export default class TrendingItem extends PureComponent {
|
||||||
})
|
})
|
||||||
|
|
||||||
const correctedAuthor = author.replace('www.', '')
|
const correctedAuthor = author.replace('www.', '')
|
||||||
const correctedDescription = description.length > 120 ? `${description.substring(0, 120).trim()}...` : description
|
const correctedDescription = description.length >= 120 ? `${description.substring(0, 120).trim()}...` : description
|
||||||
|
|
||||||
const image = (
|
const image = (
|
||||||
<Image
|
<Image
|
||||||
nullable
|
nullable
|
||||||
width='116px'
|
width='116px'
|
||||||
height='78px'
|
height='78px'
|
||||||
|
alt={title}
|
||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
className={[_s.radiusSmall, _s.overflowHidden, _s.mb10].join(' ')}
|
className={[_s.radiusSmall, _s.overflowHidden, _s.mb10].join(' ')}
|
||||||
/>
|
/>
|
||||||
|
@ -87,6 +88,7 @@ export default class TrendingItem extends PureComponent {
|
||||||
noClasses
|
noClasses
|
||||||
href={url}
|
href={url}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
|
rel='noopener noreferrer'
|
||||||
className={containerClasses}
|
className={containerClasses}
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
|
@ -104,7 +106,7 @@ export default class TrendingItem extends PureComponent {
|
||||||
|
|
||||||
{
|
{
|
||||||
!!correctedDescription &&
|
!!correctedDescription &&
|
||||||
<div className={[_s.default, _s.heightMax60PX, _s.overflowHidden, _s.py5].join(' ')}>
|
<div className={[_s.default, _s.heightMax56PX, _s.overflowHidden, _s.pt5, _s.mb5].join(' ')}>
|
||||||
<Text size='small' color='secondary'>
|
<Text size='small' color='secondary'>
|
||||||
{correctedDescription}
|
{correctedDescription}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import { is } from 'immutable'
|
import { is } from 'immutable'
|
||||||
import { throttle } from 'lodash'
|
import throttle from 'lodash.throttle'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import { decode } from 'blurhash'
|
import { decode } from 'blurhash'
|
||||||
import { isFullscreen, requestFullscreen, exitFullscreen } from '../utils/fullscreen'
|
import { isFullscreen, requestFullscreen, exitFullscreen } from '../utils/fullscreen'
|
||||||
|
|
|
@ -28,7 +28,7 @@ import { boostModal, deleteModal } from '../initial_state';
|
||||||
// import { showAlertForError } from '../actions/alerts';
|
// import { showAlertForError } from '../actions/alerts';
|
||||||
import {
|
import {
|
||||||
createRemovedAccount,
|
createRemovedAccount,
|
||||||
groupRemoveStatus
|
groupRemoveStatus,
|
||||||
} from '../actions/groups';
|
} from '../actions/groups';
|
||||||
import { makeGetStatus } from '../selectors';
|
import { makeGetStatus } from '../selectors';
|
||||||
import Status from '../components/status';
|
import Status from '../components/status';
|
||||||
|
@ -58,7 +58,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
|
|
||||||
onReply (status, router) {
|
onReply (status, router) {
|
||||||
dispatch((_, getState) => {
|
dispatch((_, getState) => {
|
||||||
let state = getState();
|
const state = getState();
|
||||||
if (state.getIn(['compose', 'text']).trim().length !== 0) {
|
if (state.getIn(['compose', 'text']).trim().length !== 0) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
message: intl.formatMessage(messages.replyMessage),
|
message: intl.formatMessage(messages.replyMessage),
|
||||||
|
@ -73,7 +73,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
|
|
||||||
onQuote (status, router) {
|
onQuote (status, router) {
|
||||||
dispatch((_, getState) => {
|
dispatch((_, getState) => {
|
||||||
let state = getState();
|
const state = getState();
|
||||||
if (state.getIn(['compose', 'text']).trim().length !== 0) {
|
if (state.getIn(['compose', 'text']).trim().length !== 0) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
message: intl.formatMessage(messages.quoteMessage),
|
message: intl.formatMessage(messages.quoteMessage),
|
||||||
|
@ -107,12 +107,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
},
|
},
|
||||||
|
|
||||||
onFavorite (status) {
|
onFavorite (status) {
|
||||||
console.log("onFavorite...", status)
|
console.log('onFavorite...', status)
|
||||||
if (status.get('favourited')) {
|
if (status.get('favourited')) {
|
||||||
console.log("unfav...")
|
console.log('unfav...')
|
||||||
dispatch(unfavorite(status));
|
dispatch(unfavorite(status));
|
||||||
} else {
|
} else {
|
||||||
console.log("fav...")
|
console.log('fav...')
|
||||||
dispatch(favorite(status));
|
dispatch(favorite(status));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { debounce, sample } from 'lodash';
|
import { sample } from 'lodash';
|
||||||
|
import debounce from 'lodash.debounce'
|
||||||
import { dequeueTimeline } from '../actions/timelines';
|
import { dequeueTimeline } from '../actions/timelines';
|
||||||
import { scrollTopTimeline } from '../actions/timelines';
|
import { scrollTopTimeline } from '../actions/timelines';
|
||||||
import { fetchStatus } from '../actions/statuses';
|
import { fetchStatus } from '../actions/statuses';
|
||||||
|
|
|
@ -84,7 +84,7 @@ class AccountGallery extends ImmutablePureComponent {
|
||||||
isLoading,
|
isLoading,
|
||||||
hasMore,
|
hasMore,
|
||||||
intl,
|
intl,
|
||||||
account
|
account,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (!account) return null
|
if (!account) return null
|
||||||
|
@ -109,7 +109,7 @@ class AccountGallery extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
{ /*
|
{ /*
|
||||||
attachments.size == 0 &&
|
attachments.size === 0 &&
|
||||||
<ColumnIndicator type='empty' message={intl.formatMessage(messages.none)} />
|
<ColumnIndicator type='empty' message={intl.formatMessage(messages.none)} />
|
||||||
*/ }
|
*/ }
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { debounce } from 'lodash'
|
import debounce from 'lodash.debounce'
|
||||||
import { fetchBlocks, expandBlocks } from '../actions/blocks'
|
import { fetchBlocks, expandBlocks } from '../actions/blocks'
|
||||||
import AccountContainer from '../containers/account_container'
|
import AccountContainer from '../containers/account_container'
|
||||||
import ColumnIndicator from '../components/column_indicator'
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { debounce } from 'lodash'
|
import debounce from 'lodash.debounce'
|
||||||
import { unblockDomain, fetchDomainBlocks, expandDomainBlocks } from '../actions/domain_blocks'
|
import { unblockDomain, fetchDomainBlocks, expandDomainBlocks } from '../actions/domain_blocks'
|
||||||
import ColumnIndicator from '../components/column_indicator'
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
import List from '../components/list'
|
import List from '../components/list'
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { length } from 'stringz'
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
|
import { length } from 'stringz'
|
||||||
import CharacterCounter from '../../../../components/character_counter'
|
import CharacterCounter from '../../../../components/character_counter'
|
||||||
import UploadForm from '../upload_form'
|
import UploadForm from '../upload_form'
|
||||||
import AutosuggestTextbox from '../../../../components/autosuggest_textbox'
|
import AutosuggestTextbox from '../../../../components/autosuggest_textbox'
|
||||||
|
@ -15,7 +15,7 @@ import StatusVisibilityButton from '../../components/status_visibility_button'
|
||||||
import EmojiPickerButton from '../../components/emoji_picker_button'
|
import EmojiPickerButton from '../../components/emoji_picker_button'
|
||||||
import PollFormContainer from '../../containers/poll_form_container'
|
import PollFormContainer from '../../containers/poll_form_container'
|
||||||
import SchedulePostButton from '../schedule_post_button'
|
import SchedulePostButton from '../schedule_post_button'
|
||||||
import QuotedStatusPreviewContainer from '../../containers/quoted_status_preview_container'
|
import StatusContainer from '../../../../containers/status_container'
|
||||||
import Button from '../../../../components/button'
|
import Button from '../../../../components/button'
|
||||||
import Avatar from '../../../../components/avatar'
|
import Avatar from '../../../../components/avatar'
|
||||||
import { isMobile } from '../../../../utils/is_mobile'
|
import { isMobile } from '../../../../utils/is_mobile'
|
||||||
|
@ -29,7 +29,7 @@ const messages = defineMessages({
|
||||||
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' },
|
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' },
|
||||||
publish: { id: 'compose_form.publish', defaultMessage: 'Gab' },
|
publish: { id: 'compose_form.publish', defaultMessage: 'Gab' },
|
||||||
publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}' },
|
publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}' },
|
||||||
schedulePost: { id: 'compose_form.schedule_post', defaultMessage: 'Schedule Post' }
|
schedulePost: { id: 'compose_form.schedule_post', defaultMessage: 'Schedule Post' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
@ -79,6 +79,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
scheduledAt: PropTypes.instanceOf(Date),
|
scheduledAt: PropTypes.instanceOf(Date),
|
||||||
setScheduledAt: PropTypes.func.isRequired,
|
setScheduledAt: PropTypes.func.isRequired,
|
||||||
replyToId: PropTypes.string,
|
replyToId: PropTypes.string,
|
||||||
|
hasPoll: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -104,7 +105,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
handleClick = (e) => {
|
handleClick = (e) => {
|
||||||
if (!this.form) return false;
|
if (!this.form) return false;
|
||||||
if (e.target) {
|
if (e.target) {
|
||||||
if (e.target.classList.contains('react-datepicker__time-list-item')) return;
|
if (e.target.classList.contains('react-datepicker__time-list-item')) return false
|
||||||
}
|
}
|
||||||
if (!this.form.contains(e.target)) {
|
if (!this.form.contains(e.target)) {
|
||||||
this.handleClickOutside();
|
this.handleClickOutside();
|
||||||
|
@ -162,11 +163,11 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
document.addEventListener("click", this.handleClick, false);
|
document.addEventListener('click', this.handleClick, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
document.removeEventListener("click", this.handleClick, false);
|
document.removeEventListener('click', this.handleClick, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
@ -201,19 +202,19 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
setForm = (c) => {
|
setForm = (c) => {
|
||||||
this.form = c;
|
this.form = c
|
||||||
}
|
}
|
||||||
|
|
||||||
setSpoilerText = (c) => {
|
setSpoilerText = (c) => {
|
||||||
this.spoilerText = c;
|
this.spoilerText = c
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEmojiPick = (data) => {
|
handleEmojiPick = (data) => {
|
||||||
const { text } = this.props;
|
const { text } = this.props
|
||||||
const position = this.autosuggestTextarea.textbox.selectionStart;
|
const position = this.autosuggestTextarea.textbox.selectionStart
|
||||||
const needsSpace = data.custom && position > 0 && !allowedAroundShortCode.includes(text[position - 1]);
|
const needsSpace = data.custom && position > 0 && !allowedAroundShortCode.includes(text[position - 1])
|
||||||
|
|
||||||
this.props.onPickEmoji(position, data, needsSpace);
|
this.props.onPickEmoji(position, data, needsSpace)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -230,11 +231,13 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
edit,
|
edit,
|
||||||
scheduledAt,
|
scheduledAt,
|
||||||
spoiler,
|
spoiler,
|
||||||
replyToId
|
replyToId,
|
||||||
|
hasPoll,
|
||||||
|
isUploading,
|
||||||
} = this.props
|
} = this.props
|
||||||
const disabled = this.props.isSubmitting;
|
const disabled = this.props.isSubmitting;
|
||||||
const text = [this.props.spoilerText, countableText(this.props.text)].join('');
|
const text = [this.props.spoilerText, countableText(this.props.text)].join('');
|
||||||
const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxPostCharacterCount || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
|
const disabledButton = disabled || isUploading || this.props.isChangingUpload || length(text) > maxPostCharacterCount || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
|
||||||
const shouldAutoFocus = autoFocus && !showSearch && !isMobile(window.innerWidth)
|
const shouldAutoFocus = autoFocus && !showSearch && !isMobile(window.innerWidth)
|
||||||
|
|
||||||
const parentContainerClasses = cx({
|
const parentContainerClasses = cx({
|
||||||
|
@ -255,7 +258,8 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
const actionsContainerClasses = cx({
|
const actionsContainerClasses = cx({
|
||||||
default: 1,
|
default: 1,
|
||||||
flexRow: 1,
|
flexRow: 1,
|
||||||
alignItemsCenter: 1,
|
alignItemsCenter: !shouldCondense,
|
||||||
|
alignItemsStart: shouldCondense,
|
||||||
mt10: !shouldCondense,
|
mt10: !shouldCondense,
|
||||||
px15: !shouldCondense,
|
px15: !shouldCondense,
|
||||||
})
|
})
|
||||||
|
@ -313,19 +317,25 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
autoFocus={shouldAutoFocus}
|
autoFocus={shouldAutoFocus}
|
||||||
small={shouldCondense}
|
small={shouldCondense}
|
||||||
textarea
|
textarea
|
||||||
>
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
(isUploading || anyMedia) &&
|
||||||
<div className={[_s.default, _s.px15].join(' ')}>
|
<div className={[_s.default, _s.px15].join(' ')}>
|
||||||
<UploadForm replyToId={replyToId} />
|
<UploadForm replyToId={replyToId} />
|
||||||
{
|
|
||||||
!edit &&
|
|
||||||
<PollFormContainer replyToId={replyToId} />
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
</AutosuggestTextbox>
|
{
|
||||||
|
!edit && hasPoll &&
|
||||||
|
<div className={[_s.default, _s.px15].join(' ')}>
|
||||||
|
<PollFormContainer replyToId={replyToId} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
{ /* quoteOfId && <QuotedStatusPreviewContainer id={quoteOfId} /> */}
|
{
|
||||||
|
/* : todo : quoteOfId && <StatusContainer id={quoteOfId} /> */
|
||||||
|
}
|
||||||
|
|
||||||
<div className={actionsContainerClasses}>
|
<div className={actionsContainerClasses}>
|
||||||
<div className={[_s.default, _s.flexRow, _s.marginRightAuto].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.marginRightAuto].join(' ')}>
|
||||||
|
@ -359,7 +369,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
<CharacterCounter max={maxPostCharacterCount} text={text} />
|
<CharacterCounter max={maxPostCharacterCount} text={text} />
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{ /* : todo : show send on shouldCondense if any text */
|
||||||
!shouldCondense &&
|
!shouldCondense &&
|
||||||
<Button
|
<Button
|
||||||
className={[_s.fontSize15PX, _s.px15].join(' ')}
|
className={[_s.fontSize15PX, _s.px15].join(' ')}
|
||||||
|
|
|
@ -7,7 +7,7 @@ const messages = defineMessages({
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
active: state.get('popover').popoverType === 'EMOJI_PICKER',
|
active: state.getIn(['popover', 'popoverType']) === 'EMOJI_PICKER',
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
|
|
@ -9,7 +9,7 @@ const messages = defineMessages({
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state) => ({
|
||||||
active: !!state.getIn(['compose', 'gif']) || state.get('modal').modalType === 'GIF_PICKER',
|
active: !!state.getIn(['compose', 'gif']) || state.getIn(['modal', 'modalType']) === 'GIF_PICKER',
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import DisplayName from '../../../components/display_name';
|
|
||||||
import StatusContent from '../../../components/status_content';
|
|
||||||
|
|
||||||
// : todo : do we need this? make work inside of status/status content
|
|
||||||
|
|
||||||
export default class QuotedStatusPreview extends PureComponent {
|
|
||||||
static propTypes = {
|
|
||||||
status: ImmutablePropTypes.map,
|
|
||||||
account: ImmutablePropTypes.map,
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { status, account } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='compose-form__quote-preview'>
|
|
||||||
<DisplayName account={account} />
|
|
||||||
<StatusContent status={status} expanded={false} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -28,6 +28,11 @@ class StatusVisibilityButton extends PureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
small: PropTypes.bool,
|
small: PropTypes.bool,
|
||||||
onOpenPopover: PropTypes.func.isRequired,
|
onOpenPopover: PropTypes.func.isRequired,
|
||||||
|
value: PropTypes.oneOf([
|
||||||
|
'private',
|
||||||
|
'unlisted',
|
||||||
|
'public',
|
||||||
|
]),
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOnClick = () => {
|
handleOnClick = () => {
|
||||||
|
@ -42,7 +47,7 @@ class StatusVisibilityButton extends PureComponent {
|
||||||
const {
|
const {
|
||||||
intl,
|
intl,
|
||||||
small,
|
small,
|
||||||
value
|
value,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
let icon;
|
let icon;
|
||||||
|
|
|
@ -24,7 +24,7 @@ class UploadForm extends ImmutablePureComponent {
|
||||||
const {
|
const {
|
||||||
mediaIds,
|
mediaIds,
|
||||||
isUploading,
|
isUploading,
|
||||||
uploadProgress
|
uploadProgress,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -71,7 +71,7 @@ class Compose extends ImmutablePureComponent {
|
||||||
render () {
|
render () {
|
||||||
const { showSearch, isSearchPage, intl } = this.props;
|
const { showSearch, isSearchPage, intl } = this.props;
|
||||||
|
|
||||||
let header = '';
|
const header = '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='drawer' role='region' aria-label={intl.formatMessage(messages.compose)}>
|
<div className='drawer' role='region' aria-label={intl.formatMessage(messages.compose)}>
|
||||||
|
|
|
@ -35,10 +35,11 @@ const mapStateToProps = (state, { replyToId }) => {
|
||||||
isUploading: !isMatch ? false : state.getIn(['compose', 'is_uploading']),
|
isUploading: !isMatch ? false : state.getIn(['compose', 'is_uploading']),
|
||||||
showSearch: !isMatch ? false : state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
|
showSearch: !isMatch ? false : state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
|
||||||
anyMedia: !isMatch ? false : state.getIn(['compose', 'media_attachments']).size > 0,
|
anyMedia: !isMatch ? false : state.getIn(['compose', 'media_attachments']).size > 0,
|
||||||
isModalOpen: !isMatch ? false : state.get('modal').modalType === 'COMPOSE',
|
isModalOpen: !isMatch ? false : state.getIn(['modal', 'modalType']) === 'COMPOSE',
|
||||||
quoteOfId: !isMatch ? null : state.getIn(['compose', 'quote_of_id']),
|
quoteOfId: !isMatch ? null : state.getIn(['compose', 'quote_of_id']),
|
||||||
scheduledAt: !isMatch ? null : state.getIn(['compose', 'scheduled_at']),
|
scheduledAt: !isMatch ? null : state.getIn(['compose', 'scheduled_at']),
|
||||||
account: state.getIn(['accounts', me]),
|
account: state.getIn(['accounts', me]),
|
||||||
|
hasPoll: !isMatch ? false : state.getIn(['compose', 'poll']),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +85,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
function mergeProps(stateProps, dispatchProps, ownProps) {
|
function mergeProps(stateProps, dispatchProps, ownProps) {
|
||||||
return Object.assign({}, ownProps, {
|
return Object.assign({}, ownProps, {
|
||||||
...stateProps,
|
...stateProps,
|
||||||
...dispatchProps
|
...dispatchProps,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import QuotedStatusPreview from '../components/quoted_status_preview';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { id }) => ({
|
|
||||||
status: state.getIn(['statuses', id]),
|
|
||||||
account: state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(QuotedStatusPreview);
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { urlRegex } from './url_regex';
|
import { urlRegex } from './url_regex'
|
||||||
|
|
||||||
const urlPlaceholder = 'xxxxxxxxxxxxxxxxxxxxxxx';
|
const urlPlaceholder = 'xxxxxxxxxxxxxxxxxxxxxxx'
|
||||||
|
|
||||||
export function countableText(inputText) {
|
export function countableText(inputText) {
|
||||||
return inputText
|
return inputText
|
||||||
.replace(urlRegex, urlPlaceholder)
|
.replace(urlRegex, urlPlaceholder)
|
||||||
.replace(/(^|[^\/\w])@(([a-z0-9_]+)@[a-z0-9\.\-]+[a-z0-9]+)/ig, '$1@$3');
|
.replace(/(^|[^\/\w])@(([a-z0-9_]+)@[a-z0-9\.\-]+[a-z0-9]+)/ig, '$1@$3');
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash.debounce'
|
||||||
import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
|
import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
import ColumnIndicator from '../../components/column_indicator';
|
||||||
import AccountAuthorize from './components/account_authorize';
|
import AccountAuthorize from './components/account_authorize';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { debounce } from 'lodash'
|
import debounce from 'lodash.debounce'
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import {
|
import {
|
||||||
fetchFollowers,
|
fetchFollowers,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { debounce } from 'lodash'
|
import debounce from 'lodash.debounce'
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import {
|
import {
|
||||||
fetchFollowing,
|
fetchFollowing,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash.debounce'
|
||||||
import {
|
import {
|
||||||
fetchMembers,
|
fetchMembers,
|
||||||
expandMembers,
|
expandMembers,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash.debounce'
|
||||||
import ColumnIndicator from '../components/column_indicator';
|
import ColumnIndicator from '../components/column_indicator';
|
||||||
import {
|
import {
|
||||||
fetchRemovedAccounts,
|
fetchRemovedAccounts,
|
||||||
|
|
|
@ -12,6 +12,7 @@ const mapStateToProps = (state, { activeTab }) => ({
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
class GroupsCollection extends ImmutablePureComponent {
|
class GroupsCollection extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
activeTab: PropTypes.string.isRequired,
|
activeTab: PropTypes.string.isRequired,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
@ -35,14 +36,32 @@ class GroupsCollection extends ImmutablePureComponent {
|
||||||
return <ColumnIndicator type='loading' />
|
return <ColumnIndicator type='loading' />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const halfCount = parseInt(groupIds.size / 2)
|
||||||
|
|
||||||
|
console.log("halfCount", halfCount)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.flexRow, _s.flexWrap].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.flexWrap].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.flexNormal].join(' ')}>
|
||||||
|
<ScrollableList scrollKey='group-collection-column-1'>
|
||||||
{
|
{
|
||||||
groupIds.map((groupId, i) => (
|
groupIds.slice(0, halfCount).map((groupId, i) => (
|
||||||
<GroupCollectionItem key={`group-collection-item-${i}`} id={groupId} />
|
<GroupCollectionItem key={`group-collection-item-${i}`} id={groupId} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
</ScrollableList>
|
||||||
|
</div>
|
||||||
|
<div className={[_s.default, _s.flexNormal].join(' ')}>
|
||||||
|
<ScrollableList scrollKey='group-collection-column-2'>
|
||||||
|
{
|
||||||
|
groupIds.slice(halfCount, groupIds.size).map((groupId, i) => (
|
||||||
|
<GroupCollectionItem key={`group-collection-item-${i}`} id={groupId} />
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ScrollableList>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import { FormattedMessage } from 'react-intl'
|
import { FormattedMessage } from 'react-intl'
|
||||||
import { isEqual } from 'lodash'
|
import isEqual from 'lodash.isequal'
|
||||||
import { expandHashtagTimeline, clearTimeline } from '../actions/timelines'
|
import { expandHashtagTimeline, clearTimeline } from '../actions/timelines'
|
||||||
import { connectHashtagStream } from '../actions/streaming'
|
import { connectHashtagStream } from '../actions/streaming'
|
||||||
import StatusListContainer from '../containers/status_list_container'
|
import StatusListContainer from '../containers/status_list_container'
|
||||||
|
@ -21,7 +21,7 @@ class HashtagTimeline extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
title = () => {
|
title = () => {
|
||||||
let title = [this.props.params.id]
|
const title = [this.props.params.id]
|
||||||
|
|
||||||
if (this.additionalFor('any')) {
|
if (this.additionalFor('any')) {
|
||||||
title.push(' ',
|
title.push(' ',
|
||||||
|
@ -29,7 +29,7 @@ class HashtagTimeline extends PureComponent {
|
||||||
key='any'
|
key='any'
|
||||||
id='hashtag.column_header.tag_mode.any'
|
id='hashtag.column_header.tag_mode.any'
|
||||||
values={{
|
values={{
|
||||||
additional: this.additionalFor('any')
|
additional: this.additionalFor('any'),
|
||||||
}}
|
}}
|
||||||
defaultMessage='or {additional}'
|
defaultMessage='or {additional}'
|
||||||
/>
|
/>
|
||||||
|
@ -42,7 +42,7 @@ class HashtagTimeline extends PureComponent {
|
||||||
key='all'
|
key='all'
|
||||||
id='hashtag.column_header.tag_mode.all'
|
id='hashtag.column_header.tag_mode.all'
|
||||||
values={{
|
values={{
|
||||||
additional: this.additionalFor('all')
|
additional: this.additionalFor('all'),
|
||||||
}}
|
}}
|
||||||
defaultMessage='and {additional}'
|
defaultMessage='and {additional}'
|
||||||
/>
|
/>
|
||||||
|
@ -55,7 +55,7 @@ class HashtagTimeline extends PureComponent {
|
||||||
key='none'
|
key='none'
|
||||||
id='hashtag.column_header.tag_mode.none'
|
id='hashtag.column_header.tag_mode.none'
|
||||||
values={{
|
values={{
|
||||||
additional: this.additionalFor('none')
|
additional: this.additionalFor('none'),
|
||||||
}}
|
}}
|
||||||
defaultMessage='without {additional}'
|
defaultMessage='without {additional}'
|
||||||
/>
|
/>
|
||||||
|
@ -76,13 +76,13 @@ class HashtagTimeline extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
_subscribe (dispatch, id, tags = {}) {
|
_subscribe (dispatch, id, tags = {}) {
|
||||||
let any = (tags.any || []).map(tag => tag.value)
|
const any = (tags.any || []).map(tag => tag.value)
|
||||||
let all = (tags.all || []).map(tag => tag.value)
|
const all = (tags.all || []).map(tag => tag.value)
|
||||||
let none = (tags.none || []).map(tag => tag.value);
|
const none = (tags.none || []).map(tag => tag.value);
|
||||||
|
|
||||||
[id, ...any].map(tag => {
|
[id, ...any].map(tag => {
|
||||||
this.disconnects.push(dispatch(connectHashtagStream(id, tag, status => {
|
this.disconnects.push(dispatch(connectHashtagStream(id, tag, status => {
|
||||||
let tags = status.tags.map(tag => tag.name)
|
const tags = status.tags.map(tag => tag.name)
|
||||||
|
|
||||||
return all.filter(tag => tags.includes(tag)).length === all.length &&
|
return all.filter(tag => tags.includes(tag)).length === all.length &&
|
||||||
none.filter(tag => tags.includes(tag)).length === 0
|
none.filter(tag => tags.includes(tag)).length === 0
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { closeOnboarding } from '../actions/onboarding';
|
||||||
|
|
||||||
// : todo :
|
// : todo :
|
||||||
|
|
||||||
class FrameWelcome extends Component {
|
class FrameWelcome extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
domain: PropTypes.string.isRequired,
|
domain: PropTypes.string.isRequired,
|
||||||
onNext: PropTypes.func.isRequired,
|
onNext: PropTypes.func.isRequired,
|
||||||
|
@ -45,7 +45,7 @@ class FrameWelcome extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FrameFederation extends Component {
|
class FrameFederation extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onNext: PropTypes.func.isRequired,
|
onNext: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ class FrameFederation extends Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FrameInteractions extends Component {
|
class FrameInteractions extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onNext: PropTypes.func.isRequired,
|
onNext: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { FormattedMessage } from 'react-intl'
|
import { FormattedMessage } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { debounce } from 'lodash'
|
import debounce from 'lodash.debounce'
|
||||||
import { fetchFavoritedStatuses, expandFavoritedStatuses } from '../actions/favorites'
|
import { fetchFavoritedStatuses, expandFavoritedStatuses } from '../actions/favorites'
|
||||||
import { meUsername } from '../initial_state'
|
import { meUsername } from '../initial_state'
|
||||||
import StatusList from '../components/status_list'
|
import StatusList from '../components/status_list'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { injectIntl, FormattedMessage } from 'react-intl'
|
import { injectIntl, FormattedMessage } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { debounce } from 'lodash'
|
import debounce from 'lodash.debounce'
|
||||||
import { fetchMutes, expandMutes } from '../actions/mutes'
|
import { fetchMutes, expandMutes } from '../actions/mutes'
|
||||||
import AccountContainer from '../containers/account_container'
|
import AccountContainer from '../containers/account_container'
|
||||||
import ColumnIndicator from '../components/column_indicator'
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
|
|
|
@ -3,7 +3,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||||
import { createSelector } from 'reselect'
|
import { createSelector } from 'reselect'
|
||||||
import { List as ImmutableList } from 'immutable'
|
import { List as ImmutableList } from 'immutable'
|
||||||
import { debounce } from 'lodash'
|
import debounce from 'lodash.debounce'
|
||||||
import {
|
import {
|
||||||
expandNotifications,
|
expandNotifications,
|
||||||
scrollTopNotifications,
|
scrollTopNotifications,
|
||||||
|
|
|
@ -50,7 +50,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
|
|
||||||
onReply (status, router) {
|
onReply (status, router) {
|
||||||
dispatch((_, getState) => {
|
dispatch((_, getState) => {
|
||||||
let state = getState();
|
const state = getState();
|
||||||
if (state.getIn(['compose', 'text']).trim().length !== 0) {
|
if (state.getIn(['compose', 'text']).trim().length !== 0) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
message: intl.formatMessage(messages.replyMessage),
|
message: intl.formatMessage(messages.replyMessage),
|
||||||
|
|
|
@ -33,7 +33,7 @@ import StatusContainer from '../../containers/status_container'
|
||||||
import { textForScreenReader, defaultMediaVisibility } from '../../components/status/status'
|
import { textForScreenReader, defaultMediaVisibility } from '../../components/status/status'
|
||||||
import ColumnIndicator from '../../components/column_indicator'
|
import ColumnIndicator from '../../components/column_indicator'
|
||||||
import Block from '../../components/block'
|
import Block from '../../components/block'
|
||||||
import Comment from '../../components/comment'
|
import CommentList from '../../components/comment_list'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||||
|
@ -57,22 +57,51 @@ const makeMapStateToProps = () => {
|
||||||
username: props.params.username,
|
username: props.params.username,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// : todo : if is comment (i.e. if any ancestorsIds) use comment not status
|
||||||
|
|
||||||
let ancestorsIds = Immutable.List()
|
let ancestorsIds = Immutable.List()
|
||||||
let descendantsIds = Immutable.List();
|
let descendantsIds = Immutable.List()
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
ancestorsIds = ancestorsIds.withMutations(mutable => {
|
// ancestorsIds = ancestorsIds.withMutations(mutable => {
|
||||||
let id = status.get('in_reply_to_id');
|
// let id = status.get('in_reply_to_id');
|
||||||
|
|
||||||
while (id) {
|
// while (id) {
|
||||||
mutable.unshift(id);
|
// mutable.unshift(id);
|
||||||
id = state.getIn(['contexts', 'inReplyTos', id]);
|
// id = state.getIn(['contexts', 'inReplyTos', id]);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // ONLY Direct descendants
|
||||||
|
// descendantsIds = state.getIn(['contexts', 'replies', status.get('id')])
|
||||||
|
|
||||||
|
let indent = -1
|
||||||
|
descendantsIds = descendantsIds.withMutations(mutable => {
|
||||||
|
const ids = [status.get('id')]
|
||||||
|
|
||||||
|
while (ids.length > 0) {
|
||||||
|
let id = ids.shift();
|
||||||
|
const replies = state.getIn(['contexts', 'replies', id])
|
||||||
|
|
||||||
|
if (status.get('id') !== id) {
|
||||||
|
mutable.push(Immutable.Map({
|
||||||
|
statusId: id,
|
||||||
|
indent: indent,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (replies) {
|
||||||
|
replies.reverse().forEach(reply => {
|
||||||
|
ids.unshift(reply)
|
||||||
});
|
});
|
||||||
|
indent++
|
||||||
// ONLY Direct descendants
|
indent = Math.min(2, indent)
|
||||||
descendantsIds = state.getIn(['contexts', 'replies', status.get('id')])
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("descendantsIds:", descendantsIds)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
|
@ -338,6 +367,7 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
renderChildren(list) {
|
renderChildren(list) {
|
||||||
console.log("list:", list)
|
console.log("list:", list)
|
||||||
|
return null
|
||||||
// : todo : comments
|
// : todo : comments
|
||||||
return list.map(id => (
|
return list.map(id => (
|
||||||
<Comment
|
<Comment
|
||||||
|
@ -383,9 +413,9 @@ class Status extends ImmutablePureComponent {
|
||||||
return <ColumnIndicator type='loading' />
|
return <ColumnIndicator type='loading' />
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ancestorsIds && ancestorsIds.size > 0) {
|
// if (ancestorsIds && ancestorsIds.size > 0) {
|
||||||
ancestors = this.renderChildren(ancestorsIds)
|
// ancestors = this.renderChildren(ancestorsIds)
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (descendantsIds && descendantsIds.size > 0) {
|
if (descendantsIds && descendantsIds.size > 0) {
|
||||||
descendants = this.renderChildren(descendantsIds)
|
descendants = this.renderChildren(descendantsIds)
|
||||||
|
@ -434,7 +464,7 @@ class Status extends ImmutablePureComponent {
|
||||||
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}/>
|
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
{descendants}
|
<CommentList descendants={descendantsIds} />
|
||||||
</Block>
|
</Block>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,7 +3,7 @@ import BundleColumnError from '../../../components/bundle_column_error'
|
||||||
import Bundle from './bundle'
|
import Bundle from './bundle'
|
||||||
import { me } from '../../../initial_state'
|
import { me } from '../../../initial_state'
|
||||||
|
|
||||||
export default class WrappedRoute extends Component {
|
export default class WrappedRoute extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
component: PropTypes.func.isRequired,
|
component: PropTypes.func.isRequired,
|
||||||
page: PropTypes.func.isRequired,
|
page: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -5,11 +5,7 @@ import { default as GabSocial, store } from './containers/gabsocial';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import ready from './ready';
|
import ready from './ready';
|
||||||
|
|
||||||
const perf = require('./performance');
|
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
perf.start('main()');
|
|
||||||
|
|
||||||
// : todo :
|
// : todo :
|
||||||
// if (window.history && history.replaceState) {
|
// if (window.history && history.replaceState) {
|
||||||
// const { pathname, search, hash } = window.location;
|
// const { pathname, search, hash } = window.location;
|
||||||
|
@ -30,7 +26,6 @@ function main() {
|
||||||
require('offline-plugin/runtime').install();
|
require('offline-plugin/runtime').install();
|
||||||
store.dispatch(registerPushNotifications.register());
|
store.dispatch(registerPushNotifications.register());
|
||||||
}
|
}
|
||||||
perf.stop('main()');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const createAudio = sources => {
|
|
||||||
const audio = new Audio();
|
|
||||||
sources.forEach(({ type, src }) => {
|
|
||||||
const source = document.createElement('source');
|
|
||||||
source.type = type;
|
|
||||||
source.src = src;
|
|
||||||
audio.appendChild(source);
|
|
||||||
});
|
|
||||||
return audio;
|
|
||||||
};
|
|
||||||
|
|
||||||
const play = audio => {
|
|
||||||
if (!audio.paused) {
|
|
||||||
audio.pause();
|
|
||||||
if (typeof audio.fastSeek === 'function') {
|
|
||||||
audio.fastSeek(0);
|
|
||||||
} else {
|
|
||||||
audio.currentTime = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// audio.play();
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function soundsMiddleware() {
|
|
||||||
const soundCache = {
|
|
||||||
boop: createAudio([
|
|
||||||
{
|
|
||||||
src: '/sounds/boop.ogg',
|
|
||||||
type: 'audio/ogg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: '/sounds/boop.mp3',
|
|
||||||
type: 'audio/mpeg',
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
ribbit: createAudio([
|
|
||||||
{
|
|
||||||
src: '/sounds/ribbit.ogg',
|
|
||||||
type: 'audio/ogg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: '/sounds/ribbit.mp3',
|
|
||||||
type: 'audio/mpeg',
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => next => action => {
|
|
||||||
if (action.meta && action.meta.sound && soundCache[action.meta.sound]) {
|
|
||||||
play(soundCache[action.meta.sound]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(action);
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -36,31 +36,31 @@ class GroupsPage extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { children, isPro, onOpenGroupCreateModal } = this.props
|
const { children, isPro, onOpenGroupCreateModal } = this.props
|
||||||
|
|
||||||
let tabs = [
|
const actions = []
|
||||||
|
const tabs = [
|
||||||
{
|
{
|
||||||
title: 'Featured',
|
title: 'Featured',
|
||||||
to: '/groups'
|
to: '/groups',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'New',
|
title: 'New',
|
||||||
to: '/groups/new'
|
to: '/groups/new',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'My Groups',
|
title: 'My Groups',
|
||||||
to: '/groups/browse/member'
|
to: '/groups/browse/member',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
let actions = []
|
|
||||||
if (isPro) {
|
if (isPro) {
|
||||||
actions = [{
|
actions.push({
|
||||||
icon: 'group-add',
|
icon: 'add',
|
||||||
onClick: onOpenGroupCreateModal,
|
onClick: onOpenGroupCreateModal,
|
||||||
}]
|
})
|
||||||
|
|
||||||
tabs.push({
|
tabs.push({
|
||||||
title: 'Admin',
|
title: 'Admin',
|
||||||
to: '/groups/browse/admin'
|
to: '/groups/browse/admin',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,4 +82,5 @@ class GroupsPage extends PureComponent {
|
||||||
</DefaultLayout>
|
</DefaultLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -31,8 +31,8 @@ class ListsPage extends PureComponent {
|
||||||
title='Lists'
|
title='Lists'
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
icon: 'list-add',
|
icon: 'add',
|
||||||
onClick: onOpenListCreateModal
|
onClick: onOpenListCreateModal,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
layout={(
|
layout={(
|
||||||
|
@ -48,4 +48,5 @@ class ListsPage extends PureComponent {
|
||||||
</DefaultLayout>
|
</DefaultLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@ import ProfileLayout from '../layouts/profile_layout'
|
||||||
|
|
||||||
const mapStateToProps = (state, { params: { username } }) => {
|
const mapStateToProps = (state, { params: { username } }) => {
|
||||||
const accounts = state.getIn(['accounts'])
|
const accounts = state.getIn(['accounts'])
|
||||||
const account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase())
|
const account = accounts.find(acct => username.toLowerCase() === acct.getIn(['acct'], '').toLowerCase())
|
||||||
|
|
||||||
const accountId = !!account ? account.get('id') : -1
|
const accountId = !!account ? account.get('id') : -1
|
||||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
|
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
|
||||||
|
@ -33,6 +33,7 @@ const mapStateToProps = (state, { params: { username } }) => {
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
class ProfilePage extends ImmutablePureComponent {
|
class ProfilePage extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
params: PropTypes.object.isRequired,
|
params: PropTypes.object.isRequired,
|
||||||
|
@ -59,7 +60,7 @@ class ProfilePage extends ImmutablePureComponent {
|
||||||
const {
|
const {
|
||||||
account,
|
account,
|
||||||
children,
|
children,
|
||||||
unavailable
|
unavailable,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -86,4 +87,5 @@ class ProfilePage extends ImmutablePureComponent {
|
||||||
</ProfileLayout>
|
</ProfileLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Tools for performance debugging, only enabled in development mode.
|
|
||||||
// Open up Chrome Dev Tools, then Timeline, then User Timing to see output.
|
|
||||||
// Also see config/webpack/loaders/mark.js for the webpack loader marks.
|
|
||||||
//
|
|
||||||
|
|
||||||
let marky;
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
if (typeof performance !== 'undefined' && performance.setResourceTimingBufferSize) {
|
|
||||||
// Increase Firefox's performance entry limit; otherwise it's capped to 150.
|
|
||||||
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1331135
|
|
||||||
performance.setResourceTimingBufferSize(Infinity);
|
|
||||||
}
|
|
||||||
marky = require('marky');
|
|
||||||
// allows us to easily do e.g. ReactPerf.printWasted() while debugging
|
|
||||||
//window.ReactPerf = require('react-addons-perf');
|
|
||||||
//window.ReactPerf.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function start(name) {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
marky.mark(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stop(name) {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
marky.stop(name);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -36,7 +36,7 @@ import {
|
||||||
COMPOSE_POLL_OPTION_REMOVE,
|
COMPOSE_POLL_OPTION_REMOVE,
|
||||||
COMPOSE_POLL_SETTINGS_CHANGE,
|
COMPOSE_POLL_SETTINGS_CHANGE,
|
||||||
COMPOSE_SCHEDULED_AT_CHANGE,
|
COMPOSE_SCHEDULED_AT_CHANGE,
|
||||||
COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY
|
COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY,
|
||||||
} from '../actions/compose';
|
} from '../actions/compose';
|
||||||
import { TIMELINE_DELETE } from '../actions/timelines';
|
import { TIMELINE_DELETE } from '../actions/timelines';
|
||||||
import { STORE_HYDRATE } from '../actions/store';
|
import { STORE_HYDRATE } from '../actions/store';
|
||||||
|
|
|
@ -1,17 +1,24 @@
|
||||||
import { MODAL_OPEN, MODAL_CLOSE } from '../actions/modal';
|
import Immutable from 'immutable'
|
||||||
|
import {
|
||||||
|
MODAL_OPEN,
|
||||||
|
MODAL_CLOSE,
|
||||||
|
} from '../actions/modal'
|
||||||
|
|
||||||
const initialState = {
|
const initialState = Immutable.Map({
|
||||||
modalType: null,
|
modalType: null,
|
||||||
modalProps: {},
|
modalProps: null,
|
||||||
};
|
})
|
||||||
|
|
||||||
export default function modal(state = initialState, action) {
|
export default function modal(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case MODAL_OPEN:
|
case MODAL_OPEN:
|
||||||
return { modalType: action.modalType, modalProps: action.modalProps };
|
return state.withMutations(map => {
|
||||||
|
map.set('modalType', action.modalType)
|
||||||
|
map.set('modalProps', action.modalProps)
|
||||||
|
})
|
||||||
case MODAL_CLOSE:
|
case MODAL_CLOSE:
|
||||||
return initialState;
|
return initialState
|
||||||
default:
|
default:
|
||||||
return state;
|
return state
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -6,16 +6,16 @@ import {
|
||||||
|
|
||||||
const initialState = Immutable.Map({
|
const initialState = Immutable.Map({
|
||||||
popoverType: null,
|
popoverType: null,
|
||||||
placement: null,
|
popoverProps: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function popoverMenu(state = initialState, action) {
|
export default function popoverMenu(state = initialState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case POPOVER_OPEN:
|
case POPOVER_OPEN:
|
||||||
return {
|
return state.withMutations(map => {
|
||||||
popoverType: action.popoverType,
|
map.set('popoverType', action.popoverType)
|
||||||
popoverProps: action.popoverProps,
|
map.set('popoverProps', action.popoverProps)
|
||||||
}
|
})
|
||||||
case POPOVER_CLOSE:
|
case POPOVER_CLOSE:
|
||||||
return initialState
|
return initialState
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
GIF_RESULTS_FETCH_FAIL,
|
GIF_RESULTS_FETCH_FAIL,
|
||||||
GIF_CATEGORIES_FETCH_REQUEST,
|
GIF_CATEGORIES_FETCH_REQUEST,
|
||||||
GIF_CATEGORIES_FETCH_SUCCESS,
|
GIF_CATEGORIES_FETCH_SUCCESS,
|
||||||
GIF_CATEGORIES_FETCH_FAIL
|
GIF_CATEGORIES_FETCH_FAIL,
|
||||||
} from '../actions/tenor'
|
} from '../actions/tenor'
|
||||||
import { Map as ImmutableMap } from 'immutable'
|
import { Map as ImmutableMap } from 'immutable'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import IntlMessageFormat from 'intl-messageformat';
|
import IntlMessageFormat from 'intl-messageformat';
|
||||||
import locales from './web_push_locales';
|
import locales from './web_push_locales';
|
||||||
import { unescape } from 'lodash';
|
import unescape from 'lodash.unescape'
|
||||||
|
|
||||||
const MAX_NOTIFICATIONS = 5;
|
const MAX_NOTIFICATIONS = 5;
|
||||||
const GROUP_TAG = 'tag';
|
const GROUP_TAG = 'tag';
|
||||||
|
|
|
@ -3,13 +3,11 @@ import thunk from 'redux-thunk';
|
||||||
import appReducer from '../reducers';
|
import appReducer from '../reducers';
|
||||||
import loadingBarMiddleware from '../middleware/loading_bar';
|
import loadingBarMiddleware from '../middleware/loading_bar';
|
||||||
import errorsMiddleware from '../middleware/errors';
|
import errorsMiddleware from '../middleware/errors';
|
||||||
import soundsMiddleware from '../middleware/sounds';
|
|
||||||
|
|
||||||
export default function configureStore() {
|
export default function configureStore() {
|
||||||
return createStore(appReducer, compose(applyMiddleware(
|
return createStore(appReducer, compose(applyMiddleware(
|
||||||
thunk,
|
thunk,
|
||||||
loadingBarMiddleware({ promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'] }),
|
loadingBarMiddleware({ promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'] }),
|
||||||
errorsMiddleware(),
|
errorsMiddleware(),
|
||||||
soundsMiddleware()
|
|
||||||
), window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : f => f));
|
), window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : f => f));
|
||||||
};
|
};
|
||||||
|
|
|
@ -58,7 +58,7 @@ export const getWindowDimension = () => {
|
||||||
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream
|
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream
|
||||||
|
|
||||||
let userTouching = false
|
let userTouching = false
|
||||||
let listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false
|
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false
|
||||||
|
|
||||||
function touchListener() {
|
function touchListener() {
|
||||||
userTouching = true
|
userTouching = true
|
||||||
|
|
|
@ -33,7 +33,6 @@ function main ( ) {
|
||||||
//(Rjc) 2019-05-24 defined but never used
|
//(Rjc) 2019-05-24 defined but never used
|
||||||
// const React = require('react');
|
// const React = require('react');
|
||||||
const ReactDOM = require('react-dom');
|
const ReactDOM = require('react-dom');
|
||||||
const Rellax = require('rellax');
|
|
||||||
const createHistory = require('history').createBrowserHistory;
|
const createHistory = require('history').createBrowserHistory;
|
||||||
|
|
||||||
const scrollToDetailedStatus = () => {
|
const scrollToDetailedStatus = () => {
|
||||||
|
@ -106,12 +105,6 @@ function main ( ) {
|
||||||
scrollToDetailedStatus();
|
scrollToDetailedStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
const parallaxComponents = document.querySelectorAll('.parallax');
|
|
||||||
|
|
||||||
if (parallaxComponents.length > 0 ) {
|
|
||||||
new Rellax('.parallax', { speed: -1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.body.classList.contains('with-modals')) {
|
if (document.body.classList.contains('with-modals')) {
|
||||||
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
||||||
const scrollbarWidthStyle = document.createElement('style');
|
const scrollbarWidthStyle = document.createElement('style');
|
||||||
|
|
|
@ -328,6 +328,10 @@ body {
|
||||||
background-color: #36e991;
|
background-color: #36e991;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.backgroundColorBrandLightOpaque_onHover:hover {
|
||||||
|
background-color: rgba(54,233,145, 0.125)
|
||||||
|
}
|
||||||
|
|
||||||
.backgroundColorBrand {
|
.backgroundColorBrand {
|
||||||
background-color: #21cf7a;
|
background-color: #21cf7a;
|
||||||
}
|
}
|
||||||
|
@ -392,6 +396,10 @@ body {
|
||||||
fill: #21cf7a;
|
fill: #21cf7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fillColorBrand_onHover:hover {
|
||||||
|
fill: #21cf7a;
|
||||||
|
}
|
||||||
|
|
||||||
.fillColorSecondary {
|
.fillColorSecondary {
|
||||||
fill: #666;
|
fill: #666;
|
||||||
}
|
}
|
||||||
|
@ -472,8 +480,8 @@ body {
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heightMax60PX {
|
.heightMax56PX {
|
||||||
max-height: 60px;
|
max-height: 56px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heightMin50VH {
|
.heightMin50VH {
|
||||||
|
@ -512,6 +520,10 @@ body {
|
||||||
height: 1px;
|
height: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.height40PX {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
.height50PX {
|
.height50PX {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
|
@ -858,6 +870,10 @@ body {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb5 {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.mt10 {
|
.mt10 {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,8 +85,6 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
|
|
||||||
def favourites_count
|
def favourites_count
|
||||||
if instance_options && instance_options[:unfavourite]
|
if instance_options && instance_options[:unfavourite]
|
||||||
# Decrement counter
|
|
||||||
# https://github.com/tootsuite/mastodon/issues/3166
|
|
||||||
object.favourites_count - 1
|
object.favourites_count - 1
|
||||||
else
|
else
|
||||||
object.favourites_count
|
object.favourites_count
|
||||||
|
|
|
@ -26,7 +26,6 @@ module.exports = (api) => {
|
||||||
case 'production':
|
case 'production':
|
||||||
envOptions.debug = false;
|
envOptions.debug = false;
|
||||||
config.plugins.push(...[
|
config.plugins.push(...[
|
||||||
'lodash',
|
|
||||||
[
|
[
|
||||||
'transform-react-remove-prop-types',
|
'transform-react-remove-prop-types',
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,12 +14,6 @@ const extensionGlob = `**/*{${settings.extensions.join(',')}}*`;
|
||||||
const entryPath = join(settings.source_path, settings.source_entry_path);
|
const entryPath = join(settings.source_path, settings.source_entry_path);
|
||||||
const packPaths = sync(join(entryPath, extensionGlob));
|
const packPaths = sync(join(entryPath, extensionGlob));
|
||||||
|
|
||||||
console.log("localePackPaths", localePackPaths);
|
|
||||||
console.log("packPaths:", packPaths);
|
|
||||||
console.log("env:", env);
|
|
||||||
console.log("settings:", settings);
|
|
||||||
console.log("output:", output);
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: Object.assign(
|
entry: Object.assign(
|
||||||
packPaths.reduce((map, entry) => {
|
packPaths.reduce((map, entry) => {
|
||||||
|
@ -70,11 +64,10 @@ module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.ProvidePlugin({
|
new webpack.ProvidePlugin({
|
||||||
React: 'react',
|
React: 'react',
|
||||||
Component: ['react', 'Component'],
|
|
||||||
PureComponent: ['react', 'PureComponent'],
|
PureComponent: ['react', 'PureComponent'],
|
||||||
connect: ['react-redux', 'connect'],
|
connect: ['react-redux', 'connect'],
|
||||||
PropTypes: 'prop-types',
|
PropTypes: 'prop-types',
|
||||||
_s: `${resolve(settings.source_path)}/styles/global.css`
|
_s: `${resolve(settings.source_path)}/styles/global.css`,
|
||||||
}),
|
}),
|
||||||
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
|
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
new webpack.NormalModuleReplacementPlugin(
|
||||||
|
|
182
package.json
182
package.json
|
@ -10,7 +10,6 @@
|
||||||
"build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/webpack",
|
"build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/webpack",
|
||||||
"manage:translations": "node ./config/webpack/translationRunner.js",
|
"manage:translations": "node ./config/webpack/translationRunner.js",
|
||||||
"start": "node ./streaming/index.js",
|
"start": "node ./streaming/index.js",
|
||||||
"storybook": "start-storybook",
|
|
||||||
"test": "${npm_execpath} run test:lint && ${npm_execpath} run test:jest",
|
"test": "${npm_execpath} run test:lint && ${npm_execpath} run test:jest",
|
||||||
"test:lint": "eslint --ext=js .",
|
"test:lint": "eslint --ext=js .",
|
||||||
"test:jest": "cross-env NODE_ENV=test jest --coverage",
|
"test:jest": "cross-env NODE_ENV=test jest --coverage",
|
||||||
|
@ -20,9 +19,6 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://code.gab.com/gab/social/gab-social"
|
"url": "https://code.gab.com/gab/social/gab-social"
|
||||||
},
|
},
|
||||||
"sideEffects": [
|
|
||||||
"*.scss"
|
|
||||||
],
|
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 2 versions",
|
"last 2 versions",
|
||||||
"IE >= 11",
|
"IE >= 11",
|
||||||
|
@ -62,6 +58,71 @@
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@clusterws/cws": "^0.14.0",
|
||||||
|
"array-includes": "^3.0.3",
|
||||||
|
"axios": "^0.19.0",
|
||||||
|
"blurhash": "^1.0.0",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"detect-passive-events": "^1.0.2",
|
||||||
|
"dotenv": "^8.0.0",
|
||||||
|
"draft-js": "^0.11.4",
|
||||||
|
"emoji-mart": "Gargron/emoji-mart#build",
|
||||||
|
"es6-symbol": "^3.1.1",
|
||||||
|
"escape-html": "^1.0.3",
|
||||||
|
"exif-js": "^2.3.0",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"glob": "^7.1.1",
|
||||||
|
"http-link-header": "^1.0.2",
|
||||||
|
"immutable": "^3.8.2",
|
||||||
|
"intersection-observer": "^0.5.1",
|
||||||
|
"intl": "^1.2.5",
|
||||||
|
"intl-messageformat": "^2.2.0",
|
||||||
|
"is-nan": "^1.2.1",
|
||||||
|
"lodash.debounce": "^4.0.8",
|
||||||
|
"lodash.isequal": "^4.5.0",
|
||||||
|
"lodash.isobject": "^3.0.2",
|
||||||
|
"lodash.pick": "^4.4.0",
|
||||||
|
"lodash.sample": "^4.2.1",
|
||||||
|
"lodash.throttle": "^4.1.1",
|
||||||
|
"lodash.unescape": "^4.0.1",
|
||||||
|
"npmlog": "^4.1.2",
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"object-fit-images": "^3.2.3",
|
||||||
|
"object.values": "^1.1.0",
|
||||||
|
"offline-plugin": "^5.0.7",
|
||||||
|
"pg": "^6.4.0",
|
||||||
|
"prop-types": "^15.5.10",
|
||||||
|
"punycode": "^2.1.0",
|
||||||
|
"rails-ujs": "^5.2.3",
|
||||||
|
"react": "^16.13.1",
|
||||||
|
"react-datepicker": "^2.14.1",
|
||||||
|
"react-dom": "^16.7.0",
|
||||||
|
"react-hotkeys": "^1.1.4",
|
||||||
|
"react-immutable-proptypes": "^2.1.0",
|
||||||
|
"react-immutable-pure-component": "^1.1.1",
|
||||||
|
"react-intl": "^2.9.0",
|
||||||
|
"react-motion": "^0.5.2",
|
||||||
|
"react-popper": "^1.3.7",
|
||||||
|
"react-redux": "^6.0.1",
|
||||||
|
"react-redux-loading-bar": "^4.0.8",
|
||||||
|
"react-router-dom": "^4.1.1",
|
||||||
|
"react-router-scroll-4": "^1.0.0-beta.1",
|
||||||
|
"react-stickynode": "^2.1.1",
|
||||||
|
"react-swipeable-views": "^0.13.0",
|
||||||
|
"redis": "^2.7.1",
|
||||||
|
"redux": "^4.0.1",
|
||||||
|
"redux-immutable": "^4.0.0",
|
||||||
|
"redux-thunk": "^2.2.0",
|
||||||
|
"requestidlecallback": "^0.3.0",
|
||||||
|
"reselect": "^4.0.0",
|
||||||
|
"stringz": "^1.0.0",
|
||||||
|
"substring-trie": "^1.0.2",
|
||||||
|
"throng": "^4.0.0",
|
||||||
|
"tiny-queue": "^0.2.1",
|
||||||
|
"uuid": "^3.1.0",
|
||||||
|
"websocket.js": "^0.1.12"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
"@babel/core": "^7.3.4",
|
"@babel/core": "^7.3.4",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.3.4",
|
"@babel/plugin-proposal-class-properties": "^7.3.4",
|
||||||
"@babel/plugin-proposal-decorators": "^7.3.0",
|
"@babel/plugin-proposal-decorators": "^7.3.0",
|
||||||
|
@ -74,111 +135,19 @@
|
||||||
"@babel/preset-env": "^7.3.4",
|
"@babel/preset-env": "^7.3.4",
|
||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"@babel/runtime": "^7.3.4",
|
"@babel/runtime": "^7.3.4",
|
||||||
"@clusterws/cws": "^0.14.0",
|
|
||||||
"array-includes": "^3.0.3",
|
|
||||||
"autoprefixer": "^9.5.1",
|
"autoprefixer": "^9.5.1",
|
||||||
"axios": "^0.19.0",
|
"babel-eslint": "^10.0.1",
|
||||||
|
"babel-jest": "^24.8.0",
|
||||||
"babel-loader": "^8.0.5",
|
"babel-loader": "^8.0.5",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
"babel-plugin-preval": "^3.0.1",
|
"babel-plugin-preval": "^3.0.1",
|
||||||
"babel-plugin-react-intl": "^3.1.0",
|
"babel-plugin-react-intl": "^3.1.0",
|
||||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"blurhash": "^1.0.0",
|
|
||||||
"classnames": "^2.2.5",
|
|
||||||
"compression-webpack-plugin": "^2.0.0",
|
"compression-webpack-plugin": "^2.0.0",
|
||||||
"cron": "^1.8.2",
|
|
||||||
"cross-env": "^5.1.4",
|
"cross-env": "^5.1.4",
|
||||||
"css-loader": "^2.1.1",
|
"css-loader": "^2.1.1",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
"detect-passive-events": "^1.0.2",
|
|
||||||
"dotenv": "^8.0.0",
|
|
||||||
"draft-js": "^0.11.4",
|
|
||||||
"emoji-mart": "Gargron/emoji-mart#build",
|
|
||||||
"es6-symbol": "^3.1.1",
|
|
||||||
"escape-html": "^1.0.3",
|
|
||||||
"exif-js": "^2.3.0",
|
|
||||||
"express": "^4.17.1",
|
|
||||||
"file-loader": "^3.0.1",
|
|
||||||
"glob": "^7.1.1",
|
|
||||||
"http-link-header": "^1.0.2",
|
|
||||||
"immutable": "^3.8.2",
|
|
||||||
"imports-loader": "^0.8.0",
|
|
||||||
"intersection-observer": "^0.5.1",
|
|
||||||
"intl": "^1.2.5",
|
|
||||||
"intl-messageformat": "^2.2.0",
|
|
||||||
"intl-relativeformat": "^2.2.0",
|
|
||||||
"is-nan": "^1.2.1",
|
|
||||||
"js-yaml": "^3.13.1",
|
|
||||||
"lodash": "^4.7.11",
|
|
||||||
"lodash.isobject": "^3.0.2",
|
|
||||||
"mark-loader": "^0.1.6",
|
|
||||||
"marky": "^1.2.1",
|
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
|
||||||
"mkdirp": "^0.5.1",
|
|
||||||
"moment": "^2.24.0",
|
|
||||||
"npmlog": "^4.1.2",
|
|
||||||
"object-assign": "^4.1.1",
|
|
||||||
"object-fit-images": "^3.2.3",
|
|
||||||
"object.values": "^1.1.0",
|
|
||||||
"offline-plugin": "^5.0.7",
|
|
||||||
"path-complete-extname": "^1.0.0",
|
|
||||||
"pg": "^6.4.0",
|
|
||||||
"postcss-loader": "^3.0.0",
|
|
||||||
"postcss-object-fit-images": "^1.1.2",
|
|
||||||
"prop-types": "^15.5.10",
|
|
||||||
"punycode": "^2.1.0",
|
|
||||||
"rails-ujs": "^5.2.3",
|
|
||||||
"react": "^16.12.0",
|
|
||||||
"react-contenteditable": "^3.3.3",
|
|
||||||
"react-datepicker": "^2.14.1",
|
|
||||||
"react-dom": "^16.7.0",
|
|
||||||
"react-hotkeys": "^1.1.4",
|
|
||||||
"react-immutable-proptypes": "^2.1.0",
|
|
||||||
"react-immutable-pure-component": "^1.1.1",
|
|
||||||
"react-intl": "^2.9.0",
|
|
||||||
"react-masonry-infinite": "^1.2.2",
|
|
||||||
"react-motion": "^0.5.2",
|
|
||||||
"react-notification": "^6.8.4",
|
|
||||||
"react-overlays": "^0.8.3",
|
|
||||||
"react-popper": "^1.3.7",
|
|
||||||
"react-redux": "^6.0.1",
|
|
||||||
"react-redux-loading-bar": "^4.0.8",
|
|
||||||
"react-router-dom": "^4.1.1",
|
|
||||||
"react-router-scroll-4": "^1.0.0-beta.1",
|
|
||||||
"react-stickynode": "^2.1.1",
|
|
||||||
"react-swipeable-views": "^0.13.0",
|
|
||||||
"react-textarea-autosize": "^7.1.0",
|
|
||||||
"react-toggle": "^4.0.1",
|
|
||||||
"redis": "^2.7.1",
|
|
||||||
"redux": "^4.0.1",
|
|
||||||
"redux-immutable": "^4.0.0",
|
|
||||||
"redux-thunk": "^2.2.0",
|
|
||||||
"rellax": "^1.7.1",
|
|
||||||
"requestidlecallback": "^0.3.0",
|
|
||||||
"reselect": "^4.0.0",
|
|
||||||
"rimraf": "^2.6.3",
|
|
||||||
"sanitize-html": "^1.22.0",
|
|
||||||
"sass": "^1.20.3",
|
|
||||||
"sass-loader": "^7.0.3",
|
|
||||||
"sass-resources-loader": "^2.0.1",
|
|
||||||
"stringz": "^1.0.0",
|
|
||||||
"style-loader": "^1.1.3",
|
|
||||||
"substring-trie": "^1.0.2",
|
|
||||||
"throng": "^4.0.0",
|
|
||||||
"tiny-queue": "^0.2.1",
|
|
||||||
"uglifyjs-webpack-plugin": "^2.1.2",
|
|
||||||
"uuid": "^3.1.0",
|
|
||||||
"webpack": "^4.41.5",
|
|
||||||
"webpack-assets-manifest": "^3.1.1",
|
|
||||||
"webpack-bundle-analyzer": "^3.1.0",
|
|
||||||
"webpack-cli": "^3.3.2",
|
|
||||||
"webpack-merge": "^4.2.1",
|
|
||||||
"websocket.js": "^0.1.12"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"babel-eslint": "^10.0.1",
|
|
||||||
"babel-jest": "^24.8.0",
|
|
||||||
"enzyme": "^3.8.0",
|
"enzyme": "^3.8.0",
|
||||||
"enzyme-adapter-react-16": "^1.7.1",
|
"enzyme-adapter-react-16": "^1.7.1",
|
||||||
"eslint": "^5.11.1",
|
"eslint": "^5.11.1",
|
||||||
|
@ -186,12 +155,27 @@
|
||||||
"eslint-plugin-jsx-a11y": "~6.2.1",
|
"eslint-plugin-jsx-a11y": "~6.2.1",
|
||||||
"eslint-plugin-promise": "~4.1.1",
|
"eslint-plugin-promise": "~4.1.1",
|
||||||
"eslint-plugin-react": "~7.12.1",
|
"eslint-plugin-react": "~7.12.1",
|
||||||
|
"file-loader": "^3.0.1",
|
||||||
|
"imports-loader": "^0.8.0",
|
||||||
"jest": "^24.8.0",
|
"jest": "^24.8.0",
|
||||||
"node-sass": "^4.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
|
"mark-loader": "^0.1.6",
|
||||||
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
"path-complete-extname": "^1.0.0",
|
||||||
|
"postcss-loader": "^3.0.0",
|
||||||
|
"postcss-object-fit-images": "^1.1.2",
|
||||||
"raf": "^3.4.1",
|
"raf": "^3.4.1",
|
||||||
"react-intl-translations-manager": "^5.0.3",
|
"react-intl-translations-manager": "^5.0.3",
|
||||||
"react-test-renderer": "^16.7.0",
|
"react-test-renderer": "^16.7.0",
|
||||||
|
"rimraf": "^2.6.3",
|
||||||
|
"uglifyjs-webpack-plugin": "^2.1.2",
|
||||||
|
"webpack": "^4.41.5",
|
||||||
|
"webpack-assets-manifest": "^3.1.1",
|
||||||
|
"webpack-bundle-analyzer": "^3.1.0",
|
||||||
|
"webpack-cli": "^3.3.11",
|
||||||
"webpack-dev-server": "^3.10.1",
|
"webpack-dev-server": "^3.10.1",
|
||||||
|
"webpack-merge": "^4.2.1",
|
||||||
"yargs": "^12.0.5"
|
"yargs": "^12.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue