Fix merge conflicts hopefully

icon_picker_admin_config
Sean King 2020-09-28 20:31:24 -06:00
commit 49ad44bcd4
60 zmienionych plików z 495 dodań i 3272 usunięć

Wyświetl plik

@ -145,7 +145,17 @@ export function logIn(username, password) {
export function logOut() {
return (dispatch, getState) => {
const state = getState();
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.', ''));
};
}

Wyświetl plik

@ -143,13 +143,13 @@ export function handleComposeSubmit(dispatch, getState, response, status) {
let dequeueArgs = {};
if (timelineId === 'community') dequeueArgs.onlyMedia = getSettings(getState()).getIn(['community', 'other', 'onlyMedia']);
dispatch(dequeueTimeline(timelineId, null, dequeueArgs));
dispatch(updateTimeline(timelineId, { ...response.data }));
dispatch(updateTimeline(timelineId, response.data.id));
}
};
if (response.data.visibility !== 'direct') {
insertIfOnline('home');
} else if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
} else if (response.data.visibility === 'public') {
insertIfOnline('community');
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) {
return (dispatch, getState) => {
const state = getState();

Wyświetl plik

@ -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 });
});
};
}

Wyświetl plik

@ -2,6 +2,7 @@ import { debounce } from 'lodash';
import { showAlertForError } from './alerts';
import { patchMe } from 'soapbox/actions/me';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import uuid from '../uuid';
export const SETTING_CHANGE = 'SETTING_CHANGE';
export const SETTING_SAVE = 'SETTING_SAVE';
@ -114,6 +115,12 @@ const defaultSettings = ImmutableMap({
trends: ImmutableMap({
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) {

Wyświetl plik

@ -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)));
};
};

Wyświetl plik

@ -25,31 +25,31 @@ export function processTimelineUpdate(timeline, status, accept) {
const columnSettings = getSettings(getState()).get(timeline, ImmutableMap());
const shouldSkipQueue = shouldFilter(fromJS(status), columnSettings);
dispatch(importFetchedStatus(status));
if (shouldSkipQueue) {
return dispatch(updateTimeline(timeline, status, accept));
return dispatch(updateTimeline(timeline, status.id, accept));
} 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 => {
if (typeof accept === 'function' && !accept(status)) {
return;
}
dispatch(importFetchedStatus(status));
dispatch({
type: TIMELINE_UPDATE,
timeline,
status,
statusId,
});
};
};
export function updateTimelineQueue(timeline, status, accept) {
export function updateTimelineQueue(timeline, statusId, accept) {
return dispatch => {
if (typeof accept === 'function' && !accept(status)) {
return;
@ -58,7 +58,7 @@ export function updateTimelineQueue(timeline, status, accept) {
dispatch({
type: TIMELINE_UPDATE_QUEUE,
timeline,
status,
statusId,
});
};
};
@ -73,8 +73,8 @@ export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) {
if (totalQueuedItemsCount === 0) {
return;
} else if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
queuedItems.forEach(status => {
dispatch(updateTimeline(timeline, status.toJS(), null));
queuedItems.forEach(statusId => {
dispatch(updateTimeline(timeline, statusId, null));
});
} else {
if (typeof expandFunc === 'function') {

Wyświetl plik

@ -1,5 +1,5 @@
import React from 'react';
import { Sparklines, SparklinesCurve } from 'react-sparklines';
// import { Sparklines, SparklinesCurve } from 'react-sparklines';
import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Permalink from './permalink';
@ -17,11 +17,12 @@ const Hashtag = ({ hashtag }) => (
</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()}>
<SparklinesCurve style={{ fill: 'none' }} />
</Sparklines>
</div>}
</div> */}
</div>
);

Wyświetl plik

@ -29,6 +29,7 @@ const messages = defineMessages({
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
admin_settings: { id: 'navigation_bar.admin_settings', defaultMessage: 'Admin settings' },
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' },
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
lists: { id: 'column.lists', defaultMessage: 'Lists' },
@ -180,6 +181,10 @@ class SidebarMenu extends ImmutablePureComponent {
<Icon id='cog' />
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.preferences)}</span>
</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}>
<Icon id='lock' />
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.security)}</span>

Wyświetl plik

@ -14,8 +14,6 @@ import { ScrollContext } from 'react-router-scroll-4';
import UI from '../features/ui';
// import Introduction from '../features/introduction';
import { fetchCustomEmojis } from '../actions/custom_emojis';
import { hydrateStore } from '../actions/store';
import initialState from '../initial_state';
import { preload } from '../actions/preload';
import { IntlProvider } from 'react-intl';
import ErrorBoundary from '../components/error_boundary';
@ -32,9 +30,6 @@ const validLocale = locale => Object.keys(messages).includes(locale);
export const store = configureStore();
const hydrateAction = hydrateStore(initialState);
store.dispatch(hydrateAction);
store.dispatch(preload());
store.dispatch(fetchMe());
store.dispatch(fetchInstance());

Wyświetl plik

@ -20,6 +20,7 @@ const messages = defineMessages({
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
admin_settings: { id: 'navigation_bar.admin_settings', defaultMessage: 'Admin settings' },
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' },
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
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.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.logout), to: '/auth/sign_out', action: onClickLogOut });

Wyświetl plik

@ -17,7 +17,10 @@ const mapDispatchToProps = dispatch => ({
isUserTouching,
onModalOpen: props => dispatch(openModal('ACTIONS', props)),
onModalClose: () => dispatch(closeModal()),
onModalClose: () => {
dispatch(closeModal());
dispatch(openModal('COMPOSE'));
},
});

Wyświetl plik

@ -55,23 +55,27 @@ exports[`<RadioGroup /> renders correctly 1`] = `
`;
exports[`<SelectDropdown /> renders correctly 1`] = `
<select>
<option
value="one"
>
One
</option>
<option
value="two"
>
Two
</option>
<option
value="three"
>
Three
</option>
</select>
<div
class="select-wrapper"
>
<select>
<option
value="one"
>
One
</option>
<option
value="two"
>
Two
</option>
<option
value="three"
>
Three
</option>
</select>
</div>
`;
exports[`<SimpleForm /> renders correctly 1`] = `

Wyświetl plik

@ -270,7 +270,7 @@ export class SelectDropdown extends ImmutablePureComponent {
<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 ? (
<LabelInputContainer label={label} hint={hint}>{selectElem}</LabelInputContainer>

Wyświetl plik

@ -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>
);
}
}

Wyświetl plik

@ -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>
);
}
}

Wyświetl plik

@ -321,7 +321,7 @@ class SoapboxConfig extends ImmutablePureComponent {
</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>
<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`' />
@ -345,7 +345,7 @@ class SoapboxConfig extends ImmutablePureComponent {
<FormattedMessage id='soapbox_config.fields.custom_css.add' defaultMessage='Add another custom CSS URL' />
</div>
</div>
</div>
</div> */}
</FieldsGroup>
<FieldsGroup>
<div className={this.state.jsonValid ? 'code-editor' : 'code-editor code-editor--invalid'}>

Wyświetl plik

@ -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>
);
}
}

Wyświetl plik

@ -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>
);
}
}

Wyświetl plik

@ -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>
);
}
}

Wyświetl plik

@ -175,7 +175,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
</NavLink>
<DisplayName account={status.get('account')}>
<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>
</DisplayName>
</div>

Wyświetl plik

@ -78,6 +78,7 @@ import {
Preferences,
EditProfile,
SoapboxConfig,
ImportData,
PasswordReset,
SecurityForm,
MfaForm,
@ -263,6 +264,7 @@ class SwitchingColumnsArea extends React.PureComponent {
<Redirect exact from='/settings' to='/settings/preferences' />
<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/import' layout={LAYOUT.DEFAULT} component={ImportData} content={children} />
<WrappedRoute path='/soapbox/config' layout={LAYOUT.DEFAULT} component={SoapboxConfig} content={children} />
<WrappedRoute layout={LAYOUT.EMPTY} component={GenericNotFound} content={children} />

Wyświetl plik

@ -186,6 +186,10 @@ export function SoapboxConfig() {
return import(/* webpackChunkName: "features/soapbox_config" */'../../soapbox_config');
}
export function ImportData() {
return import(/* webpackChunkName: "features/import_data" */'../../import_data');
}
export function PasswordReset() {
return import(/* webpackChunkName: "features/auth_login" */'../../auth_login/components/password_reset');
}

Wyświetl plik

@ -18,7 +18,7 @@ class WrappedRoute extends React.Component {
static propTypes = {
component: PropTypes.func.isRequired,
page: PropTypes.func,
page: PropTypes.object,
content: PropTypes.node,
componentParams: PropTypes.object,
layout: PropTypes.object,

Wyświetl plik

@ -1,6 +0,0 @@
'use strict';
const element = document.getElementById('initial-state');
const initialState = element ? JSON.parse(element.textContent) : {};
export default initialState;

Wyświetl plik

@ -3,18 +3,18 @@ import { Map as ImmutableMap } from 'immutable';
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
import { SETTING_CHANGE } from 'soapbox/actions/settings';
import * as actions from 'soapbox/actions/compose';
//import { STORE_HYDRATE } from 'soapbox/actions/store';
//import { REDRAFT } from 'soapbox/actions/statuses';
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
describe('compose reducer', () => {
it('returns the initial state by default', () => {
expect(reducer(undefined, {}).toJS()).toMatchObject({
const state = reducer(undefined, {});
expect(state.toJS()).toMatchObject({
mounted: 0,
sensitive: false,
spoiler: false,
spoiler_text: '',
privacy: null,
privacy: 'public',
text: '',
focusDate: null,
caretPosition: null,
@ -30,10 +30,10 @@ describe('compose reducer', () => {
suggestions: [],
default_privacy: 'public',
default_sensitive: false,
idempotencyKey: null,
tagHistory: [],
content_type: 'text/markdown',
});
expect(state.get('idempotencyKey').length === 36);
});
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', () => {
const state = ImmutableMap({ mounted: 1 });
const action = {

Wyświetl plik

@ -38,21 +38,22 @@ import {
COMPOSE_POLL_SETTINGS_CHANGE,
} from '../actions/compose';
import { TIMELINE_DELETE } from '../actions/timelines';
import { STORE_HYDRATE } from '../actions/store';
import { REDRAFT } from '../actions/statuses';
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from '../actions/me';
import { SETTING_CHANGE, FE_NAME } from '../actions/settings';
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import { tagHistory } from 'soapbox/settings';
import uuid from '../uuid';
import { unescapeHTML } from '../utils/html';
const initialState = ImmutableMap({
id: null,
mounted: 0,
sensitive: false,
spoiler: false,
spoiler_text: '',
content_type: 'text/markdown',
privacy: null,
privacy: 'public',
text: '',
focusDate: null,
caretPosition: null,
@ -69,7 +70,7 @@ const initialState = ImmutableMap({
default_privacy: 'public',
default_sensitive: false,
resetFileKey: Math.floor((Math.random() * 0x10000)),
idempotencyKey: null,
idempotencyKey: uuid(),
tagHistory: ImmutableList(),
});
@ -178,16 +179,6 @@ const privacyPreference = (a, b) => {
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 expandMentions = status => {
@ -204,8 +195,6 @@ const expandMentions = status => {
export default function compose(state = initialState, action) {
let me, defaultPrivacy;
switch(action.type) {
case STORE_HYDRATE:
return hydrate(state, action.state.get('compose'));
case COMPOSE_MOUNT:
return state.set('mounted', state.get('mounted') + 1);
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));
case ME_FETCH_SUCCESS:
me = fromJS(action.me);
defaultPrivacy = me.getIn(['pleroma', 'settings_store', FE_NAME, 'defaultPrivacy']);
if (!defaultPrivacy) return state;
return state.set('default_privacy', defaultPrivacy).set('privacy', defaultPrivacy);
defaultPrivacy = me.getIn(['pleroma', 'settings_store', FE_NAME, 'defaultPrivacy'], 'public');
return state.merge({
default_privacy: defaultPrivacy,
privacy: defaultPrivacy,
tagHistory: ImmutableList(tagHistory.get(action.me.id)),
});
case ME_PATCH_SUCCESS:
me = fromJS(action.me);
defaultPrivacy = me.getIn(['pleroma', 'settings_store', FE_NAME, 'defaultPrivacy']);

Wyświetl plik

@ -3,7 +3,8 @@ import {
ACCOUNT_MUTE_SUCCESS,
} from '../actions/accounts';
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';
const initialState = ImmutableMap({
@ -87,8 +88,12 @@ export default function replies(state = initialState, action) {
return normalizeContext(state, action.id, action.ancestors, action.descendants);
case TIMELINE_DELETE:
return deleteFromContexts(state, [action.id]);
case TIMELINE_UPDATE:
case STATUS_IMPORT:
return updateContext(state, action.status);
case STATUSES_IMPORT:
return state.withMutations(mutable =>
action.statuses.forEach(status => updateContext(mutable, status)));
default:
return state;
}

Wyświetl plik

@ -1,4 +1,6 @@
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 timelines from './timelines';
import meta from './meta';
@ -48,7 +50,7 @@ import chat_messages from './chat_messages';
import chat_message_lists from './chat_message_lists';
import profile_hover_card from './profile_hover_card';
const reducers = {
const appReducer = combineReducers({
dropdown_menu,
timelines,
meta,
@ -97,6 +99,27 @@ const reducers = {
chat_messages,
chat_message_lists,
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;

Wyświetl plik

@ -1,4 +1,3 @@
import { STORE_HYDRATE } from '../actions/store';
import {
Map as ImmutableMap,
List as ImmutableList,
@ -35,8 +34,6 @@ const initialState = ImmutableMap({
export default function meta(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE:
return state.merge(action.state.get('media_attachments'));
default:
return state;
}

Wyświetl plik

@ -1,6 +1,5 @@
'use strict';
import { STORE_HYDRATE } from '../actions/store';
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
import { Map as ImmutableMap, fromJS } from 'immutable';
@ -8,8 +7,6 @@ const initialState = ImmutableMap();
export default function meta(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE:
return state.merge(action.state.get('meta'));
case ME_FETCH_SUCCESS:
case ME_PATCH_SUCCESS:
const me = fromJS(action.me);

Wyświetl plik

@ -32,8 +32,9 @@ const initialState = ImmutableMap({
// For sorting the notifications
const comparator = (a, b) => {
if (a.get('id') < b.get('id')) return 1;
if (a.get('id') > b.get('id')) return -1;
const parse = m => parseInt(m.get('id'), 10);
if (parse(a) < parse(b)) return 1;
if (parse(a) > parse(b)) return -1;
return 0;
};

Wyświetl plik

@ -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 Immutable from 'immutable';
@ -17,21 +16,6 @@ const initialState = Immutable.Map({
export default function push_subscriptions(state = initialState, action) {
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:
return state
.set('subscription', new Immutable.Map({

Wyświetl plik

@ -1,11 +1,9 @@
import { SETTING_CHANGE, SETTING_SAVE, FE_NAME } from '../actions/settings';
import { NOTIFICATIONS_FILTER_SET } from '../actions/notifications';
import { STORE_HYDRATE } from '../actions/store';
import { EMOJI_USE } from '../actions/emojis';
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists';
import { ME_FETCH_SUCCESS } from 'soapbox/actions/me';
import { Map as ImmutableMap, fromJS } from 'immutable';
import uuid from '../uuid';
// Default settings are in action/settings.js
//
@ -15,22 +13,12 @@ const initialState = ImmutableMap({
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 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) {
switch(action.type) {
case STORE_HYDRATE:
return hydrate(state, action.state.get('settings'));
case ME_FETCH_SUCCESS:
const me = fromJS(action.me);
let fePrefs = me.getIn(['pleroma', 'settings_store', FE_NAME], ImmutableMap());

Wyświetl plik

@ -2,6 +2,7 @@ import {
REBLOG_REQUEST,
REBLOG_FAIL,
FAVOURITE_REQUEST,
UNFAVOURITE_REQUEST,
FAVOURITE_FAIL,
} from '../actions/interactions';
import {
@ -12,11 +13,12 @@ import {
} from '../actions/statuses';
import {
EMOJI_REACT_REQUEST,
UNEMOJI_REACT_REQUEST,
} from '../actions/emoji_reacts';
import { TIMELINE_DELETE } from '../actions/timelines';
import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
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));
@ -40,11 +42,27 @@ export default function statuses(state = initialState, action) {
case STATUSES_IMPORT:
return importStatuses(state, action.statuses);
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:
const path = [action.status.get('id'), 'pleroma', 'emoji_reactions'];
const emojiReacts = state.getIn(path);
return state.setIn(path, simulateEmojiReact(emojiReacts, action.emoji));
return state
.updateIn(
[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:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false);
case REBLOG_REQUEST:

Wyświetl plik

@ -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 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);
if (includesId) {
@ -80,17 +80,17 @@ const updateTimeline = (state, timeline, status) => {
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
if (!top) mMap.set('unread', unread + 1);
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 listedStatuses = state.getIn([timeline, 'items'], ImmutableList());
const totalQueuedItemsCount = state.getIn([timeline, 'totalQueuedItemsCount'], 0);
let alreadyExists = queuedStatuses.find(existingQueuedStatus => existingQueuedStatus.get('id') === status.get('id'));
if (!alreadyExists) alreadyExists = listedStatuses.find(existingListedStatusId => existingListedStatusId === status.get('id'));
let alreadyExists = queuedStatuses.find(existingQueuedStatus => existingQueuedStatus === statusId);
if (!alreadyExists) alreadyExists = listedStatuses.find(existingListedStatusId => existingListedStatusId === statusId);
if (alreadyExists) {
return state;
@ -100,7 +100,7 @@ const updateTimelineQueue = (state, timeline, status) => {
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
if (totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
mMap.set('queuedItems', newQueuedStatuses.push(status));
mMap.set('queuedItems', newQueuedStatuses.push(statusId));
}
mMap.set('totalQueuedItemsCount', totalQueuedItemsCount + 1);
}));
@ -165,9 +165,9 @@ export default function timelines(state = initialState, action) {
case TIMELINE_EXPAND_SUCCESS:
return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent);
case TIMELINE_UPDATE:
return updateTimeline(state, action.timeline, fromJS(action.status));
return updateTimeline(state, action.timeline, action.statusId);
case TIMELINE_UPDATE_QUEUE:
return updateTimelineQueue(state, action.timeline, fromJS(action.status));
return updateTimelineQueue(state, action.timeline, action.statusId);
case TIMELINE_DEQUEUE:
return state.update(action.timeline, initialTimeline, map => map.withMutations(mMap => {
mMap.set('queuedItems', ImmutableList());

Wyświetl plik

@ -6,6 +6,7 @@ import {
reduceEmoji,
getReactForStatus,
simulateEmojiReact,
simulateUnEmojiReact,
} from '../emoji_reacts';
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': '❤' },
]));
});
});

Wyświetl plik

@ -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;
}
};

Wyświetl plik

@ -1,14 +1,14 @@
// Detect backend features to conditionally render elements
import semver from 'semver';
import gte from 'semver/functions/gte';
export const getFeatures = instance => {
const v = parseVersion(instance.get('version'));
return {
suggestions: v.software === 'Mastodon' && semver.gte(v.compatVersion, '2.4.3'),
trends: v.software === 'Mastodon' && semver.gte(v.compatVersion, '3.0.0'),
emojiReacts: v.software === 'Pleroma' && semver.gte(v.version, '2.0.0'),
suggestions: v.software === 'Mastodon' && gte(v.compatVersion, '2.4.3'),
trends: v.software === 'Mastodon' && gte(v.compatVersion, '3.0.0'),
emojiReacts: v.software === 'Pleroma' && gte(v.version, '2.0.0'),
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'),
};
};

Wyświetl plik

@ -1,13 +1,72 @@
import { Map as ImmutableMap } from 'immutable';
import { convert } from 'chromatism';
export const generateThemeCss = brandColor => {
if (!brandColor) return null;
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 => {
const { h, s, l } = convert(brandColor).hsl;
const { h, s, l } = rgbToHsl(hexToRgb(brandColor));
return ImmutableMap({
'brand-color_h': h,
'brand-color_s': `${s}%`,

Plik diff jest za duży Load Diff

Wyświetl plik

@ -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 {
display: inline-block;
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 {
padding: 10px;
position: relative;

Wyświetl plik

@ -5,22 +5,16 @@
@import 'reset';
@import 'basics';
@import 'containers';
@import 'lists';
@import 'footer';
@import 'compact_header';
@import 'widgets';
@import 'forms';
@import 'accounts';
@import 'stream_entries';
@import 'boost';
@import 'loading';
@import 'ui';
@import 'polls';
@import 'introduction';
// @import 'introduction';
@import 'emoji_picker';
@import 'about';
@import 'tables';
@import 'dashboard';
@import 'rtl';
@import 'accessibility';
@import 'donations';
@ -38,10 +32,10 @@
@import 'components/account-header';
@import 'components/user-panel';
@import 'components/compose-form';
@import 'components/group-card';
@import 'components/group-detail';
@import 'components/group-form';
@import 'components/group-sidebar-panel';
// @import 'components/group-card';
// @import 'components/group-detail';
// @import 'components/group-form';
// @import 'components/group-sidebar-panel';
@import 'components/sidebar-menu';
@import 'components/hotkeys-modal';
@import 'components/emoji-reacts';

Wyświetl plik

@ -176,13 +176,6 @@ body {
margin-top: 1em;
}
&__dismiss {
display: inline-block;
text-transform: uppercase;
margin-left: 5px;
font-size: 13px;
}
a {
color: var(--brand-color--hicontrast);
text-decoration: underline;

Wyświetl plik

@ -5,7 +5,7 @@
bottom: 0;
right: 20px;
width: 265px;
height: 265px;
height: 350px;
max-height: calc(100vh - 70px);
display: flex;
flex-direction: column;

Wyświetl plik

@ -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;
}
}
}

Wyświetl plik

@ -114,6 +114,10 @@
color: var(--primary-text-color);
}
span.hover-ref-wrapper {
display: inline;
}
.display-name__account {
display: block;
margin-top: -10px;

Wyświetl plik

@ -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 {
margin: 100px auto 50px;
@ -111,80 +100,3 @@
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;
}
}
}

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -1,5 +1,6 @@
.dyslexic {
font-family: 'OpenDyslexic' !important;
margin-bottom: 8px;
}
body.dyslexic {

Wyświetl plik

@ -13,7 +13,7 @@ code {
.simple_form {
.input {
margin-bottom: 15px;
margin-bottom: 8px;
overflow: hidden;
&.hidden {
@ -43,7 +43,6 @@ code {
&.boolean {
position: relative;
margin-bottom: 0;
.label_input > label {
font-family: inherit;
@ -111,7 +110,6 @@ code {
span.hint {
display: block;
font-size: 12px;
margin-top: 4px;
}
p.hint {
@ -172,15 +170,10 @@ code {
font-size: 14px;
color: var(--primary-text-color);
display: block;
margin-bottom: 8px;
word-wrap: break-word;
font-weight: 500;
}
.hint {
margin-top: 6px;
}
ul {
flex: 390px;
}
@ -446,6 +439,7 @@ code {
}
select {
appearance: none;
box-sizing: border-box;
font-size: 16px;
color: var(--primary-text-color);
@ -461,6 +455,23 @@ code {
padding-right: 30px;
height: 41px;
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 {
@ -645,155 +656,6 @@ code {
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 {
flex: 0 0 auto;
background: var(--foreground-color);
@ -808,35 +670,7 @@ code {
}
}
.qr-alternative {
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 {
.simple_form {
.warning {
box-sizing: border-box;
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 {
form.simple_form {
padding: 15px;

Wyświetl plik

@ -43,13 +43,13 @@ body.halloween {
}
.app-holder {
// Black vignette
// Vignette
&::before {
background-image: radial-gradient(
circle,
transparent 0%,
transparent 60%,
#000 100%
var(--vignette-color) 100%
);
}

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -7,16 +7,6 @@ body.rtl {
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-header__icon {
margin-right: 0;
@ -83,23 +73,16 @@ body.rtl {
right: 10px;
}
.status,
.activity-stream .status.light {
.status {
padding-left: 10px;
padding-right: 68px;
}
.status__info .status__display-name,
.activity-stream .status.light .status__display-name {
.status__info .status__display-name {
padding-left: 25px;
padding-right: 0;
}
.activity-stream .pre-header {
padding-right: 68px;
padding-left: 0;
}
.status__prepend {
margin-left: 0;
margin-right: 68px;
@ -110,11 +93,6 @@ body.rtl {
right: -26px;
}
.activity-stream .pre-header .pre-header__icon {
left: auto;
right: 42px;
}
.account__avatar-overlay-overlay {
right: auto;
left: 0;
@ -125,8 +103,7 @@ body.rtl {
left: 0;
}
.status__relative-time,
.activity-stream .status.light .status__header .status__meta {
.status__relative-time {
float: left;
}
@ -256,44 +233,6 @@ body.rtl {
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) {
.column,
.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 {
margin-left: 0;
margin-right: 15px;

Wyświetl plik

@ -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;
}
}
}

Wyświetl plik

@ -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;
}
}
}

Wyświetl plik

@ -64,6 +64,7 @@ body.theme-mode-light {
var(--brand-color_s),
calc(var(--brand-color_l) - 8%)
);
--vignette-color: transparent;
// Meta-variables
--primary-text-color_h: 0;
@ -92,6 +93,7 @@ body.theme-mode-dark {
var(--brand-color_s),
calc(var(--brand-color_l) + 8%)
);
--vignette-color: #000;
// Meta-variables
--primary-text-color_h: 0;

Wyświetl plik

@ -219,12 +219,6 @@
display: flex;
}
.domain_buttons {
height: 18px;
padding: 10px;
white-space: nowrap;
}
.muted {
.status__content p,
.status__content a {
@ -670,52 +664,6 @@
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 {
display: inline-block;
margin: 0 4px 0 1px;

Wyświetl plik

@ -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;
}
}
}

Wyświetl plik

@ -58,7 +58,6 @@
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"babel-runtime": "^6.26.0",
"blurhash": "^1.0.0",
"chromatism": "^3.0.0",
"classnames": "^2.2.5",
"compression-webpack-plugin": "^3.0.0",
"cross-env": "^6.0.0",
@ -103,7 +102,6 @@
"prop-types": "^15.5.10",
"punycode": "^2.1.0",
"qrcode.react": "^1.0.0",
"rails-ujs": "^5.2.3",
"react": "^16.13.1",
"react-color": "^2.18.1",
"react-dom": "^16.13.1",

Wyświetl plik

@ -3077,11 +3077,6 @@ chownr@^1.1.1:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
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:
version "1.0.2"
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"
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:
version "0.4.6"
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"