Fix merge conflicts hopefully
This commit is contained in:
commit
49ad44bcd4
|
@ -145,7 +145,17 @@ export function logIn(username, password) {
|
||||||
|
|
||||||
export function logOut() {
|
export function logOut() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
|
const state = getState();
|
||||||
|
|
||||||
dispatch({ type: AUTH_LOGGED_OUT });
|
dispatch({ type: AUTH_LOGGED_OUT });
|
||||||
|
|
||||||
|
// Attempt to destroy OAuth token on logout
|
||||||
|
api(getState).post('/oauth/revoke', {
|
||||||
|
client_id: state.getIn(['auth', 'app', 'client_id']),
|
||||||
|
client_secret: state.getIn(['auth', 'app', 'client_secret']),
|
||||||
|
token: state.getIn(['auth', 'user', 'access_token']),
|
||||||
|
});
|
||||||
|
|
||||||
dispatch(showAlert('Successfully logged out.', ''));
|
dispatch(showAlert('Successfully logged out.', ''));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,13 +143,13 @@ export function handleComposeSubmit(dispatch, getState, response, status) {
|
||||||
let dequeueArgs = {};
|
let dequeueArgs = {};
|
||||||
if (timelineId === 'community') dequeueArgs.onlyMedia = getSettings(getState()).getIn(['community', 'other', 'onlyMedia']);
|
if (timelineId === 'community') dequeueArgs.onlyMedia = getSettings(getState()).getIn(['community', 'other', 'onlyMedia']);
|
||||||
dispatch(dequeueTimeline(timelineId, null, dequeueArgs));
|
dispatch(dequeueTimeline(timelineId, null, dequeueArgs));
|
||||||
dispatch(updateTimeline(timelineId, { ...response.data }));
|
dispatch(updateTimeline(timelineId, response.data.id));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (response.data.visibility !== 'direct') {
|
if (response.data.visibility !== 'direct') {
|
||||||
insertIfOnline('home');
|
insertIfOnline('home');
|
||||||
} else if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
} else if (response.data.visibility === 'public') {
|
||||||
insertIfOnline('community');
|
insertIfOnline('community');
|
||||||
insertIfOnline('public');
|
insertIfOnline('public');
|
||||||
}
|
}
|
||||||
|
@ -440,17 +440,6 @@ export function updateTagHistory(tags) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hydrateCompose() {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const me = getState().get('me');
|
|
||||||
const history = tagHistory.get(me);
|
|
||||||
|
|
||||||
if (history !== null) {
|
|
||||||
dispatch(updateTagHistory(history));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function insertIntoTagHistory(recognizedTags, text) {
|
function insertIntoTagHistory(recognizedTags, text) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import api from '../api';
|
||||||
|
import { showAlert } from 'soapbox/actions/alerts';
|
||||||
|
|
||||||
|
export const IMPORT_FOLLOWS_REQUEST = 'IMPORT_FOLLOWS_REQUEST';
|
||||||
|
export const IMPORT_FOLLOWS_SUCCESS = 'IMPORT_FOLLOWS_SUCCESS';
|
||||||
|
export const IMPORT_FOLLOWS_FAIL = 'IMPORT_FOLLOWS_FAIL';
|
||||||
|
|
||||||
|
export const IMPORT_BLOCKS_REQUEST = 'IMPORT_BLOCKS_REQUEST';
|
||||||
|
export const IMPORT_BLOCKS_SUCCESS = 'IMPORT_BLOCKS_SUCCESS';
|
||||||
|
export const IMPORT_BLOCKS_FAIL = 'IMPORT_BLOCKS_FAIL';
|
||||||
|
|
||||||
|
export const IMPORT_MUTES_REQUEST = 'IMPORT_MUTES_REQUEST';
|
||||||
|
export const IMPORT_MUTES_SUCCESS = 'IMPORT_MUTES_SUCCESS';
|
||||||
|
export const IMPORT_MUTES_FAIL = 'IMPORT_MUTES_FAIL';
|
||||||
|
|
||||||
|
export function importFollows(params) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: IMPORT_FOLLOWS_REQUEST });
|
||||||
|
return api(getState)
|
||||||
|
.post('/api/pleroma/follow_import', params)
|
||||||
|
.then(response => {
|
||||||
|
dispatch(showAlert('', 'Followers imported successfully'));
|
||||||
|
dispatch({ type: IMPORT_FOLLOWS_SUCCESS, config: response.data });
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: IMPORT_FOLLOWS_FAIL, error });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function importBlocks(params) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: IMPORT_BLOCKS_REQUEST });
|
||||||
|
return api(getState)
|
||||||
|
.post('/api/pleroma/blocks_import', params)
|
||||||
|
.then(response => {
|
||||||
|
dispatch(showAlert('', 'Blocks imported successfully'));
|
||||||
|
dispatch({ type: IMPORT_BLOCKS_SUCCESS, config: response.data });
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: IMPORT_BLOCKS_FAIL, error });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function importMutes(params) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: IMPORT_MUTES_REQUEST });
|
||||||
|
return api(getState)
|
||||||
|
.post('/api/pleroma/mutes_import', params)
|
||||||
|
.then(response => {
|
||||||
|
dispatch(showAlert('', 'Mutes imported successfully'));
|
||||||
|
dispatch({ type: IMPORT_MUTES_SUCCESS, config: response.data });
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: IMPORT_MUTES_FAIL, error });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import { debounce } from 'lodash';
|
||||||
import { showAlertForError } from './alerts';
|
import { showAlertForError } from './alerts';
|
||||||
import { patchMe } from 'soapbox/actions/me';
|
import { patchMe } from 'soapbox/actions/me';
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
|
import uuid from '../uuid';
|
||||||
|
|
||||||
export const SETTING_CHANGE = 'SETTING_CHANGE';
|
export const SETTING_CHANGE = 'SETTING_CHANGE';
|
||||||
export const SETTING_SAVE = 'SETTING_SAVE';
|
export const SETTING_SAVE = 'SETTING_SAVE';
|
||||||
|
@ -114,6 +115,12 @@ const defaultSettings = ImmutableMap({
|
||||||
trends: ImmutableMap({
|
trends: ImmutableMap({
|
||||||
show: true,
|
show: true,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
columns: ImmutableList([
|
||||||
|
ImmutableMap({ id: 'COMPOSE', uuid: uuid(), params: {} }),
|
||||||
|
ImmutableMap({ id: 'HOME', uuid: uuid(), params: {} }),
|
||||||
|
ImmutableMap({ id: 'NOTIFICATIONS', uuid: uuid(), params: {} }),
|
||||||
|
]),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function getSettings(state) {
|
export function getSettings(state) {
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { Iterable, fromJS } from 'immutable';
|
|
||||||
import { hydrateCompose } from './compose';
|
|
||||||
|
|
||||||
export const STORE_HYDRATE = 'STORE_HYDRATE';
|
|
||||||
export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY';
|
|
||||||
|
|
||||||
const convertState = rawState =>
|
|
||||||
fromJS(rawState, (k, v) =>
|
|
||||||
Iterable.isIndexed(v) ? v.toList() : v.toMap());
|
|
||||||
|
|
||||||
export function hydrateStore(rawState) {
|
|
||||||
return dispatch => {
|
|
||||||
const state = convertState(rawState);
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: STORE_HYDRATE,
|
|
||||||
state,
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(hydrateCompose());
|
|
||||||
// dispatch(importFetchedAccounts(Object.values(rawState.accounts)));
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -25,31 +25,31 @@ export function processTimelineUpdate(timeline, status, accept) {
|
||||||
const columnSettings = getSettings(getState()).get(timeline, ImmutableMap());
|
const columnSettings = getSettings(getState()).get(timeline, ImmutableMap());
|
||||||
const shouldSkipQueue = shouldFilter(fromJS(status), columnSettings);
|
const shouldSkipQueue = shouldFilter(fromJS(status), columnSettings);
|
||||||
|
|
||||||
|
dispatch(importFetchedStatus(status));
|
||||||
|
|
||||||
if (shouldSkipQueue) {
|
if (shouldSkipQueue) {
|
||||||
return dispatch(updateTimeline(timeline, status, accept));
|
return dispatch(updateTimeline(timeline, status.id, accept));
|
||||||
} else {
|
} else {
|
||||||
return dispatch(updateTimelineQueue(timeline, status, accept));
|
return dispatch(updateTimelineQueue(timeline, status.id, accept));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateTimeline(timeline, status, accept) {
|
export function updateTimeline(timeline, statusId, accept) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
if (typeof accept === 'function' && !accept(status)) {
|
if (typeof accept === 'function' && !accept(status)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(importFetchedStatus(status));
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: TIMELINE_UPDATE,
|
type: TIMELINE_UPDATE,
|
||||||
timeline,
|
timeline,
|
||||||
status,
|
statusId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function updateTimelineQueue(timeline, status, accept) {
|
export function updateTimelineQueue(timeline, statusId, accept) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
if (typeof accept === 'function' && !accept(status)) {
|
if (typeof accept === 'function' && !accept(status)) {
|
||||||
return;
|
return;
|
||||||
|
@ -58,7 +58,7 @@ export function updateTimelineQueue(timeline, status, accept) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: TIMELINE_UPDATE_QUEUE,
|
type: TIMELINE_UPDATE_QUEUE,
|
||||||
timeline,
|
timeline,
|
||||||
status,
|
statusId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -73,8 +73,8 @@ export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) {
|
||||||
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(statusId => {
|
||||||
dispatch(updateTimeline(timeline, status.toJS(), null));
|
dispatch(updateTimeline(timeline, statusId, null));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (typeof expandFunc === 'function') {
|
if (typeof expandFunc === 'function') {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
// import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Permalink from './permalink';
|
import Permalink from './permalink';
|
||||||
|
@ -17,11 +17,12 @@ const Hashtag = ({ hashtag }) => (
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{hashtag.get('history') && <div className='trends__item__sparkline'>
|
{/* Pleroma doesn't support tag history yet */}
|
||||||
|
{/* hashtag.get('history') && <div className='trends__item__sparkline'>
|
||||||
<Sparklines width={50} height={28} data={hashtag.get('history').reverse().map(day => day.get('uses')).toArray()}>
|
<Sparklines width={50} height={28} data={hashtag.get('history').reverse().map(day => day.get('uses')).toArray()}>
|
||||||
<SparklinesCurve style={{ fill: 'none' }} />
|
<SparklinesCurve style={{ fill: 'none' }} />
|
||||||
</Sparklines>
|
</Sparklines>
|
||||||
</div>}
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ const messages = defineMessages({
|
||||||
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
||||||
admin_settings: { id: 'navigation_bar.admin_settings', defaultMessage: 'Admin settings' },
|
admin_settings: { id: 'navigation_bar.admin_settings', defaultMessage: 'Admin settings' },
|
||||||
soapbox_config: { id: 'navigation_bar.soapbox_config', defaultMessage: 'Soapbox config' },
|
soapbox_config: { id: 'navigation_bar.soapbox_config', defaultMessage: 'Soapbox config' },
|
||||||
|
import_data: { id: 'navigation_bar.import_data', defaultMessage: 'Import data' },
|
||||||
security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
|
security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
|
||||||
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' },
|
||||||
|
@ -180,6 +181,10 @@ class SidebarMenu extends ImmutablePureComponent {
|
||||||
<Icon id='cog' />
|
<Icon id='cog' />
|
||||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.preferences)}</span>
|
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.preferences)}</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
<NavLink className='sidebar-menu-item' to='/settings/import' onClick={onClose}>
|
||||||
|
<Icon id='cloud-upload' />
|
||||||
|
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.import_data)}</span>
|
||||||
|
</NavLink>
|
||||||
<NavLink className='sidebar-menu-item' to='/auth/edit' onClick={onClose}>
|
<NavLink className='sidebar-menu-item' to='/auth/edit' onClick={onClose}>
|
||||||
<Icon id='lock' />
|
<Icon id='lock' />
|
||||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.security)}</span>
|
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.security)}</span>
|
||||||
|
|
|
@ -14,8 +14,6 @@ import { ScrollContext } from 'react-router-scroll-4';
|
||||||
import UI from '../features/ui';
|
import UI from '../features/ui';
|
||||||
// import Introduction from '../features/introduction';
|
// import Introduction from '../features/introduction';
|
||||||
import { fetchCustomEmojis } from '../actions/custom_emojis';
|
import { fetchCustomEmojis } from '../actions/custom_emojis';
|
||||||
import { hydrateStore } from '../actions/store';
|
|
||||||
import initialState from '../initial_state';
|
|
||||||
import { preload } from '../actions/preload';
|
import { preload } from '../actions/preload';
|
||||||
import { IntlProvider } from 'react-intl';
|
import { IntlProvider } from 'react-intl';
|
||||||
import ErrorBoundary from '../components/error_boundary';
|
import ErrorBoundary from '../components/error_boundary';
|
||||||
|
@ -32,9 +30,6 @@ const validLocale = locale => Object.keys(messages).includes(locale);
|
||||||
|
|
||||||
export const store = configureStore();
|
export const store = configureStore();
|
||||||
|
|
||||||
const hydrateAction = hydrateStore(initialState);
|
|
||||||
|
|
||||||
store.dispatch(hydrateAction);
|
|
||||||
store.dispatch(preload());
|
store.dispatch(preload());
|
||||||
store.dispatch(fetchMe());
|
store.dispatch(fetchMe());
|
||||||
store.dispatch(fetchInstance());
|
store.dispatch(fetchInstance());
|
||||||
|
|
|
@ -20,6 +20,7 @@ const messages = defineMessages({
|
||||||
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
||||||
admin_settings: { id: 'navigation_bar.admin_settings', defaultMessage: 'Admin settings' },
|
admin_settings: { id: 'navigation_bar.admin_settings', defaultMessage: 'Admin settings' },
|
||||||
soapbox_config: { id: 'navigation_bar.soapbox_config', defaultMessage: 'Soapbox config' },
|
soapbox_config: { id: 'navigation_bar.soapbox_config', defaultMessage: 'Soapbox config' },
|
||||||
|
import_data: { id: 'navigation_bar.import_data', defaultMessage: 'Import data' },
|
||||||
security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
|
security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
|
||||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||||
keyboard_shortcuts: { id: 'navigation_bar.keyboard_shortcuts', defaultMessage: 'Hotkeys' },
|
keyboard_shortcuts: { id: 'navigation_bar.keyboard_shortcuts', defaultMessage: 'Hotkeys' },
|
||||||
|
@ -84,6 +85,7 @@ class ActionBar extends React.PureComponent {
|
||||||
menu.push({ text: intl.formatMessage(messages.soapbox_config), to: '/soapbox/config' });
|
menu.push({ text: intl.formatMessage(messages.soapbox_config), to: '/soapbox/config' });
|
||||||
}
|
}
|
||||||
menu.push({ text: intl.formatMessage(messages.preferences), to: '/settings/preferences' });
|
menu.push({ text: intl.formatMessage(messages.preferences), to: '/settings/preferences' });
|
||||||
|
menu.push({ text: intl.formatMessage(messages.import_data), to: '/settings/import' });
|
||||||
menu.push({ text: intl.formatMessage(messages.security), to: '/auth/edit' });
|
menu.push({ text: intl.formatMessage(messages.security), to: '/auth/edit' });
|
||||||
menu.push({ text: intl.formatMessage(messages.logout), to: '/auth/sign_out', action: onClickLogOut });
|
menu.push({ text: intl.formatMessage(messages.logout), to: '/auth/sign_out', action: onClickLogOut });
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,10 @@ const mapDispatchToProps = dispatch => ({
|
||||||
|
|
||||||
isUserTouching,
|
isUserTouching,
|
||||||
onModalOpen: props => dispatch(openModal('ACTIONS', props)),
|
onModalOpen: props => dispatch(openModal('ACTIONS', props)),
|
||||||
onModalClose: () => dispatch(closeModal()),
|
onModalClose: () => {
|
||||||
|
dispatch(closeModal());
|
||||||
|
dispatch(openModal('COMPOSE'));
|
||||||
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -55,23 +55,27 @@ exports[`<RadioGroup /> renders correctly 1`] = `
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<SelectDropdown /> renders correctly 1`] = `
|
exports[`<SelectDropdown /> renders correctly 1`] = `
|
||||||
<select>
|
<div
|
||||||
<option
|
class="select-wrapper"
|
||||||
value="one"
|
>
|
||||||
>
|
<select>
|
||||||
One
|
<option
|
||||||
</option>
|
value="one"
|
||||||
<option
|
>
|
||||||
value="two"
|
One
|
||||||
>
|
</option>
|
||||||
Two
|
<option
|
||||||
</option>
|
value="two"
|
||||||
<option
|
>
|
||||||
value="three"
|
Two
|
||||||
>
|
</option>
|
||||||
Three
|
<option
|
||||||
</option>
|
value="three"
|
||||||
</select>
|
>
|
||||||
|
Three
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<SimpleForm /> renders correctly 1`] = `
|
exports[`<SimpleForm /> renders correctly 1`] = `
|
||||||
|
|
|
@ -270,7 +270,7 @@ export class SelectDropdown extends ImmutablePureComponent {
|
||||||
<option key={item} value={item}>{items[item]}</option>
|
<option key={item} value={item}>{items[item]}</option>
|
||||||
));
|
));
|
||||||
|
|
||||||
const selectElem = <select {...props}>{optionElems}</select>;
|
const selectElem = <div class='select-wrapper'><select {...props}>{optionElems}</select></div>;
|
||||||
|
|
||||||
return label ? (
|
return label ? (
|
||||||
<LabelInputContainer label={label} hint={hint}>{selectElem}</LabelInputContainer>
|
<LabelInputContainer label={label} hint={hint}>{selectElem}</LabelInputContainer>
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { injectIntl } from 'react-intl';
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
SimpleInput,
|
||||||
|
SimpleForm,
|
||||||
|
FieldsGroup,
|
||||||
|
} from 'soapbox/features/forms';
|
||||||
|
|
||||||
|
export default @connect()
|
||||||
|
@injectIntl
|
||||||
|
class CSVImporter extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
action: PropTypes.func.isRequired,
|
||||||
|
messages: PropTypes.object.isRequired,
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
file: null,
|
||||||
|
isLoading: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit = (event) => {
|
||||||
|
const { dispatch, action } = this.props;
|
||||||
|
|
||||||
|
let params = new FormData();
|
||||||
|
params.append('list', this.state.file);
|
||||||
|
|
||||||
|
this.setState({ isLoading: true });
|
||||||
|
dispatch(action(params)).then(() => {
|
||||||
|
this.setState({ isLoading: false });
|
||||||
|
}).catch((error) => {
|
||||||
|
this.setState({ isLoading: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFileChange = e => {
|
||||||
|
const [file] = e.target.files || [];
|
||||||
|
this.setState({ file });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl, messages } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SimpleForm onSubmit={this.handleSubmit}>
|
||||||
|
<fieldset disabled={this.state.isLoading}>
|
||||||
|
<FieldsGroup>
|
||||||
|
<div className='fields-row file-picker'>
|
||||||
|
<div className='fields-row__column fields-group fields-row__column-6'>
|
||||||
|
<SimpleInput
|
||||||
|
type='file'
|
||||||
|
accept={['.csv', 'text/csv']}
|
||||||
|
label={intl.formatMessage(messages.input_label)}
|
||||||
|
hint={intl.formatMessage(messages.input_hint)}
|
||||||
|
onChange={this.handleFileChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FieldsGroup>
|
||||||
|
</fieldset>
|
||||||
|
<div className='actions'>
|
||||||
|
<button name='button' type='submit' className='btn button button-primary'>
|
||||||
|
{intl.formatMessage(messages.submit)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</SimpleForm>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Column from '../ui/components/column';
|
||||||
|
import {
|
||||||
|
importFollows,
|
||||||
|
importBlocks,
|
||||||
|
// importMutes,
|
||||||
|
} from 'soapbox/actions/import_data';
|
||||||
|
import CSVImporter from './components/csv_importer';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
heading: { id: 'column.import_data', defaultMessage: 'Import data' },
|
||||||
|
submit: { id: 'import_data.actions.import', defaultMessage: 'Import' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const followMessages = defineMessages({
|
||||||
|
input_label: { id: 'import_data.follows_label', defaultMessage: 'Follows' },
|
||||||
|
input_hint: { id: 'import_data.hints.follows', defaultMessage: 'CSV file containing a list of followed accounts' },
|
||||||
|
submit: { id: 'import_data.actions.import_follows', defaultMessage: 'Import follows' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const blockMessages = defineMessages({
|
||||||
|
input_label: { id: 'import_data.blocks_label', defaultMessage: 'Blocks' },
|
||||||
|
input_hint: { id: 'import_data.hints.blocks', defaultMessage: 'CSV file containing a list of blocked accounts' },
|
||||||
|
submit: { id: 'import_data.actions.import_blocks', defaultMessage: 'Import blocks' },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Not yet supported by Pleroma stable, in develop branch
|
||||||
|
// const muteMessages = defineMessages({
|
||||||
|
// input_label: { id: 'import_data.mutes_label', defaultMessage: 'Mutes' },
|
||||||
|
// input_hint: { id: 'import_data.hints.mutes', defaultMessage: 'CSV file containing a list of muted accounts' },
|
||||||
|
// submit: { id: 'import_data.actions.import_mutes', defaultMessage: 'Import mutes' },
|
||||||
|
// });
|
||||||
|
|
||||||
|
export default @injectIntl
|
||||||
|
class ImportData extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column icon='cloud-upload' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||||
|
<CSVImporter action={importFollows} messages={followMessages} />
|
||||||
|
<CSVImporter action={importBlocks} messages={blockMessages} />
|
||||||
|
{/* <CSVImporter action={importMutes} messages={muteMessages} /> */}
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -321,7 +321,7 @@ class SoapboxConfig extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='input with_block_label'>
|
{/* <div className='input with_block_label'>
|
||||||
<label><FormattedMessage id='soapbox_config.fields.custom_css_fields_label' defaultMessage='Custom CSS' /></label>
|
<label><FormattedMessage id='soapbox_config.fields.custom_css_fields_label' defaultMessage='Custom CSS' /></label>
|
||||||
<span className='hint'>
|
<span className='hint'>
|
||||||
<FormattedMessage id='soapbox_config.hints.custom_css_fields' defaultMessage='Insert a URL to a CSS file like `https://mysite.com/instance/custom.css`, or simply `/instance/custom.css`' />
|
<FormattedMessage id='soapbox_config.hints.custom_css_fields' defaultMessage='Insert a URL to a CSS file like `https://mysite.com/instance/custom.css`, or simply `/instance/custom.css`' />
|
||||||
|
@ -345,7 +345,7 @@ class SoapboxConfig extends ImmutablePureComponent {
|
||||||
<FormattedMessage id='soapbox_config.fields.custom_css.add' defaultMessage='Add another custom CSS URL' />
|
<FormattedMessage id='soapbox_config.fields.custom_css.add' defaultMessage='Add another custom CSS URL' />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
</FieldsGroup>
|
</FieldsGroup>
|
||||||
<FieldsGroup>
|
<FieldsGroup>
|
||||||
<div className={this.state.jsonValid ? 'code-editor' : 'code-editor code-editor--invalid'}>
|
<div className={this.state.jsonValid ? 'code-editor' : 'code-editor code-editor--invalid'}>
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import ComposeFormContainer from '../../compose/containers/compose_form_container';
|
|
||||||
import NotificationsContainer from '../../ui/containers/notifications_container';
|
|
||||||
import LoadingBarContainer from '../../ui/containers/loading_bar_container';
|
|
||||||
import ModalContainer from '../../ui/containers/modal_container';
|
|
||||||
|
|
||||||
export default class Compose extends React.PureComponent {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<ComposeFormContainer />
|
|
||||||
<NotificationsContainer />
|
|
||||||
<ModalContainer />
|
|
||||||
<LoadingBarContainer className='loading-bar' />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import { expandHashtagTimeline } from 'soapbox/actions/timelines';
|
|
||||||
import Masonry from 'react-masonry-infinite';
|
|
||||||
import { List as ImmutableList } from 'immutable';
|
|
||||||
import DetailedStatusContainer from 'soapbox/features/status/containers/detailed_status_container';
|
|
||||||
import { debounce } from 'lodash';
|
|
||||||
import LoadingIndicator from 'soapbox/components/loading_indicator';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { hashtag }) => ({
|
|
||||||
statusIds: state.getIn(['timelines', `hashtag:${hashtag}`, 'items'], ImmutableList()),
|
|
||||||
isLoading: state.getIn(['timelines', `hashtag:${hashtag}`, 'isLoading'], false),
|
|
||||||
hasMore: state.getIn(['timelines', `hashtag:${hashtag}`, 'hasMore'], false),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
|
||||||
class HashtagTimeline extends React.PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
dispatch: PropTypes.func.isRequired,
|
|
||||||
statusIds: ImmutablePropTypes.list.isRequired,
|
|
||||||
isLoading: PropTypes.bool.isRequired,
|
|
||||||
hasMore: PropTypes.bool.isRequired,
|
|
||||||
hashtag: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const { dispatch, hashtag } = this.props;
|
|
||||||
|
|
||||||
dispatch(expandHashtagTimeline(hashtag));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLoadMore = () => {
|
|
||||||
const maxId = this.props.statusIds.last();
|
|
||||||
|
|
||||||
if (maxId) {
|
|
||||||
this.props.dispatch(expandHashtagTimeline(this.props.hashtag, { maxId }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setRef = c => {
|
|
||||||
this.masonry = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleHeightChange = debounce(() => {
|
|
||||||
if (!this.masonry) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.masonry.forcePack();
|
|
||||||
}, 50)
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { statusIds, hasMore, isLoading } = this.props;
|
|
||||||
|
|
||||||
const sizes = [
|
|
||||||
{ columns: 1, gutter: 0 },
|
|
||||||
{ mq: '415px', columns: 1, gutter: 10 },
|
|
||||||
{ mq: '640px', columns: 2, gutter: 10 },
|
|
||||||
{ mq: '960px', columns: 3, gutter: 10 },
|
|
||||||
{ mq: '1255px', columns: 3, gutter: 10 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const loader = (isLoading && statusIds.isEmpty()) ? <LoadingIndicator key={0} /> : undefined;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Masonry ref={this.setRef} className='statuses-grid' hasMore={hasMore} loadMore={this.handleLoadMore} sizes={sizes} loader={loader}>
|
|
||||||
{statusIds.map(statusId => (
|
|
||||||
<div className='statuses-grid__item' key={statusId}>
|
|
||||||
<DetailedStatusContainer
|
|
||||||
id={statusId}
|
|
||||||
compact
|
|
||||||
measureHeight
|
|
||||||
onHeightChange={this.handleHeightChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)).toArray()}
|
|
||||||
</Masonry>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import { expandPublicTimeline, expandCommunityTimeline } from 'soapbox/actions/timelines';
|
|
||||||
import Masonry from 'react-masonry-infinite';
|
|
||||||
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
|
||||||
import DetailedStatusContainer from 'soapbox/features/status/containers/detailed_status_container';
|
|
||||||
import { debounce } from 'lodash';
|
|
||||||
import LoadingIndicator from 'soapbox/components/loading_indicator';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { local }) => {
|
|
||||||
const timeline = state.getIn(['timelines', local ? 'community' : 'public'], ImmutableMap());
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusIds: timeline.get('items', ImmutableList()),
|
|
||||||
isLoading: timeline.get('isLoading', false),
|
|
||||||
hasMore: timeline.get('hasMore', false),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
|
||||||
class PublicTimeline extends React.PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
dispatch: PropTypes.func.isRequired,
|
|
||||||
statusIds: ImmutablePropTypes.list.isRequired,
|
|
||||||
isLoading: PropTypes.bool.isRequired,
|
|
||||||
hasMore: PropTypes.bool.isRequired,
|
|
||||||
local: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this._connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
if (prevProps.local !== this.props.local) {
|
|
||||||
this._connect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_connect() {
|
|
||||||
const { dispatch, local } = this.props;
|
|
||||||
|
|
||||||
dispatch(local ? expandCommunityTimeline() : expandPublicTimeline());
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLoadMore = () => {
|
|
||||||
const { dispatch, statusIds, local } = this.props;
|
|
||||||
const maxId = statusIds.last();
|
|
||||||
|
|
||||||
if (maxId) {
|
|
||||||
dispatch(local ? expandCommunityTimeline({ maxId }) : expandPublicTimeline({ maxId }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setRef = c => {
|
|
||||||
this.masonry = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleHeightChange = debounce(() => {
|
|
||||||
if (!this.masonry) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.masonry.forcePack();
|
|
||||||
}, 50)
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { statusIds, hasMore, isLoading } = this.props;
|
|
||||||
|
|
||||||
const sizes = [
|
|
||||||
{ columns: 1, gutter: 0 },
|
|
||||||
{ mq: '415px', columns: 1, gutter: 10 },
|
|
||||||
{ mq: '640px', columns: 2, gutter: 10 },
|
|
||||||
{ mq: '960px', columns: 3, gutter: 10 },
|
|
||||||
{ mq: '1255px', columns: 3, gutter: 10 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const loader = (isLoading && statusIds.isEmpty()) ? <LoadingIndicator key={0} /> : undefined;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Masonry ref={this.setRef} className='statuses-grid' hasMore={hasMore} loadMore={this.handleLoadMore} sizes={sizes} loader={loader}>
|
|
||||||
{statusIds.map(statusId => (
|
|
||||||
<div className='statuses-grid__item' key={statusId}>
|
|
||||||
<DetailedStatusContainer
|
|
||||||
id={statusId}
|
|
||||||
compact
|
|
||||||
measureHeight
|
|
||||||
onHeightChange={this.handleHeightChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)).toArray()}
|
|
||||||
</Masonry>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -175,7 +175,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<DisplayName account={status.get('account')}>
|
<DisplayName account={status.get('account')}>
|
||||||
<HoverRefWrapper accountId={status.getIn(['account', 'id'])}>
|
<HoverRefWrapper accountId={status.getIn(['account', 'id'])}>
|
||||||
<NavLink to={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} />
|
<NavLink className='floating-link' to={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} />
|
||||||
</HoverRefWrapper>
|
</HoverRefWrapper>
|
||||||
</DisplayName>
|
</DisplayName>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -78,6 +78,7 @@ import {
|
||||||
Preferences,
|
Preferences,
|
||||||
EditProfile,
|
EditProfile,
|
||||||
SoapboxConfig,
|
SoapboxConfig,
|
||||||
|
ImportData,
|
||||||
PasswordReset,
|
PasswordReset,
|
||||||
SecurityForm,
|
SecurityForm,
|
||||||
MfaForm,
|
MfaForm,
|
||||||
|
@ -263,6 +264,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
||||||
<Redirect exact from='/settings' to='/settings/preferences' />
|
<Redirect exact from='/settings' to='/settings/preferences' />
|
||||||
<WrappedRoute path='/settings/preferences' layout={LAYOUT.DEFAULT} component={Preferences} content={children} />
|
<WrappedRoute path='/settings/preferences' layout={LAYOUT.DEFAULT} component={Preferences} content={children} />
|
||||||
<WrappedRoute path='/settings/profile' layout={LAYOUT.DEFAULT} component={EditProfile} content={children} />
|
<WrappedRoute path='/settings/profile' layout={LAYOUT.DEFAULT} component={EditProfile} content={children} />
|
||||||
|
<WrappedRoute path='/settings/import' layout={LAYOUT.DEFAULT} component={ImportData} content={children} />
|
||||||
<WrappedRoute path='/soapbox/config' layout={LAYOUT.DEFAULT} component={SoapboxConfig} content={children} />
|
<WrappedRoute path='/soapbox/config' layout={LAYOUT.DEFAULT} component={SoapboxConfig} content={children} />
|
||||||
|
|
||||||
<WrappedRoute layout={LAYOUT.EMPTY} component={GenericNotFound} content={children} />
|
<WrappedRoute layout={LAYOUT.EMPTY} component={GenericNotFound} content={children} />
|
||||||
|
|
|
@ -186,6 +186,10 @@ export function SoapboxConfig() {
|
||||||
return import(/* webpackChunkName: "features/soapbox_config" */'../../soapbox_config');
|
return import(/* webpackChunkName: "features/soapbox_config" */'../../soapbox_config');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ImportData() {
|
||||||
|
return import(/* webpackChunkName: "features/import_data" */'../../import_data');
|
||||||
|
}
|
||||||
|
|
||||||
export function PasswordReset() {
|
export function PasswordReset() {
|
||||||
return import(/* webpackChunkName: "features/auth_login" */'../../auth_login/components/password_reset');
|
return import(/* webpackChunkName: "features/auth_login" */'../../auth_login/components/password_reset');
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ class WrappedRoute extends React.Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
component: PropTypes.func.isRequired,
|
component: PropTypes.func.isRequired,
|
||||||
page: PropTypes.func,
|
page: PropTypes.object,
|
||||||
content: PropTypes.node,
|
content: PropTypes.node,
|
||||||
componentParams: PropTypes.object,
|
componentParams: PropTypes.object,
|
||||||
layout: PropTypes.object,
|
layout: PropTypes.object,
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const element = document.getElementById('initial-state');
|
|
||||||
const initialState = element ? JSON.parse(element.textContent) : {};
|
|
||||||
|
|
||||||
export default initialState;
|
|
|
@ -3,18 +3,18 @@ import { Map as ImmutableMap } from 'immutable';
|
||||||
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
|
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
|
||||||
import { SETTING_CHANGE } from 'soapbox/actions/settings';
|
import { SETTING_CHANGE } from 'soapbox/actions/settings';
|
||||||
import * as actions from 'soapbox/actions/compose';
|
import * as actions from 'soapbox/actions/compose';
|
||||||
//import { STORE_HYDRATE } from 'soapbox/actions/store';
|
|
||||||
//import { REDRAFT } from 'soapbox/actions/statuses';
|
//import { REDRAFT } from 'soapbox/actions/statuses';
|
||||||
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
|
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
|
||||||
|
|
||||||
describe('compose reducer', () => {
|
describe('compose reducer', () => {
|
||||||
it('returns the initial state by default', () => {
|
it('returns the initial state by default', () => {
|
||||||
expect(reducer(undefined, {}).toJS()).toMatchObject({
|
const state = reducer(undefined, {});
|
||||||
|
expect(state.toJS()).toMatchObject({
|
||||||
mounted: 0,
|
mounted: 0,
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
spoiler: false,
|
spoiler: false,
|
||||||
spoiler_text: '',
|
spoiler_text: '',
|
||||||
privacy: null,
|
privacy: 'public',
|
||||||
text: '',
|
text: '',
|
||||||
focusDate: null,
|
focusDate: null,
|
||||||
caretPosition: null,
|
caretPosition: null,
|
||||||
|
@ -30,10 +30,10 @@ describe('compose reducer', () => {
|
||||||
suggestions: [],
|
suggestions: [],
|
||||||
default_privacy: 'public',
|
default_privacy: 'public',
|
||||||
default_sensitive: false,
|
default_sensitive: false,
|
||||||
idempotencyKey: null,
|
|
||||||
tagHistory: [],
|
tagHistory: [],
|
||||||
content_type: 'text/markdown',
|
content_type: 'text/markdown',
|
||||||
});
|
});
|
||||||
|
expect(state.get('idempotencyKey').length === 36);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses \'public\' scope as default', () => {
|
it('uses \'public\' scope as default', () => {
|
||||||
|
@ -132,23 +132,6 @@ describe('compose reducer', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should handle STORE_HYDRATE', () => {
|
|
||||||
// const state = ImmutableMap({ });
|
|
||||||
// const action = {
|
|
||||||
// type: STORE_HYDRATE,
|
|
||||||
// state: ImmutableMap({
|
|
||||||
// compose: true,
|
|
||||||
// text: 'newtext',
|
|
||||||
// }),
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action)).toEqual(ImmutableMap({
|
|
||||||
// state: ImmutableMap({
|
|
||||||
// compose: true,
|
|
||||||
// text: 'newtext',
|
|
||||||
// }),
|
|
||||||
// }));
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should handle COMPOSE_MOUNT', () => {
|
it('should handle COMPOSE_MOUNT', () => {
|
||||||
const state = ImmutableMap({ mounted: 1 });
|
const state = ImmutableMap({ mounted: 1 });
|
||||||
const action = {
|
const action = {
|
||||||
|
|
|
@ -38,21 +38,22 @@ import {
|
||||||
COMPOSE_POLL_SETTINGS_CHANGE,
|
COMPOSE_POLL_SETTINGS_CHANGE,
|
||||||
} 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 { REDRAFT } from '../actions/statuses';
|
import { REDRAFT } from '../actions/statuses';
|
||||||
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from '../actions/me';
|
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from '../actions/me';
|
||||||
import { SETTING_CHANGE, FE_NAME } from '../actions/settings';
|
import { SETTING_CHANGE, FE_NAME } from '../actions/settings';
|
||||||
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
||||||
|
import { tagHistory } from 'soapbox/settings';
|
||||||
import uuid from '../uuid';
|
import uuid from '../uuid';
|
||||||
import { unescapeHTML } from '../utils/html';
|
import { unescapeHTML } from '../utils/html';
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
|
id: null,
|
||||||
mounted: 0,
|
mounted: 0,
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
spoiler: false,
|
spoiler: false,
|
||||||
spoiler_text: '',
|
spoiler_text: '',
|
||||||
content_type: 'text/markdown',
|
content_type: 'text/markdown',
|
||||||
privacy: null,
|
privacy: 'public',
|
||||||
text: '',
|
text: '',
|
||||||
focusDate: null,
|
focusDate: null,
|
||||||
caretPosition: null,
|
caretPosition: null,
|
||||||
|
@ -69,7 +70,7 @@ const initialState = ImmutableMap({
|
||||||
default_privacy: 'public',
|
default_privacy: 'public',
|
||||||
default_sensitive: false,
|
default_sensitive: false,
|
||||||
resetFileKey: Math.floor((Math.random() * 0x10000)),
|
resetFileKey: Math.floor((Math.random() * 0x10000)),
|
||||||
idempotencyKey: null,
|
idempotencyKey: uuid(),
|
||||||
tagHistory: ImmutableList(),
|
tagHistory: ImmutableList(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -178,16 +179,6 @@ const privacyPreference = (a, b) => {
|
||||||
return order[Math.max(order.indexOf(a), order.indexOf(b), 0)];
|
return order[Math.max(order.indexOf(a), order.indexOf(b), 0)];
|
||||||
};
|
};
|
||||||
|
|
||||||
const hydrate = (state, hydratedState = ImmutableMap()) => {
|
|
||||||
state = clearAll(state.merge(hydratedState));
|
|
||||||
|
|
||||||
if (hydratedState.has('text')) {
|
|
||||||
state = state.set('text', hydratedState.get('text'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
};
|
|
||||||
|
|
||||||
const domParser = new DOMParser();
|
const domParser = new DOMParser();
|
||||||
|
|
||||||
const expandMentions = status => {
|
const expandMentions = status => {
|
||||||
|
@ -204,8 +195,6 @@ const expandMentions = status => {
|
||||||
export default function compose(state = initialState, action) {
|
export default function compose(state = initialState, action) {
|
||||||
let me, defaultPrivacy;
|
let me, defaultPrivacy;
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case STORE_HYDRATE:
|
|
||||||
return hydrate(state, action.state.get('compose'));
|
|
||||||
case COMPOSE_MOUNT:
|
case COMPOSE_MOUNT:
|
||||||
return state.set('mounted', state.get('mounted') + 1);
|
return state.set('mounted', state.get('mounted') + 1);
|
||||||
case COMPOSE_UNMOUNT:
|
case COMPOSE_UNMOUNT:
|
||||||
|
@ -374,9 +363,12 @@ export default function compose(state = initialState, action) {
|
||||||
return state.update('poll', poll => poll.set('expires_in', action.expiresIn).set('multiple', action.isMultiple));
|
return state.update('poll', poll => poll.set('expires_in', action.expiresIn).set('multiple', action.isMultiple));
|
||||||
case ME_FETCH_SUCCESS:
|
case ME_FETCH_SUCCESS:
|
||||||
me = fromJS(action.me);
|
me = fromJS(action.me);
|
||||||
defaultPrivacy = me.getIn(['pleroma', 'settings_store', FE_NAME, 'defaultPrivacy']);
|
defaultPrivacy = me.getIn(['pleroma', 'settings_store', FE_NAME, 'defaultPrivacy'], 'public');
|
||||||
if (!defaultPrivacy) return state;
|
return state.merge({
|
||||||
return state.set('default_privacy', defaultPrivacy).set('privacy', defaultPrivacy);
|
default_privacy: defaultPrivacy,
|
||||||
|
privacy: defaultPrivacy,
|
||||||
|
tagHistory: ImmutableList(tagHistory.get(action.me.id)),
|
||||||
|
});
|
||||||
case ME_PATCH_SUCCESS:
|
case ME_PATCH_SUCCESS:
|
||||||
me = fromJS(action.me);
|
me = fromJS(action.me);
|
||||||
defaultPrivacy = me.getIn(['pleroma', 'settings_store', FE_NAME, 'defaultPrivacy']);
|
defaultPrivacy = me.getIn(['pleroma', 'settings_store', FE_NAME, 'defaultPrivacy']);
|
||||||
|
|
|
@ -3,7 +3,8 @@ import {
|
||||||
ACCOUNT_MUTE_SUCCESS,
|
ACCOUNT_MUTE_SUCCESS,
|
||||||
} from '../actions/accounts';
|
} from '../actions/accounts';
|
||||||
import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses';
|
import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses';
|
||||||
import { TIMELINE_DELETE, TIMELINE_UPDATE } from '../actions/timelines';
|
import { TIMELINE_DELETE } from '../actions/timelines';
|
||||||
|
import { STATUS_IMPORT, STATUSES_IMPORT } from 'soapbox/actions/importer';
|
||||||
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
|
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
|
@ -87,8 +88,12 @@ export default function replies(state = initialState, action) {
|
||||||
return normalizeContext(state, action.id, action.ancestors, action.descendants);
|
return normalizeContext(state, action.id, action.ancestors, action.descendants);
|
||||||
case TIMELINE_DELETE:
|
case TIMELINE_DELETE:
|
||||||
return deleteFromContexts(state, [action.id]);
|
return deleteFromContexts(state, [action.id]);
|
||||||
case TIMELINE_UPDATE:
|
case STATUS_IMPORT:
|
||||||
return updateContext(state, action.status);
|
return updateContext(state, action.status);
|
||||||
|
case STATUSES_IMPORT:
|
||||||
|
return state.withMutations(mutable =>
|
||||||
|
action.statuses.forEach(status => updateContext(mutable, status)));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import { combineReducers } from 'redux-immutable';
|
import { combineReducers } from 'redux-immutable';
|
||||||
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
import { AUTH_LOGGED_OUT } from 'soapbox/actions/auth';
|
||||||
import dropdown_menu from './dropdown_menu';
|
import dropdown_menu from './dropdown_menu';
|
||||||
import timelines from './timelines';
|
import timelines from './timelines';
|
||||||
import meta from './meta';
|
import meta from './meta';
|
||||||
|
@ -48,7 +50,7 @@ import chat_messages from './chat_messages';
|
||||||
import chat_message_lists from './chat_message_lists';
|
import chat_message_lists from './chat_message_lists';
|
||||||
import profile_hover_card from './profile_hover_card';
|
import profile_hover_card from './profile_hover_card';
|
||||||
|
|
||||||
const reducers = {
|
const appReducer = combineReducers({
|
||||||
dropdown_menu,
|
dropdown_menu,
|
||||||
timelines,
|
timelines,
|
||||||
meta,
|
meta,
|
||||||
|
@ -97,6 +99,27 @@ const reducers = {
|
||||||
chat_messages,
|
chat_messages,
|
||||||
chat_message_lists,
|
chat_message_lists,
|
||||||
profile_hover_card,
|
profile_hover_card,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear the state (mostly) when the user logs out
|
||||||
|
const logOut = (state = ImmutableMap()) => {
|
||||||
|
const whitelist = ['instance', 'soapbox', 'custom_emojis'];
|
||||||
|
|
||||||
|
return ImmutableMap(
|
||||||
|
whitelist.reduce((acc, curr) => {
|
||||||
|
acc[curr] = state.get(curr);
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default combineReducers(reducers);
|
const rootReducer = (state, action) => {
|
||||||
|
switch(action.type) {
|
||||||
|
case AUTH_LOGGED_OUT:
|
||||||
|
return appReducer(logOut(state), action);
|
||||||
|
default:
|
||||||
|
return appReducer(state, action);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default rootReducer;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { STORE_HYDRATE } from '../actions/store';
|
|
||||||
import {
|
import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
List as ImmutableList,
|
List as ImmutableList,
|
||||||
|
@ -35,8 +34,6 @@ const initialState = ImmutableMap({
|
||||||
|
|
||||||
export default function meta(state = initialState, action) {
|
export default function meta(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case STORE_HYDRATE:
|
|
||||||
return state.merge(action.state.get('media_attachments'));
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { STORE_HYDRATE } from '../actions/store';
|
|
||||||
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
|
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
|
@ -8,8 +7,6 @@ const initialState = ImmutableMap();
|
||||||
|
|
||||||
export default function meta(state = initialState, action) {
|
export default function meta(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case STORE_HYDRATE:
|
|
||||||
return state.merge(action.state.get('meta'));
|
|
||||||
case ME_FETCH_SUCCESS:
|
case ME_FETCH_SUCCESS:
|
||||||
case ME_PATCH_SUCCESS:
|
case ME_PATCH_SUCCESS:
|
||||||
const me = fromJS(action.me);
|
const me = fromJS(action.me);
|
||||||
|
|
|
@ -32,8 +32,9 @@ const initialState = ImmutableMap({
|
||||||
|
|
||||||
// For sorting the notifications
|
// For sorting the notifications
|
||||||
const comparator = (a, b) => {
|
const comparator = (a, b) => {
|
||||||
if (a.get('id') < b.get('id')) return 1;
|
const parse = m => parseInt(m.get('id'), 10);
|
||||||
if (a.get('id') > b.get('id')) return -1;
|
if (parse(a) < parse(b)) return 1;
|
||||||
|
if (parse(a) > parse(b)) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { STORE_HYDRATE } from '../actions/store';
|
|
||||||
import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, CLEAR_SUBSCRIPTION, SET_ALERTS } from '../actions/push_notifications';
|
import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, CLEAR_SUBSCRIPTION, SET_ALERTS } from '../actions/push_notifications';
|
||||||
import Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
|
|
||||||
|
@ -17,21 +16,6 @@ const initialState = Immutable.Map({
|
||||||
|
|
||||||
export default function push_subscriptions(state = initialState, action) {
|
export default function push_subscriptions(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case STORE_HYDRATE: {
|
|
||||||
const push_subscription = action.state.get('push_subscription');
|
|
||||||
|
|
||||||
if (push_subscription) {
|
|
||||||
return state
|
|
||||||
.set('subscription', new Immutable.Map({
|
|
||||||
id: push_subscription.get('id'),
|
|
||||||
endpoint: push_subscription.get('endpoint'),
|
|
||||||
}))
|
|
||||||
.set('alerts', push_subscription.get('alerts') || initialState.get('alerts'))
|
|
||||||
.set('isSubscribed', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
case SET_SUBSCRIPTION:
|
case SET_SUBSCRIPTION:
|
||||||
return state
|
return state
|
||||||
.set('subscription', new Immutable.Map({
|
.set('subscription', new Immutable.Map({
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { SETTING_CHANGE, SETTING_SAVE, FE_NAME } from '../actions/settings';
|
import { SETTING_CHANGE, SETTING_SAVE, FE_NAME } from '../actions/settings';
|
||||||
import { NOTIFICATIONS_FILTER_SET } from '../actions/notifications';
|
import { NOTIFICATIONS_FILTER_SET } from '../actions/notifications';
|
||||||
import { STORE_HYDRATE } from '../actions/store';
|
|
||||||
import { EMOJI_USE } from '../actions/emojis';
|
import { EMOJI_USE } from '../actions/emojis';
|
||||||
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists';
|
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists';
|
||||||
import { ME_FETCH_SUCCESS } from 'soapbox/actions/me';
|
import { ME_FETCH_SUCCESS } from 'soapbox/actions/me';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
import uuid from '../uuid';
|
|
||||||
|
|
||||||
// Default settings are in action/settings.js
|
// Default settings are in action/settings.js
|
||||||
//
|
//
|
||||||
|
@ -15,22 +13,12 @@ const initialState = ImmutableMap({
|
||||||
saved: true,
|
saved: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultColumns = fromJS([
|
|
||||||
{ id: 'COMPOSE', uuid: uuid(), params: {} },
|
|
||||||
{ id: 'HOME', uuid: uuid(), params: {} },
|
|
||||||
{ id: 'NOTIFICATIONS', uuid: uuid(), params: {} },
|
|
||||||
]);
|
|
||||||
|
|
||||||
const hydrate = (state, settings) => state.mergeDeep(settings).update('columns', (val = defaultColumns) => val);
|
|
||||||
|
|
||||||
const updateFrequentEmojis = (state, emoji) => state.update('frequentlyUsedEmojis', ImmutableMap(), map => map.update(emoji.id, 0, count => count + 1)).set('saved', false);
|
const updateFrequentEmojis = (state, emoji) => state.update('frequentlyUsedEmojis', ImmutableMap(), map => map.update(emoji.id, 0, count => count + 1)).set('saved', false);
|
||||||
|
|
||||||
const filterDeadListColumns = (state, listId) => state.update('columns', columns => columns.filterNot(column => column.get('id') === 'LIST' && column.get('params').get('id') === listId));
|
const filterDeadListColumns = (state, listId) => state.update('columns', columns => columns.filterNot(column => column.get('id') === 'LIST' && column.get('params').get('id') === listId));
|
||||||
|
|
||||||
export default function settings(state = initialState, action) {
|
export default function settings(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case STORE_HYDRATE:
|
|
||||||
return hydrate(state, action.state.get('settings'));
|
|
||||||
case ME_FETCH_SUCCESS:
|
case ME_FETCH_SUCCESS:
|
||||||
const me = fromJS(action.me);
|
const me = fromJS(action.me);
|
||||||
let fePrefs = me.getIn(['pleroma', 'settings_store', FE_NAME], ImmutableMap());
|
let fePrefs = me.getIn(['pleroma', 'settings_store', FE_NAME], ImmutableMap());
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
REBLOG_REQUEST,
|
REBLOG_REQUEST,
|
||||||
REBLOG_FAIL,
|
REBLOG_FAIL,
|
||||||
FAVOURITE_REQUEST,
|
FAVOURITE_REQUEST,
|
||||||
|
UNFAVOURITE_REQUEST,
|
||||||
FAVOURITE_FAIL,
|
FAVOURITE_FAIL,
|
||||||
} from '../actions/interactions';
|
} from '../actions/interactions';
|
||||||
import {
|
import {
|
||||||
|
@ -12,11 +13,12 @@ import {
|
||||||
} from '../actions/statuses';
|
} from '../actions/statuses';
|
||||||
import {
|
import {
|
||||||
EMOJI_REACT_REQUEST,
|
EMOJI_REACT_REQUEST,
|
||||||
|
UNEMOJI_REACT_REQUEST,
|
||||||
} from '../actions/emoji_reacts';
|
} from '../actions/emoji_reacts';
|
||||||
import { TIMELINE_DELETE } from '../actions/timelines';
|
import { TIMELINE_DELETE } from '../actions/timelines';
|
||||||
import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
|
import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
import { simulateEmojiReact } from 'soapbox/utils/emoji_reacts';
|
import { simulateEmojiReact, simulateUnEmojiReact } from 'soapbox/utils/emoji_reacts';
|
||||||
|
|
||||||
const importStatus = (state, status) => state.set(status.id, fromJS(status));
|
const importStatus = (state, status) => state.set(status.id, fromJS(status));
|
||||||
|
|
||||||
|
@ -40,11 +42,27 @@ export default function statuses(state = initialState, action) {
|
||||||
case STATUSES_IMPORT:
|
case STATUSES_IMPORT:
|
||||||
return importStatuses(state, action.statuses);
|
return importStatuses(state, action.statuses);
|
||||||
case FAVOURITE_REQUEST:
|
case FAVOURITE_REQUEST:
|
||||||
return state.setIn([action.status.get('id'), 'favourited'], true);
|
return state.update(action.status.get('id'), status =>
|
||||||
|
status
|
||||||
|
.set('favourited', true)
|
||||||
|
.update('favourites_count', count => count + 1));
|
||||||
|
case UNFAVOURITE_REQUEST:
|
||||||
|
return state.update(action.status.get('id'), status =>
|
||||||
|
status
|
||||||
|
.set('favourited', false)
|
||||||
|
.update('favourites_count', count => Math.max(0, count - 1)));
|
||||||
case EMOJI_REACT_REQUEST:
|
case EMOJI_REACT_REQUEST:
|
||||||
const path = [action.status.get('id'), 'pleroma', 'emoji_reactions'];
|
return state
|
||||||
const emojiReacts = state.getIn(path);
|
.updateIn(
|
||||||
return state.setIn(path, simulateEmojiReact(emojiReacts, action.emoji));
|
[action.status.get('id'), 'pleroma', 'emoji_reactions'],
|
||||||
|
emojiReacts => simulateEmojiReact(emojiReacts, action.emoji)
|
||||||
|
);
|
||||||
|
case UNEMOJI_REACT_REQUEST:
|
||||||
|
return state
|
||||||
|
.updateIn(
|
||||||
|
[action.status.get('id'), 'pleroma', 'emoji_reactions'],
|
||||||
|
emojiReacts => simulateUnEmojiReact(emojiReacts, action.emoji)
|
||||||
|
);
|
||||||
case FAVOURITE_FAIL:
|
case FAVOURITE_FAIL:
|
||||||
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false);
|
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false);
|
||||||
case REBLOG_REQUEST:
|
case REBLOG_REQUEST:
|
||||||
|
|
|
@ -65,10 +65,10 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, is
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateTimeline = (state, timeline, status) => {
|
const updateTimeline = (state, timeline, statusId) => {
|
||||||
const top = state.getIn([timeline, 'top']);
|
const top = state.getIn([timeline, 'top']);
|
||||||
const ids = state.getIn([timeline, 'items'], ImmutableList());
|
const ids = state.getIn([timeline, 'items'], ImmutableList());
|
||||||
const includesId = ids.includes(status.get('id'));
|
const includesId = ids.includes(statusId);
|
||||||
const unread = state.getIn([timeline, 'unread'], 0);
|
const unread = state.getIn([timeline, 'unread'], 0);
|
||||||
|
|
||||||
if (includesId) {
|
if (includesId) {
|
||||||
|
@ -80,17 +80,17 @@ const updateTimeline = (state, timeline, status) => {
|
||||||
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
||||||
if (!top) mMap.set('unread', unread + 1);
|
if (!top) mMap.set('unread', unread + 1);
|
||||||
if (top && ids.size > 40) newIds = newIds.take(20);
|
if (top && ids.size > 40) newIds = newIds.take(20);
|
||||||
mMap.set('items', newIds.unshift(status.get('id')));
|
mMap.set('items', newIds.unshift(statusId));
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateTimelineQueue = (state, timeline, status) => {
|
const updateTimelineQueue = (state, timeline, statusId) => {
|
||||||
const queuedStatuses = state.getIn([timeline, 'queuedItems'], ImmutableList());
|
const queuedStatuses = state.getIn([timeline, 'queuedItems'], ImmutableList());
|
||||||
const listedStatuses = state.getIn([timeline, 'items'], ImmutableList());
|
const listedStatuses = state.getIn([timeline, 'items'], ImmutableList());
|
||||||
const totalQueuedItemsCount = state.getIn([timeline, 'totalQueuedItemsCount'], 0);
|
const totalQueuedItemsCount = state.getIn([timeline, 'totalQueuedItemsCount'], 0);
|
||||||
|
|
||||||
let alreadyExists = queuedStatuses.find(existingQueuedStatus => existingQueuedStatus.get('id') === status.get('id'));
|
let alreadyExists = queuedStatuses.find(existingQueuedStatus => existingQueuedStatus === statusId);
|
||||||
if (!alreadyExists) alreadyExists = listedStatuses.find(existingListedStatusId => existingListedStatusId === status.get('id'));
|
if (!alreadyExists) alreadyExists = listedStatuses.find(existingListedStatusId => existingListedStatusId === statusId);
|
||||||
|
|
||||||
if (alreadyExists) {
|
if (alreadyExists) {
|
||||||
return state;
|
return state;
|
||||||
|
@ -100,7 +100,7 @@ const updateTimelineQueue = (state, timeline, status) => {
|
||||||
|
|
||||||
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
||||||
if (totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
|
if (totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
|
||||||
mMap.set('queuedItems', newQueuedStatuses.push(status));
|
mMap.set('queuedItems', newQueuedStatuses.push(statusId));
|
||||||
}
|
}
|
||||||
mMap.set('totalQueuedItemsCount', totalQueuedItemsCount + 1);
|
mMap.set('totalQueuedItemsCount', totalQueuedItemsCount + 1);
|
||||||
}));
|
}));
|
||||||
|
@ -165,9 +165,9 @@ export default function timelines(state = initialState, action) {
|
||||||
case TIMELINE_EXPAND_SUCCESS:
|
case TIMELINE_EXPAND_SUCCESS:
|
||||||
return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent);
|
return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent);
|
||||||
case TIMELINE_UPDATE:
|
case TIMELINE_UPDATE:
|
||||||
return updateTimeline(state, action.timeline, fromJS(action.status));
|
return updateTimeline(state, action.timeline, action.statusId);
|
||||||
case TIMELINE_UPDATE_QUEUE:
|
case TIMELINE_UPDATE_QUEUE:
|
||||||
return updateTimelineQueue(state, action.timeline, fromJS(action.status));
|
return updateTimelineQueue(state, action.timeline, action.statusId);
|
||||||
case TIMELINE_DEQUEUE:
|
case TIMELINE_DEQUEUE:
|
||||||
return state.update(action.timeline, initialTimeline, map => map.withMutations(mMap => {
|
return state.update(action.timeline, initialTimeline, map => map.withMutations(mMap => {
|
||||||
mMap.set('queuedItems', ImmutableList());
|
mMap.set('queuedItems', ImmutableList());
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
reduceEmoji,
|
reduceEmoji,
|
||||||
getReactForStatus,
|
getReactForStatus,
|
||||||
simulateEmojiReact,
|
simulateEmojiReact,
|
||||||
|
simulateUnEmojiReact,
|
||||||
} from '../emoji_reacts';
|
} from '../emoji_reacts';
|
||||||
import { fromJS } from 'immutable';
|
import { fromJS } from 'immutable';
|
||||||
|
|
||||||
|
@ -205,3 +206,28 @@ describe('simulateEmojiReact', () => {
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('simulateUnEmojiReact', () => {
|
||||||
|
it('removes the emoji from the list', () => {
|
||||||
|
const emojiReacts = fromJS([
|
||||||
|
{ 'count': 2, 'me': false, 'name': '👍' },
|
||||||
|
{ 'count': 3, 'me': true, 'name': '❤' },
|
||||||
|
]);
|
||||||
|
expect(simulateUnEmojiReact(emojiReacts, '❤')).toEqual(fromJS([
|
||||||
|
{ 'count': 2, 'me': false, 'name': '👍' },
|
||||||
|
{ 'count': 2, 'me': false, 'name': '❤' },
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes the emoji if it\'s the last one in the list', () => {
|
||||||
|
const emojiReacts = fromJS([
|
||||||
|
{ 'count': 2, 'me': false, 'name': '👍' },
|
||||||
|
{ 'count': 2, 'me': false, 'name': '❤' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '😯' },
|
||||||
|
]);
|
||||||
|
expect(simulateUnEmojiReact(emojiReacts, '😯')).toEqual(fromJS([
|
||||||
|
{ 'count': 2, 'me': false, 'name': '👍' },
|
||||||
|
{ 'count': 2, 'me': false, 'name': '❤' },
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -100,3 +100,20 @@ export const simulateEmojiReact = (emojiReacts, emoji) => {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const simulateUnEmojiReact = (emojiReacts, emoji) => {
|
||||||
|
const idx = emojiReacts.findIndex(e =>
|
||||||
|
e.get('name') === emoji && e.get('me') === true);
|
||||||
|
|
||||||
|
if (idx > -1) {
|
||||||
|
const emojiReact = emojiReacts.get(idx);
|
||||||
|
const newCount = emojiReact.get('count') - 1;
|
||||||
|
if (newCount < 1) return emojiReacts.delete(idx);
|
||||||
|
return emojiReacts.set(idx, emojiReact.merge({
|
||||||
|
count: emojiReact.get('count') - 1,
|
||||||
|
me: false,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return emojiReacts;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
// Detect backend features to conditionally render elements
|
// Detect backend features to conditionally render elements
|
||||||
import semver from 'semver';
|
import gte from 'semver/functions/gte';
|
||||||
|
|
||||||
export const getFeatures = instance => {
|
export const getFeatures = instance => {
|
||||||
const v = parseVersion(instance.get('version'));
|
const v = parseVersion(instance.get('version'));
|
||||||
return {
|
return {
|
||||||
suggestions: v.software === 'Mastodon' && semver.gte(v.compatVersion, '2.4.3'),
|
suggestions: v.software === 'Mastodon' && gte(v.compatVersion, '2.4.3'),
|
||||||
trends: v.software === 'Mastodon' && semver.gte(v.compatVersion, '3.0.0'),
|
trends: v.software === 'Mastodon' && gte(v.compatVersion, '3.0.0'),
|
||||||
emojiReacts: v.software === 'Pleroma' && semver.gte(v.version, '2.0.0'),
|
emojiReacts: v.software === 'Pleroma' && gte(v.version, '2.0.0'),
|
||||||
attachmentLimit: v.software === 'Pleroma' ? Infinity : 4,
|
attachmentLimit: v.software === 'Pleroma' ? Infinity : 4,
|
||||||
focalPoint: v.software === 'Mastodon' && semver.gte(v.compatVersion, '2.3.0'),
|
focalPoint: v.software === 'Mastodon' && gte(v.compatVersion, '2.3.0'),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,72 @@
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import { convert } from 'chromatism';
|
|
||||||
|
|
||||||
export const generateThemeCss = brandColor => {
|
export const generateThemeCss = brandColor => {
|
||||||
if (!brandColor) return null;
|
if (!brandColor) return null;
|
||||||
return themeDataToCss(brandColorToThemeData(brandColor));
|
return themeDataToCss(brandColorToThemeData(brandColor));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/5624139
|
||||||
|
function hexToRgb(hex) {
|
||||||
|
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
|
||||||
|
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||||
|
hex = hex.replace(shorthandRegex, (m, r, g, b) => (
|
||||||
|
r + r + g + g + b + b
|
||||||
|
));
|
||||||
|
|
||||||
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||||
|
return result ? {
|
||||||
|
r: parseInt(result[1], 16),
|
||||||
|
g: parseInt(result[2], 16),
|
||||||
|
b: parseInt(result[3], 16),
|
||||||
|
} : {
|
||||||
|
// fall back to Azure
|
||||||
|
r: 4,
|
||||||
|
g: 130,
|
||||||
|
b: 216,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Taken from chromatism.js
|
||||||
|
// https://github.com/graypegg/chromatism/blob/master/src/conversions/rgb.js
|
||||||
|
const rgbToHsl = value => {
|
||||||
|
var r = value.r / 255;
|
||||||
|
var g = value.g / 255;
|
||||||
|
var b = value.b / 255;
|
||||||
|
var rgbOrdered = [ r, g, b ].sort();
|
||||||
|
var l = ((rgbOrdered[0] + rgbOrdered[2]) / 2) * 100;
|
||||||
|
var s, h;
|
||||||
|
if (rgbOrdered[0] === rgbOrdered[2]) {
|
||||||
|
s = 0;
|
||||||
|
h = 0;
|
||||||
|
} else {
|
||||||
|
if (l >= 50) {
|
||||||
|
s = ((rgbOrdered[2] - rgbOrdered[0]) / ((2.0 - rgbOrdered[2]) - rgbOrdered[0])) * 100;
|
||||||
|
} else {
|
||||||
|
s = ((rgbOrdered[2] - rgbOrdered[0]) / (rgbOrdered[2] + rgbOrdered[0])) * 100;
|
||||||
|
}
|
||||||
|
if (rgbOrdered[2] === r) {
|
||||||
|
h = ((g - b) / (rgbOrdered[2] - rgbOrdered[0])) * 60;
|
||||||
|
} else if (rgbOrdered[2] === g) {
|
||||||
|
h = (2 + ((b - r) / (rgbOrdered[2] - rgbOrdered[0]))) * 60;
|
||||||
|
} else {
|
||||||
|
h = (4 + ((r - g) / (rgbOrdered[2] - rgbOrdered[0]))) * 60;
|
||||||
|
}
|
||||||
|
if (h < 0) {
|
||||||
|
h += 360;
|
||||||
|
} else if (h > 360) {
|
||||||
|
h = h % 360;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
h: h,
|
||||||
|
s: s,
|
||||||
|
l: l,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const brandColorToThemeData = brandColor => {
|
export const brandColorToThemeData = brandColor => {
|
||||||
const { h, s, l } = convert(brandColor).hsl;
|
const { h, s, l } = rgbToHsl(hexToRgb(brandColor));
|
||||||
return ImmutableMap({
|
return ImmutableMap({
|
||||||
'brand-color_h': h,
|
'brand-color_h': h,
|
||||||
'brand-color_s': `${s}%`,
|
'brand-color_s': `${s}%`,
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -177,31 +177,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nothing-here {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
cursor: default;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 20px;
|
|
||||||
min-height: 30vh;
|
|
||||||
|
|
||||||
&--under-tabs {
|
|
||||||
border-radius: 0 0 4px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--flexible {
|
|
||||||
box-sizing: border-box;
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-role {
|
.account-role {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
|
@ -227,104 +202,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.account__header__fields {
|
|
||||||
padding: 0;
|
|
||||||
margin: 15px -15px -15px;
|
|
||||||
border: 0 none;
|
|
||||||
border-top: 1px solid var(--brand-color--med);
|
|
||||||
border-bottom: 1px solid var(--brand-color--med);
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 20px;
|
|
||||||
|
|
||||||
dl {
|
|
||||||
display: flex;
|
|
||||||
border-bottom: 1px solid var(--brand-color--med);
|
|
||||||
}
|
|
||||||
|
|
||||||
dt,
|
|
||||||
dd {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 14px;
|
|
||||||
text-align: center;
|
|
||||||
max-height: 48px;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt {
|
|
||||||
font-weight: 500;
|
|
||||||
width: 120px;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
background: hsla(var(--background-color_hsl), 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--highlight-text-color);
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.verified {
|
|
||||||
border: 1px solid rgba($valid-value-color, 0.5);
|
|
||||||
background: rgba($valid-value-color, 0.25);
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: $valid-value-color;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__mark {
|
|
||||||
color: $valid-value-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dl:last-child {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory__tag .trends__item__current {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pending-account {
|
|
||||||
&__header {
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--background-color);
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:active,
|
|
||||||
&:focus {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__body {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.account {
|
.account {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -5,22 +5,16 @@
|
||||||
@import 'reset';
|
@import 'reset';
|
||||||
@import 'basics';
|
@import 'basics';
|
||||||
@import 'containers';
|
@import 'containers';
|
||||||
@import 'lists';
|
|
||||||
@import 'footer';
|
@import 'footer';
|
||||||
@import 'compact_header';
|
|
||||||
@import 'widgets';
|
|
||||||
@import 'forms';
|
@import 'forms';
|
||||||
@import 'accounts';
|
@import 'accounts';
|
||||||
@import 'stream_entries';
|
|
||||||
@import 'boost';
|
@import 'boost';
|
||||||
@import 'loading';
|
@import 'loading';
|
||||||
@import 'ui';
|
@import 'ui';
|
||||||
@import 'polls';
|
@import 'polls';
|
||||||
@import 'introduction';
|
// @import 'introduction';
|
||||||
@import 'emoji_picker';
|
@import 'emoji_picker';
|
||||||
@import 'about';
|
@import 'about';
|
||||||
@import 'tables';
|
|
||||||
@import 'dashboard';
|
|
||||||
@import 'rtl';
|
@import 'rtl';
|
||||||
@import 'accessibility';
|
@import 'accessibility';
|
||||||
@import 'donations';
|
@import 'donations';
|
||||||
|
@ -38,10 +32,10 @@
|
||||||
@import 'components/account-header';
|
@import 'components/account-header';
|
||||||
@import 'components/user-panel';
|
@import 'components/user-panel';
|
||||||
@import 'components/compose-form';
|
@import 'components/compose-form';
|
||||||
@import 'components/group-card';
|
// @import 'components/group-card';
|
||||||
@import 'components/group-detail';
|
// @import 'components/group-detail';
|
||||||
@import 'components/group-form';
|
// @import 'components/group-form';
|
||||||
@import 'components/group-sidebar-panel';
|
// @import 'components/group-sidebar-panel';
|
||||||
@import 'components/sidebar-menu';
|
@import 'components/sidebar-menu';
|
||||||
@import 'components/hotkeys-modal';
|
@import 'components/hotkeys-modal';
|
||||||
@import 'components/emoji-reacts';
|
@import 'components/emoji-reacts';
|
||||||
|
|
|
@ -176,13 +176,6 @@ body {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__dismiss {
|
|
||||||
display: inline-block;
|
|
||||||
text-transform: uppercase;
|
|
||||||
margin-left: 5px;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: var(--brand-color--hicontrast);
|
color: var(--brand-color--hicontrast);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
width: 265px;
|
width: 265px;
|
||||||
height: 265px;
|
height: 350px;
|
||||||
max-height: calc(100vh - 70px);
|
max-height: calc(100vh - 70px);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
.compact-header {
|
|
||||||
h1 {
|
|
||||||
font-size: 24px;
|
|
||||||
line-height: 28px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
font-weight: 500;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
padding: 0 10px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
|
|
||||||
@media screen and (max-width: 740px) {
|
|
||||||
text-align: center;
|
|
||||||
padding: 20px 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
font-weight: 400;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: -5px;
|
|
||||||
margin-right: 15px;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -114,6 +114,10 @@
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.hover-ref-wrapper {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
.display-name__account {
|
.display-name__account {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
|
|
|
@ -1,14 +1,3 @@
|
||||||
.container-alt {
|
|
||||||
width: 700px;
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-top: 40px;
|
|
||||||
|
|
||||||
@media screen and (max-width: 740px) {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-container {
|
.logo-container {
|
||||||
margin: 100px auto 50px;
|
margin: 100px auto 50px;
|
||||||
|
|
||||||
|
@ -111,80 +100,3 @@
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-3 {
|
|
||||||
display: grid;
|
|
||||||
grid-gap: 10px;
|
|
||||||
grid-template-columns: 3fr 1fr;
|
|
||||||
grid-auto-columns: 25%;
|
|
||||||
grid-auto-rows: max-content;
|
|
||||||
|
|
||||||
.column-0 {
|
|
||||||
grid-column: 1 / 3;
|
|
||||||
grid-row: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-1 {
|
|
||||||
grid-column: 1;
|
|
||||||
grid-row: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-2 {
|
|
||||||
grid-column: 2;
|
|
||||||
grid-row: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-3 {
|
|
||||||
grid-column: 1 / 3;
|
|
||||||
grid-row: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page__call-to-action {
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 738px) {
|
|
||||||
grid-template-columns: minmax(0, 50%) minmax(0, 50%);
|
|
||||||
|
|
||||||
.landing-page__call-to-action {
|
|
||||||
padding: 20px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row__information-board {
|
|
||||||
width: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row__mascot {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
grid-gap: 0;
|
|
||||||
grid-template-columns: minmax(0, 100%);
|
|
||||||
|
|
||||||
.column-0 {
|
|
||||||
grid-column: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-1 {
|
|
||||||
grid-column: 1;
|
|
||||||
grid-row: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-2 {
|
|
||||||
grid-column: 1;
|
|
||||||
grid-row: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-3 {
|
|
||||||
grid-column: 1;
|
|
||||||
grid-row: 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
.dashboard__counters {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin: 0 -5px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
& > div {
|
|
||||||
box-sizing: border-box;
|
|
||||||
flex: 0 0 33.333%;
|
|
||||||
padding: 0 5px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
& > div,
|
|
||||||
& > a {
|
|
||||||
padding: 20px;
|
|
||||||
background: var(--brand-color--faint);
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: inherit;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__num,
|
|
||||||
&__text {
|
|
||||||
text-align: center;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 24px;
|
|
||||||
line-height: 21px;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
font-family: var(--font-display), sans-serif;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
line-height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__text {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
text-align: center;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard__widgets {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin: 0 -5px;
|
|
||||||
|
|
||||||
& > div {
|
|
||||||
flex: 0 0 33.333%;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
& > div {
|
|
||||||
padding: 0 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a:not(.name-tag) {
|
|
||||||
color: var(--background-color);
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
.dyslexic {
|
.dyslexic {
|
||||||
font-family: 'OpenDyslexic' !important;
|
font-family: 'OpenDyslexic' !important;
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dyslexic {
|
body.dyslexic {
|
||||||
|
|
|
@ -13,7 +13,7 @@ code {
|
||||||
|
|
||||||
.simple_form {
|
.simple_form {
|
||||||
.input {
|
.input {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&.hidden {
|
&.hidden {
|
||||||
|
@ -43,7 +43,6 @@ code {
|
||||||
|
|
||||||
&.boolean {
|
&.boolean {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 0;
|
|
||||||
|
|
||||||
.label_input > label {
|
.label_input > label {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
|
@ -111,7 +110,6 @@ code {
|
||||||
span.hint {
|
span.hint {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.hint {
|
p.hint {
|
||||||
|
@ -172,15 +170,10 @@ code {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 8px;
|
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hint {
|
|
||||||
margin-top: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
flex: 390px;
|
flex: 390px;
|
||||||
}
|
}
|
||||||
|
@ -446,6 +439,7 @@ code {
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
appearance: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
|
@ -461,6 +455,23 @@ code {
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
height: 41px;
|
height: 41px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin-top: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-wrapper::after {
|
||||||
|
display: block;
|
||||||
|
font-family: 'ForkAwesome';
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
position: absolute;
|
||||||
|
right: 12px;
|
||||||
|
top: 1px;
|
||||||
|
border-left: 1px solid var(--highlight-text-color);
|
||||||
|
height: 39px;
|
||||||
|
padding: 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label_input {
|
.label_input {
|
||||||
|
@ -645,155 +656,6 @@ code {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flash-message {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 15px 10px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&.notice {
|
|
||||||
border: 1px solid rgba($valid-value-color, 0.5);
|
|
||||||
background: rgba($valid-value-color, 0.25);
|
|
||||||
color: $valid-value-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.alert {
|
|
||||||
border: 1px solid rgba($error-value-color, 0.5);
|
|
||||||
background: rgba($error-value-color, 0.25);
|
|
||||||
color: $error-value-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: inline-block;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.oauth-code {
|
|
||||||
outline: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
border: 0;
|
|
||||||
padding: 10px;
|
|
||||||
font-family: var(--font-monospace), monospace;
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
font-size: 14px;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
&::-moz-focus-inner {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-moz-focus-inner,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
outline: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
background: var(--brand-color--faint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
@each $lang in $cjk-langs {
|
|
||||||
&:lang(#{$lang}) {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 740px) and (min-width: 441px) {
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-footer {
|
|
||||||
margin-top: 30px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-nav {
|
|
||||||
list-style: none;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--highlight-text-color);
|
|
||||||
text-transform: uppercase;
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 700;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
color: var(--highlight-text-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.oauth-prompt,
|
|
||||||
.follow-prompt {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 16px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
@each $lang in $cjk-langs {
|
|
||||||
&:lang(#{$lang}) {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 740px) and (min-width: 441px) {
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-wrapper {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-code {
|
.qr-code {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
background: var(--foreground-color);
|
background: var(--foreground-color);
|
||||||
|
@ -808,35 +670,7 @@ code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.qr-alternative {
|
.simple_form {
|
||||||
margin-bottom: 20px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
flex: 150px;
|
|
||||||
|
|
||||||
samp {
|
|
||||||
display: block;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-form {
|
|
||||||
p {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
@each $lang in $cjk-langs {
|
|
||||||
&:lang(#{$lang}) {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.simple_form,
|
|
||||||
.table-form {
|
|
||||||
.warning {
|
.warning {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background: rgba($error-value-color, 0.5);
|
background: rgba($error-value-color, 0.5);
|
||||||
|
@ -876,173 +710,6 @@ code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-pagination {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.actions,
|
|
||||||
.pagination {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
padding: 30px 0;
|
|
||||||
padding-right: 20px;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-follow-actions {
|
|
||||||
text-align: center;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
|
|
||||||
div {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.alternative-login {
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: 16px;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scope-danger {
|
|
||||||
color: $warning-red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form_admin_settings_site_short_description,
|
|
||||||
.form_admin_settings_site_description,
|
|
||||||
.form_admin_settings_site_extended_description,
|
|
||||||
.form_admin_settings_site_terms,
|
|
||||||
.form_admin_settings_custom_css,
|
|
||||||
.form_admin_settings_closed_registrations_message {
|
|
||||||
textarea {
|
|
||||||
font-family: var(--font-monospace), monospace;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-copy {
|
|
||||||
background: var(--background-color);
|
|
||||||
border: 1px solid var(--background-color);
|
|
||||||
border-radius: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-right: 4px;
|
|
||||||
position: relative;
|
|
||||||
top: 1px;
|
|
||||||
transition: border-color 300ms linear;
|
|
||||||
|
|
||||||
&__wrapper {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=text] {
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
padding: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-family: var(--font-monospace), monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
margin: 4px;
|
|
||||||
text-transform: none;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 7px 18px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
width: auto;
|
|
||||||
transition: background 300ms linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.copied {
|
|
||||||
border-color: $valid-value-color;
|
|
||||||
transition: none;
|
|
||||||
|
|
||||||
button {
|
|
||||||
background: $valid-value-color;
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.connection-prompt {
|
|
||||||
margin-bottom: 25px;
|
|
||||||
|
|
||||||
.fa-link {
|
|
||||||
background-color: var(--brand-color--med);
|
|
||||||
border-radius: 100%;
|
|
||||||
font-size: 24px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__column {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-shrink: 1;
|
|
||||||
max-width: 50%;
|
|
||||||
|
|
||||||
&-sep {
|
|
||||||
align-self: center;
|
|
||||||
flex-grow: 0;
|
|
||||||
overflow: visible;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.account__avatar {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__connection {
|
|
||||||
background-color: var(--brand-color--med);
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 25px 10px;
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
background-color: var(--brand-color--med);
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
left: 50%;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__row {
|
|
||||||
align-items: flex-start;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.columns-area {
|
.columns-area {
|
||||||
form.simple_form {
|
form.simple_form {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
|
|
@ -43,13 +43,13 @@ body.halloween {
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-holder {
|
.app-holder {
|
||||||
// Black vignette
|
// Vignette
|
||||||
&::before {
|
&::before {
|
||||||
background-image: radial-gradient(
|
background-image: radial-gradient(
|
||||||
circle,
|
circle,
|
||||||
transparent 0%,
|
transparent 0%,
|
||||||
transparent 60%,
|
transparent 60%,
|
||||||
#000 100%
|
var(--vignette-color) 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
.no-list {
|
|
||||||
list-style: none;
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.recovery-codes {
|
|
||||||
list-style: none;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
li {
|
|
||||||
font-size: 125%;
|
|
||||||
line-height: 1.5;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,16 +7,6 @@ body.rtl {
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-page__logo {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page .features-list .features-list__row .visual {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-link__icon,
|
.column-link__icon,
|
||||||
.column-header__icon {
|
.column-header__icon {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
@ -83,23 +73,16 @@ body.rtl {
|
||||||
right: 10px;
|
right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status,
|
.status {
|
||||||
.activity-stream .status.light {
|
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 68px;
|
padding-right: 68px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status__info .status__display-name,
|
.status__info .status__display-name {
|
||||||
.activity-stream .status.light .status__display-name {
|
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.activity-stream .pre-header {
|
|
||||||
padding-right: 68px;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status__prepend {
|
.status__prepend {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 68px;
|
margin-right: 68px;
|
||||||
|
@ -110,11 +93,6 @@ body.rtl {
|
||||||
right: -26px;
|
right: -26px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.activity-stream .pre-header .pre-header__icon {
|
|
||||||
left: auto;
|
|
||||||
right: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account__avatar-overlay-overlay {
|
.account__avatar-overlay-overlay {
|
||||||
right: auto;
|
right: auto;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -125,8 +103,7 @@ body.rtl {
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status__relative-time,
|
.status__relative-time {
|
||||||
.activity-stream .status.light .status__header .status__meta {
|
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,44 +233,6 @@ body.rtl {
|
||||||
margin-left: 45px;
|
margin-left: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-page .header-wrapper .mascot {
|
|
||||||
right: 60px;
|
|
||||||
left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page__call-to-action .row__information-board {
|
|
||||||
direction: rtl;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page .header .hero .floats .float-1 {
|
|
||||||
left: -120px;
|
|
||||||
right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page .header .hero .floats .float-2 {
|
|
||||||
left: 210px;
|
|
||||||
right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page .header .hero .floats .float-3 {
|
|
||||||
left: 110px;
|
|
||||||
right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page .header .links .brand img {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page .fa-external-link {
|
|
||||||
padding-right: 5px;
|
|
||||||
padding-left: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-page .features #soapbox-timeline {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 631px) {
|
@media screen and (min-width: 631px) {
|
||||||
.column,
|
.column,
|
||||||
.drawer {
|
.drawer {
|
||||||
|
@ -329,18 +268,6 @@ body.rtl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-page__information {
|
|
||||||
.account__display-name {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account__avatar-wrapper {
|
|
||||||
margin-left: 12px;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card__bar .display-name {
|
.card__bar .display-name {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
.activity-stream {
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
margin-bottom: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--headless {
|
|
||||||
border-radius: 0;
|
|
||||||
margin: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
.detailed-status,
|
|
||||||
.status {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
div[data-component] {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
|
|
||||||
.detailed-status,
|
|
||||||
.status,
|
|
||||||
.load-more {
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
.detailed-status,
|
|
||||||
.status,
|
|
||||||
.load-more {
|
|
||||||
border-bottom: 0;
|
|
||||||
border-radius: 0 0 4px 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
.detailed-status,
|
|
||||||
.status,
|
|
||||||
.load-more {
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
.detailed-status,
|
|
||||||
.status,
|
|
||||||
.load-more {
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 740px) {
|
|
||||||
.detailed-status,
|
|
||||||
.status,
|
|
||||||
.load-more {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--highlighted .entry {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button.logo-button {
|
|
||||||
flex: 0 auto;
|
|
||||||
font-size: 14px;
|
|
||||||
background: var(--brand-color);
|
|
||||||
color: #fff;
|
|
||||||
text-transform: none;
|
|
||||||
line-height: 36px;
|
|
||||||
height: auto;
|
|
||||||
padding: 3px 15px;
|
|
||||||
border: 0;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 20px;
|
|
||||||
height: auto;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 5px;
|
|
||||||
fill: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active,
|
|
||||||
&:focus,
|
|
||||||
&:hover {
|
|
||||||
background: var(--brand-color--hicontrast);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled,
|
|
||||||
&.disabled {
|
|
||||||
&:active,
|
|
||||||
&:focus,
|
|
||||||
&:hover {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.button--destructive {
|
|
||||||
&:active,
|
|
||||||
&:focus,
|
|
||||||
&:hover {
|
|
||||||
background: $error-red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
svg {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.embed,
|
|
||||||
.public-layout {
|
|
||||||
.detailed-status {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status {
|
|
||||||
padding: 15px 15px 15px (48px + 15px * 2);
|
|
||||||
min-height: 48px + 2px;
|
|
||||||
|
|
||||||
&__avatar {
|
|
||||||
left: 15px;
|
|
||||||
top: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
padding-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__prepend {
|
|
||||||
margin-left: 48px + 15px * 2;
|
|
||||||
padding-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__prepend-icon-wrapper {
|
|
||||||
left: -32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-gallery,
|
|
||||||
&__action-bar,
|
|
||||||
.video-player {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,243 +0,0 @@
|
||||||
.table {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
border-spacing: 0;
|
|
||||||
border-collapse: collapse;
|
|
||||||
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 8px;
|
|
||||||
line-height: 18px;
|
|
||||||
vertical-align: top;
|
|
||||||
border-top: 1px solid var(--brand-color--med);
|
|
||||||
text-align: left;
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
}
|
|
||||||
|
|
||||||
& > thead > tr > th {
|
|
||||||
vertical-align: bottom;
|
|
||||||
border-bottom: 2px solid var(--brand-color--med);
|
|
||||||
border-top: 0;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > tbody > tr > th {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > tbody > tr:nth-child(odd) > td,
|
|
||||||
& > tbody > tr:nth-child(odd) > th {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--highlight-text-color);
|
|
||||||
text-decoration: underline;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
@each $lang in $cjk-langs {
|
|
||||||
&:lang(#{$lang}) {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.inline-table {
|
|
||||||
& > tbody > tr:nth-child(odd) {
|
|
||||||
& > td,
|
|
||||||
& > th {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > tbody > tr:first-child {
|
|
||||||
& > td,
|
|
||||||
& > th {
|
|
||||||
border-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.batch-table {
|
|
||||||
& > thead > tr > th {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
border-top: 1px solid var(--background-color);
|
|
||||||
border-bottom: 1px solid var(--background-color);
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
border-radius: 4px 0 0;
|
|
||||||
border-left: 1px solid var(--background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-radius: 0 4px 0 0;
|
|
||||||
border-right: 1px solid var(--background-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--invites tbody td {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-wrapper {
|
|
||||||
overflow: auto;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
samp {
|
|
||||||
font-family: var(--font-monospace), monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.table-action-link {
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
font: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.table-action-link,
|
|
||||||
a.table-action-link {
|
|
||||||
text-decoration: none;
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 5px;
|
|
||||||
padding: 0 10px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
i.fa {
|
|
||||||
font-weight: 400;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.batch-table {
|
|
||||||
&__toolbar,
|
|
||||||
&__row {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
&__select {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 8px 16px;
|
|
||||||
cursor: pointer;
|
|
||||||
min-height: 100%;
|
|
||||||
|
|
||||||
input {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--aligned {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
input {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__actions,
|
|
||||||
&__content {
|
|
||||||
padding: 8px 0;
|
|
||||||
padding-right: 16px;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__toolbar {
|
|
||||||
border: 1px solid var(--background-color);
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
border-radius: 4px 0 0;
|
|
||||||
height: 47px;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&__actions {
|
|
||||||
text-align: right;
|
|
||||||
padding-right: 16px - 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__row {
|
|
||||||
border: 1px solid var(--background-color);
|
|
||||||
border-top: 0;
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
&:first-child {
|
|
||||||
border-top: 1px solid var(--background-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(even) {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--brand-color--faint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
padding-top: 12px;
|
|
||||||
padding-bottom: 16px;
|
|
||||||
|
|
||||||
&--unpadded {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.status__content {
|
|
||||||
padding-top: 0;
|
|
||||||
|
|
||||||
summary {
|
|
||||||
display: list-item;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nothing-here {
|
|
||||||
border: 1px solid var(--background-color);
|
|
||||||
border-top: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
border-top: 1px solid var(--background-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 870px) {
|
|
||||||
.accounts-table tbody td.optional {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -64,6 +64,7 @@ body.theme-mode-light {
|
||||||
var(--brand-color_s),
|
var(--brand-color_s),
|
||||||
calc(var(--brand-color_l) - 8%)
|
calc(var(--brand-color_l) - 8%)
|
||||||
);
|
);
|
||||||
|
--vignette-color: transparent;
|
||||||
|
|
||||||
// Meta-variables
|
// Meta-variables
|
||||||
--primary-text-color_h: 0;
|
--primary-text-color_h: 0;
|
||||||
|
@ -92,6 +93,7 @@ body.theme-mode-dark {
|
||||||
var(--brand-color_s),
|
var(--brand-color_s),
|
||||||
calc(var(--brand-color_l) + 8%)
|
calc(var(--brand-color_l) + 8%)
|
||||||
);
|
);
|
||||||
|
--vignette-color: #000;
|
||||||
|
|
||||||
// Meta-variables
|
// Meta-variables
|
||||||
--primary-text-color_h: 0;
|
--primary-text-color_h: 0;
|
||||||
|
|
|
@ -219,12 +219,6 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.domain_buttons {
|
|
||||||
height: 18px;
|
|
||||||
padding: 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.muted {
|
.muted {
|
||||||
.status__content p,
|
.status__content p,
|
||||||
.status__content a {
|
.status__content a {
|
||||||
|
@ -670,52 +664,6 @@
|
||||||
100% { opacity: 1; }
|
100% { opacity: 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-toggle {
|
|
||||||
display: flex;
|
|
||||||
padding: 5px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
box-sizing: border-box;
|
|
||||||
flex: 0 0 50%;
|
|
||||||
background: transparent;
|
|
||||||
padding: 5px;
|
|
||||||
border: 0;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
svg path:first-child {
|
|
||||||
fill: var(--background-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
|
|
||||||
path:first-child {
|
|
||||||
fill: var(--brand-color--med);
|
|
||||||
}
|
|
||||||
|
|
||||||
path:last-child {
|
|
||||||
fill: var(--background-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__active {
|
|
||||||
color: var(--brand-color);
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
border-radius: 50%;
|
|
||||||
padding: 0.35rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.verified-icon {
|
.verified-icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 4px 0 1px;
|
margin: 0 4px 0 1px;
|
||||||
|
|
|
@ -1,534 +0,0 @@
|
||||||
.hero-widget {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
|
|
||||||
&__img {
|
|
||||||
width: 100%;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
background: $base-shadow-color;
|
|
||||||
|
|
||||||
img {
|
|
||||||
object-fit: cover;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__text {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 0 0 4px 4px;
|
|
||||||
font-size: 15px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
line-height: 20px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
.emojione {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
margin: -3px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
em {
|
|
||||||
display: inline;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-weight: 700;
|
|
||||||
background: transparent;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.endorsements-widget {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
padding: 10px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
}
|
|
||||||
|
|
||||||
.account {
|
|
||||||
padding: 10px 0;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account__display-name {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account__avatar {
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
background-size: 44px 44px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.box-widget {
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--background-color);
|
|
||||||
box-shadow: 0 0 1px 1px rgba($base-shadow-color, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-widget,
|
|
||||||
.landing-page__information.contact-widget {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 20px;
|
|
||||||
min-height: 100%;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-widget {
|
|
||||||
font-size: 15px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
line-height: 20px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__mail {
|
|
||||||
margin-top: 10px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.moved-account-widget {
|
|
||||||
padding: 15px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
font-weight: 400;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
strong,
|
|
||||||
a {
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
@each $lang in $cjk-langs {
|
|
||||||
&:lang(#{$lang}) {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: underline;
|
|
||||||
|
|
||||||
&.mention {
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
span {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus,
|
|
||||||
&:hover,
|
|
||||||
&:active {
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
span {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__message {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
margin-right: 5px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__card {
|
|
||||||
.detailed-status__display-avatar {
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detailed-status__display-name {
|
|
||||||
margin-bottom: 0;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.memoriam-widget {
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: $base-shadow-color;
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 60px 15px;
|
|
||||||
text-align: center;
|
|
||||||
margin: 10px 0;
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
font-size: 36px;
|
|
||||||
line-height: 1.1;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 15px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
margin-top: 0;
|
|
||||||
background: var(--brand-color--faint);
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
|
|
||||||
&__tag {
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
& > a,
|
|
||||||
& > div {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 15px;
|
|
||||||
text-decoration: none;
|
|
||||||
color: inherit;
|
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
& > a {
|
|
||||||
&:hover,
|
|
||||||
&:active,
|
|
||||||
&:focus {
|
|
||||||
background: var(--brand-color--med);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active > a {
|
|
||||||
background: var(--brand-color);
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled > div {
|
|
||||||
opacity: 0.5;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
display: block;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 15px;
|
|
||||||
margin-top: 8px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active h4 {
|
|
||||||
&,
|
|
||||||
.fa,
|
|
||||||
small {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-stack {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: (36px + 4px) * 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active .avatar-stack .account__avatar {
|
|
||||||
border-color: var(--brand-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-stack {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.account__avatar {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 50%;
|
|
||||||
position: relative;
|
|
||||||
margin-left: -10px;
|
|
||||||
background: var(--background-color);
|
|
||||||
border: 2px solid var(--brand-color--med);
|
|
||||||
|
|
||||||
&:nth-child(1) {
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(3) {
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.accounts-table {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.account {
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead th {
|
|
||||||
text-align: center;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
font-weight: 700;
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody td {
|
|
||||||
padding: 15px 0;
|
|
||||||
vertical-align: middle;
|
|
||||||
border-bottom: 1px solid var(--brand-color--med);
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:last-child td {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__count {
|
|
||||||
width: 120px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
|
|
||||||
small {
|
|
||||||
display: block;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__comment {
|
|
||||||
width: 50%;
|
|
||||||
vertical-align: initial !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
tbody td.optional {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.moved-account-widget,
|
|
||||||
.memoriam-widget,
|
|
||||||
.box-widget,
|
|
||||||
.contact-widget,
|
|
||||||
.landing-page__information.contact-widget,
|
|
||||||
.directory,
|
|
||||||
.page-header {
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
margin-bottom: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$maximum-width: 1235px;
|
|
||||||
$fluid-breakpoint: $maximum-width + 20px;
|
|
||||||
|
|
||||||
.statuses-grid {
|
|
||||||
min-height: 600px;
|
|
||||||
|
|
||||||
@media screen and (max-width: 640px) {
|
|
||||||
width: 100% !important; // Masonry layout is unnecessary at this width
|
|
||||||
}
|
|
||||||
|
|
||||||
&__item {
|
|
||||||
width: (960px - 20px) / 3;
|
|
||||||
|
|
||||||
@media screen and (max-width: $fluid-breakpoint) {
|
|
||||||
width: (940px - 20px) / 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 640px) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
width: 100vw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.detailed-status {
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
@media screen and (max-width: $no-gap-breakpoint) {
|
|
||||||
border-top: 1px solid var(--background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.compact {
|
|
||||||
.detailed-status__meta {
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status__content {
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 20px;
|
|
||||||
|
|
||||||
.emojione {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
margin: -3px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status__content__spoiler-link {
|
|
||||||
line-height: 20px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-gallery,
|
|
||||||
.status-card,
|
|
||||||
.video-player {
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.notice-widget {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
color: var(--primary-text-color--faint);
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 20px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--brand-color);
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -58,7 +58,6 @@
|
||||||
"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",
|
"blurhash": "^1.0.0",
|
||||||
"chromatism": "^3.0.0",
|
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"compression-webpack-plugin": "^3.0.0",
|
"compression-webpack-plugin": "^3.0.0",
|
||||||
"cross-env": "^6.0.0",
|
"cross-env": "^6.0.0",
|
||||||
|
@ -103,7 +102,6 @@
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"punycode": "^2.1.0",
|
"punycode": "^2.1.0",
|
||||||
"qrcode.react": "^1.0.0",
|
"qrcode.react": "^1.0.0",
|
||||||
"rails-ujs": "^5.2.3",
|
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-color": "^2.18.1",
|
"react-color": "^2.18.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -3077,11 +3077,6 @@ chownr@^1.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
|
||||||
integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
|
integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
|
||||||
|
|
||||||
chromatism@^3.0.0:
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/chromatism/-/chromatism-3.0.0.tgz#a7249d353c1e4f3577e444ac41171c4e2e624b12"
|
|
||||||
integrity sha1-pySdNTweTzV35ESsQRccTi5iSxI=
|
|
||||||
|
|
||||||
chrome-trace-event@^1.0.2:
|
chrome-trace-event@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
|
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
|
||||||
|
@ -9411,11 +9406,6 @@ railroad-diagrams@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
|
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
|
||||||
integrity sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=
|
integrity sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=
|
||||||
|
|
||||||
rails-ujs@^5.2.3:
|
|
||||||
version "5.2.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/rails-ujs/-/rails-ujs-5.2.3.tgz#4b65ea781a6befe62e96da6362165286a1fe4099"
|
|
||||||
integrity sha512-rYgj185MowWFBJI1wdac2FkX4yFYe4+3jJPlB+CTY7a4rmIyg0TqE4vYZmSBBesp7blPUa57oqKzwQjN7eVbEQ==
|
|
||||||
|
|
||||||
randexp@0.4.6:
|
randexp@0.4.6:
|
||||||
version "0.4.6"
|
version "0.4.6"
|
||||||
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
|
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
|
||||||
|
|
Loading…
Reference in New Issue