Merge pull request #913 from ThibG/glitch-soc/merge-upstream

Merge upstream changes
This commit is contained in:
ThibG
2019-02-12 20:29:55 +01:00
committed by GitHub
101 changed files with 853 additions and 278 deletions

View File

@ -1,3 +1,10 @@
import { defineMessages } from 'react-intl';
const messages = defineMessages({
unexpectedTitle: { id: 'alert.unexpected.title', defaultMessage: 'Oops!' },
unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'An unexpected error occurred.' },
});
export const ALERT_SHOW = 'ALERT_SHOW';
export const ALERT_DISMISS = 'ALERT_DISMISS';
export const ALERT_CLEAR = 'ALERT_CLEAR';
@ -15,10 +22,28 @@ export function clearAlert() {
};
};
export function showAlert(title, message) {
export function showAlert(title = messages.unexpectedTitle, message = messages.unexpectedMessage) {
return {
type: ALERT_SHOW,
title,
message,
};
};
export function showAlertForError(error) {
if (error.response) {
const { data, status, statusText } = error.response;
let message = statusText;
let title = `${status}`;
if (data.error) {
message = data.error;
}
return showAlert(title, message);
} else {
console.error(error);
return showAlert();
}
}

View File

@ -1,5 +1,5 @@
import api from 'flavours/glitch/util/api';
import { CancelToken } from 'axios';
import { CancelToken, isCancel } from 'axios';
import { throttle } from 'lodash';
import { search as emojiSearch } from 'flavours/glitch/util/emoji/emoji_mart_search_light';
import { useEmoji } from './emojis';
@ -8,6 +8,9 @@ import { recoverHashtags } from 'flavours/glitch/util/hashtag';
import resizeImage from 'flavours/glitch/util/resize_image';
import { updateTimeline } from './timelines';
import { showAlertForError } from './alerts';
import { showAlert } from './alerts';
import { defineMessages } from 'react-intl';
let cancelFetchComposeSuggestionsAccounts;
@ -52,6 +55,10 @@ export const COMPOSE_UPLOAD_CHANGE_FAIL = 'COMPOSE_UPLOAD_UPDATE_FAIL';
export const COMPOSE_DOODLE_SET = 'COMPOSE_DOODLE_SET';
const messages = defineMessages({
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
});
export function changeCompose(text) {
return {
type: COMPOSE_CHANGE,
@ -207,20 +214,32 @@ export function doodleSet(options) {
export function uploadCompose(files) {
return function (dispatch, getState) {
if (getState().getIn(['compose', 'media_attachments']).size > 3) {
const uploadLimit = 4;
const media = getState().getIn(['compose', 'media_attachments']);
const total = Array.from(files).reduce((a, v) => a + v.size, 0);
const progress = new Array(files.length).fill(0);
if (files.length + media.size > uploadLimit) {
dispatch(showAlert(undefined, messages.uploadErrorLimit));
return;
}
dispatch(uploadComposeRequest());
resizeImage(files[0]).then(file => {
const data = new FormData();
data.append('file', file);
for (const [i, f] of Array.from(files).entries()) {
if (media.size + i > 3) break;
return api(getState).post('/api/v1/media', data, {
onUploadProgress: ({ loaded, total }) => dispatch(uploadComposeProgress(loaded, total)),
}).then(({ data }) => dispatch(uploadComposeSuccess(data)));
}).catch(error => dispatch(uploadComposeFail(error)));
resizeImage(f).then(file => {
const data = new FormData();
data.append('file', file);
return api(getState).post('/api/v1/media', data, {
onUploadProgress: function({ loaded }){
progress[i] = loaded;
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total));
},
}).then(({ data }) => dispatch(uploadComposeSuccess(data)));
}).catch(error => dispatch(uploadComposeFail(error)));
};
};
};
@ -320,6 +339,10 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
},
}).then(response => {
dispatch(readyComposeSuggestionsAccounts(token, response.data));
}).catch(error => {
if (!isCancel(error)) {
dispatch(showAlertForError(error));
}
});
}, 200, { leading: true, trailing: true });

View File

@ -1,4 +1,5 @@
import api from 'flavours/glitch/util/api';
import { showAlertForError } from './alerts';
export const LIST_FETCH_REQUEST = 'LIST_FETCH_REQUEST';
export const LIST_FETCH_SUCCESS = 'LIST_FETCH_SUCCESS';
@ -239,7 +240,8 @@ export const fetchListSuggestions = q => (dispatch, getState) => {
};
api(getState).get('/api/v1/accounts/search', { params })
.then(({ data }) => dispatch(fetchListSuggestionsReady(q, data)));
.then(({ data }) => dispatch(fetchListSuggestionsReady(q, data)))
.catch(error => dispatch(showAlertForError(error)));
};
export const fetchListSuggestionsReady = (query, accounts) => ({

View File

@ -109,14 +109,11 @@ export function register () {
pushNotificationsSetting.remove(me);
}
try {
getRegistration()
.then(getPushSubscription)
.then(unsubscribe);
} catch (e) {
}
});
return getRegistration()
.then(getPushSubscription)
.then(unsubscribe);
})
.catch(console.warn);
} else {
console.warn('Your browser does not support Web Push Notifications.');
}
@ -137,6 +134,6 @@ export function saveSettings() {
if (me) {
pushNotificationsSetting.set(me, data);
}
});
}).catch(console.warn);
};
}

View File

@ -1,5 +1,6 @@
import api from 'flavours/glitch/util/api';
import { debounce } from 'lodash';
import { showAlertForError } from './alerts';
export const SETTING_CHANGE = 'SETTING_CHANGE';
export const SETTING_SAVE = 'SETTING_SAVE';
@ -23,7 +24,9 @@ const debouncedSave = debounce((dispatch, getState) => {
const data = getState().get('settings').filter((_, path) => path !== 'saved').toJS();
api(getState).put('/api/web/settings', { data }).then(() => dispatch({ type: SETTING_SAVE }));
api(getState).put('/api/web/settings', { data })
.then(() => dispatch({ type: SETTING_SAVE }))
.catch(error => dispatch(showAlertForError(error)));
}, 5000, { trailing: true });
export function saveSettings() {

View File

@ -7,6 +7,7 @@ import { IntlProvider, addLocaleData } from 'react-intl';
import { getLocale } from 'mastodon/locales';
import Compose from 'flavours/glitch/features/standalone/compose';
import initialState from 'flavours/glitch/util/initial_state';
import { fetchCustomEmojis } from 'flavours/glitch/actions/custom_emojis';
const { localeData, messages } = getLocale();
addLocaleData(localeData);
@ -17,6 +18,8 @@ if (initialState) {
store.dispatch(hydrateStore(initialState));
}
store.dispatch(fetchCustomEmojis());
export default class TimelineContainer extends React.PureComponent {
static propTypes = {

View File

@ -25,6 +25,7 @@ import { openModal } from 'flavours/glitch/actions/modal';
import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/util/initial_state';
import { showAlertForError } from '../actions/alerts';
const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
@ -134,7 +135,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
},
onEmbed (status) {
dispatch(openModal('EMBED', { url: status.get('url') }));
dispatch(openModal('EMBED', {
url: status.get('url'),
onError: error => dispatch(showAlertForError(error)),
}));
},
onDelete (status, history, withRedraft = false) {

View File

@ -214,6 +214,7 @@ export default class ComposerOptions extends React.PureComponent {
onChange={handleChangeFiles}
ref={handleRefFileElement}
type='file'
multiple
{...hiddenComponent}
/>
<Dropdown

View File

@ -166,7 +166,7 @@ export default class GettingStarted extends ImmutablePureComponent {
<div className='getting-started__footer'>
<ul>
{invitesEnabled && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
<li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this instance' /></a> · </li>
<li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></a> · </li>
<li><a href='https://joinmastodon.org/apps' target='_blank'><FormattedMessage id='navigation_bar.apps' defaultMessage='Mobile apps' /></a> · </li>
<li><a href='/terms' target='_blank'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of service' /></a> · </li>
<li><a href='https://docs.joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a></li>

View File

@ -127,7 +127,7 @@ export default class PublicTimeline extends React.PureComponent {
onLoadMore={this.handleLoadMore}
trackScroll={!pinned}
scrollKey={`public_timeline-${columnId}`}
emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other instances to fill it up' />}
emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other servers to fill it up' />}
/>
</Column>
);

View File

@ -10,6 +10,7 @@ export default class EmbedModal extends ImmutablePureComponent {
static propTypes = {
url: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired,
onError: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
}
@ -35,6 +36,8 @@ export default class EmbedModal extends ImmutablePureComponent {
iframeDocument.body.style.margin = 0;
this.iframe.width = iframeDocument.body.scrollWidth;
this.iframe.height = iframeDocument.body.scrollHeight;
}).catch(error => {
this.props.onError(error);
});
}

View File

@ -97,7 +97,7 @@ export default class ReportModal extends ImmutablePureComponent {
<div className='report-modal__container'>
<div className='report-modal__comment'>
<p><FormattedMessage id='report.hint' defaultMessage='The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:' /></p>
<p><FormattedMessage id='report.hint' defaultMessage='The report will be sent to your server moderators. You can provide an explanation of why you are reporting this account below:' /></p>
<textarea
className='setting-text light'

View File

@ -186,7 +186,7 @@ export default class UI extends React.Component {
this.setState({ draggingOver: false });
this.dragTargets = [];
if (e.dataTransfer && e.dataTransfer.files.length === 1) {
if (e.dataTransfer && e.dataTransfer.files.length >= 1) {
this.props.dispatch(uploadCompose(e.dataTransfer.files));
}
}

View File

@ -1,4 +1,4 @@
import { showAlert } from 'flavours/glitch/actions/alerts';
import { showAlertForError } from 'flavours/glitch/actions/alerts';
const defaultFailSuffix = 'FAIL';
@ -8,21 +8,7 @@ export default function errorsMiddleware() {
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
if (action.type.match(isFail)) {
if (action.error.response) {
const { data, status, statusText } = action.error.response;
let message = statusText;
let title = `${status}`;
if (data.error) {
message = data.error;
}
dispatch(showAlert(title, message));
} else {
console.error(action.error);
dispatch(showAlert('Oops!', 'An unexpected error occurred.'));
}
dispatch(showAlertForError(action.error));
}
}

View File

@ -290,3 +290,7 @@
border-bottom: 0;
}
}
.directory__tag .trends__item__current {
width: auto;
}

View File

@ -153,10 +153,15 @@ $content-width: 840px;
font-weight: 500;
}
.directory__tag a {
.directory__tag > a,
.directory__tag > div {
box-shadow: none;
}
.directory__tag .table-action-link .fa {
color: inherit;
}
.directory__tag h4 {
font-size: 18px;
font-weight: 700;

View File

@ -269,7 +269,8 @@
box-sizing: border-box;
margin-bottom: 10px;
a {
& > a,
& > div {
display: flex;
align-items: center;
justify-content: space-between;
@ -279,7 +280,9 @@
text-decoration: none;
color: inherit;
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
}
& > a {
&:hover,
&:active,
&:focus {
@ -287,7 +290,7 @@
}
}
&.active a {
&.active > a {
background: $ui-highlight-color;
cursor: default;
}

View File

@ -31,7 +31,7 @@ const loadImage = inputFile => new Promise((resolve, reject) => {
});
const getOrientation = (img, type = 'image/png') => new Promise(resolve => {
if (type !== 'image/jpeg') {
if (!['image/jpeg', 'image/webp'].includes(type)) {
resolve(1);
return;
}