Compare commits

...

7 commits

Author SHA1 Message Date
29278e8802 add CI, lint files
Some checks failed
ci/woodpecker/tag/woodpecker Pipeline failed
2022-06-17 11:43:45 +01:00
Haelwenn
d7088dbd06 Merge branch 'glitch-flavour-skin-only' into 'rebase/glitch-soc'
Use Glitch-soc flavour/skin only

See merge request pleroma/mastofe!34
2020-09-23 16:08:52 +00:00
Sean King
8586ff5b53 Use glitch flavour/skin only 2020-09-23 07:50:23 -06:00
Haelwenn (lanodan) Monnier
9762592e51
log_out.js: Fix for WebKit
My guess is that hidden forms are broken or forbidden on it.
This greatly simplifies the code anyway.

Tested in: WebKitGTK 2.28.3, Firefox 78.0.2-1, Chromium 84.0.4147.89-1
Closes: https://git.pleroma.social/pleroma/mastofe/-/issues/85
2020-07-27 18:50:31 +02:00
Haelwenn (lanodan) Monnier
e0788087c8
Merge branch 'bugfix/links-to-pleromafe' into rebase/glitch-soc 2020-07-27 18:13:02 +02:00
Haelwenn (lanodan) Monnier
a62d84e898
Onboarding Modal: Adapt for Pleroma 2020-07-27 17:53:32 +02:00
Haelwenn (lanodan) Monnier
2b4a5956e0
Remove links to PleromaFE 2020-07-27 17:53:22 +02:00
74 changed files with 266 additions and 226 deletions

49
.woodpecker.yml Normal file
View file

@ -0,0 +1,49 @@
pipeline:
lint:
when:
event:
- push
- pull_request
image: node:16
commands:
- yarn
- yarn test:lint
test:
when:
event:
- push
- pull_request
image: node:16
commands:
- apt update
- apt install firefox-esr -y --no-install-recommends
- yarn
- yarn test
build:
when:
event:
- tag
image: node:16
commands:
- yarn
- TARGET=distribution ./build.sh
release:
when:
event:
- tag
image: node:16
secrets:
- SCW_ACCESS_KEY
- SCW_SECRET_KEY
- SCW_DEFAULT_ORGANIZATION_ID
commands:
- apt-get update && apt-get install -y rclone wget zip
- wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
- mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
- chmod +x scaleway-cli
- ./scaleway-cli object config install type=rclone
- zip mastofe.zip -r distribution
- rclone copyto akkoma-fe.zip scaleway:akkoma-updates/frontend/$CI_COMMIT_BRANCH/masto-fe.zip

View file

@ -1,7 +1,9 @@
// This file will be loaded on settings pages, regardless of theme.
import escapeTextContentForBrowser from 'escape-html';
const { delegate } = require('@rails/ujs');
import emojify from '../mastodon/features/emoji/emoji';
delegate(document, '#account_display_name', 'input', ({ target }) => {
@ -62,7 +64,7 @@ delegate(document, '.input-copy button', 'click', ({ target }) => {
input.blur();
target.parentNode.classList.add('copied');
setTimeout(() => {
setTimeout(() => {
target.parentNode.classList.remove('copied');
}, 700);
}

View file

@ -760,7 +760,7 @@ export function fetchPinnedAccounts() {
return (dispatch, getState) => {
dispatch(fetchPinnedAccountsRequest());
api(getState).get(`/api/v1/endorsements`, { params: { limit: 0 } }).then(response => {
api(getState).get('/api/v1/endorsements', { params: { limit: 0 } }).then(response => {
dispatch(importFetchedAccounts(response.data));
dispatch(fetchPinnedAccountsSuccess(response.data));
}).catch(err => dispatch(fetchPinnedAccountsFail(err)));
@ -822,7 +822,7 @@ export function changePinnedAccountsSuggestions(value) {
return {
type: PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE,
value,
}
};
};
export function resetPinnedAccountsEditor() {

View file

@ -246,34 +246,34 @@ export function uploadCompose(files) {
for (const [i, file] of Array.from(files).entries()) {
if (media.size + i > 3) break;
const data = new FormData();
data.append('file', file);
const data = new FormData();
data.append('file', file);
return api(getState).post('/api/v2/media', data, {
onUploadProgress: function({ loaded }){
progress[i] = loaded;
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total));
},
}).then(({ status, data }) => {
// If server-side processing of the media attachment has not completed yet,
// poll the server until it is, before showing the media attachment as uploaded
return api(getState).post('/api/v2/media', data, {
onUploadProgress: function({ loaded }){
progress[i] = loaded;
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total));
},
}).then(({ status, data }) => {
// If server-side processing of the media attachment has not completed yet,
// poll the server until it is, before showing the media attachment as uploaded
if (status === 200) {
dispatch(uploadComposeSuccess(data, file));
} else if (status === 202) {
const poll = () => {
api(getState).get(`/api/v1/media/${data.id}`).then(response => {
if (response.status === 200) {
dispatch(uploadComposeSuccess(response.data, file));
} else if (response.status === 206) {
setTimeout(() => poll(), 1000);
}
}).catch(error => dispatch(uploadComposeFail(error)));
};
if (status === 200) {
dispatch(uploadComposeSuccess(data, file));
} else if (status === 202) {
const poll = () => {
api(getState).get(`/api/v1/media/${data.id}`).then(response => {
if (response.status === 200) {
dispatch(uploadComposeSuccess(response.data, file));
} else if (response.status === 206) {
setTimeout(() => poll(), 1000);
}
}).catch(error => dispatch(uploadComposeFail(error)));
};
poll();
}
});
poll();
}
});
};
};
};

View file

@ -36,15 +36,15 @@ export const submitMarkers = () => (dispatch, getState) => {
};
export const fetchMarkers = () => (dispatch, getState) => {
const params = { timeline: ['notifications'] };
const params = { timeline: ['notifications'] };
dispatch(fetchMarkersRequest());
dispatch(fetchMarkersRequest());
api(getState).get('/api/v1/markers', { params }).then(response => {
dispatch(fetchMarkersSuccess(response.data));
}).catch(error => {
dispatch(fetchMarkersFail(error));
});
api(getState).get('/api/v1/markers', { params }).then(response => {
dispatch(fetchMarkersSuccess(response.data));
}).catch(error => {
dispatch(fetchMarkersFail(error));
});
};
export function fetchMarkersRequest() {

View file

@ -27,7 +27,7 @@ const debouncedSave = debounce((dispatch, getState) => {
api(getState).put(
'/api/pleroma/notification_settings',
{ exclude_types: excludeTypesFromSettings(getState()) }
{ exclude_types: excludeTypesFromSettings(getState()) },
).catch(error => dispatch(showAlertForError(error)));
api(getState).put('/api/web/settings', { data })

View file

@ -47,7 +47,7 @@ export function updateTimeline(timeline, status, accept) {
timeline,
status,
usePendingItems: preferPendingItems,
filtered
filtered,
});
};
};

View file

@ -87,7 +87,7 @@ export default class DisplayName extends React.PureComponent {
)).reduce((prev, cur) => [prev, ', ', cur]);
if (others.size - 2 > 0) {
displayName.push(` +${others.size - 2}`);
displayName.push(` +${others.size - 2}`);
}
suffix = (

View file

@ -104,16 +104,17 @@ export default class ErrorBoundary extends React.PureComponent {
/>
</li>
)}
<li>
<FormattedMessage
<li>
<FormattedMessage
id='web_app_crash.load_pleromafe'
defaultMessage='Load {pleromafe} instead of mastofe'
values={{ pleromafe: <a href='/main/all'><FormattedMessage id='web_app_crash.pleromafe' defaultMessage='Pleroma Frontend' /></a> }}
/>
</li>
/>
</li>
</ul>
</div>
</div>
);
}
}

View file

@ -121,8 +121,9 @@ export default class IntersectionObserverArticle extends React.Component {
aria-setsize={listLength}
data-id={id}
tabIndex='0'
style={style}>
{children && React.cloneElement(children, { hidden: !isIntersecting && (isHidden || !!cachedHeight) })}
style={style}
>
{children && React.cloneElement(children, { hidden: !isIntersecting && (isHidden || !!cachedHeight) })}
</article>
);
}

View file

@ -233,14 +233,14 @@ class Item extends React.PureComponent {
aria-label={attachment.get('description')}
role='application'
>
<span><p>sound<br/>only</p></span>
<span><p>sound<br />only</p></span>
<span><p>{attachment.get('description')}</p></span>
<audio
src={attachment.get('url')}
controls
/>
</div>
);
);
} else if (attachment.get('type') === 'gifv') {
const autoPlay = !isIOS() && this.getAutoPlay();
@ -367,7 +367,7 @@ class MediaGallery extends React.PureComponent {
} else if (width) {
style.height = width / (16/9);
} else {
return (<div className={computedClass} ref={this.handleRef}></div>);
return (<div className={computedClass} ref={this.handleRef} />);
}
if (this.isStandaloneEligible()) {

View file

@ -4,6 +4,7 @@ import 'wicg-inert';
import { createBrowserHistory } from 'history';
export default class ModalRoot extends React.PureComponent {
static contextTypes = {
router: PropTypes.object,
};
@ -104,7 +105,7 @@ export default class ModalRoot extends React.PureComponent {
handleModalOpen () {
const history = this.history;
const state = {...history.location.state, mastodonModalOpen: true};
const state = { ...history.location.state, mastodonModalOpen: true };
history.push(history.location.pathname, state);
this.unlistenHistory = history.listen(() => {
this.props.onClose();

View file

@ -24,7 +24,7 @@ export default class Permalink extends React.PureComponent {
if (this.context.router) {
e.preventDefault();
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(this.props.to, state);
}

View file

@ -4,6 +4,7 @@ import { FormattedMessage } from 'react-intl';
export default
class Spoilers extends React.PureComponent {
static propTypes = {
spoilerText: PropTypes.string,
children: PropTypes.node,
@ -21,17 +22,17 @@ class Spoilers extends React.PureComponent {
const { spoilerText, children } = this.props;
const { hidden } = this.state;
const toggleText = hidden ?
<FormattedMessage
id='status.show_more'
defaultMessage='Show more'
key='0'
/> :
<FormattedMessage
id='status.show_less'
defaultMessage='Show less'
key='0'
/>;
const toggleText = hidden ?
(<FormattedMessage
id='status.show_more'
defaultMessage='Show more'
key='0'
/>) :
(<FormattedMessage
id='status.show_less'
defaultMessage='Show less'
key='0'
/>);
return ([
<p className='spoiler__text'>
@ -43,8 +44,9 @@ class Spoilers extends React.PureComponent {
</p>,
<div className={`status__content__spoiler ${!hidden ? 'status__content__spoiler--visible' : ''}`}>
{children}
</div>
</div>,
]);
}
}

View file

@ -53,7 +53,7 @@ export const defaultMediaVisibility = (status, settings) => {
}
return (displayMedia !== 'hide_all' && !status.get('sensitive') || displayMedia === 'show_all');
}
};
export default @injectIntl
class Status extends ImmutablePureComponent {
@ -291,7 +291,9 @@ class Status extends ImmutablePureComponent {
if (this.node && this.props.getScrollPosition) {
const position = this.props.getScrollPosition();
if (position !== null && this.node.offsetTop < position.top) {
requestAnimationFrame(() => { this.props.updateScrollBottom(position.height - position.top); });
requestAnimationFrame(() => {
this.props.updateScrollBottom(position.height - position.top);
});
}
}
}
@ -344,7 +346,7 @@ class Status extends ImmutablePureComponent {
status.getIn(['reblog', 'id'], status.get('id'))
}`;
}
let state = {...router.history.location.state};
let state = { ...router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
router.history.push(destination, state);
}
@ -360,7 +362,7 @@ class Status extends ImmutablePureComponent {
if (this.context.router && e.button === 0) {
const id = e.currentTarget.getAttribute('data-id');
e.preventDefault();
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(`/accounts/${id}`, state);
}
@ -415,13 +417,13 @@ class Status extends ImmutablePureComponent {
}
handleHotkeyOpen = () => {
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(`/statuses/${this.props.status.get('id')}`, state);
}
handleHotkeyOpenProfile = () => {
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`, state);
}

View file

@ -122,7 +122,7 @@ class StatusActionBar extends ImmutablePureComponent {
_openInteractionDialog = type => {
window.open(`/interact/${this.props.status.get('id')}?type=${type}`, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
}
}
handleDeleteClick = () => {
this.props.onDelete(this.props.status, this.context.router.history);
@ -153,7 +153,7 @@ class StatusActionBar extends ImmutablePureComponent {
}
handleOpen = () => {
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
if (state.mastodonModalOpen) {
this.context.router.history.replace(`/statuses/${this.props.status.get('id')}`, { mastodonBackSteps: (state.mastodonBackSteps || 0) + 1 });
} else {

View file

@ -13,7 +13,7 @@ const textMatchesTarget = (text, origin, host) => {
return (text === origin || text === host
|| text.startsWith(origin + '/') || text.startsWith(host + '/')
|| 'www.' + text === host || ('www.' + text).startsWith(host + '/'));
}
};
const isLinkMisleading = (link) => {
let linkTextParts = [];

View file

@ -48,16 +48,16 @@ class StatusIcons extends React.PureComponent {
const { intl, mediaIcon } = this.props;
switch (mediaIcon) {
case 'link':
return intl.formatMessage(messages.previewCard);
case 'picture-o':
return intl.formatMessage(messages.pictures);
case 'tasks':
return intl.formatMessage(messages.poll);
case 'video-camera':
return intl.formatMessage(messages.video);
case 'music':
return intl.formatMessage(messages.audio);
case 'link':
return intl.formatMessage(messages.previewCard);
case 'picture-o':
return intl.formatMessage(messages.pictures);
case 'tasks':
return intl.formatMessage(messages.poll);
case 'video-camera':
return intl.formatMessage(messages.video);
case 'music':
return intl.formatMessage(messages.audio);
}
}

View file

@ -19,8 +19,10 @@ const mapDispatchToProps = (dispatch, { status, items }) => ({
(item, i) => item ? {
...item,
name: `${item.text}-${i}`,
onClick: item.action ? ((e) => { return onItemClick(i, e) }) : null,
} : null
onClick: item.action ? ((e) => {
return onItemClick(i, e);
}) : null,
} : null,
),
}) : openDropdownMenu(id, dropdownPlacement, keyboard));
},

View file

@ -201,7 +201,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
<Spoilers spoilerText={intl.formatMessage(messages.author)}>
<AccountContainer id={status.getIn(['account', 'id'])} />
</Spoilers>
<Spoilers spoilerText={intl.formatMessage(messages.matchingFilters, {count: matchingFilters.size})}>
<Spoilers spoilerText={intl.formatMessage(messages.matchingFilters, { count: matchingFilters.size })}>
<ul>
{matchingFilters.map(filter => (
<li>
@ -221,7 +221,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
))}
</ul>
</Spoilers>
</div>
</div>,
],
confirm: intl.formatMessage(messages.unfilterConfirm),
onConfirm: onConfirm,

View file

@ -128,8 +128,7 @@ class Header extends ImmutablePureComponent {
if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
info.push(<span className='relationship-tag'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>);
}
else if (me !== account.get('id') && account.getIn(['relationship', 'blocking'])) {
} else if (me !== account.get('id') && account.getIn(['relationship', 'blocking'])) {
info.push(<span className='relationship-tag'><FormattedMessage id='account.blocked' defaultMessage='Blocked' /></span>);
}
@ -297,7 +296,7 @@ class Header extends ImmutablePureComponent {
{fields.map((pair, i) => (
<dl key={i}>
<dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} />
<dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}>
{pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} />
</dd>
@ -308,9 +307,9 @@ class Header extends ImmutablePureComponent {
{account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content' dangerouslySetInnerHTML={content} />}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

View file

@ -21,7 +21,7 @@ export default class MovedNote extends ImmutablePureComponent {
handleAccountClick = e => {
if (e.button === 0) {
e.preventDefault();
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(`/accounts/${this.props.to.get('id')}`, state);
}

View file

@ -12,7 +12,7 @@ import {
} from 'flavours/glitch/actions/accounts';
import {
mentionCompose,
directCompose
directCompose,
} from 'flavours/glitch/actions/compose';
import { initMuteModal } from 'flavours/glitch/actions/mutes';
import { initBlockModal } from 'flavours/glitch/actions/blocks';

View file

@ -12,7 +12,7 @@ const mapStateToProps = (state, { columnId }) => {
settings: (uuid && index >= 0) ? columns.get(index).get('params') : state.getIn(['settings', 'community']),
};
};
const mapDispatchToProps = (dispatch, { columnId }) => {
return {
onChange (key, checked) {

View file

@ -20,9 +20,9 @@ import CharacterCounter from './character_counter';
const messages = defineMessages({
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
missingDescriptionMessage: { id: 'confirmations.missing_media_description.message',
defaultMessage: 'At least one media attachment is lacking a description. Consider describing all media attachments for the visually impaired before sending your toot.' },
defaultMessage: 'At least one media attachment is lacking a description. Consider describing all media attachments for the visually impaired before sending your toot.' },
missingDescriptionConfirm: { id: 'confirmations.missing_media_description.confirm',
defaultMessage: 'Send anyway' },
defaultMessage: 'Send anyway' },
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' },
});

View file

@ -141,7 +141,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
onChange(name);
component.setState({ needsModalUpdate: true });
},
})
}),
),
};
}
@ -166,7 +166,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
const { items } = this.props;
const { needsModalUpdate } = this.state;
if (needsModalUpdate && items.find(
(item, i) => item.on !== prevProps.items[i].on
(item, i) => item.on !== prevProps.items[i].on,
)) {
this.handleUpdate();
this.setState({ needsModalUpdate: false });

View file

@ -167,7 +167,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
if (on !== null && typeof on !== 'undefined') {
prefix = <Toggle checked={on} onChange={this.handleClick.bind(this, name)} />;
} else if (icon) {
prefix = <Icon className='icon' fixedWidth id={icon} />
prefix = <Icon className='icon' fixedWidth id={icon} />;
}
return (

View file

@ -47,6 +47,7 @@ const messages = defineMessages({
export default @injectIntl
class Header extends ImmutablePureComponent {
static propTypes = {
columns: ImmutablePropTypes.list,
unreadNotifications: PropTypes.number,
@ -71,8 +72,8 @@ class Header extends ImmutablePureComponent {
// Only renders the component if the column isn't being shown.
const renderForColumn = conditionalRender.bind(null,
columnId => !columns || !columns.some(
column => column.get('id') === columnId
)
column => column.get('id') === columnId,
),
);
// The result.
@ -125,10 +126,11 @@ class Header extends ImmutablePureComponent {
<a
aria-label={intl.formatMessage(messages.logout)}
onClick={this.handleLogoutClick}
href={ signOutLink }
href={signOutLink}
title={intl.formatMessage(messages.logout)}
><Icon id='sign-out' /></a>
</nav>
);
};
}

View file

@ -28,11 +28,12 @@ export default class NavigationBar extends ImmutablePureComponent {
{ profileLink !== undefined && (
<a
className='edit'
href={ profileLink }
href={profileLink}
><FormattedMessage id='navigation_bar.edit_profile' defaultMessage='Edit profile' /></a>
)}
</div>
</div>
);
};
}

View file

@ -115,4 +115,5 @@ class Publisher extends ImmutablePureComponent {
</div>
);
};
}

View file

@ -97,7 +97,7 @@ class SearchResults extends ImmutablePureComponent {
<section>
<h5><Icon id='quote-right' fixedWidth /><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5>
{results.get('statuses').map(statusId => <StatusContainer id={statusId} key={statusId}/>)}
{results.get('statuses').map(statusId => <StatusContainer id={statusId} key={statusId} />)}
{results.get('statuses').size >= 5 && <LoadMore visible onClick={this.handleLoadMoreStatuses} />}
</section>
@ -131,4 +131,5 @@ class SearchResults extends ImmutablePureComponent {
</div>
);
};
}

View file

@ -51,9 +51,10 @@ class TextareaIcons extends ImmutablePureComponent {
id={icon}
/>
</span>
) : null
) : null,
) : null}
</div>
);
}
}

View file

@ -40,7 +40,7 @@ export default class Upload extends ImmutablePureComponent {
return (
<div className='composer--upload_form--item' tabIndex='0' role='button'>
<Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12, }) }}>
<Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12 }) }}>
{({ scale }) => (
<div style={{ transform: `scale(${scale})`, backgroundImage: `url(${media.get('preview_url')})`, backgroundPosition: `${x}% ${y}%` }}>
<div className={classNames('composer--upload_form--actions', { active: true })}>

View file

@ -7,6 +7,7 @@ import SensitiveButtonContainer from '../containers/sensitive_button_container';
import { FormattedMessage } from 'react-intl';
export default class UploadForm extends ImmutablePureComponent {
static propTypes = {
mediaIds: ImmutablePropTypes.list.isRequired,
};

View file

@ -30,7 +30,8 @@ export default class UploadProgress extends React.PureComponent {
<div className='backdrop'>
<Motion defaultStyle={{ width: 0 }} style={{ width: spring(progress) }}>
{({ width }) =>
(<div className='tracker' style={{ width: `${width}%` }}
(<div
className='tracker' style={{ width: `${width}%` }}
/>)
}
</Motion>

View file

@ -22,11 +22,11 @@ import { privacyPreference } from 'flavours/glitch/util/privacy_preference';
const messages = defineMessages({
missingDescriptionMessage: { id: 'confirmations.missing_media_description.message',
defaultMessage: 'At least one media attachment is lacking a description. Consider describing all media attachments for the visually impaired before sending your toot.' },
defaultMessage: 'At least one media attachment is lacking a description. Consider describing all media attachments for the visually impaired before sending your toot.' },
missingDescriptionConfirm: { id: 'confirmations.missing_media_description.confirm',
defaultMessage: 'Send anyway' },
defaultMessage: 'Send anyway' },
missingDescriptionEdit: { id: 'confirmations.missing_media_description.edit',
defaultMessage: 'Edit media' },
defaultMessage: 'Edit media' },
});
// State mapping.
@ -38,12 +38,12 @@ function mapStateToProps (state) {
const sideArmRestrictedPrivacy = replyPrivacy ? privacyPreference(replyPrivacy, sideArmBasePrivacy) : null;
let sideArmPrivacy = null;
switch (state.getIn(['local_settings', 'side_arm_reply_mode'])) {
case 'copy':
sideArmPrivacy = replyPrivacy;
break;
case 'restrict':
sideArmPrivacy = sideArmRestrictedPrivacy;
break;
case 'copy':
sideArmPrivacy = replyPrivacy;
break;
case 'restrict':
sideArmPrivacy = sideArmRestrictedPrivacy;
break;
}
sideArmPrivacy = sideArmPrivacy || sideArmBasePrivacy;
return {

View file

@ -34,6 +34,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
export default @connect(mapStateToProps, mapDispatchToProps)
@injectIntl
class Compose extends React.PureComponent {
static propTypes = {
multiColumn: PropTypes.bool,
showSearch: PropTypes.bool,

View file

@ -59,7 +59,7 @@ class Conversation extends ImmutablePureComponent {
}
destination = `/statuses/${lastStatus.get('id')}`;
}
let state = {...router.history.location.state};
let state = { ...router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
router.history.push(destination, state);
e.preventDefault();

View file

@ -83,9 +83,9 @@ const badgeDisplay = (number, limit) => {
const NAVIGATION_PANEL_BREAKPOINT = 600 + (285 * 2) + (10 * 2);
export default @connect(makeMapStateToProps, mapDispatchToProps)
export default @connect(makeMapStateToProps, mapDispatchToProps)
@injectIntl
class GettingStarted extends ImmutablePureComponent {
class GettingStarted extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object.isRequired,
@ -172,12 +172,12 @@ const NAVIGATION_PANEL_BREAKPOINT = 600 + (285 * 2) + (10 * 2);
<div key='9'>
<ColumnLink key='10' icon='bars' text={intl.formatMessage(messages.lists)} to='/lists' />
{lists.map(list =>
<ColumnLink key={(11 + Number(list.get('id'))).toString()} to={`/timelines/list/${list.get('id')}`} icon='list-ul' text={list.get('title')} />
<ColumnLink key={(11 + Number(list.get('id'))).toString()} to={`/timelines/list/${list.get('id')}`} icon='list-ul' text={list.get('title')} />,
)}
</div>,
]);
const instance_panel = (customPanelEnabled ? <div className='getting-started getting-started__panel' dangerouslySetInnerHTML={{__html: customPanel}} /> : null);
const instance_panel = (customPanelEnabled ? <div className='getting-started getting-started__panel' dangerouslySetInnerHTML={{ __html: customPanel }} /> : null);
return (
<Column bindToDocument={!multiColumn} name='getting-started' icon='asterisk' heading={intl.formatMessage(messages.heading)} label={intl.formatMessage(messages.menu)} hideHeadingOnMobile>

View file

@ -59,7 +59,6 @@ class gettingStartedMisc extends ImmutablePureComponent {
<ColumnLink key='{i++}' icon='ban' text={intl.formatMessage(messages.blocks)} to='/blocks' />
<ColumnLink key='{i++}' icon='minus-circle' text={intl.formatMessage(messages.domain_blocks)} to='/domain_blocks' />
<ColumnLink key='{i++}' icon='question' text={intl.formatMessage(messages.keyboard_shortcuts)} to='/keyboard-shortcuts' />
<ColumnLink key='{i++}' icon='book' text={intl.formatMessage(messages.info)} href='/about/more' />
<ColumnLink key='{i++}' icon='hand-o-right' text={intl.formatMessage(messages.show_me_around)} onClick={this.openOnboardingModal} />
</div>
</Column>

View file

@ -80,7 +80,7 @@ class LocalSettingsNavigation extends React.PureComponent {
/>
<LocalSettingsNavigationItem
active={index === 6}
href={ preferencesLink }
href={preferencesLink}
index={6}
icon='cog'
title={intl.formatMessage(messages.preferences)}

View file

@ -59,7 +59,7 @@ class LocalSettingsPage extends React.PureComponent {
onChange={onChange}
>
<FormattedMessage id='settings.hicolor_privacy_icons' defaultMessage='High color privacy icons' />
<span className='hint'><FormattedMessage id='settings.hicolor_privacy_icons.hint' defaultMessage="Display privacy icons in bright and easily distinguishable colors" /></span>
<span className='hint'><FormattedMessage id='settings.hicolor_privacy_icons.hint' defaultMessage='Display privacy icons in bright and easily distinguishable colors' /></span>
</LocalSettingsPageItem>
<LocalSettingsPageItem
settings={settings}
@ -76,7 +76,7 @@ class LocalSettingsPage extends React.PureComponent {
onChange={onChange}
>
<FormattedMessage id='settings.tag_misleading_links' defaultMessage='Tag misleading links' />
<span className='hint'><FormattedMessage id='settings.tag_misleading_links.hint' defaultMessage="Add a visual indication with the link target host to every link not mentioning it explicitly" /></span>
<span className='hint'><FormattedMessage id='settings.tag_misleading_links.hint' defaultMessage='Add a visual indication with the link target host to every link not mentioning it explicitly' /></span>
</LocalSettingsPageItem>
<LocalSettingsPageItem
settings={settings}
@ -99,7 +99,7 @@ class LocalSettingsPage extends React.PureComponent {
id='mastodon-settings--notifications-tab_badge'
onChange={onChange}
>
<FormattedMessage id='settings.notifications.tab_badge' defaultMessage="Unread notifications badge" />
<FormattedMessage id='settings.notifications.tab_badge' defaultMessage='Unread notifications badge' />
<span className='hint'><FormattedMessage id='settings.notifications.tab_badge.hint' defaultMessage="Display a badge for unread notifications in the column icons when the notifications column isn't open" /></span>
</LocalSettingsPageItem>
<LocalSettingsPageItem
@ -109,7 +109,7 @@ class LocalSettingsPage extends React.PureComponent {
onChange={onChange}
>
<FormattedMessage id='settings.notifications.favicon_badge' defaultMessage='Unread notifications favicon badge' />
<span className='hint'><FormattedMessage id='settings.notifications.favicon_badge.hint' defaultMessage="Add a badge for unread notifications to the favicon" /></span>
<span className='hint'><FormattedMessage id='settings.notifications.favicon_badge.hint' defaultMessage='Add a badge for unread notifications to the favicon' /></span>
</LocalSettingsPageItem>
</section>
<section>
@ -272,7 +272,7 @@ class LocalSettingsPage extends React.PureComponent {
{ value: 'drop', message: intl.formatMessage(messages.filters_drop) },
{ value: 'upstream', message: intl.formatMessage(messages.filters_upstream) },
{ value: 'hide', message: intl.formatMessage(messages.filters_hide) },
{ value: 'content_warning', message: intl.formatMessage(messages.filters_cw) }
{ value: 'content_warning', message: intl.formatMessage(messages.filters_cw) },
]}
>
<FormattedMessage id='settings.filtering_behavior' defaultMessage='Filtering behavior' />

View file

@ -53,13 +53,14 @@ export default class LocalSettingsPageItem extends React.PureComponent {
let optionId = `${id}--${opt.value}`;
return (
<label htmlFor={optionId}>
<input type='radio'
<input
type='radio'
name={id}
id={optionId}
value={opt.value}
onBlur={handleChange}
onChange={handleChange}
checked={ currentValue === opt.value }
checked={currentValue === opt.value}
disabled={!enabled}
/>
{opt.message}

View file

@ -4,7 +4,7 @@ import { injectIntl } from 'react-intl';
import {
fetchPinnedAccountsSuggestions,
clearPinnedAccountsSuggestions,
changePinnedAccountsSuggestions
changePinnedAccountsSuggestions,
} from '../../../actions/accounts';
import Search from 'flavours/glitch/features/list_editor/components/search';

View file

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import ColumnSettings from '../components/column_settings';
import { changeSetting } from 'flavours/glitch/actions/settings';
import { changeColumnParams } from 'flavours/glitch/actions/columns';
const mapStateToProps = (state, { columnId }) => {
const uuid = columnId;
const columns = state.getIn(['settings', 'columns']);

View file

@ -46,7 +46,7 @@ class PublicTimeline extends React.PureComponent {
dispatch(local ? expandCommunityTimeline() : expandPublicTimeline());
}
handleLoadMore = () => {
const { dispatch, statusIds, local } = this.props;
const maxId = statusIds.last();

View file

@ -47,7 +47,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
handleAccountClick = (e) => {
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey) && this.context.router) {
e.preventDefault();
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`, state);
}
@ -58,7 +58,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
parseClick = (e, destination) => {
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey) && this.context.router) {
e.preventDefault();
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(destination, state);
}

View file

@ -402,7 +402,7 @@ class Status extends ImmutablePureComponent {
}
handleHotkeyOpenProfile = () => {
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`, state);
}

View file

@ -44,7 +44,7 @@ class BoostModal extends ImmutablePureComponent {
if (e.button === 0) {
e.preventDefault();
this.props.onClose();
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`, state);
}
@ -90,9 +90,9 @@ class BoostModal extends ImmutablePureComponent {
<div className='boost-modal__action-bar'>
<div>
{ missingMediaDescription ?
<FormattedMessage id='boost_modal.missing_description' defaultMessage='This toot contains some media without description' />
<FormattedMessage id='boost_modal.missing_description' defaultMessage='This toot contains some media without description' />
:
<FormattedMessage id='boost_modal.combo' defaultMessage='You can press {combo} to skip this next time' values={{ combo: <span>Shift + <Icon id='retweet' /></span> }} />
<FormattedMessage id='boost_modal.combo' defaultMessage='You can press {combo} to skip this next time' values={{ combo: <span>Shift + <Icon id='retweet' /></span> }} />
}
</div>
<Button text={intl.formatMessage(buttonText)} onClick={this.handleReblog} ref={this.setRef} />

View file

@ -27,7 +27,7 @@ const ColumnLink = ({ icon, text, to, onClick, href, method, badge }) => {
e.preventDefault();
e.stopPropagation();
return onClick(e);
}
};
return (
<a href='#' onClick={onClick && handleOnClick} className='column-link' tabIndex='0'>
<Icon id={icon} fixedWidth className='column-link__icon' />

View file

@ -575,7 +575,7 @@ class DoodleModal extends ImmutablePureComponent {
<div>
<select aria-label='Canvas size' onInput={this.changeSize} defaultValue={this.size}>
{ Object.values(mapValues(DOODLE_SIZES, (val, k) =>
<option key={k} value={k}>{val[2]}</option>
<option key={k} value={k}>{val[2]}</option>,
)) }
</select>
</div>
@ -602,7 +602,7 @@ class DoodleModal extends ImmutablePureComponent {
'foreground': this.fg === c[0],
'background': this.bg === c[0],
})}
/>
/>,
)
}
</div>

View file

@ -41,7 +41,7 @@ class FavouriteModal extends ImmutablePureComponent {
if (e.button === 0) {
e.preventDefault();
this.props.onClose();
let state = {...this.context.router.history.location.state};
let state = { ...this.context.router.history.location.state };
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`, state);
}

View file

@ -21,11 +21,12 @@ class LinkFooter extends React.PureComponent {
mastofe: <a href='https://git.pleroma.social/pleroma/mastofe' rel='noopener noreferrer' target='_blank'>Mastofe</a>,
glitchsoc: <a href='https://github.com/glitch-soc/mastodon' rel='noopener noreferrer' target='_blank'>glitch-soc</a>,
mastodon: <a href='https://github.com/tootsuite/mastodon' rel='noopener noreferrer' target='_blank'>Mastodon</a>,
pleroma: <a href='https://pleroma.social' rel='noopener noreferrer' target='_blank'>Pleroma</a>
pleroma: <a href='https://pleroma.social' rel='noopener noreferrer' target='_blank'>Pleroma</a>,
}}
/>
</p>
</div>
);
}
};

View file

@ -29,8 +29,8 @@ const PageOne = ({ acct, domain }) => (
<div>
<h1><FormattedMessage id='onboarding.page_one.welcome' defaultMessage='Welcome to {domain}!' values={{ domain }} /></h1>
<p><FormattedMessage id='onboarding.page_one.federation' defaultMessage='{domain} is an "instance" of Mastodon. Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.' values={{ domain }} /></p>
<p><FormattedMessage id='onboarding.page_one.handle' defaultMessage='You are on {domain}, so your full handle is {handle}' values={{ domain, handle: <strong>@{acct}@{domain}</strong> }} /></p>
<p><FormattedMessage id='onboarding.page_one.fediverse' defaultMessage='{domain} is a Fediverse node, running Pleroma. The Fediverse is decentralized federated network made of many independent nodes, like email.' values={{ domain, handle: <strong>{acct}@{domain}</strong> }} /></p>
</div>
</div>
);
@ -49,7 +49,7 @@ const PageTwo = ({ intl, myAccount }) => (
privacy='public'
text='Awoo! #introductions'
spoilerText=''
suggestions={ [] }
suggestions={[]}
/>
</div>
</div>
@ -131,8 +131,6 @@ const PageSix = ({ admin, domain }) => {
adminSection = (
<p>
<FormattedMessage id='onboarding.page_six.admin' defaultMessage="Your instance's admin is {admin}." values={{ admin: <Permalink href={admin.get('url')} to={`/accounts/${admin.get('id')}`}>@{admin.get('acct')}</Permalink> }} />
<br />
<FormattedMessage id='onboarding.page_six.read_guidelines' defaultMessage="Please read {domain}'s {guidelines}!" values={{ domain, guidelines: <a href='/about/more' target='_blank'><FormattedMessage id='onboarding.page_six.guidelines' defaultMessage='community guidelines' /></a> }} />
</p>
);
}
@ -141,9 +139,8 @@ const PageSix = ({ admin, domain }) => {
<div className='onboarding-modal__page onboarding-modal__page-six'>
<h1><FormattedMessage id='onboarding.page_six.almost_done' defaultMessage='Almost done...' /></h1>
{adminSection}
<p><FormattedMessage id='onboarding.page_six.github' defaultMessage='{domain} runs on Glitchsoc. Glitchsoc is a friendly {fork} of {Mastodon}. Glitchsoc is fully compatible with all Mastodon apps and instances. Glitchsoc is free open-source software. You can report bugs, request features, or contribute to the code on {github}.' values={{ domain, fork: <a href='https://en.wikipedia.org/wiki/Fork_(software_development)' target='_blank' rel='noopener'>fork</a>, Mastodon: <a href='https://github.com/tootsuite/mastodon' target='_blank' rel='noopener'>Mastodon</a>, github: <a href='https://github.com/glitch-soc/mastodon' target='_blank' rel='noopener'>GitHub</a> }} /></p>
<p><FormattedMessage id='onboarding.page_six.apps_available' defaultMessage='There are {apps} available for iOS, Android and other platforms.' values={{ domain, apps: <a href='https://joinmastodon.org/apps' target='_blank' rel='noopener'><FormattedMessage id='onboarding.page_six.various_app' defaultMessage='mobile apps' /></a> }} /></p>
<p><em><FormattedMessage id='onboarding.page_six.appetoot' defaultMessage='Bon Appetoot!' /></em></p>
<p><FormattedMessage id='onboarding.page_six.github' defaultMessage='{domain} runs on Pleroma. Pleroma is a free, federated social networking server built on open protocols. It is compatible with GNU Social, Mastodon, and many other ActivityPub implementations. You can report bugs, request features, or contribute to the code on {gitlab}.' values={{ domain, gitlab: <a href='https://git.pleroma.social/pleroma/' target='_blank' rel='noopener'>Pleroma's Gitlab</a> }} /></p>
<p><FormattedMessage id='onboarding.page_six.apps_available' defaultMessage='There are {apps} available for iOS, Android, SailfishOS and other platforms.' values={{ domain, apps: <a href='https://docs.pleroma.social/backend/clients/' target='_blank' rel='noopener'><FormattedMessage id='onboarding.page_six.various_app' defaultMessage='mobile apps' /></a> }} /></p>
</div>
);
};

View file

@ -386,7 +386,7 @@ class UI extends React.Component {
navigator.serviceWorker.addEventListener('message', this.handleServiceWorkerPostMessage);
}
this.favicon = new Favico({ animation:"none" });
this.favicon = new Favico({ animation:'none' });
this.props.dispatch(fetchMarkers());
this.props.dispatch(expandHomeTimeline());
@ -596,7 +596,7 @@ class UI extends React.Component {
<PermaLink href={moved.get('url')} to={`/accounts/${moved.get('id')}`}>
@{moved.get('acct')}
</PermaLink>
)}}
) }}
/>
</div>)}
<SwitchingColumnsArea location={location} layout={layout} navbarUnder={navbarUnder} onLayoutChange={this.handleLayoutChange}>

View file

@ -429,7 +429,7 @@ class Video extends React.PureComponent {
playerStyle.height = height;
} else if (inline) {
return (<div className={computedClass} ref={this.setPlayerRef} tabindex={0}></div>);
return (<div className={computedClass} ref={this.setPlayerRef} tabindex={0} />);
}
let warning;

View file

@ -84,7 +84,7 @@ const messages = {
'navigation_bar.direct': 'ダイレクトメッセージ',
'navigation_bar.bookmarks': 'ブックマーク',
'column.bookmarks': 'ブックマーク'
'column.bookmarks': 'ブックマーク',
};
export default Object.assign({}, inherited, messages);

View file

@ -67,13 +67,13 @@ const messages = {
'advanced_options.threaded_mode.short': 'Tryb wątków',
'advanced_options.threaded_mode.long': 'Przechodzi do tworzenia odpowiedzi po publikacji wpisu',
'advanced_options.threaded_mode.tooltip': 'Włączono tryb wątków',
'column.bookmarks': 'Zakładki',
'compose_form.sensitive': 'Oznacz zawartość multimedialną jako wrażliwą',
'compose_form.spoiler': 'Ukryj tekst za ostrzeżeniem',
'favourite_modal.combo': 'Możesz nacisnąć {combo}, aby pominąć to następnym razem',
'tabs_bar.compose': 'Napisz',
};
export default Object.assign({}, inherited, messages);

View file

@ -128,16 +128,16 @@ function apiStatusToTextMentions (state, status) {
}
return set.union(status.mentions.filter(
mention => mention.id !== me
mention => mention.id !== me,
).map(
mention => `@${mention.acct} `
mention => `@${mention.acct} `,
)).join('');
}
function apiStatusToTextHashtags (state, status) {
const text = unescapeHTML(status.content);
return ImmutableOrderedSet([]).union(recoverHashtags(status.tags, text).map(
(name) => `#${name} `
(name) => `#${name} `,
)).join('');
}
@ -152,7 +152,7 @@ function clearAll(state) {
map.set('in_reply_to', null);
map.update(
'advanced_options',
map => map.mergeWith(overwrite, state.get('default_advanced_options'))
map => map.mergeWith(overwrite, state.get('default_advanced_options')),
);
map.set('privacy', state.get('default_privacy'));
map.set('sensitive', false);
@ -178,7 +178,7 @@ function continueThread (state, status) {
map.set('in_reply_to', status.id);
map.update(
'advanced_options',
map => map.merge(new ImmutableMap({ do_not_federate: /👁\ufe0f?\u200b?(?:<\/p>)?$/.test(status.content) }))
map => map.merge(new ImmutableMap({ do_not_federate: /👁\ufe0f?\u200b?(?:<\/p>)?$/.test(status.content) })),
);
map.set('privacy', status.visibility);
map.set('sensitive', false);
@ -377,7 +377,7 @@ export default function compose(state = initialState, action) {
map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy')));
map.update(
'advanced_options',
map => map.merge(new ImmutableMap({ do_not_federate: /👁\ufe0f?\u200b?(?:<\/p>)?$/.test(action.status.get('content')) }))
map => map.merge(new ImmutableMap({ do_not_federate: /👁\ufe0f?\u200b?(?:<\/p>)?$/.test(action.status.get('content')) })),
);
map.set('focusDate', new Date());
map.set('caretPosition', null);
@ -409,7 +409,7 @@ export default function compose(state = initialState, action) {
map.set('poll', null);
map.update(
'advanced_options',
map => map.mergeWith(overwrite, state.get('default_advanced_options'))
map => map.mergeWith(overwrite, state.get('default_advanced_options')),
);
map.set('idempotencyKey', uuid());
});

View file

@ -67,7 +67,7 @@ const deleteFromContexts = (immutableState, ids) => immutableState.withMutations
const filterContexts = (state, relationship, statuses) => {
const ownedStatusIds = statuses.filter(status => status.get('account') === relationship.id)
.map(status => status.get('id'));
.map(status => status.get('id'));
return deleteFromContexts(state, ownedStatusIds);
};

View file

@ -54,10 +54,10 @@ export default function listEditorReducer(state = initialState, action) {
});
case LIST_CREATE_REQUEST:
case LIST_UPDATE_REQUEST:
return state.withMutations(map => {
map.set('isSubmitting', true);
map.set('isChanged', false);
});
return state.withMutations(map => {
map.set('isSubmitting', true);
map.set('isChanged', false);
});
case LIST_CREATE_FAIL:
case LIST_UPDATE_FAIL:
return state.set('isSubmitting', false);

View file

@ -127,7 +127,7 @@ const clearUnread = (state) => {
state = state.set('unread', state.get('pendingItems').size);
const lastNotification = state.get('items').find(item => item !== null);
return state.set('lastReadId', lastNotification ? lastNotification.get('id') : '0');
}
};
const updateTop = (state, top) => {
state = state.set('top', top);
@ -210,7 +210,7 @@ const recountUnread = (state, last_read_id) => {
mutable.set('unread', mutable.get('pendingItems').count(item => item !== null) + mutable.get('items').count(item => item && compareId(item.get('id'), last_read_id) > 0));
}
});
}
};
export default function notifications(state = initialState, action) {
let st;

View file

@ -3,7 +3,7 @@ import { PANEL_FETCH_SUCCESS, PLEROMA_CONFIG_FETCH_SUCCESS } from 'mastodon/acti
const initialPanel = ImmutableMap({
enabled: false,
panel: ''
panel: '',
});
export default function custom_panel(state = initialPanel, action) {

View file

@ -1,7 +1,7 @@
export const preferencesLink = '/settings';
export const profileLink = '/user-settings';
export const preferencesLink = undefined; // '/settings/preferences';
export const profileLink = undefined; // '/settings/profile';
export const signOutLink = '/auth/sign_out';
export const termsLink = '/terms';
export const termsLink = undefined; // '/terms';
export const accountAdminLink = (id) => `/pleroma/admin/#/users/${id}/`;
export const statusAdminLink = (account_id, status_id) => `/pleroma/admin/#/users/${account_id}/`;
export const filterEditLink = undefined; // (id) => `/filters/${id}/edit`;

View file

@ -1,8 +1,8 @@
export function recoverHashtags (recognizedTags, text) {
return recognizedTags.map(tag => {
const re = new RegExp(`(?:^|[^\/\)\w])#(${tag.name})`, 'i');
const matched_hashtag = text.match(re);
return matched_hashtag ? matched_hashtag[1] : null;
}
const re = new RegExp(`(?:^|[^\/\)\w])#(${tag.name})`, 'i');
const matched_hashtag = text.match(re);
return matched_hashtag ? matched_hashtag[1] : null;
},
).filter(x => x !== null);
}

View file

@ -9,7 +9,7 @@ const maybeSetNotificationsSettings = result => {
excludeTypes.forEach(x => showTypes[x] = false);
set(result, ['settings', 'notifications', 'shows'], showTypes);
}
};
const element = document.getElementById('initial-state');
const initialState = element && function () {

View file

@ -2,33 +2,9 @@ import Rails from '@rails/ujs';
import { signOutLink } from 'flavours/glitch/util/backend_links';
export const logOut = () => {
const form = document.createElement('form');
const methodInput = document.createElement('input');
methodInput.setAttribute('name', '_method');
methodInput.setAttribute('value', 'delete');
methodInput.setAttribute('type', 'hidden');
form.appendChild(methodInput);
const csrfToken = Rails.csrfToken();
const csrfParam = Rails.csrfParam();
if (csrfParam && csrfToken) {
const csrfInput = document.createElement('input');
csrfInput.setAttribute('name', csrfParam);
csrfInput.setAttribute('value', csrfToken);
csrfInput.setAttribute('type', 'hidden');
form.appendChild(csrfInput);
}
const submitButton = document.createElement('input');
submitButton.setAttribute('type', 'submit');
form.appendChild(submitButton);
form.method = 'post';
form.action = signOutLink;
form.style.display = 'none';
document.body.appendChild(form);
submitButton.click();
fetch(signOutLink, {
method: 'DELETE',
}).then(() => {
window.location = '/web/';
});
};

View file

@ -7,7 +7,7 @@ export function assignHandlers (target, handlers) {
// We just bind each handler to the `target`.
const handle = target.handlers = {};
Object.keys(handlers).forEach(
key => handle[key] = handlers[key].bind(target)
key => handle[key] = handlers[key].bind(target),
);
}

View file

@ -27,6 +27,7 @@ store.dispatch(fetchCustomEmojis());
@connect(mapStateToProps)
class MastodonMount extends React.PureComponent {
shouldUpdateScroll (_, { location }) {
return location.state !== previewMediaState && location.state !== previewVideoState;
}

View file

@ -1,20 +1,20 @@
#!/bin/sh
TARGET="${TARGET:-../pleroma}" # Where pleromas repository is sitting
static_dir="priv/static" # Set this to instance/static when testing production build
TARGET="${TARGET:-./distribution}" # Where pleromas repository is sitting
mkdir -p $TARGET/emoji
die() {
echo "Die: $@"
exit 1
}
[ -d "${TARGET}/priv/static" ] || die "${TARGET}/priv/static directory is missing, are you sure TARGET is set to a pleroma repository? (Info: TARGET=${TARGET} )"
[ -d "${TARGET}" ] || die "${TARGET} directory is missing, are you sure TARGET is set to a pleroma repository? (Info: TARGET=${TARGET} )"
yarn install -D || die "Installing dependencies via yarn failed"
rm -rf public/packs public/assets
env -i "PATH=$PATH" npm run build || die "Building the frontend failed"
cp public/assets/sw.js "${TARGET}/${static_dir}/sw.js" || die "installing sw.js (service-worker) failed"
rm -rf "${TARGET}/${static_dir}/packs" || die "Removing old assets in priv/static/packs failed"
cp -r public/packs "${TARGET}/${static_dir}/packs" || die "Copying new assets in priv/static/packs failed"
rm -rf "${TARGET}/${static_dir}/emoji/*.svg" || die "Removing the old emoji assets failed"
cp -r public/emoji/* "${TARGET}/${static_dir}/emoji" || die "Installing the new emoji assets failed"
cp public/assets/sw.js "${TARGET}/sw.js" || die "installing sw.js (service-worker) failed"
rm -rf "${TARGET}/packs" || die "Removing old assets in priv/static/packs failed"
cp -r public/packs "${TARGET}/packs" || die "Copying new assets in priv/static/packs failed"
rm -rf "${TARGET}/emoji/*.svg" || die "Removing the old emoji assets failed"
cp -r public/emoji/* "${TARGET}/emoji" || die "Installing the new emoji assets failed"

View file

@ -8,8 +8,8 @@ const glob = require('glob');
const configPath = resolve('config', 'webpacker.yml');
const settings = safeLoad(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env.NODE_ENV];
const flavourFiles = glob.sync('app/javascript/flavours/*/theme.yml');
const skinFiles = glob.sync('app/javascript/skins/*/*');
const flavourFiles = glob.sync('app/javascript/flavours/glitch/theme.yml');
const skinFiles = glob.sync('app/javascript/skins/glitch/*');
const flavours = {};
const core = function () {

View file

@ -21,7 +21,7 @@ module.exports = Object.keys(flavours).reduce(function (map, entry) {
return map;
}
const locales = readdirSync(flavour.locales).filter(
filename => /\.js(?:on)?$/.test(filename) && !/defaultMessages|whitelist|index/.test(filename)
filename => /\.js(?:on)?$/.test(filename) && !/defaultMessages|whitelist|index/.test(filename),
);
const outPath = resolve('tmp', 'locales', entry);
@ -40,9 +40,9 @@ module.exports = Object.keys(flavours).reduce(function (map, entry) {
// fall back to English (this is what react-intl does anyway)
'node_modules/react-intl/locale-data/en.js',
].filter(
filename => existsSync(filename)
filename => existsSync(filename),
).map(
filename => filename.replace(/(?:node_modules|app\/javascript)\//, '')
filename => filename.replace(/(?:node_modules|app\/javascript)\//, ''),
)[0];
const localeContent = `//
// locales/${entry}/${localeName}.js

View file

@ -50,7 +50,7 @@ const entries = Object.assign(
{ locales: resolve('app', 'javascript', 'locales') },
localePacks,
reducePacks(core),
Object.keys(flavours).reduce((map, entry) => reducePacks(flavours[entry], map), {})
Object.keys(flavours).reduce((map, entry) => reducePacks(flavours[entry], map), {}),
);

View file

@ -2,9 +2,6 @@
"name": "@tootsuite/mastodon",
"description": "mastodon",
"license": "AGPL-3.0-or-later",
"engines": {
"node": ">=10.13 <13"
},
"scripts": {
"postversion": "git push --tags",
"build:development": "cross-env NODE_ENV=development webpack --config config/webpack/development.js",