sforkowany z mirror/soapbox
Merge branch 'account-aliases' into 'develop'
Account aliases See merge request soapbox-pub/soapbox-fe!663groups^2
commit
bde53541b7
|
@ -0,0 +1,128 @@
|
|||
import { defineMessages } from 'react-intl';
|
||||
import api from '../api';
|
||||
import { importFetchedAccount, importFetchedAccounts } from './importer';
|
||||
import { showAlertForError } from './alerts';
|
||||
import snackbar from './snackbar';
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { ME_PATCH_SUCCESS } from './me';
|
||||
|
||||
export const ALIASES_SUGGESTIONS_CHANGE = 'ALIASES_SUGGESTIONS_CHANGE';
|
||||
export const ALIASES_SUGGESTIONS_READY = 'ALIASES_SUGGESTIONS_READY';
|
||||
export const ALIASES_SUGGESTIONS_CLEAR = 'ALIASES_SUGGESTIONS_CLEAR';
|
||||
|
||||
export const ALIASES_ADD_REQUEST = 'ALIASES_ADD_REQUEST';
|
||||
export const ALIASES_ADD_SUCCESS = 'ALIASES_ADD_SUCCESS';
|
||||
export const ALIASES_ADD_FAIL = 'ALIASES_ADD_FAIL';
|
||||
|
||||
export const ALIASES_REMOVE_REQUEST = 'ALIASES_REMOVE_REQUEST';
|
||||
export const ALIASES_REMOVE_SUCCESS = 'ALIASES_REMOVE_SUCCESS';
|
||||
export const ALIASES_REMOVE_FAIL = 'ALIASES_REMOVE_FAIL';
|
||||
|
||||
const messages = defineMessages({
|
||||
createSuccess: { id: 'aliases.success.add', defaultMessage: 'Account alias created successfully' },
|
||||
removeSuccess: { id: 'aliases.success.remove', defaultMessage: 'Account alias removed successfully' },
|
||||
});
|
||||
|
||||
export const fetchAliasesSuggestions = q => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const params = {
|
||||
q,
|
||||
resolve: true,
|
||||
limit: 4,
|
||||
};
|
||||
|
||||
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
dispatch(fetchAliasesSuggestionsReady(q, data));
|
||||
}).catch(error => dispatch(showAlertForError(error)));
|
||||
};
|
||||
|
||||
export const fetchAliasesSuggestionsReady = (query, accounts) => ({
|
||||
type: ALIASES_SUGGESTIONS_READY,
|
||||
query,
|
||||
accounts,
|
||||
});
|
||||
|
||||
export const clearAliasesSuggestions = () => ({
|
||||
type: ALIASES_SUGGESTIONS_CLEAR,
|
||||
});
|
||||
|
||||
export const changeAliasesSuggestions = value => ({
|
||||
type: ALIASES_SUGGESTIONS_CHANGE,
|
||||
value,
|
||||
});
|
||||
|
||||
export const addToAliases = (intl, apId) => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const alsoKnownAs = getState().getIn(['meta', 'pleroma', 'also_known_as']);
|
||||
|
||||
dispatch(addToAliasesRequest(apId));
|
||||
|
||||
api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: [...alsoKnownAs, apId] })
|
||||
.then((response => {
|
||||
dispatch(snackbar.success(intl.formatMessage(messages.createSuccess)));
|
||||
dispatch(addToAliasesSuccess(response.data));
|
||||
}))
|
||||
.catch(err => dispatch(addToAliasesFail(err)));
|
||||
};
|
||||
|
||||
export const addToAliasesRequest = (apId) => ({
|
||||
type: ALIASES_ADD_REQUEST,
|
||||
apId,
|
||||
});
|
||||
|
||||
export const addToAliasesSuccess = me => dispatch => {
|
||||
dispatch(importFetchedAccount(me));
|
||||
dispatch({
|
||||
type: ME_PATCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
dispatch({
|
||||
type: ALIASES_ADD_SUCCESS,
|
||||
});
|
||||
};
|
||||
|
||||
export const addToAliasesFail = (apId, error) => ({
|
||||
type: ALIASES_ADD_FAIL,
|
||||
apId,
|
||||
error,
|
||||
});
|
||||
|
||||
export const removeFromAliases = (intl, apId) => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const alsoKnownAs = getState().getIn(['meta', 'pleroma', 'also_known_as']);
|
||||
|
||||
dispatch(removeFromAliasesRequest(apId));
|
||||
|
||||
api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: alsoKnownAs.filter(id => id !== apId) })
|
||||
.then(response => {
|
||||
dispatch(snackbar.success(intl.formatMessage(messages.removeSuccess)));
|
||||
dispatch(removeFromAliasesSuccess(response.data));
|
||||
})
|
||||
.catch(err => dispatch(removeFromAliasesFail(apId, err)));
|
||||
};
|
||||
|
||||
export const removeFromAliasesRequest = (apId) => ({
|
||||
type: ALIASES_REMOVE_REQUEST,
|
||||
apId,
|
||||
});
|
||||
|
||||
export const removeFromAliasesSuccess = me => dispatch => {
|
||||
dispatch(importFetchedAccount(me));
|
||||
dispatch({
|
||||
type: ME_PATCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
dispatch({
|
||||
type: ALIASES_REMOVE_SUCCESS,
|
||||
});
|
||||
};
|
||||
|
||||
export const removeFromAliasesFail = (apId, error) => ({
|
||||
type: ALIASES_REMOVE_FAIL,
|
||||
apId,
|
||||
error,
|
||||
});
|
|
@ -33,6 +33,7 @@ const messages = defineMessages({
|
|||
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' },
|
||||
account_aliases: { id: 'navigation_bar.account_aliases', defaultMessage: 'Account aliases' },
|
||||
security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
|
||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||
lists: { id: 'column.lists', defaultMessage: 'Lists' },
|
||||
|
@ -258,6 +259,10 @@ class SidebarMenu extends ImmutablePureComponent {
|
|||
<Icon id='cloud-upload' />
|
||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.import_data)}</span>
|
||||
</NavLink>
|
||||
<NavLink className='sidebar-menu-item' to='/settings/aliases' onClick={this.handleClose}>
|
||||
<Icon id='suitcase' />
|
||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.account_aliases)}</span>
|
||||
</NavLink>
|
||||
<NavLink className='sidebar-menu-item' to='/auth/edit' onClick={this.handleClose}>
|
||||
<Icon id='lock' />
|
||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.security)}</span>
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { makeGetAccount } from '../../../selectors';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Avatar from '../../../components/avatar';
|
||||
import DisplayName from '../../../components/display_name';
|
||||
import IconButton from '../../../components/icon_button';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { addToAliases } from '../../../actions/aliases';
|
||||
|
||||
const messages = defineMessages({
|
||||
add: { id: 'aliases.account.add', defaultMessage: 'Create alias' },
|
||||
});
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = (state, { accountId, added }) => {
|
||||
const account = getAccount(state, accountId);
|
||||
const apId = account.getIn(['pleroma', 'ap_id']);
|
||||
|
||||
return {
|
||||
account,
|
||||
apId,
|
||||
added: typeof added === 'undefined' ? state.getIn(['meta', 'pleroma', 'also_known_as']).includes(apId) : added,
|
||||
me: state.get('me'),
|
||||
};
|
||||
};
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onAdd: (intl, apId) => dispatch(addToAliases(intl, apId)),
|
||||
});
|
||||
|
||||
export default @connect(makeMapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Account extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
apId: PropTypes.string.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onAdd: PropTypes.func.isRequired,
|
||||
added: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
added: false,
|
||||
};
|
||||
|
||||
handleOnAdd = () => this.props.onAdd(this.props.intl, this.props.apId);
|
||||
|
||||
render() {
|
||||
const { account, accountId, intl, added, me } = this.props;
|
||||
|
||||
let button;
|
||||
|
||||
if (!added && accountId !== me) {
|
||||
button = (
|
||||
<div className='account__relationship'>
|
||||
<IconButton icon='plus' title={intl.formatMessage(messages.add)} onClick={this.handleOnAdd} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='account'>
|
||||
<div className='account__wrapper'>
|
||||
<div className='account__display-name'>
|
||||
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
|
||||
<DisplayName account={account} />
|
||||
</div>
|
||||
|
||||
{button}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { fetchAliasesSuggestions, clearAliasesSuggestions, changeAliasesSuggestions } from '../../../actions/aliases';
|
||||
import classNames from 'classnames';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import Button from 'soapbox/components/button';
|
||||
|
||||
const messages = defineMessages({
|
||||
search: { id: 'aliases.search', defaultMessage: 'Search your old account' },
|
||||
searchTitle: { id: 'tabs_bar.search', defaultMessage: 'Search' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
value: state.getIn(['aliases', 'suggestions', 'value']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onSubmit: value => dispatch(fetchAliasesSuggestions(value)),
|
||||
onClear: () => dispatch(clearAliasesSuggestions()),
|
||||
onChange: value => dispatch(changeAliasesSuggestions(value)),
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Search extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
onClear: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
handleChange = e => {
|
||||
this.props.onChange(e.target.value);
|
||||
}
|
||||
|
||||
handleKeyUp = e => {
|
||||
if (e.keyCode === 13) {
|
||||
this.props.onSubmit(this.props.value);
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
this.props.onSubmit(this.props.value);
|
||||
}
|
||||
|
||||
handleClear = () => {
|
||||
this.props.onClear();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value, intl } = this.props;
|
||||
const hasValue = value.length > 0;
|
||||
|
||||
return (
|
||||
<div className='aliases_search search'>
|
||||
<label>
|
||||
<span style={{ display: 'none' }}>{intl.formatMessage(messages.search)}</span>
|
||||
|
||||
<input
|
||||
className='search__input'
|
||||
type='text'
|
||||
value={value}
|
||||
onChange={this.handleChange}
|
||||
onKeyUp={this.handleKeyUp}
|
||||
placeholder={intl.formatMessage(messages.search)}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div role='button' tabIndex='0' className='search__icon' onClick={this.handleClear}>
|
||||
<Icon id='search' className={classNames({ active: !hasValue })} />
|
||||
<Icon id='times-circle' aria-label={intl.formatMessage(messages.search)} className={classNames({ active: hasValue })} />
|
||||
</div>
|
||||
<Button onClick={this.handleSubmit}>{intl.formatMessage(messages.searchTitle)}</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import Column from '../ui/components/column';
|
||||
import ColumnSubheading from '../ui/components/column_subheading';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import Search from './components/search';
|
||||
import Account from './components/account';
|
||||
import { removeFromAliases } from '../../actions/aliases';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.aliases', defaultMessage: 'Account aliases' },
|
||||
subheading_add_new: { id: 'column.aliases.subheading_add_new', defaultMessage: 'Add New Alias' },
|
||||
create_error: { id: 'column.aliases.create_error', defaultMessage: 'Error creating alias' },
|
||||
delete_error: { id: 'column.aliases.delete_error', defaultMessage: 'Error deleting alias' },
|
||||
subheading_aliases: { id: 'column.aliases.subheading_aliases', defaultMessage: 'Current aliases' },
|
||||
delete: { id: 'column.aliases.delete', defaultMessage: 'Delete' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
aliases: state.getIn(['meta', 'pleroma', 'also_known_as']),
|
||||
searchAccountIds: state.getIn(['aliases', 'suggestions', 'items']),
|
||||
loaded: state.getIn(['aliases', 'suggestions', 'loaded']),
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Aliases extends ImmutablePureComponent {
|
||||
|
||||
handleFilterDelete = e => {
|
||||
const { dispatch, intl } = this.props;
|
||||
dispatch(removeFromAliases(intl, e.currentTarget.dataset.value));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, aliases, searchAccountIds, loaded } = this.props;
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.aliases' defaultMessage="You haven't created any account alias yet." />;
|
||||
|
||||
return (
|
||||
<Column className='aliases-settings-panel' icon='suitcase' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||
<ColumnSubheading text={intl.formatMessage(messages.subheading_add_new)} />
|
||||
<Search />
|
||||
{
|
||||
loaded && searchAccountIds.size === 0 ? (
|
||||
<div className='aliases__accounts empty-column-indicator'>
|
||||
<FormattedMessage id='empty_column.aliases.suggestions' defaultMessage='There are no account suggestions available for the provided term.' />
|
||||
</div>
|
||||
) : (
|
||||
<div className='aliases__accounts'>
|
||||
{searchAccountIds.map(accountId => <Account key={accountId} accountId={accountId} />)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<ColumnSubheading text={intl.formatMessage(messages.subheading_aliases)} />
|
||||
<div className='aliases-settings-panel'>
|
||||
<ScrollableList
|
||||
scrollKey='aliases'
|
||||
emptyMessage={emptyMessage}
|
||||
>
|
||||
{aliases.map((alias, i) => (
|
||||
<div key={i} className='alias__container'>
|
||||
<div className='alias__details'>
|
||||
<span className='alias__list-label'><FormattedMessage id='aliases.account_label' defaultMessage='Old account:' /></span>
|
||||
<span className='alias__list-value'>{alias}</span>
|
||||
</div>
|
||||
<div className='alias__delete' role='button' tabIndex='0' onClick={this.handleFilterDelete} data-value={alias} aria-label={intl.formatMessage(messages.delete)}>
|
||||
<Icon className='alias__delete-icon' id='times' size={40} />
|
||||
<span className='alias__delete-label'><FormattedMessage id='aliases.aliases_list_delete' defaultMessage='Unlink alias' /></span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -38,6 +38,7 @@ const LinkFooter = ({ onOpenHotkeys, account, onClickLogOut }) => (
|
|||
{isAdmin(account) && <li><a href='/pleroma/admin'><FormattedMessage id='navigation_bar.admin_settings' defaultMessage='AdminFE' /></a></li>}
|
||||
{isAdmin(account) && <li><Link to='/soapbox/config'><FormattedMessage id='navigation_bar.soapbox_config' defaultMessage='Soapbox config' /></Link></li>}
|
||||
<li><Link to='/settings/import'><FormattedMessage id='navigation_bar.import_data' defaultMessage='Import data' /></Link></li>
|
||||
<li><Link to='/settings/aliases'><FormattedMessage id='navigation_bar.account_aliases' defaultMessage='Account aliases' /></Link></li>
|
||||
<li><a href='#' onClick={onOpenHotkeys}><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></a></li>
|
||||
</>}
|
||||
<li><Link to='/about'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></Link></li>
|
||||
|
|
|
@ -98,6 +98,7 @@ import {
|
|||
ScheduledStatuses,
|
||||
UserIndex,
|
||||
FederationRestrictions,
|
||||
Aliases,
|
||||
} from './util/async-components';
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
|
@ -261,6 +262,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
<WrappedRoute path='/settings/preferences' page={DefaultPage} component={Preferences} content={children} />
|
||||
<WrappedRoute path='/settings/profile' page={DefaultPage} component={EditProfile} content={children} />
|
||||
<WrappedRoute path='/settings/import' page={DefaultPage} component={ImportData} content={children} />
|
||||
<WrappedRoute path='/settings/aliases' page={DefaultPage} component={Aliases} content={children} />
|
||||
<WrappedRoute path='/backups' page={DefaultPage} component={Backups} content={children} />
|
||||
<WrappedRoute path='/soapbox/config' page={DefaultPage} component={SoapboxConfig} content={children} />
|
||||
|
||||
|
|
|
@ -249,3 +249,7 @@ export function UserIndex() {
|
|||
export function FederationRestrictions() {
|
||||
return import(/* webpackChunkName: "features/federation_restrictions" */'../../federation_restrictions');
|
||||
}
|
||||
|
||||
export function Aliases() {
|
||||
return import(/* webpackChunkName: "features/aliases" */'../../aliases');
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@
|
|||
"account.share": "Udostępnij profil @{name}",
|
||||
"account.show_reblogs": "Pokazuj podbicia od @{name}",
|
||||
"account.subscribe": "Subskrybuj wpisy @{name}",
|
||||
"account.unblock": "Odblokuj @{name}",
|
||||
"account.subscribed": "Subscribed",
|
||||
"account.unblock": "Zasubskrybowano",
|
||||
"account.unblock_domain": "Odblokuj domenę {domain}",
|
||||
"account.unendorse": "Przestań polecać",
|
||||
"account.unfollow": "Przestań śledzić",
|
||||
|
@ -50,8 +51,6 @@
|
|||
"account.unmute_notifications": "Cofnij wyciszenie powiadomień od @{name}",
|
||||
"account.unsubscribe": "Przestań subskrybować wpisy @{name}",
|
||||
"account_gallery.none": "Brak zawartości multimedialnej do wyświetlenia.",
|
||||
"auth.invalid_credentials": "Nieprawidłowa nazwa użytkownika lub hasło",
|
||||
"auth.logged_out": "Wylogowano.",
|
||||
"admin.awaiting_approval.approved_message": "Przyjęto {acct}!",
|
||||
"admin.awaiting_approval.empty_message": "Nikt nie oczekuje przyjęcia. Gdy zarejestruje się nowy użytkownik, możesz zatwierdzić go tutaj.",
|
||||
"admin.awaiting_approval.rejected_message": "Odrzucono {acct}!",
|
||||
|
@ -95,7 +94,7 @@
|
|||
"admin.users.actions.promote_to_admin": "Mianuj @{name} administratorem",
|
||||
"admin.users.actions.promote_to_admin_message": "Mianowano @{acct} administratorem",
|
||||
"admin.users.actions.promote_to_moderator": "Mianuj @{name} moderatorem",
|
||||
"admin.users.actions.promote_to_moderatorem_message": "Mianowano @{acct} moderatorem",
|
||||
"admin.users.actions.promote_to_moderator_message": "Mianowano @{acct} moderatorem",
|
||||
"admin.users.actions.unverify_user": "Cofnij weryfikację @{name}",
|
||||
"admin.users.actions.verify_user": "Weryfikuj @{name}",
|
||||
"admin.users.user_deactivated_message": "Zdezaktywowano @{acct}",
|
||||
|
@ -110,13 +109,14 @@
|
|||
"alert.unexpected.message": "Wystąpił nieoczekiwany błąd.",
|
||||
"alert.unexpected.return_home": "Wróć na stronę główną",
|
||||
"alert.unexpected.title": "O nie!",
|
||||
"audio.close": "Zamknij dźwięk",
|
||||
"audio.expand": "Rozwiń dźwięk",
|
||||
"audio.hide": "Ukryj dźwięk",
|
||||
"audio.mute": "Wycisz",
|
||||
"audio.pause": "Pauzuj",
|
||||
"audio.play": "Odtwórz",
|
||||
"audio.unmute": "Cofnij wyciszenie",
|
||||
"aliases.account.add": "Utwórz alias",
|
||||
"aliases.account_label": "Stare konto:",
|
||||
"aliases.aliases_list_delete": "Odłącz alias",
|
||||
"aliases.search": "Szukaj swojego starego konta",
|
||||
"aliases.success.add": "Pomyślnie utworzono alias konta",
|
||||
"aliases.success.remove": "Pomyślnie usunięto alias konta",
|
||||
"auth.invalid_credentials": "Nieprawidłowa nazwa użytkownika lub hasło",
|
||||
"auth.logged_out": "Wylogowano.",
|
||||
"backups.actions.create": "Utwórz kopię zapasową",
|
||||
"backups.empty_message": "Nie znaleziono kopii zapasaowych. {action}",
|
||||
"backups.empty_message.action": "Chcesz utworzyć?",
|
||||
|
@ -143,14 +143,20 @@
|
|||
"column.admin.moderation_log": "Dziennik moderacyjny",
|
||||
"column.admin.reports": "Zgłoszenia",
|
||||
"column.admin.reports.menu.moderation_log": "Dziennik moderacji",
|
||||
"column.aliases": "Aliasy kont",
|
||||
"column.aliases.create_error": "Błąd tworzenia aliasu",
|
||||
"column.aliases.delete": "Usuń",
|
||||
"column.aliases.delete_error": "Błąd usuwania aliasu",
|
||||
"column.aliases.subheading_add_new": "Dodaj nowy alias",
|
||||
"column.aliases.subheading_aliases": "Istniejące aliasy",
|
||||
"column.backups": "Kopie zapasowe",
|
||||
"column.blocks": "Zablokowani użytkownicy",
|
||||
"column.bookmarks": "Załadki",
|
||||
"column.chats": "Rozmowy",
|
||||
"column.community": "Lokalna oś czasu",
|
||||
"column.crypto_donate": "Przekaż kryptowalutę",
|
||||
"column.direct": "Wiadomości bezpośrednie",
|
||||
"column.domain_blocks": "Ukryte domeny",
|
||||
"column.crypto_donate": "Przekaż kryptowalutę",
|
||||
"column.edit_profile": "Edytuj profil",
|
||||
"column.federation_restrictions": "Ograniczenia federacji",
|
||||
"column.filters": "Wyciszone słowa",
|
||||
|
@ -195,6 +201,7 @@
|
|||
"column_header.hide_settings": "Ukryj ustawienia",
|
||||
"column_header.show_settings": "Pokaż ustawienia",
|
||||
"community.column_settings.media_only": "Tylko zawartość multimedialna",
|
||||
"compose.invalid_schedule": "Musisz zaplanować wpis przynajmniej 5 minut wcześniej.",
|
||||
"compose_form.direct_message_warning": "Ten wpis będzie widoczny tylko dla wszystkich wspomnianych użytkowników.",
|
||||
"compose_form.direct_message_warning_learn_more": "Dowiedz się więcej",
|
||||
"compose_form.hashtag_warning": "Ten wpis nie będzie widoczny pod podanymi hashtagami, ponieważ jest oznaczony jako niewidoczny. Tylko publiczne wpisy mogą zostać znalezione z użyciem hashtagów.",
|
||||
|
@ -250,10 +257,11 @@
|
|||
"confirmations.reply.message": "W ten sposób utracisz wpis który obecnie tworzysz. Czy na pewno chcesz to zrobić?",
|
||||
"confirmations.unfollow.confirm": "Przestań śledzić",
|
||||
"confirmations.unfollow.message": "Czy na pewno zamierzasz przestać śledzić {name}?",
|
||||
"crypto_donate_panel.actions.more": "Naciśnij, aby zobaczyć {count} more {count, plural, one {portfel} few {portfele} many {portfeli} other {portfeli}}",
|
||||
"crypto_donate.explanation_box.message": "{siteTitle} przyjmuje darowizny w kryptowalutach. Możesz wysłać darowiznę na jeden z poniższych adresów. Dziękujemy za Wasze wsparcie!",
|
||||
"crypto_donate_panel.intro.message": "{siteTitle} przyjmuje darowizny w kryptowalutach, aby utrzymać naszą usługę. Dziękujemy za Wasze wsparcie!",
|
||||
"crypto_donate.explanation_box.title": "Przeaż darowiznę w kryptowalutach",
|
||||
"crypto_donate_panel.actions.more": "Naciśnij, aby zobaczyć {count} more {count, plural, one {portfel} few {portfele} many {portfeli} other {portfeli}}",
|
||||
"crypto_donate_panel.heading": "Przekaż kryptowalutę",
|
||||
"crypto_donate_panel.intro.message": "{siteTitle} przyjmuje darowizny w kryptowalutach, aby utrzymać naszą usługę. Dziękujemy za Wasze wsparcie!",
|
||||
"datepicker.hint": "Zaplanowano publikację na…",
|
||||
"donate": "Przekaż darowiznę",
|
||||
"donate_crypto": "Przekaż kryptowalutę",
|
||||
|
@ -277,7 +285,7 @@
|
|||
"edit_profile.fields.meta_fields_label": "Metadane profilu",
|
||||
"edit_profile.fields.stranger_notifications_label": "Blokuj powiadomienia od nieznajomych",
|
||||
"edit_profile.fields.verified_display_name": "Zweryfikowani użytkownicy nie mogą zmieniać nazwy wyświetlanej",
|
||||
"edit_profile.hints.accepts_email_list_label": "Otrzymuj wiadomości i nowości marketingowe",
|
||||
"edit_profile.hints.accepts_email_list": "Otrzymuj wiadomości i nowości marketingowe.",
|
||||
"edit_profile.hints.avatar": "PNG, GIF lub JPG. Maksymalnie 2 MB. Zostanie zmniejszony do 400x400px",
|
||||
"edit_profile.hints.bot": "To konto podejmuje głównie zautomatyzowane działania i może nie być nadzorowane",
|
||||
"edit_profile.hints.header": "PNG, GIF lub JPG. Maksymalnie 2 MB. Zostanie zmniejszony do 1500x500px",
|
||||
|
@ -306,6 +314,8 @@
|
|||
"emoji_button.travel": "Podróże i miejsca",
|
||||
"empty_column.account_timeline": "Brak wpisów tutaj!",
|
||||
"empty_column.account_unavailable": "Profil niedostępny",
|
||||
"empty_column.aliases": "Nie utworzyłeś(-aś) jeszcze żadnego aliasu konta.",
|
||||
"empty_column.aliases.suggestions": "Brak propozycji kont dla podanej frazy.",
|
||||
"empty_column.blocks": "Nie zablokowałeś(-aś) jeszcze żadnego użytkownika.",
|
||||
"empty_column.bookmarks": "Nie masz jeszcze żadnej zakładki. Kiedy dodasz jakąś, pojawi się ona tutaj.",
|
||||
"empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby zagaić!",
|
||||
|
@ -334,11 +344,14 @@
|
|||
"federation_restriction.full_media_removal": "Pełne usunięcie mediów",
|
||||
"federation_restriction.media_nsfw": "Załączniki oznaczone jako NSFW",
|
||||
"federation_restriction.partial_media_removal": "Częściowe usunięcie mediów",
|
||||
"federation_restrictions.empty_message": "{siteTitle} nie nakłada restrykcji na żadne instancje.",
|
||||
"federation_restrictions.explanation_box.message": "Zwykle serwery w Fediwersum mogą swobodnie porozumiewać się. {siteTitle} nakłada pewne ograniczenia na następujące serwery.",
|
||||
"federation_restrictions.explanation_box.title": "Zasady dla poszczególnych instancji",
|
||||
"federation_restrictions.not_disclosed_message": "{siteTitle} nie udostępnia informacji o ograniczeniach federacji przez API.",
|
||||
"fediverse_tab.explanation_box.dismiss": "Nie pokazuj ponownie",
|
||||
"fediverse_tab.explanation_box.explanation": "{site_title} jest częścią Fediwersum, sieci społecznościowej na którą składają się tysiące niezależnie funkcjonujących stron (serwerów). Wpisy które tu widzisz pochodzą z serwerów podmiotów trzecich. Możesz do woli wchodzić z nimi w interakcje lub blokować serwery których nie lubisz. Zwracaj uwagę na pełną nazwę użytkownika po znaku @, aby wiedzieć z jakiego serwera pochodzi on. Aby widzieć tylko wpisy z {site_title}, odwiedź kartę {local}.",
|
||||
"fediverse_tab.explanation_box.title": "Czym jest Fediverse?",
|
||||
"filters.added": "Dodano filtr.",
|
||||
"filters.context_header": "Konteksty filtru",
|
||||
"filters.context_hint": "Jedno lub więcej miejsc, gdzie filtr powinien zostać zaaplikowany",
|
||||
"filters.filters_list_context_label": "Konteksty filtru:",
|
||||
|
@ -348,12 +361,12 @@
|
|||
"filters.filters_list_hide": "Ukrywaj",
|
||||
"filters.filters_list_phrase_label": "Słowo kluczowe lub fraza:",
|
||||
"filters.filters_list_whole-word": "Całe słowo",
|
||||
"filters.added": "Dodano filtr.",
|
||||
"filters.deleted": "Usunięto filtr.",
|
||||
"filters.removed": "Usunięto filtr.",
|
||||
"follow_request.authorize": "Autoryzuj",
|
||||
"follow_request.reject": "Odrzuć",
|
||||
"forms.copy": "Kopiuj",
|
||||
"getting_started.open_source_notice": "{code_name} jest oprogramowaniem o otwartym źródle. Możesz pomóc w rozwoju lub zgłaszać błędy na GitLabie tutaj: {code_link} (v{code_version}).",
|
||||
"group.detail.archived_group": "Zarchiwizowana grupa",
|
||||
"group.members.empty": "Ta grupa nie ma żadnych członków.",
|
||||
"group.removed_accounts.empty": "Ta grupa nie ma żadnych usuniętych kont.",
|
||||
"groups.card.join": "Dołącz",
|
||||
|
@ -362,13 +375,21 @@
|
|||
"groups.card.roles.member": "Jesteś członkiem",
|
||||
"groups.card.view": "Zobacz",
|
||||
"groups.create": "Utwórz grupę",
|
||||
"groups.detail.role_admin": "Jesteś administratorem",
|
||||
"groups.edit": "Edytuj",
|
||||
"groups.form.coverImage": "Wyślij obraz baneru (nieobowiązkowe)",
|
||||
"groups.form.coverImageChange": "Wybrano obraz baneru",
|
||||
"groups.form.create": "Utwórz grupę",
|
||||
"groups.form.description": "Opis",
|
||||
"groups.form.title": "Tytuł",
|
||||
"groups.form.update": "Aktualizuj grupę",
|
||||
"groups.join": "Dołącz do grupy",
|
||||
"groups.leave": "Opuść grupę",
|
||||
"groups.removed_accounts": "Usunięte konta",
|
||||
"groups.sidebar-panel.item.no_recent_activity": "Brak ostatniej aktywności",
|
||||
"groups.sidebar-panel.item.view": "nowe wpisy",
|
||||
"groups.sidebar-panel.show_all": "Pokaż wszystkie",
|
||||
"groups.sidebar-panel.title": "Grupy do których należysz",
|
||||
"groups.tab_admin": "Zarządzaj",
|
||||
"groups.tab_featured": "Wyróżnione",
|
||||
"groups.tab_member": "Członek",
|
||||
|
@ -407,9 +428,7 @@
|
|||
"keyboard_shortcuts.back": "aby cofnąć się",
|
||||
"keyboard_shortcuts.blocked": "aby przejść do listy zablokowanych użytkowników",
|
||||
"keyboard_shortcuts.boost": "aby podbić wpis",
|
||||
"keyboard_shortcuts.column": "aby przejść do wpisu z jednej z kolumn",
|
||||
"keyboard_shortcuts.compose": "aby przejść do pola tworzenia wpisu",
|
||||
"keyboard_shortcuts.direct": "aby otworzyć kolumnę wiadomości bezpośrednich",
|
||||
"keyboard_shortcuts.down": "aby przejść na dół listy",
|
||||
"keyboard_shortcuts.enter": "aby otworzyć wpis",
|
||||
"keyboard_shortcuts.favourite": "aby dodać do ulubionych",
|
||||
|
@ -428,7 +447,6 @@
|
|||
"keyboard_shortcuts.reply": "aby odpowiedzieć",
|
||||
"keyboard_shortcuts.requests": "aby przejść do listy próśb o możliwość śledzenia",
|
||||
"keyboard_shortcuts.search": "aby przejść do pola wyszukiwania",
|
||||
"keyboard_shortcuts.start": "aby otworzyć kolumnę „Rozpocznij”",
|
||||
"keyboard_shortcuts.toggle_hidden": "aby wyświetlić lub ukryć wpis spod CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "by pokazać/ukryć multimedia",
|
||||
"keyboard_shortcuts.toot": "aby utworzyć nowy wpis",
|
||||
|
@ -484,8 +502,10 @@
|
|||
"morefollows.followers_label": "…i {count} więcej {count, plural, one {obserwujący(-a)} few {obserwujących} many {obserwujących} other {obserwujących}} na zdalnych stronach.",
|
||||
"morefollows.following_label": "…i {count} więcej {count, plural, one {obserwowany(-a)} few {obserwowanych} many {obserwowanych} other {obserwowanych}} na zdalnych stronach.",
|
||||
"mute_modal.hide_notifications": "Chcesz ukryć powiadomienia od tego użytkownika?",
|
||||
"navigation_bar.account_aliases": "Aliasy kont",
|
||||
"navigation_bar.admin_settings": "Ustawienia administracyjne",
|
||||
"navigation_bar.blocks": "Zablokowani użytkownicy",
|
||||
"navigation_bar.bookmarks": "Zakładki",
|
||||
"navigation_bar.compose": "Utwórz nowy wpis",
|
||||
"navigation_bar.domain_blocks": "Ukryte domeny",
|
||||
"navigation_bar.favourites": "Ulubione",
|
||||
|
@ -494,7 +514,9 @@
|
|||
"navigation_bar.import_data": "Importuj dane",
|
||||
"navigation_bar.info": "Szczegółowe informacje",
|
||||
"navigation_bar.keyboard_shortcuts": "Skróty klawiszowe",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.logout": "Wyloguj",
|
||||
"navigation_bar.messages": "Messages",
|
||||
"navigation_bar.mutes": "Wyciszeni użytkownicy",
|
||||
"navigation_bar.pins": "Przypięte wpisy",
|
||||
"navigation_bar.preferences": "Preferencje",
|
||||
|
@ -613,6 +635,7 @@
|
|||
"relative_time.minutes": "{number} min.",
|
||||
"relative_time.seconds": "{number} s.",
|
||||
"remote_instance.edit_federation": "Edytuj federację",
|
||||
"remote_instance.federation_panel.heading": "Federation Restrictions",
|
||||
"remote_instance.federation_panel.no_restrictions_message": "{siteTitle} nie nakłada ograniczeń na {host}.",
|
||||
"remote_instance.federation_panel.restricted_message": "{siteTitle} blokuje wszystkie aktywności z {host}.",
|
||||
"remote_instance.federation_panel.some_restrictions_message": "{siteTitle} nakłada pewne ograniczenia na {host}.",
|
||||
|
@ -641,8 +664,6 @@
|
|||
"search_results.hashtags": "Hashtagi",
|
||||
"search_results.statuses": "Wpisy",
|
||||
"search_results.top": "Góra",
|
||||
"search_results.total": "{count, number} {count, plural, one {wynik} few {wyniki} many {wyników} more {wyników}}",
|
||||
"search_results.total.has_more": "{count, number} Ponad {count, plural, one {wynik} few {wyniki} many {wyników} more {wyników}}",
|
||||
"security.codes.fail": "Nie udało się uzyskać zapasowych kodów",
|
||||
"security.confirm.fail": "Nieprawidłowy kod lub hasło. Spróbuj ponownie.",
|
||||
"security.delete_account.fail": "Nie udało się usunąć konta.",
|
||||
|
@ -788,7 +809,6 @@
|
|||
"upload_error.limit": "Przekroczono limit plików do wysłania.",
|
||||
"upload_error.poll": "Dołączanie plików nie dozwolone z głosowaniami.",
|
||||
"upload_form.description": "Wprowadź opis dla niewidomych i niedowidzących",
|
||||
"upload_form.focus": "Zmień podgląd",
|
||||
"upload_form.preview": "Podgląd",
|
||||
"upload_form.undo": "Usuń",
|
||||
"upload_progress.label": "Wysyłanie…",
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
import {
|
||||
ALIASES_SUGGESTIONS_READY,
|
||||
ALIASES_SUGGESTIONS_CLEAR,
|
||||
ALIASES_SUGGESTIONS_CHANGE,
|
||||
} from '../actions/aliases';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
suggestions: ImmutableMap({
|
||||
value: '',
|
||||
loaded: false,
|
||||
items: ImmutableList(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default function aliasesReducer(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case ALIASES_SUGGESTIONS_CHANGE:
|
||||
return state
|
||||
.setIn(['suggestions', 'value'], action.value)
|
||||
.setIn(['suggestions', 'loaded'], false);
|
||||
case ALIASES_SUGGESTIONS_READY:
|
||||
return state
|
||||
.setIn(['suggestions', 'items'], ImmutableList(action.accounts.map(item => item.id)))
|
||||
.setIn(['suggestions', 'loaded'], true);
|
||||
case ALIASES_SUGGESTIONS_CLEAR:
|
||||
return state.update('suggestions', suggestions => suggestions.withMutations(map => {
|
||||
map.set('items', ImmutableList());
|
||||
map.set('value', '');
|
||||
map.set('loaded', false);
|
||||
}));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
|
@ -53,6 +53,7 @@ import backups from './backups';
|
|||
import admin_log from './admin_log';
|
||||
import security from './security';
|
||||
import scheduled_statuses from './scheduled_statuses';
|
||||
import aliases from './aliases';
|
||||
|
||||
const appReducer = combineReducers({
|
||||
dropdown_menu,
|
||||
|
@ -107,6 +108,7 @@ const appReducer = combineReducers({
|
|||
admin_log,
|
||||
security,
|
||||
scheduled_statuses,
|
||||
aliases,
|
||||
});
|
||||
|
||||
// Clear the state (mostly) when the user logs out
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
@import 'components/datepicker';
|
||||
@import 'components/remote-timeline';
|
||||
@import 'components/federation-restrictions';
|
||||
@import 'components/aliases';
|
||||
|
||||
// Holiday
|
||||
@import 'holiday/halloween';
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
.aliases {
|
||||
&__accounts {
|
||||
overflow-y: auto;
|
||||
|
||||
.account__display-name {
|
||||
&:hover strong {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.account__avatar {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&.empty-column-indicator {
|
||||
min-height: unset;
|
||||
overflow-y: unset;
|
||||
}
|
||||
}
|
||||
|
||||
&_search {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 10px;
|
||||
|
||||
.search__input {
|
||||
padding: 7px 30px 6px 10px;
|
||||
}
|
||||
|
||||
> label {
|
||||
flex: 1 1;
|
||||
}
|
||||
|
||||
> .search__icon .fa {
|
||||
top: 8px;
|
||||
right: 102px !important;
|
||||
}
|
||||
|
||||
> .button {
|
||||
width: 80px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.aliases-settings-panel {
|
||||
flex: 1;
|
||||
|
||||
.item-list article {
|
||||
border-bottom: 1px solid var(--primary-text-color--faint);
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.alias__container {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
|
||||
span.alias__list-label {
|
||||
padding-right: 5px;
|
||||
color: var(--primary-text-color--faint);
|
||||
}
|
||||
|
||||
span.alias__list-value span {
|
||||
padding-right: 5px;
|
||||
text-transform: capitalize;
|
||||
|
||||
&::after {
|
||||
content: ',';
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
&::after {
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alias__delete {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
cursor: pointer;
|
||||
|
||||
span.alias__delete-label {
|
||||
color: var(--primary-text-color--faint);
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.alias__delete-icon {
|
||||
background: none;
|
||||
color: var(--primary-text-color--faint);
|
||||
padding: 0 5px;
|
||||
margin: 0 auto;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slist--flex {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue