Merge branch 'master' into glitch-soc/merge-upstream
Manually-resolved conflicts: .circleci/config.yml app/controllers/accounts_controller.rb app/controllers/auth/passwords_controller.rb app/controllers/statuses_controller.rb app/javascript/packs/public.js app/models/media_attachment.rb app/views/stream_entries/_content_spoiler.html.haml app/views/stream_entries/_media.html.haml config/locales/en.yml config/locales/ja.yml config/locales/pl.yml lib/mastodon/version.rb Some content from app/javascript/packs/public.js has been split to app/javascript/core/settings.js. Translation strings for glitch-soc's keyword mutes were dropped. Everything else was mostly “take both”.
This commit is contained in:
commit
c1c514ca70
187 changed files with 3356 additions and 2009 deletions
|
@ -31,7 +31,7 @@ class AboutController < ApplicationController
|
|||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'about-body'
|
||||
@body_classes = 'with-modals'
|
||||
end
|
||||
|
||||
def initial_state_params
|
||||
|
|
|
@ -11,6 +11,7 @@ class AccountsController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html do
|
||||
use_pack 'public'
|
||||
@body_classes = 'with-modals'
|
||||
@pinned_statuses = []
|
||||
|
||||
if current_account && @account.blocking?(current_account)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
||||
layout 'auth'
|
||||
|
||||
before_action :set_body_classes
|
||||
before_action :set_user, only: [:finish_signup]
|
||||
before_action :set_pack
|
||||
|
||||
|
@ -28,6 +29,10 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
|
|||
@user = current_user
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'lighter'
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:email)
|
||||
end
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
class Auth::PasswordsController < Devise::PasswordsController
|
||||
before_action :check_validity_of_reset_password_token, only: :edit
|
||||
before_action :set_pack
|
||||
before_action :set_body_classes
|
||||
|
||||
layout 'auth'
|
||||
|
||||
|
@ -15,6 +16,10 @@ class Auth::PasswordsController < Devise::PasswordsController
|
|||
end
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'lighter'
|
||||
end
|
||||
|
||||
def reset_password_token_is_valid?
|
||||
resource_class.with_reset_password_token(params[:reset_password_token]).present?
|
||||
end
|
||||
|
|
|
@ -9,6 +9,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||
before_action :set_pack
|
||||
before_action :set_sessions, only: [:edit, :update]
|
||||
before_action :set_instance_presenter, only: [:new, :create, :update]
|
||||
before_action :set_body_classes, only: [:new, :create]
|
||||
|
||||
def destroy
|
||||
not_found
|
||||
|
@ -84,6 +85,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||
@instance_presenter = InstancePresenter.new
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'lighter'
|
||||
end
|
||||
|
||||
def set_invite
|
||||
@invite = invite_code.present? ? Invite.find_by(code: invite_code) : nil
|
||||
end
|
||||
|
|
|
@ -10,6 +10,7 @@ class Auth::SessionsController < Devise::SessionsController
|
|||
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
|
||||
prepend_before_action :set_pack
|
||||
before_action :set_instance_presenter, only: [:new]
|
||||
before_action :set_body_classes
|
||||
|
||||
def new
|
||||
Devise.omniauth_configs.each do |provider, config|
|
||||
|
@ -114,6 +115,10 @@ class Auth::SessionsController < Devise::SessionsController
|
|||
@instance_presenter = InstancePresenter.new
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'lighter'
|
||||
end
|
||||
|
||||
def home_paths(resource)
|
||||
paths = [about_path]
|
||||
if single_user_mode? && resource.is_a?(User)
|
||||
|
|
|
@ -8,6 +8,7 @@ module AccountControllerConcern
|
|||
included do
|
||||
layout 'public'
|
||||
before_action :set_account
|
||||
before_action :set_instance_presenter
|
||||
before_action :set_link_headers
|
||||
before_action :check_account_suspension
|
||||
end
|
||||
|
@ -18,6 +19,10 @@ module AccountControllerConcern
|
|||
@account = Account.find_local!(params[:account_username])
|
||||
end
|
||||
|
||||
def set_instance_presenter
|
||||
@instance_presenter = InstancePresenter.new
|
||||
end
|
||||
|
||||
def set_link_headers
|
||||
response.headers['Link'] = LinkHeader.new(
|
||||
[
|
||||
|
|
|
@ -43,7 +43,7 @@ class InvitesController < ApplicationController
|
|||
end
|
||||
|
||||
def invites
|
||||
Invite.where(user: current_user)
|
||||
Invite.where(user: current_user).order(id: :desc)
|
||||
end
|
||||
|
||||
def resource_params
|
||||
|
|
|
@ -12,6 +12,7 @@ class StatusesController < ApplicationController
|
|||
|
||||
before_action :set_account
|
||||
before_action :set_status
|
||||
before_action :set_instance_presenter
|
||||
before_action :set_link_headers
|
||||
before_action :check_account_suspension
|
||||
before_action :redirect_to_original, only: [:show]
|
||||
|
@ -22,6 +23,8 @@ class StatusesController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html do
|
||||
use_pack 'public'
|
||||
@body_classes = 'with-modals'
|
||||
|
||||
set_ancestors
|
||||
set_descendants
|
||||
|
||||
|
@ -150,6 +153,10 @@ class StatusesController < ApplicationController
|
|||
raise ActiveRecord::RecordNotFound
|
||||
end
|
||||
|
||||
def set_instance_presenter
|
||||
@instance_presenter = InstancePresenter.new
|
||||
end
|
||||
|
||||
def check_account_suspension
|
||||
gone if @account.suspended?
|
||||
end
|
||||
|
|
|
@ -38,7 +38,7 @@ class TagsController < ApplicationController
|
|||
private
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'tag-body'
|
||||
@body_classes = 'with-modals'
|
||||
end
|
||||
|
||||
def set_instance_presenter
|
||||
|
|
|
@ -12,6 +12,52 @@ module StreamEntriesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def account_action_button(account)
|
||||
if user_signed_in?
|
||||
if account.id == current_user.account_id
|
||||
link_to settings_profile_url, class: 'button logo-button' do
|
||||
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('settings.edit_profile')])
|
||||
end
|
||||
elsif current_account.following?(account) || current_account.requested?(account)
|
||||
link_to account_unfollow_path(account), class: 'button logo-button', data: { method: :post } do
|
||||
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.unfollow')])
|
||||
end
|
||||
else
|
||||
link_to account_follow_path(account), class: 'button logo-button', data: { method: :post } do
|
||||
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')])
|
||||
end
|
||||
end
|
||||
else
|
||||
link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do
|
||||
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def account_badge(account)
|
||||
if account.bot?
|
||||
content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
|
||||
elsif Setting.show_staff_badge && account.user_staff?
|
||||
content_tag(:div, class: 'roles') do
|
||||
if account.user_admin?
|
||||
content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin')
|
||||
elsif account.user_moderator?
|
||||
content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_more(url)
|
||||
link_to t('statuses.show_more'), url, class: 'load-more load-gap'
|
||||
end
|
||||
|
||||
def nothing_here(extra_classes = '')
|
||||
content_tag(:div, class: "nothing-here #{extra_classes}") do
|
||||
t('accounts.nothing_here')
|
||||
end
|
||||
end
|
||||
|
||||
def account_description(account)
|
||||
prepend_str = [
|
||||
[
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// This file will be loaded on public pages, regardless of theme.
|
||||
|
||||
const { delegate } = require('rails-ujs');
|
||||
const { length } = require('stringz');
|
||||
|
||||
delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
|
||||
if (button !== 0) {
|
||||
|
|
|
@ -3,24 +3,29 @@
|
|||
const { length } = require('stringz');
|
||||
const { delegate } = require('rails-ujs');
|
||||
|
||||
delegate(document, '.account_display_name', 'input', ({ target }) => {
|
||||
delegate(document, '#account_display_name', 'input', ({ target }) => {
|
||||
const nameCounter = document.querySelector('.name-counter');
|
||||
const name = document.querySelector('.card .display-name strong');
|
||||
|
||||
if (nameCounter) {
|
||||
nameCounter.textContent = 30 - length(target.value);
|
||||
}
|
||||
|
||||
if (name) {
|
||||
name.innerHTML = emojify(target.value);
|
||||
}
|
||||
});
|
||||
|
||||
delegate(document, '.account_note', 'input', ({ target }) => {
|
||||
delegate(document, '#account_note', 'input', ({ target }) => {
|
||||
const noteCounter = document.querySelector('.note-counter');
|
||||
|
||||
if (noteCounter) {
|
||||
noteCounter.textContent = 500 - length(target.value);
|
||||
noteCounter.textContent = 160 - length(target.value);
|
||||
}
|
||||
});
|
||||
|
||||
delegate(document, '#account_avatar', 'change', ({ target }) => {
|
||||
const avatar = document.querySelector('.card.compact .avatar img');
|
||||
const avatar = document.querySelector('.card .avatar img');
|
||||
const [file] = target.files || [];
|
||||
const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
|
||||
|
||||
|
@ -28,9 +33,19 @@ delegate(document, '#account_avatar', 'change', ({ target }) => {
|
|||
});
|
||||
|
||||
delegate(document, '#account_header', 'change', ({ target }) => {
|
||||
const header = document.querySelector('.card.compact');
|
||||
const header = document.querySelector('.card .card__img img');
|
||||
const [file] = target.files || [];
|
||||
const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
|
||||
|
||||
header.style.backgroundImage = `url(${url})`;
|
||||
header.src = url;
|
||||
});
|
||||
|
||||
delegate(document, '#account_locked', 'change', ({ target }) => {
|
||||
const lock = document.querySelector('.card .display-name i');
|
||||
|
||||
if (target.checked) {
|
||||
lock.style.display = 'inline';
|
||||
} else {
|
||||
lock.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
|
|
@ -60,6 +60,32 @@ const getUnitDelay = units => {
|
|||
}
|
||||
};
|
||||
|
||||
export const timeAgoString = (intl, date, now, year) => {
|
||||
const delta = now - date.getTime();
|
||||
|
||||
let relativeTime;
|
||||
|
||||
if (delta < 10 * SECOND) {
|
||||
relativeTime = intl.formatMessage(messages.just_now);
|
||||
} else if (delta < 7 * DAY) {
|
||||
if (delta < MINUTE) {
|
||||
relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) });
|
||||
} else if (delta < HOUR) {
|
||||
relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) });
|
||||
} else if (delta < DAY) {
|
||||
relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) });
|
||||
} else {
|
||||
relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) });
|
||||
}
|
||||
} else if (date.getFullYear() === year) {
|
||||
relativeTime = intl.formatDate(date, shortDateFormatOptions);
|
||||
} else {
|
||||
relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' });
|
||||
}
|
||||
|
||||
return relativeTime;
|
||||
};
|
||||
|
||||
@injectIntl
|
||||
export default class RelativeTimestamp extends React.Component {
|
||||
|
||||
|
@ -122,27 +148,7 @@ export default class RelativeTimestamp extends React.Component {
|
|||
const { timestamp, intl, year } = this.props;
|
||||
|
||||
const date = new Date(timestamp);
|
||||
const delta = this.state.now - date.getTime();
|
||||
|
||||
let relativeTime;
|
||||
|
||||
if (delta < 10 * SECOND) {
|
||||
relativeTime = intl.formatMessage(messages.just_now);
|
||||
} else if (delta < 7 * DAY) {
|
||||
if (delta < MINUTE) {
|
||||
relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) });
|
||||
} else if (delta < HOUR) {
|
||||
relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) });
|
||||
} else if (delta < DAY) {
|
||||
relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) });
|
||||
} else {
|
||||
relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) });
|
||||
}
|
||||
} else if (date.getFullYear() === year) {
|
||||
relativeTime = intl.formatDate(date, shortDateFormatOptions);
|
||||
} else {
|
||||
relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' });
|
||||
}
|
||||
const relativeTime = timeAgoString(intl, date, this.state.now, year);
|
||||
|
||||
return (
|
||||
<time dateTime={timestamp} title={intl.formatDate(date, dateFormatOptions)}>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { debounce } from 'lodash';
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import StatusContainer from '../containers/status_container';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import LoadGap from './load_gap';
|
||||
import ScrollableList from './scrollable_list';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
export default class StatusList extends ImmutablePureComponent {
|
||||
|
||||
|
@ -71,7 +71,7 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { statusIds, featuredStatusIds, onLoadMore, timelineId, ...other } = this.props;
|
||||
const { statusIds, featuredStatusIds, shouldUpdateScroll, onLoadMore, timelineId, ...other } = this.props;
|
||||
const { isLoading, isPartial } = other;
|
||||
|
||||
if (isPartial) {
|
||||
|
@ -122,7 +122,7 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<ScrollableList {...other} onLoadMore={onLoadMore && this.handleLoadOlder} ref={this.setRef}>
|
||||
<ScrollableList {...other} onLoadMore={onLoadMore && this.handleLoadOlder} shouldUpdateScroll={shouldUpdateScroll} ref={this.setRef}>
|
||||
{scrollableContent}
|
||||
</ScrollableList>
|
||||
);
|
||||
|
|
|
@ -29,19 +29,19 @@ export default class MediaContainer extends PureComponent {
|
|||
};
|
||||
|
||||
handleOpenMedia = (media, index) => {
|
||||
document.body.classList.add('media-standalone__body');
|
||||
document.body.classList.add('with-modals--active');
|
||||
this.setState({ media, index });
|
||||
}
|
||||
|
||||
handleOpenVideo = (video, time) => {
|
||||
const media = ImmutableList([video]);
|
||||
|
||||
document.body.classList.add('media-standalone__body');
|
||||
document.body.classList.add('with-modals--active');
|
||||
this.setState({ media, time });
|
||||
}
|
||||
|
||||
handleCloseMedia = () => {
|
||||
document.body.classList.remove('media-standalone__body');
|
||||
document.body.classList.remove('with-modals--active');
|
||||
this.setState({ media: null, index: null, time: null });
|
||||
}
|
||||
|
||||
|
|
|
@ -142,17 +142,17 @@ export default class ActionBar extends React.PureComponent {
|
|||
<div className='account__action-bar'>
|
||||
<div className='account__action-bar-links'>
|
||||
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}`}>
|
||||
<span><FormattedMessage id='account.posts' defaultMessage='Toots' /></span>
|
||||
<FormattedMessage id='account.posts' defaultMessage='Toots' />
|
||||
<strong>{shortNumberFormat(account.get('statuses_count'))}</strong>
|
||||
</Link>
|
||||
|
||||
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`}>
|
||||
<span><FormattedMessage id='account.follows' defaultMessage='Follows' /></span>
|
||||
<FormattedMessage id='account.follows' defaultMessage='Follows' />
|
||||
<strong>{shortNumberFormat(account.get('following_count'))}</strong>
|
||||
</Link>
|
||||
|
||||
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`}>
|
||||
<span><FormattedMessage id='account.followers' defaultMessage='Followers' /></span>
|
||||
<FormattedMessage id='account.followers' defaultMessage='Followers' />
|
||||
<strong>{shortNumberFormat(account.get('followers_count'))}</strong>
|
||||
</Link>
|
||||
</div>
|
||||
|
|
|
@ -23,6 +23,7 @@ const mapStateToProps = (state, props) => ({
|
|||
class LoadMoreMedia extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
maxId: PropTypes.string,
|
||||
onLoadMore: PropTypes.func.isRequired,
|
||||
};
|
||||
|
@ -90,7 +91,7 @@ export default class AccountGallery extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { medias, isLoading, hasMore } = this.props;
|
||||
const { medias, shouldUpdateScroll, isLoading, hasMore } = this.props;
|
||||
|
||||
let loadOlder = null;
|
||||
|
||||
|
@ -110,7 +111,7 @@ export default class AccountGallery extends ImmutablePureComponent {
|
|||
<Column>
|
||||
<ColumnBackButton />
|
||||
|
||||
<ScrollContainer scrollKey='account_gallery'>
|
||||
<ScrollContainer scrollKey='account_gallery' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className='scrollable' onScroll={this.handleScroll}>
|
||||
<HeaderContainer accountId={this.props.params.accountId} />
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ export default class AccountTimeline extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
statusIds: ImmutablePropTypes.list,
|
||||
featuredStatusIds: ImmutablePropTypes.list,
|
||||
isLoading: PropTypes.bool,
|
||||
|
@ -61,7 +62,7 @@ export default class AccountTimeline extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { statusIds, featuredStatusIds, isLoading, hasMore } = this.props;
|
||||
const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore } = this.props;
|
||||
|
||||
if (!statusIds && isLoading) {
|
||||
return (
|
||||
|
@ -83,6 +84,7 @@ export default class AccountTimeline extends ImmutablePureComponent {
|
|||
isLoading={isLoading}
|
||||
hasMore={hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import LoadingIndicator from '../../components/loading_indicator';
|
||||
|
@ -8,8 +10,6 @@ import Column from '../ui/components/column';
|
|||
import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||
import AccountContainer from '../../containers/account_container';
|
||||
import { fetchBlocks, expandBlocks } from '../../actions/blocks';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.blocks', defaultMessage: 'Blocked users' },
|
||||
|
@ -26,6 +26,7 @@ export default class Blocks extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
@ -43,7 +44,7 @@ export default class Blocks extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { intl, accountIds } = this.props;
|
||||
const { intl, accountIds, shouldUpdateScroll } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
|
@ -56,7 +57,7 @@ export default class Blocks extends ImmutablePureComponent {
|
|||
return (
|
||||
<Column icon='ban' heading={intl.formatMessage(messages.heading)}>
|
||||
<ColumnBackButtonSlim />
|
||||
<ScrollContainer scrollKey='blocks'>
|
||||
<ScrollContainer scrollKey='blocks' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className='scrollable' onScroll={this.handleScroll}>
|
||||
{accountIds.map(id =>
|
||||
<AccountContainer key={id} id={id} />
|
||||
|
|
|
@ -39,6 +39,7 @@ export default class CommunityTimeline extends React.PureComponent {
|
|||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
columnId: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hasUnread: PropTypes.bool,
|
||||
|
@ -100,7 +101,7 @@ export default class CommunityTimeline extends React.PureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { intl, hasUnread, columnId, multiColumn, onlyMedia } = this.props;
|
||||
const { intl, shouldUpdateScroll, hasUnread, columnId, multiColumn, onlyMedia } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
||||
return (
|
||||
|
@ -124,6 +125,7 @@ export default class CommunityTimeline extends React.PureComponent {
|
|||
timelineId={`community${onlyMedia ? ':media' : ''}`}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -23,6 +23,7 @@ export default class DirectTimeline extends React.PureComponent {
|
|||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
columnId: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hasUnread: PropTypes.bool,
|
||||
|
@ -71,7 +72,7 @@ export default class DirectTimeline extends React.PureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { intl, hasUnread, columnId, multiColumn } = this.props;
|
||||
const { intl, shouldUpdateScroll, hasUnread, columnId, multiColumn } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
||||
return (
|
||||
|
@ -93,6 +94,7 @@ export default class DirectTimeline extends React.PureComponent {
|
|||
timelineId='direct'
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='empty_column.direct' defaultMessage="You don't have any direct messages yet. When you send or receive one, it will show up here." />}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { debounce } from 'lodash';
|
||||
import LoadingIndicator from '../../components/loading_indicator';
|
||||
import Column from '../ui/components/column';
|
||||
import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||
import DomainContainer from '../../containers/domain_container';
|
||||
import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_blocks';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { debounce } from 'lodash';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -28,6 +28,7 @@ export default class Blocks extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
domains: ImmutablePropTypes.orderedSet,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
@ -41,7 +42,7 @@ export default class Blocks extends ImmutablePureComponent {
|
|||
}, 300, { leading: true });
|
||||
|
||||
render () {
|
||||
const { intl, domains } = this.props;
|
||||
const { intl, domains, shouldUpdateScroll } = this.props;
|
||||
|
||||
if (!domains) {
|
||||
return (
|
||||
|
@ -54,7 +55,7 @@ export default class Blocks extends ImmutablePureComponent {
|
|||
return (
|
||||
<Column icon='minus-circle' heading={intl.formatMessage(messages.heading)}>
|
||||
<ColumnBackButtonSlim />
|
||||
<ScrollableList scrollKey='domain_blocks' onLoadMore={this.handleLoadMore}>
|
||||
<ScrollableList scrollKey='domain_blocks' onLoadMore={this.handleLoadMore} shouldUpdateScroll={shouldUpdateScroll}>
|
||||
{domains.map(domain =>
|
||||
<DomainContainer key={domain} domain={domain} />
|
||||
)}
|
||||
|
|
|
@ -27,6 +27,7 @@ export default class Favourites extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
statusIds: ImmutablePropTypes.list.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
columnId: PropTypes.string,
|
||||
|
@ -67,7 +68,7 @@ export default class Favourites extends ImmutablePureComponent {
|
|||
}, 300, { leading: true })
|
||||
|
||||
render () {
|
||||
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
|
||||
const { intl, shouldUpdateScroll, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
||||
return (
|
||||
|
@ -90,6 +91,7 @@ export default class Favourites extends ImmutablePureComponent {
|
|||
hasMore={hasMore}
|
||||
isLoading={isLoading}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import LoadingIndicator from '../../components/loading_indicator';
|
||||
|
@ -8,7 +9,6 @@ import { ScrollContainer } from 'react-router-scroll-4';
|
|||
import AccountContainer from '../../containers/account_container';
|
||||
import Column from '../ui/components/column';
|
||||
import ColumnBackButton from '../../components/column_back_button';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId]),
|
||||
|
@ -20,6 +20,7 @@ export default class Favourites extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
};
|
||||
|
||||
|
@ -34,7 +35,7 @@ export default class Favourites extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { accountIds } = this.props;
|
||||
const { shouldUpdateScroll, accountIds } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
|
@ -48,7 +49,7 @@ export default class Favourites extends ImmutablePureComponent {
|
|||
<Column>
|
||||
<ColumnBackButton />
|
||||
|
||||
<ScrollContainer scrollKey='favourites'>
|
||||
<ScrollContainer scrollKey='favourites' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className='scrollable'>
|
||||
{accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import LoadingIndicator from '../../components/loading_indicator';
|
||||
|
@ -8,8 +10,6 @@ import Column from '../ui/components/column';
|
|||
import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||
import AccountAuthorizeContainer from './containers/account_authorize_container';
|
||||
import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.follow_requests', defaultMessage: 'Follow requests' },
|
||||
|
@ -26,6 +26,7 @@ export default class FollowRequests extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
@ -43,7 +44,7 @@ export default class FollowRequests extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { intl, accountIds } = this.props;
|
||||
const { intl, shouldUpdateScroll, accountIds } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
|
@ -57,7 +58,7 @@ export default class FollowRequests extends ImmutablePureComponent {
|
|||
<Column icon='users' heading={intl.formatMessage(messages.heading)}>
|
||||
<ColumnBackButtonSlim />
|
||||
|
||||
<ScrollContainer scrollKey='follow_requests'>
|
||||
<ScrollContainer scrollKey='follow_requests' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className='scrollable' onScroll={this.handleScroll}>
|
||||
{accountIds.map(id =>
|
||||
<AccountAuthorizeContainer key={id} id={id} />
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import LoadingIndicator from '../../components/loading_indicator';
|
||||
|
@ -14,7 +15,6 @@ import Column from '../ui/components/column';
|
|||
import HeaderContainer from '../account_timeline/containers/header_container';
|
||||
import LoadMore from '../../components/load_more';
|
||||
import ColumnBackButton from '../../components/column_back_button';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
accountIds: state.getIn(['user_lists', 'followers', props.params.accountId, 'items']),
|
||||
|
@ -27,6 +27,7 @@ export default class Followers extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
hasMore: PropTypes.bool,
|
||||
};
|
||||
|
@ -57,7 +58,7 @@ export default class Followers extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { accountIds, hasMore } = this.props;
|
||||
const { shouldUpdateScroll, accountIds, hasMore } = this.props;
|
||||
|
||||
let loadMore = null;
|
||||
|
||||
|
@ -77,7 +78,7 @@ export default class Followers extends ImmutablePureComponent {
|
|||
<Column>
|
||||
<ColumnBackButton />
|
||||
|
||||
<ScrollContainer scrollKey='followers'>
|
||||
<ScrollContainer scrollKey='followers' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className='scrollable' onScroll={this.handleScroll}>
|
||||
<div className='followers'>
|
||||
<HeaderContainer accountId={this.props.params.accountId} hideTabs />
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import LoadingIndicator from '../../components/loading_indicator';
|
||||
|
@ -14,7 +15,6 @@ import Column from '../ui/components/column';
|
|||
import HeaderContainer from '../account_timeline/containers/header_container';
|
||||
import LoadMore from '../../components/load_more';
|
||||
import ColumnBackButton from '../../components/column_back_button';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
accountIds: state.getIn(['user_lists', 'following', props.params.accountId, 'items']),
|
||||
|
@ -27,6 +27,7 @@ export default class Following extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
hasMore: PropTypes.bool,
|
||||
};
|
||||
|
@ -57,7 +58,7 @@ export default class Following extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { accountIds, hasMore } = this.props;
|
||||
const { shouldUpdateScroll, accountIds, hasMore } = this.props;
|
||||
|
||||
let loadMore = null;
|
||||
|
||||
|
@ -77,7 +78,7 @@ export default class Following extends ImmutablePureComponent {
|
|||
<Column>
|
||||
<ColumnBackButton />
|
||||
|
||||
<ScrollContainer scrollKey='following'>
|
||||
<ScrollContainer scrollKey='following' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className='scrollable' onScroll={this.handleScroll}>
|
||||
<div className='following'>
|
||||
<HeaderContainer accountId={this.props.params.accountId} hideTabs />
|
||||
|
|
|
@ -20,6 +20,7 @@ export default class HashtagTimeline extends React.PureComponent {
|
|||
params: PropTypes.object.isRequired,
|
||||
columnId: PropTypes.string,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
hasUnread: PropTypes.bool,
|
||||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
@ -83,7 +84,7 @@ export default class HashtagTimeline extends React.PureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { hasUnread, columnId, multiColumn } = this.props;
|
||||
const { shouldUpdateScroll, hasUnread, columnId, multiColumn } = this.props;
|
||||
const { id } = this.props.params;
|
||||
const pinned = !!columnId;
|
||||
|
||||
|
@ -107,6 +108,7 @@ export default class HashtagTimeline extends React.PureComponent {
|
|||
timelineId={`hashtag:${id}`}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -25,6 +25,7 @@ export default class HomeTimeline extends React.PureComponent {
|
|||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hasUnread: PropTypes.bool,
|
||||
isPartial: PropTypes.bool,
|
||||
|
@ -93,7 +94,7 @@ export default class HomeTimeline extends React.PureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { intl, hasUnread, columnId, multiColumn } = this.props;
|
||||
const { intl, shouldUpdateScroll, hasUnread, columnId, multiColumn } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
||||
return (
|
||||
|
@ -117,6 +118,7 @@ export default class HomeTimeline extends React.PureComponent {
|
|||
onLoadMore={this.handleLoadMore}
|
||||
timelineId='home'
|
||||
emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage='Your home timeline is empty! Visit {public} or use search to get started and meet other users.' values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -35,6 +35,7 @@ export default class ListTimeline extends React.PureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
columnId: PropTypes.string,
|
||||
hasUnread: PropTypes.bool,
|
||||
multiColumn: PropTypes.bool,
|
||||
|
@ -112,7 +113,7 @@ export default class ListTimeline extends React.PureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { hasUnread, columnId, multiColumn, list } = this.props;
|
||||
const { shouldUpdateScroll, hasUnread, columnId, multiColumn, list } = this.props;
|
||||
const { id } = this.props.params;
|
||||
const pinned = !!columnId;
|
||||
const title = list ? list.get('title') : id;
|
||||
|
@ -166,6 +167,7 @@ export default class ListTimeline extends React.PureComponent {
|
|||
timelineId={`list:${id}`}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' />}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import LoadingIndicator from '../../components/loading_indicator';
|
||||
|
@ -8,8 +10,6 @@ import Column from '../ui/components/column';
|
|||
import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||
import AccountContainer from '../../containers/account_container';
|
||||
import { fetchMutes, expandMutes } from '../../actions/mutes';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.mutes', defaultMessage: 'Muted users' },
|
||||
|
@ -26,6 +26,7 @@ export default class Mutes extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
@ -43,7 +44,7 @@ export default class Mutes extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { intl, accountIds } = this.props;
|
||||
const { intl, shouldUpdateScroll, accountIds } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
|
@ -56,7 +57,7 @@ export default class Mutes extends ImmutablePureComponent {
|
|||
return (
|
||||
<Column icon='volume-off' heading={intl.formatMessage(messages.heading)}>
|
||||
<ColumnBackButtonSlim />
|
||||
<ScrollContainer scrollKey='mutes'>
|
||||
<ScrollContainer scrollKey='mutes' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className='scrollable mutes' onScroll={this.handleScroll}>
|
||||
{accountIds.map(id =>
|
||||
<AccountContainer key={id} id={id} />
|
||||
|
|
|
@ -24,6 +24,7 @@ export default class PinnedStatuses extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
statusIds: ImmutablePropTypes.list.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hasMore: PropTypes.bool.isRequired,
|
||||
|
@ -42,7 +43,7 @@ export default class PinnedStatuses extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { intl, statusIds, hasMore } = this.props;
|
||||
const { intl, shouldUpdateScroll, statusIds, hasMore } = this.props;
|
||||
|
||||
return (
|
||||
<Column icon='thumb-tack' heading={intl.formatMessage(messages.heading)} ref={this.setRef}>
|
||||
|
@ -51,6 +52,7 @@ export default class PinnedStatuses extends ImmutablePureComponent {
|
|||
statusIds={statusIds}
|
||||
scrollKey='pinned_statuses'
|
||||
hasMore={hasMore}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -39,6 +39,7 @@ export default class PublicTimeline extends React.PureComponent {
|
|||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
intl: PropTypes.object.isRequired,
|
||||
columnId: PropTypes.string,
|
||||
multiColumn: PropTypes.bool,
|
||||
|
@ -107,7 +108,7 @@ export default class PublicTimeline extends React.PureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { intl, columnId, hasUnread, multiColumn, onlyMedia } = this.props;
|
||||
const { intl, shouldUpdateScroll, columnId, hasUnread, multiColumn, onlyMedia } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
||||
return (
|
||||
|
@ -131,6 +132,7 @@ export default class PublicTimeline extends React.PureComponent {
|
|||
trackScroll={!pinned}
|
||||
scrollKey={`public_timeline-${columnId}`}
|
||||
emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other instances to fill it up' />}
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import LoadingIndicator from '../../components/loading_indicator';
|
||||
|
@ -8,7 +9,6 @@ import { ScrollContainer } from 'react-router-scroll-4';
|
|||
import AccountContainer from '../../containers/account_container';
|
||||
import Column from '../ui/components/column';
|
||||
import ColumnBackButton from '../../components/column_back_button';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
accountIds: state.getIn(['user_lists', 'reblogged_by', props.params.statusId]),
|
||||
|
@ -20,6 +20,7 @@ export default class Reblogs extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
};
|
||||
|
||||
|
@ -34,7 +35,7 @@ export default class Reblogs extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { accountIds } = this.props;
|
||||
const { shouldUpdateScroll, accountIds } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
|
@ -48,7 +49,7 @@ export default class Reblogs extends ImmutablePureComponent {
|
|||
<Column>
|
||||
<ColumnBackButton />
|
||||
|
||||
<ScrollContainer scrollKey='reblogs'>
|
||||
<ScrollContainer scrollKey='reblogs' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className='scrollable reblogs'>
|
||||
{accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
|
||||
</div>
|
||||
|
|
|
@ -42,7 +42,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { HotKeys } from 'react-hotkeys';
|
||||
import { boostModal, deleteModal } from '../../initial_state';
|
||||
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../../features/ui/util/fullscreen';
|
||||
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen';
|
||||
|
||||
const messages = defineMessages({
|
||||
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||
|
@ -370,7 +370,7 @@ export default class Status extends ImmutablePureComponent {
|
|||
|
||||
render () {
|
||||
let ancestors, descendants;
|
||||
const { status, ancestorsIds, descendantsIds, intl } = this.props;
|
||||
const { shouldUpdateScroll, status, ancestorsIds, descendantsIds, intl } = this.props;
|
||||
const { fullscreen } = this.state;
|
||||
|
||||
if (status === null) {
|
||||
|
@ -410,7 +410,7 @@ export default class Status extends ImmutablePureComponent {
|
|||
)}
|
||||
/>
|
||||
|
||||
<ScrollContainer scrollKey='thread'>
|
||||
<ScrollContainer scrollKey='thread' shouldUpdateScroll={shouldUpdateScroll}>
|
||||
<div className={classNames('scrollable', 'detailed-status__wrapper', { fullscreen })} ref={this.setRef}>
|
||||
{ancestors}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ const messages = defineMessages({
|
|||
next: { id: 'lightbox.next', defaultMessage: 'Next' },
|
||||
});
|
||||
|
||||
const previewState = 'previewMediaModal';
|
||||
export const previewState = 'previewMediaModal';
|
||||
|
||||
@injectIntl
|
||||
export default class MediaModal extends ImmutablePureComponent {
|
||||
|
|
|
@ -41,14 +41,15 @@ export default class ModalRoot extends React.PureComponent {
|
|||
};
|
||||
|
||||
getSnapshotBeforeUpdate () {
|
||||
const visible = !!this.props.type;
|
||||
return {
|
||||
overflowY: visible ? 'hidden' : null,
|
||||
};
|
||||
return { visible: !!this.props.type };
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps, prevState, { overflowY }) {
|
||||
document.body.style.overflowY = overflowY;
|
||||
componentDidUpdate (prevProps, prevState, { visible }) {
|
||||
if (visible) {
|
||||
document.body.classList.add('with-modals--active');
|
||||
} else {
|
||||
document.body.classList.remove('with-modals--active');
|
||||
}
|
||||
}
|
||||
|
||||
renderLoading = modalId => () => {
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import NotificationsContainer from './containers/notifications_container';
|
||||
import { HotKeys } from 'react-hotkeys';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import { Redirect, withRouter } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import NotificationsContainer from './containers/notifications_container';
|
||||
import LoadingBarContainer from './containers/loading_bar_container';
|
||||
import TabsBar from './components/tabs_bar';
|
||||
import ModalContainer from './containers/modal_container';
|
||||
import { connect } from 'react-redux';
|
||||
import { Redirect, withRouter } from 'react-router-dom';
|
||||
import { isMobile } from '../../is_mobile';
|
||||
import { debounce } from 'lodash';
|
||||
import { uploadCompose, resetCompose } from '../../actions/compose';
|
||||
|
@ -44,9 +46,8 @@ import {
|
|||
PinnedStatuses,
|
||||
Lists,
|
||||
} from './util/async-components';
|
||||
import { HotKeys } from 'react-hotkeys';
|
||||
import { me } from '../../initial_state';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { previewState } from './components/media_modal';
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
// Without this it ends up in ~8 very commonly used bundles.
|
||||
|
@ -117,6 +118,10 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
window.removeEventListener('resize', this.handleResize);
|
||||
}
|
||||
|
||||
shouldUpdateScroll (_, { location }) {
|
||||
return location.state !== previewState;
|
||||
}
|
||||
|
||||
handleResize = debounce(() => {
|
||||
// The cached heights are no longer accurate, invalidate
|
||||
this.props.onLayoutChange();
|
||||
|
@ -141,36 +146,36 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
{redirect}
|
||||
<WrappedRoute path='/getting-started' component={GettingStarted} content={children} />
|
||||
<WrappedRoute path='/keyboard-shortcuts' component={KeyboardShortcuts} content={children} />
|
||||
<WrappedRoute path='/timelines/home' component={HomeTimeline} content={children} />
|
||||
<WrappedRoute path='/timelines/public' exact component={PublicTimeline} content={children} />
|
||||
<WrappedRoute path='/timelines/public/media' component={PublicTimeline} content={children} componentParams={{ onlyMedia: true }} />
|
||||
<WrappedRoute path='/timelines/public/local' exact component={CommunityTimeline} content={children} />
|
||||
<WrappedRoute path='/timelines/public/local/media' component={CommunityTimeline} content={children} componentParams={{ onlyMedia: true }} />
|
||||
<WrappedRoute path='/timelines/direct' component={DirectTimeline} content={children} />
|
||||
<WrappedRoute path='/timelines/tag/:id' component={HashtagTimeline} content={children} />
|
||||
<WrappedRoute path='/timelines/list/:id' component={ListTimeline} content={children} />
|
||||
<WrappedRoute path='/timelines/home' component={HomeTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/timelines/public' exact component={PublicTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/timelines/public/media' component={PublicTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll, onlyMedia: true }} />
|
||||
<WrappedRoute path='/timelines/public/local' exact component={CommunityTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/timelines/public/local/media' component={CommunityTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll, onlyMedia: true }} />
|
||||
<WrappedRoute path='/timelines/direct' component={DirectTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/timelines/tag/:id' component={HashtagTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/timelines/list/:id' component={ListTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
|
||||
<WrappedRoute path='/notifications' component={Notifications} content={children} />
|
||||
<WrappedRoute path='/favourites' component={FavouritedStatuses} content={children} />
|
||||
<WrappedRoute path='/pinned' component={PinnedStatuses} content={children} />
|
||||
<WrappedRoute path='/notifications' component={Notifications} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/favourites' component={FavouritedStatuses} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/pinned' component={PinnedStatuses} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
|
||||
<WrappedRoute path='/search' component={Compose} content={children} componentParams={{ isSearchPage: true }} />
|
||||
|
||||
<WrappedRoute path='/statuses/new' component={Compose} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId/reblogs' component={Reblogs} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/statuses/:statusId/reblogs' component={Reblogs} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
|
||||
<WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} />
|
||||
<WrappedRoute path='/accounts/:accountId/with_replies' component={AccountTimeline} content={children} componentParams={{ withReplies: true }} />
|
||||
<WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} />
|
||||
<WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} />
|
||||
<WrappedRoute path='/accounts/:accountId/media' component={AccountGallery} content={children} />
|
||||
<WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/accounts/:accountId/with_replies' component={AccountTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll, withReplies: true }} />
|
||||
<WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/accounts/:accountId/media' component={AccountGallery} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
|
||||
<WrappedRoute path='/follow_requests' component={FollowRequests} content={children} />
|
||||
<WrappedRoute path='/blocks' component={Blocks} content={children} />
|
||||
<WrappedRoute path='/domain_blocks' component={DomainBlocks} content={children} />
|
||||
<WrappedRoute path='/mutes' component={Mutes} content={children} />
|
||||
<WrappedRoute path='/follow_requests' component={FollowRequests} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/blocks' component={Blocks} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/domain_blocks' component={DomainBlocks} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/mutes' component={Mutes} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
<WrappedRoute path='/lists' component={Lists} content={children} />
|
||||
|
||||
<WrappedRoute component={GenericNotFound} content={children} />
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"account.badges.bot": "Robot",
|
||||
"account.block": "Blokovat @{name}",
|
||||
"account.block": "Zablokovat uživatele @{name}",
|
||||
"account.block_domain": "Skrýt vše z {domain}",
|
||||
"account.blocked": "Blokován/a",
|
||||
"account.direct": "Přímá zpráva pro uživatele @{name}",
|
||||
"account.disclaimer_full": "Níže uvedené informace nemusejí zcela odrážet profil uživatele.",
|
||||
"account.domain_blocked": "Doména skryta",
|
||||
"account.edit_profile": "Uprav profil",
|
||||
"account.edit_profile": "Upravit profil",
|
||||
"account.follow": "Sleduj",
|
||||
"account.followers": "Sledovatelé",
|
||||
"account.follows": "Sleduje",
|
||||
"account.follows_you": "Sleduje vás",
|
||||
"account.hide_reblogs": "Skrýt povýšení od uživatele @{name}",
|
||||
"account.hide_reblogs": "Skrýt boosty od uživatele @{name}",
|
||||
"account.media": "Média",
|
||||
"account.mention": "Zmínit uživatele @{name}",
|
||||
"account.moved_to": "{name} se přesunul/a na:",
|
||||
|
@ -23,7 +23,7 @@
|
|||
"account.report": "Nahlásit uživatele @{name}",
|
||||
"account.requested": "Požadavek čeká na schválení. Kliknutím zrušíte požadavek o sledování",
|
||||
"account.share": "Sdílet profil uživatele @{name}",
|
||||
"account.show_reblogs": "Zobrazit povýšení od uživatele @{name}",
|
||||
"account.show_reblogs": "Zobrazit boosty od uživatele @{name}",
|
||||
"account.unblock": "Odblokovat uživatele @{name}",
|
||||
"account.unblock_domain": "Odkrýt doménu {domain}",
|
||||
"account.unfollow": "Přestat sledovat",
|
||||
|
@ -64,7 +64,7 @@
|
|||
"compose_form.direct_message_warning_learn_more": "Zjistit více",
|
||||
"compose_form.hashtag_warning": "Tento toot nebude zobrazen pod žádným hashtagem, neboť je neuvedený. Pouze veřejné tooty mohou být vyhledány podle hashtagu.",
|
||||
"compose_form.lock_disclaimer": "Váš účet není {locked}. Kdokoliv vás může sledovat a vidět vaše příspěvky pouze pro sledovatele.",
|
||||
"compose_form.lock_disclaimer.lock": "zamknutý",
|
||||
"compose_form.lock_disclaimer.lock": "zamčený",
|
||||
"compose_form.placeholder": "Co máte na mysli?",
|
||||
"compose_form.publish": "Tootnout",
|
||||
"compose_form.publish_loud": "{publish}!",
|
||||
|
@ -85,225 +85,225 @@
|
|||
"confirmations.mute.confirm": "Ignorovat",
|
||||
"confirmations.mute.message": "Jste si jistý/á, že chcete ignorovat uživatele {name}?",
|
||||
"confirmations.redraft.confirm": "Vymazat a přepsat",
|
||||
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
|
||||
"confirmations.unfollow.confirm": "Unfollow",
|
||||
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
|
||||
"embed.instructions": "Embed this status on your website by copying the code below.",
|
||||
"embed.preview": "Here is what it will look like:",
|
||||
"emoji_button.activity": "Activity",
|
||||
"emoji_button.custom": "Custom",
|
||||
"emoji_button.flags": "Flags",
|
||||
"emoji_button.food": "Food & Drink",
|
||||
"emoji_button.label": "Insert emoji",
|
||||
"emoji_button.nature": "Nature",
|
||||
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
|
||||
"emoji_button.objects": "Objects",
|
||||
"emoji_button.people": "People",
|
||||
"emoji_button.recent": "Frequently used",
|
||||
"emoji_button.search": "Search...",
|
||||
"emoji_button.search_results": "Search results",
|
||||
"emoji_button.symbols": "Symbols",
|
||||
"emoji_button.travel": "Travel & Places",
|
||||
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
|
||||
"empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
|
||||
"empty_column.hashtag": "There is nothing in this hashtag yet.",
|
||||
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
|
||||
"empty_column.home.public_timeline": "the public timeline",
|
||||
"empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
|
||||
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
|
||||
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
|
||||
"follow_request.authorize": "Authorize",
|
||||
"follow_request.reject": "Reject",
|
||||
"getting_started.developers": "Developers",
|
||||
"confirmations.redraft.message": "Jste si jistý/á, že chcete vymazat a přepsat tento status? Ztratíte všechny jeho odpovědi, boosty a oblíbení.",
|
||||
"confirmations.unfollow.confirm": "Přestat sledovat",
|
||||
"confirmations.unfollow.message": "jste si jistý/á, že chcete přestat sledovat uživatele {name}?",
|
||||
"embed.instructions": "Pro přidání statusu na vaši webovou stránku zkopírujte níže uvedený kód.",
|
||||
"embed.preview": "Takhle to bude vypadat:",
|
||||
"emoji_button.activity": "Aktivita",
|
||||
"emoji_button.custom": "Vlastní",
|
||||
"emoji_button.flags": "Vlajky",
|
||||
"emoji_button.food": "Jídla a nápoje",
|
||||
"emoji_button.label": "Vložit emoji",
|
||||
"emoji_button.nature": "Příroda",
|
||||
"emoji_button.not_found": "Žádné emoji!! (╯°□°)╯︵ ┻━┻",
|
||||
"emoji_button.objects": "Předměty",
|
||||
"emoji_button.people": "Lidé",
|
||||
"emoji_button.recent": "Často používané",
|
||||
"emoji_button.search": "Hledat...",
|
||||
"emoji_button.search_results": "Výsledky hledání",
|
||||
"emoji_button.symbols": "Symboly",
|
||||
"emoji_button.travel": "Cestování a místa",
|
||||
"empty_column.community": "Místní časová osa je prázdná. Napište něco veřejně a rozhýbejte to tu!",
|
||||
"empty_column.direct": "Ještě nemáte žádné přímé zprávy. Pokud nějakou pošlete nebo dostanete, zobrazí se zde.",
|
||||
"empty_column.hashtag": "Pod tímto hashtagem ještě nic není.",
|
||||
"empty_column.home": "Vaše domovská časová osa je prázdná! Začněte navštívením {public} nebo použijte hledání a seznamte se s dalšími uživateli.",
|
||||
"empty_column.home.public_timeline": "veřejné časové osy",
|
||||
"empty_column.list": "V tomto seznamu ještě nic není. Pokud budou členové tohoto seznamu psát nové statusy, objeví se zde.",
|
||||
"empty_column.notifications": "Ještě nemáte žádná oznámení. Začněte konverzaci komunikováním s ostatními.",
|
||||
"empty_column.public": "Tady nic není! Napište něco veřejně, nebo manuálně začněte sledovat uživatele z jiných instancí, aby tu něco přibylo",
|
||||
"follow_request.authorize": "Autorizovat",
|
||||
"follow_request.reject": "Odmítnout",
|
||||
"getting_started.developers": "Vývojáři",
|
||||
"getting_started.documentation": "Documentation",
|
||||
"getting_started.find_friends": "Find friends from Twitter",
|
||||
"getting_started.heading": "Getting started",
|
||||
"getting_started.invite": "Invite people",
|
||||
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
|
||||
"getting_started.security": "Security",
|
||||
"getting_started.terms": "Terms of service",
|
||||
"home.column_settings.basic": "Basic",
|
||||
"home.column_settings.show_reblogs": "Show boosts",
|
||||
"home.column_settings.show_replies": "Show replies",
|
||||
"keyboard_shortcuts.back": "to navigate back",
|
||||
"keyboard_shortcuts.boost": "to boost",
|
||||
"keyboard_shortcuts.column": "to focus a status in one of the columns",
|
||||
"keyboard_shortcuts.compose": "to focus the compose textarea",
|
||||
"keyboard_shortcuts.description": "Description",
|
||||
"keyboard_shortcuts.down": "to move down in the list",
|
||||
"keyboard_shortcuts.enter": "to open status",
|
||||
"keyboard_shortcuts.favourite": "to favourite",
|
||||
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
|
||||
"keyboard_shortcuts.hotkey": "Hotkey",
|
||||
"keyboard_shortcuts.legend": "to display this legend",
|
||||
"keyboard_shortcuts.mention": "to mention author",
|
||||
"getting_started.find_friends": "Najděte si přátele z Twitteru",
|
||||
"getting_started.heading": "Začínáme",
|
||||
"getting_started.invite": "Pozvat lidi",
|
||||
"getting_started.open_source_notice": "Mastodon je otevřený software. Na GitHubu k němu můžete přispět nebo nahlásit chyby: {github}.",
|
||||
"getting_started.security": "Zabezpečení",
|
||||
"getting_started.terms": "Podmínky používání",
|
||||
"home.column_settings.basic": "Základní",
|
||||
"home.column_settings.show_reblogs": "Zobrazit boosty",
|
||||
"home.column_settings.show_replies": "Zobrazit odpovědi",
|
||||
"keyboard_shortcuts.back": "k návratu zpět",
|
||||
"keyboard_shortcuts.boost": "k boostnutí",
|
||||
"keyboard_shortcuts.column": "k zaměření na status v jednom ze sloupců",
|
||||
"keyboard_shortcuts.compose": "k zaměření na psací prostor",
|
||||
"keyboard_shortcuts.description": "Popis",
|
||||
"keyboard_shortcuts.down": "k přesunutí dolů v seznamu",
|
||||
"keyboard_shortcuts.enter": "k otevření statusu",
|
||||
"keyboard_shortcuts.favourite": "k oblíbení",
|
||||
"keyboard_shortcuts.heading": "Klávesové zkratky",
|
||||
"keyboard_shortcuts.hotkey": "Horká klávesa",
|
||||
"keyboard_shortcuts.legend": "k zobrazení této legendy",
|
||||
"keyboard_shortcuts.mention": "ke zmínění autora",
|
||||
"keyboard_shortcuts.profile": "to open author's profile",
|
||||
"keyboard_shortcuts.reply": "to reply",
|
||||
"keyboard_shortcuts.search": "to focus search",
|
||||
"keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
|
||||
"keyboard_shortcuts.toot": "to start a brand new toot",
|
||||
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
|
||||
"keyboard_shortcuts.up": "to move up in the list",
|
||||
"lightbox.close": "Close",
|
||||
"lightbox.next": "Next",
|
||||
"lightbox.previous": "Previous",
|
||||
"lists.account.add": "Add to list",
|
||||
"lists.account.remove": "Remove from list",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Toggle visibility",
|
||||
"missing_indicator.label": "Not found",
|
||||
"missing_indicator.sublabel": "This resource could not be found",
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Local timeline",
|
||||
"navigation_bar.direct": "Direct messages",
|
||||
"navigation_bar.discover": "Discover",
|
||||
"navigation_bar.domain_blocks": "Hidden domains",
|
||||
"navigation_bar.edit_profile": "Edit profile",
|
||||
"navigation_bar.favourites": "Favourites",
|
||||
"navigation_bar.filters": "Muted words",
|
||||
"navigation_bar.follow_requests": "Follow requests",
|
||||
"navigation_bar.info": "About this instance",
|
||||
"navigation_bar.keyboard_shortcuts": "Hotkeys",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.logout": "Logout",
|
||||
"navigation_bar.mutes": "Muted users",
|
||||
"navigation_bar.personal": "Personal",
|
||||
"navigation_bar.pins": "Pinned toots",
|
||||
"navigation_bar.preferences": "Preferences",
|
||||
"navigation_bar.public_timeline": "Federated timeline",
|
||||
"navigation_bar.security": "Security",
|
||||
"notification.favourite": "{name} favourited your status",
|
||||
"notification.follow": "{name} followed you",
|
||||
"notification.mention": "{name} mentioned you",
|
||||
"notification.reblog": "{name} boosted your status",
|
||||
"notifications.clear": "Clear notifications",
|
||||
"notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
|
||||
"notifications.column_settings.alert": "Desktop notifications",
|
||||
"notifications.column_settings.favourite": "Favourites:",
|
||||
"notifications.column_settings.follow": "New followers:",
|
||||
"notifications.column_settings.mention": "Mentions:",
|
||||
"notifications.column_settings.push": "Push notifications",
|
||||
"notifications.column_settings.push_meta": "This device",
|
||||
"notifications.column_settings.reblog": "Boosts:",
|
||||
"notifications.column_settings.show": "Show in column",
|
||||
"notifications.column_settings.sound": "Play sound",
|
||||
"notifications.group": "{count} notifications",
|
||||
"onboarding.done": "Done",
|
||||
"onboarding.next": "Next",
|
||||
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",
|
||||
"onboarding.page_four.home": "The home timeline shows posts from people you follow.",
|
||||
"onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.",
|
||||
"onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
|
||||
"onboarding.page_one.full_handle": "Your full handle",
|
||||
"onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.",
|
||||
"onboarding.page_one.welcome": "Welcome to Mastodon!",
|
||||
"onboarding.page_six.admin": "Your instance's admin is {admin}.",
|
||||
"onboarding.page_six.almost_done": "Almost done...",
|
||||
"onboarding.page_six.appetoot": "Bon Appetoot!",
|
||||
"onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.",
|
||||
"onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.",
|
||||
"onboarding.page_six.guidelines": "community guidelines",
|
||||
"onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!",
|
||||
"onboarding.page_six.various_app": "mobile apps",
|
||||
"onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.",
|
||||
"onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.",
|
||||
"onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.",
|
||||
"onboarding.skip": "Skip",
|
||||
"privacy.change": "Adjust status privacy",
|
||||
"privacy.direct.long": "Post to mentioned users only",
|
||||
"privacy.direct.short": "Direct",
|
||||
"privacy.private.long": "Post to followers only",
|
||||
"privacy.private.short": "Followers-only",
|
||||
"privacy.public.long": "Post to public timelines",
|
||||
"privacy.public.short": "Public",
|
||||
"keyboard_shortcuts.reply": "k odpovězení",
|
||||
"keyboard_shortcuts.search": "k zaměření na vyhledávání",
|
||||
"keyboard_shortcuts.toggle_hidden": "k zobrazení/skrytí textu za CW",
|
||||
"keyboard_shortcuts.toot": "k napsání úplně nového tootu",
|
||||
"keyboard_shortcuts.unfocus": "ke zrušení soustředění na psací prostor/hledání",
|
||||
"keyboard_shortcuts.up": "k posunutí nahoru v seznamu",
|
||||
"lightbox.close": "Zavřít",
|
||||
"lightbox.next": "Další",
|
||||
"lightbox.previous": "Předchozí",
|
||||
"lists.account.add": "Přidat do seznamu",
|
||||
"lists.account.remove": "Odebrat ze seznamu",
|
||||
"lists.delete": "Smazat seznam",
|
||||
"lists.edit": "Upravit seznam",
|
||||
"lists.new.create": "Přidat seznam",
|
||||
"lists.new.title_placeholder": "Název nového seznamu",
|
||||
"lists.search": "Hledejte mezi uživateli, které sledujete",
|
||||
"lists.subheading": "Vaše seznamy",
|
||||
"loading_indicator.label": "Načítám...",
|
||||
"media_gallery.toggle_visible": "Přepínat viditelnost",
|
||||
"missing_indicator.label": "Nenalezeno",
|
||||
"missing_indicator.sublabel": "Tento zdroj se nepodažilo najít",
|
||||
"mute_modal.hide_notifications": "Skrýt oznámení před tímto uživatelem?",
|
||||
"navigation_bar.blocks": "Blokovaní uživatelé",
|
||||
"navigation_bar.community_timeline": "Místní časová osa",
|
||||
"navigation_bar.direct": "Přímé zprávy",
|
||||
"navigation_bar.discover": "Objevujte",
|
||||
"navigation_bar.domain_blocks": "Skryté domény",
|
||||
"navigation_bar.edit_profile": "Upravit profil",
|
||||
"navigation_bar.favourites": "Oblíbené",
|
||||
"navigation_bar.filters": "Skrytá slova",
|
||||
"navigation_bar.follow_requests": "Žádosti o sledování",
|
||||
"navigation_bar.info": "O této instanci",
|
||||
"navigation_bar.keyboard_shortcuts": "Klávesové zkratky",
|
||||
"navigation_bar.lists": "Seznamy",
|
||||
"navigation_bar.logout": "Odhlásit se",
|
||||
"navigation_bar.mutes": "Ignorovaní uživatelé",
|
||||
"navigation_bar.personal": "Osobní",
|
||||
"navigation_bar.pins": "Připnuté tooty",
|
||||
"navigation_bar.preferences": "Předvolby",
|
||||
"navigation_bar.public_timeline": "Federovaná časová osa",
|
||||
"navigation_bar.security": "Zabezpečení",
|
||||
"notification.favourite": "{name} označil/a váš status jako oblíbený",
|
||||
"notification.follow": "{name} vás začal/a sledovat",
|
||||
"notification.mention": "{name} vás zmínil/a",
|
||||
"notification.reblog": "{name} vám boostnul/a status",
|
||||
"notifications.clear": "Vymazat oznámení",
|
||||
"notifications.clear_confirmation": "Jste si jistý/á, že chcete trvale vymazat všechna vaše oznámení?",
|
||||
"notifications.column_settings.alert": "Desktopová oznámení",
|
||||
"notifications.column_settings.favourite": "Oblíbené:",
|
||||
"notifications.column_settings.follow": "Noví sledovatelé:",
|
||||
"notifications.column_settings.mention": "Zmínky:",
|
||||
"notifications.column_settings.push": "Push oznámení",
|
||||
"notifications.column_settings.push_meta": "Toto zařízení",
|
||||
"notifications.column_settings.reblog": "Boosty:",
|
||||
"notifications.column_settings.show": "Zobrazit ve sloupci",
|
||||
"notifications.column_settings.sound": "Přehrát zvuk",
|
||||
"notifications.group": "{count} oznámení",
|
||||
"onboarding.done": "Hotovo",
|
||||
"onboarding.next": "Další",
|
||||
"onboarding.page_five.public_timelines": "Místní časová osa zobrazuje veřejné příspěvky od všech lidí na {domain}. Federovaná časová osa zobrazuje veřejné příspěvky ode všech, které lidé na {domain} sledují. Toto jsou veřejné časové osy, výborný způsob, jak objevovat nové lidi.",
|
||||
"onboarding.page_four.home": "Domovská časová osa zobrazuje příspěvky od lidí, které sledujete.",
|
||||
"onboarding.page_four.notifications": "Sloupec oznámení se zobrazí, když s vámi někdo bude komunikovat.",
|
||||
"onboarding.page_one.federation": "Mastodon je síť nezávislých serverů, jejichž propojením vzniká jedna velká sociální síť. Těmto serverům říkáme instance.",
|
||||
"onboarding.page_one.full_handle": "Vaše celá adresa profilu",
|
||||
"onboarding.page_one.handle_hint": "Tohle je, co byste řekl/a svým přátelům, aby hledali.",
|
||||
"onboarding.page_one.welcome": "Vítejte na Mastodonu!",
|
||||
"onboarding.page_six.admin": "Administrátorem vaší instance je {admin}.",
|
||||
"onboarding.page_six.almost_done": "Skoro hotovo...",
|
||||
"onboarding.page_six.appetoot": "Bon appetoot!",
|
||||
"onboarding.page_six.apps_available": "Jsou dostupné {apps} pro iOS, Android a jiné platformy.",
|
||||
"onboarding.page_six.github": "Mastodon je svobodný a otevřený software. Na {github} můžete nahlásit chyby, požádat o nové funkce, nebo přispívat ke kódu.",
|
||||
"onboarding.page_six.guidelines": "komunitní pravidla",
|
||||
"onboarding.page_six.read_guidelines": "Prosím přečtěte si {guidelines} {domain}!",
|
||||
"onboarding.page_six.various_app": "mobilní aplikace",
|
||||
"onboarding.page_three.profile": "Upravte si svůj profil a změňte si svůj avatar, popis profilu a zobrazované jméno. V nastaveních najdete i další možnosti.",
|
||||
"onboarding.page_three.search": "Pomocí vyhledávacího řádku najděte lidi a podívejte se na hashtagy jako {illustration} a {introductions}. Chcete-li najít někoho, kdo není na této instanci, použijte jeho celou adresu profilu.",
|
||||
"onboarding.page_two.compose": "Příspěvky pište z pole na komponování. Ikonami níže můžete nahrávat obrázky, změnit nastavení soukromí a přidat varování o obsahu.",
|
||||
"onboarding.skip": "Přeskočit",
|
||||
"privacy.change": "Změnit viditelnost statusu",
|
||||
"privacy.direct.long": "Odeslat pouze zmíněným uživatelům",
|
||||
"privacy.direct.short": "Přímé",
|
||||
"privacy.private.long": "Odeslat pouze sledovatelům",
|
||||
"privacy.private.short": "Pouze pro sledovatele",
|
||||
"privacy.public.long": "Odeslat na veřejné časové osy",
|
||||
"privacy.public.short": "Veřejné",
|
||||
"privacy.unlisted.long": "Do not show in public timelines",
|
||||
"privacy.unlisted.short": "Unlisted",
|
||||
"regeneration_indicator.label": "Loading…",
|
||||
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
|
||||
"privacy.unlisted.short": "Nezobrazované",
|
||||
"regeneration_indicator.label": "Načítám…",
|
||||
"regeneration_indicator.sublabel": "Váš domovský proud se připravuje!",
|
||||
"relative_time.days": "{number}d",
|
||||
"relative_time.hours": "{number}h",
|
||||
"relative_time.just_now": "now",
|
||||
"relative_time.just_now": "teď",
|
||||
"relative_time.minutes": "{number}m",
|
||||
"relative_time.seconds": "{number}s",
|
||||
"reply_indicator.cancel": "Cancel",
|
||||
"report.forward": "Forward to {target}",
|
||||
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
|
||||
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
|
||||
"report.placeholder": "Additional comments",
|
||||
"report.submit": "Submit",
|
||||
"report.target": "Report {target}",
|
||||
"search.placeholder": "Search",
|
||||
"search_popout.search_format": "Advanced search format",
|
||||
"search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.",
|
||||
"reply_indicator.cancel": "Zrušit",
|
||||
"report.forward": "Přeposlat k {target}",
|
||||
"report.forward_hint": "Tento účet je z jiného serveru. Chcete na něj také poslat anonymizovanou kopii?",
|
||||
"report.hint": "Toto nahlášení bude zasláno moderátorům vaší instance. Níže můžete uvést, proč tento účet nahlašujete:",
|
||||
"report.placeholder": "Další komentáře",
|
||||
"report.submit": "Odeslat",
|
||||
"report.target": "Nahlásit {target}",
|
||||
"search.placeholder": "Hledat",
|
||||
"search_popout.search_format": "Pokročilé vyhledávání",
|
||||
"search_popout.tips.full_text": "Jednoduchý textový výpis statusů, které jste napsal/a, oblíbil/a si, povýšil/a, nebo v nich byl/a zmíněn/a, včetně odpovídajících přezdívek, jmen a hashtagů.",
|
||||
"search_popout.tips.hashtag": "hashtag",
|
||||
"search_popout.tips.status": "status",
|
||||
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
|
||||
"search_popout.tips.user": "user",
|
||||
"search_results.accounts": "People",
|
||||
"search_results.hashtags": "Hashtags",
|
||||
"search_results.statuses": "Toots",
|
||||
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
|
||||
"standalone.public_title": "A look inside...",
|
||||
"status.block": "Block @{name}",
|
||||
"status.cancel_reblog_private": "Unboost",
|
||||
"status.cannot_reblog": "This post cannot be boosted",
|
||||
"search_popout.tips.text": "Jednoduchý textový výpis odpovídajících jmen, přezdívek a hashtagů",
|
||||
"search_popout.tips.user": "uživatel",
|
||||
"search_results.accounts": "Lidé",
|
||||
"search_results.hashtags": "Hashtagy",
|
||||
"search_results.statuses": "Tooty",
|
||||
"search_results.total": "{count, number} {count, plural, one {výsledek} other {výsledků}}",
|
||||
"standalone.public_title": "Nahlédnout dovnitř...",
|
||||
"status.block": "Zablokovat uživatele @{name}",
|
||||
"status.cancel_reblog_private": "Zrušit boost",
|
||||
"status.cannot_reblog": "Tento příspěvek nemůže být boostnutý",
|
||||
"status.delete": "Delete",
|
||||
"status.direct": "Direct message @{name}",
|
||||
"status.embed": "Embed",
|
||||
"status.favourite": "Favourite",
|
||||
"status.filtered": "Filtered",
|
||||
"status.load_more": "Load more",
|
||||
"status.media_hidden": "Media hidden",
|
||||
"status.mention": "Mention @{name}",
|
||||
"status.more": "More",
|
||||
"status.mute": "Mute @{name}",
|
||||
"status.mute_conversation": "Mute conversation",
|
||||
"status.open": "Expand this status",
|
||||
"status.pin": "Pin on profile",
|
||||
"status.pinned": "Pinned toot",
|
||||
"status.reblog": "Boost",
|
||||
"status.reblog_private": "Boost to original audience",
|
||||
"status.reblogged_by": "{name} boosted",
|
||||
"status.redraft": "Delete & re-draft",
|
||||
"status.reply": "Reply",
|
||||
"status.replyAll": "Reply to thread",
|
||||
"status.report": "Report @{name}",
|
||||
"status.sensitive_toggle": "Click to view",
|
||||
"status.sensitive_warning": "Sensitive content",
|
||||
"status.share": "Share",
|
||||
"status.show_less": "Show less",
|
||||
"status.show_less_all": "Show less for all",
|
||||
"status.show_more": "Show more",
|
||||
"status.show_more_all": "Show more for all",
|
||||
"status.unmute_conversation": "Unmute conversation",
|
||||
"status.unpin": "Unpin from profile",
|
||||
"tabs_bar.federated_timeline": "Federated",
|
||||
"tabs_bar.home": "Home",
|
||||
"tabs_bar.local_timeline": "Local",
|
||||
"tabs_bar.notifications": "Notifications",
|
||||
"tabs_bar.search": "Search",
|
||||
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
|
||||
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
|
||||
"upload_area.title": "Drag & drop to upload",
|
||||
"upload_button.label": "Add media",
|
||||
"upload_form.description": "Describe for the visually impaired",
|
||||
"upload_form.focus": "Crop",
|
||||
"upload_form.undo": "Delete",
|
||||
"upload_progress.label": "Uploading...",
|
||||
"video.close": "Close video",
|
||||
"video.exit_fullscreen": "Exit full screen",
|
||||
"video.expand": "Expand video",
|
||||
"video.fullscreen": "Full screen",
|
||||
"video.hide": "Hide video",
|
||||
"video.mute": "Mute sound",
|
||||
"video.pause": "Pause",
|
||||
"video.play": "Play",
|
||||
"video.unmute": "Unmute sound"
|
||||
"status.direct": "Poslat přímou zprávu uživateli @{name}",
|
||||
"status.embed": "Vložit",
|
||||
"status.favourite": "Oblíbit",
|
||||
"status.filtered": "Filtrováno",
|
||||
"status.load_more": "Zobrazit více",
|
||||
"status.media_hidden": "Média skryta",
|
||||
"status.mention": "Zmínit uživatele @{name}",
|
||||
"status.more": "Více",
|
||||
"status.mute": "Ignorovat uživatele @{name}",
|
||||
"status.mute_conversation": "Ignorovat konverzaci",
|
||||
"status.open": "Otevřít tento status",
|
||||
"status.pin": "Připnout na profil",
|
||||
"status.pinned": "Připnutý toot",
|
||||
"status.reblog": "Boostnout",
|
||||
"status.reblog_private": "Boostnout původnímu publiku",
|
||||
"status.reblogged_by": "{name} boostnul/a",
|
||||
"status.redraft": "Vymazat a přepsat",
|
||||
"status.reply": "Odpovědět",
|
||||
"status.replyAll": "Odpovědět na vlákno",
|
||||
"status.report": "Nahlásit uživatele @{name}",
|
||||
"status.sensitive_toggle": "Klikněte pro zobrazení",
|
||||
"status.sensitive_warning": "Citlivý obsah",
|
||||
"status.share": "Sdílet",
|
||||
"status.show_less": "Zobrazit méně",
|
||||
"status.show_less_all": "Zobrazit méně pro všechny",
|
||||
"status.show_more": "Zobrazit více",
|
||||
"status.show_more_all": "Zobrazit více pro všechny",
|
||||
"status.unmute_conversation": "Přestat ignorovat konverzaci",
|
||||
"status.unpin": "Odepnout z profilu",
|
||||
"tabs_bar.federated_timeline": "Federovaná",
|
||||
"tabs_bar.home": "Domů",
|
||||
"tabs_bar.local_timeline": "Místní",
|
||||
"tabs_bar.notifications": "Oznámení",
|
||||
"tabs_bar.search": "Hledat",
|
||||
"trends.count_by_accounts": "{count} {rawCount, plural, one {člověk} other {lidí}} diskutuje",
|
||||
"ui.beforeunload": "Váš koncept se ztratí, pokud Mastodon opustíte.",
|
||||
"upload_area.title": "Přetažením nahrajete",
|
||||
"upload_button.label": "Přidat média",
|
||||
"upload_form.description": "Popis pro zrakově postižené",
|
||||
"upload_form.focus": "Vystřihnout",
|
||||
"upload_form.undo": "Smazat",
|
||||
"upload_progress.label": "Nahrávám...",
|
||||
"video.close": "Zavřít video",
|
||||
"video.exit_fullscreen": "Ukončit celou obrazovku",
|
||||
"video.expand": "Otevřít video",
|
||||
"video.fullscreen": "Celá obrazovka",
|
||||
"video.hide": "Skrýt video",
|
||||
"video.mute": "Vypnout zvuk",
|
||||
"video.pause": "Pauza",
|
||||
"video.play": "Přehrát",
|
||||
"video.unmute": "Zapnout zvuk"
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@
|
|||
"navigation_bar.domain_blocks": "숨겨진 도메인",
|
||||
"navigation_bar.edit_profile": "프로필 편집",
|
||||
"navigation_bar.favourites": "즐겨찾기",
|
||||
"navigation_bar.filters": "Muted words",
|
||||
"navigation_bar.filters": "뮤트",
|
||||
"navigation_bar.follow_requests": "팔로우 요청",
|
||||
"navigation_bar.info": "이 인스턴스에 대해서",
|
||||
"navigation_bar.keyboard_shortcuts": "단축키",
|
||||
|
|
|
@ -129,11 +129,11 @@
|
|||
"keyboard_shortcuts.boost": "para compartilhar",
|
||||
"keyboard_shortcuts.column": "Focar um status em uma das colunas",
|
||||
"keyboard_shortcuts.compose": "para focar a área de redação",
|
||||
"keyboard_shortcuts.description": "Description",
|
||||
"keyboard_shortcuts.description": "Descrição",
|
||||
"keyboard_shortcuts.down": "para mover para baixo na lista",
|
||||
"keyboard_shortcuts.enter": "to open status",
|
||||
"keyboard_shortcuts.enter": "para expandir um status",
|
||||
"keyboard_shortcuts.favourite": "para adicionar aos favoritos",
|
||||
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
|
||||
"keyboard_shortcuts.heading": "Atalhos de teclado",
|
||||
"keyboard_shortcuts.hotkey": "Atalho",
|
||||
"keyboard_shortcuts.legend": "para mostrar essa legenda",
|
||||
"keyboard_shortcuts.mention": "para mencionar o autor",
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
"compose_form.hashtag_warning": "ఈ టూట్ అన్లిస్టెడ్ కాబట్టి ఏ హాష్ ట్యాగ్ క్రిందకూ రాదు. పబ్లిక్ టూట్ లను మాత్రమే హాష్ ట్యాగ్ ద్వారా శోధించవచ్చు.",
|
||||
"compose_form.lock_disclaimer": "మీ ఖాతా {locked} చేయబడలేదు. ఎవరైనా మిమ్మల్ని అనుసరించి మీ అనుచరులకు-మాత్రమే పోస్ట్లను వీక్షించవచ్చు.",
|
||||
"compose_form.lock_disclaimer.lock": "బిగించబడినది",
|
||||
"compose_form.placeholder": "మీ మనస్సులో ఏమి ఉంది?",
|
||||
"compose_form.placeholder": "మీ మనస్సులో ఏముంది?",
|
||||
"compose_form.publish": "టూట్",
|
||||
"compose_form.publish_loud": "{publish}!",
|
||||
"compose_form.sensitive.marked": "మీడియా సున్నితమైనదిగా గుర్తించబడింది",
|
||||
|
@ -115,7 +115,7 @@
|
|||
"follow_request.authorize": "అనుమతించు",
|
||||
"follow_request.reject": "తిరస్కరించు",
|
||||
"getting_started.developers": "డెవలపర్లు",
|
||||
"getting_started.documentation": "Documentation",
|
||||
"getting_started.documentation": "డాక్యుమెంటేషన్",
|
||||
"getting_started.find_friends": "ట్విట్టర్ నుండి స్నేహితులను కనుగొనండి",
|
||||
"getting_started.heading": "మొదలుపెడదాం",
|
||||
"getting_started.invite": "వ్యక్తులను ఆహ్వానించండి",
|
||||
|
@ -167,7 +167,7 @@
|
|||
"navigation_bar.domain_blocks": "దాచిన డొమైన్లు",
|
||||
"navigation_bar.edit_profile": "ప్రొఫైల్ని సవరించండి",
|
||||
"navigation_bar.favourites": "ఇష్టపడినవి",
|
||||
"navigation_bar.filters": "Muted words",
|
||||
"navigation_bar.filters": "మ్యూట్ చేయబడిన పదాలు",
|
||||
"navigation_bar.follow_requests": "అనుసరించడానికి అభ్యర్ధనలు",
|
||||
"navigation_bar.info": "ఈ దృష్టాంతం గురించి",
|
||||
"navigation_bar.keyboard_shortcuts": "హాట్ కీలు",
|
||||
|
@ -258,7 +258,7 @@
|
|||
"status.direct": "@{name}కు నేరుగా సందేశం పంపు",
|
||||
"status.embed": "ఎంబెడ్",
|
||||
"status.favourite": "ఇష్టపడు",
|
||||
"status.filtered": "Filtered",
|
||||
"status.filtered": "వడకట్టబడిన",
|
||||
"status.load_more": "మరిన్ని లోడ్ చేయి",
|
||||
"status.media_hidden": "మీడియా దాచబడింది",
|
||||
"status.mention": "@{name}ను ప్రస్తావించు",
|
||||
|
|
|
@ -5,14 +5,16 @@ import { start } from '../mastodon/common';
|
|||
start();
|
||||
|
||||
function main() {
|
||||
const IntlRelativeFormat = require('intl-relativeformat').default;
|
||||
const { length } = require('stringz');
|
||||
const IntlMessageFormat = require('intl-messageformat').default;
|
||||
const { timeAgoString } = require('../mastodon/components/relative_timestamp');
|
||||
const { delegate } = require('rails-ujs');
|
||||
const emojify = require('../mastodon/features/emoji/emoji').default;
|
||||
const { getLocale } = require('../mastodon/locales');
|
||||
const { localeData } = getLocale();
|
||||
const { messages } = getLocale();
|
||||
const React = require('react');
|
||||
const ReactDOM = require('react-dom');
|
||||
|
||||
localeData.forEach(IntlRelativeFormat.__addLocaleData);
|
||||
const Rellax = require('rellax');
|
||||
|
||||
ready(() => {
|
||||
const locale = document.documentElement.lang;
|
||||
|
@ -25,8 +27,6 @@ function main() {
|
|||
minute: 'numeric',
|
||||
});
|
||||
|
||||
const relativeFormat = new IntlRelativeFormat(locale);
|
||||
|
||||
[].forEach.call(document.querySelectorAll('.emojify'), (content) => {
|
||||
content.innerHTML = emojify(content.innerHTML);
|
||||
});
|
||||
|
@ -41,12 +41,16 @@ function main() {
|
|||
|
||||
[].forEach.call(document.querySelectorAll('time.time-ago'), (content) => {
|
||||
const datetime = new Date(content.getAttribute('datetime'));
|
||||
const now = new Date();
|
||||
|
||||
content.title = dateTimeFormat.format(datetime);
|
||||
content.textContent = relativeFormat.format(datetime);
|
||||
content.textContent = timeAgoString({
|
||||
formatMessage: ({ id, defaultMessage }, values) => (new IntlMessageFormat(messages[id] || defaultMessage, locale)).format(values),
|
||||
formatDate: (date, options) => (new Intl.DateTimeFormat(locale, options)).format(date),
|
||||
}, datetime, now, datetime.getFullYear());
|
||||
});
|
||||
|
||||
[].forEach.call(document.querySelectorAll('.logo-button'), (content) => {
|
||||
[].forEach.call(document.querySelectorAll('.modal-button'), (content) => {
|
||||
content.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
window.open(e.target.href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
|
||||
|
@ -64,6 +68,8 @@ function main() {
|
|||
})
|
||||
.catch(error => console.error(error));
|
||||
}
|
||||
|
||||
new Rellax('.parallax', { speed: -1 });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
@import 'mastodon/lists';
|
||||
@import 'mastodon/footer';
|
||||
@import 'mastodon/compact_header';
|
||||
@import 'mastodon/landing_strip';
|
||||
@import 'mastodon/widgets';
|
||||
@import 'mastodon/forms';
|
||||
@import 'mastodon/accounts';
|
||||
@import 'mastodon/stream_entries';
|
||||
|
|
|
@ -1115,6 +1115,21 @@ $small-breakpoint: 960px;
|
|||
}
|
||||
|
||||
&.tag-page {
|
||||
@media screen and (max-width: $column-breakpoint) {
|
||||
padding: 0;
|
||||
|
||||
.container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#mastodon-timeline {
|
||||
display: block;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.grid {
|
||||
@media screen and (min-width: $small-breakpoint) {
|
||||
grid-template-columns: 33% 67%;
|
||||
|
@ -1146,24 +1161,17 @@ $small-breakpoint: 960px;
|
|||
|
||||
@media screen and (max-width: $column-breakpoint) {
|
||||
.grid {
|
||||
.column-1 {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
grid-gap: 0;
|
||||
|
||||
.column-2 {
|
||||
.column-1 {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.brand {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.landing-page__features {
|
||||
.column-2 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,241 +1,98 @@
|
|||
.card {
|
||||
background-color: $base-shadow-color;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
border-radius: 4px 4px 0 0;
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
||||
&::after {
|
||||
background: rgba(darken($ui-base-color, 8%), 0.5);
|
||||
& > a {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 740px) {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.card__illustration {
|
||||
padding: 60px 0;
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.card__bio {
|
||||
max-width: 260px;
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background: rgba(darken($ui-base-color, 8%), 0.8);
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&.compact {
|
||||
padding: 30px 0;
|
||||
border-radius: 4px;
|
||||
|
||||
.avatar {
|
||||
margin-bottom: 0;
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
display: block;
|
||||
font-size: 20px;
|
||||
line-height: 18px * 1.5;
|
||||
color: $primary-text-color;
|
||||
padding: 10px 15px;
|
||||
padding-bottom: 0;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
margin-bottom: 30px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
small {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: $highlight-text-color;
|
||||
font-weight: 400;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
.fa {
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
display: block;
|
||||
border-radius: 120px;
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.roles {
|
||||
margin-bottom: 30px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.details-counters {
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.counter {
|
||||
width: 33.3%;
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 auto;
|
||||
color: $darker-text-color;
|
||||
padding: 5px 10px 0;
|
||||
margin-bottom: 10px;
|
||||
border-right: 1px solid lighten($ui-base-color, 4%);
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -10px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-bottom: 4px solid $ui-primary-color;
|
||||
opacity: 0.5;
|
||||
transition: all 400ms ease;
|
||||
}
|
||||
|
||||
&.active {
|
||||
&::after {
|
||||
border-bottom: 4px solid $highlight-text-color;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
opacity: 1;
|
||||
transition-duration: 100ms;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
|
||||
.counter-label {
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.counter-number {
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
color: $primary-text-color;
|
||||
font-family: 'mastodon-font-display', sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
.bio {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
padding: 0 15px;
|
||||
color: $secondary-text-color;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
display: block;
|
||||
|
||||
.card__bio {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.name,
|
||||
.roles {
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.bio {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card,
|
||||
.account-grid-card {
|
||||
.controls {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
z-index: 2;
|
||||
|
||||
.icon-button {
|
||||
color: rgba($white, 0.8);
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
font-weight: 500;
|
||||
|
||||
.fa {
|
||||
font-weight: 400;
|
||||
margin-right: 5px;
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: $white;
|
||||
.card__bar {
|
||||
background: lighten($ui-base-color, 8%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.account-grid-card .controls {
|
||||
left: auto;
|
||||
right: 15px;
|
||||
&__img {
|
||||
height: 130px;
|
||||
position: relative;
|
||||
background: darken($ui-base-color, 12%);
|
||||
border-radius: 4px 4px 0 0;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
object-fit: cover;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__bar {
|
||||
position: relative;
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
background: lighten($ui-base-color, 4%);
|
||||
border-radius: 0 0 4px 4px;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
flex: 0 0 auto;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
padding-top: 2px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
margin: 0;
|
||||
border-radius: 4px;
|
||||
background: darken($ui-base-color, 8%);
|
||||
}
|
||||
}
|
||||
|
||||
.display-name {
|
||||
margin-left: 15px;
|
||||
text-align: left;
|
||||
|
||||
strong {
|
||||
font-size: 15px;
|
||||
color: $primary-text-color;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: $darker-text-color;
|
||||
font-weight: 400;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
|
@ -314,289 +171,23 @@
|
|||
}
|
||||
}
|
||||
|
||||
.accounts-grid {
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
background: darken($simple-background-color, 8%);
|
||||
border-radius: 0 0 4px 4px;
|
||||
padding: 20px 5px;
|
||||
padding-bottom: 10px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
|
||||
&.empty img {
|
||||
position: absolute;
|
||||
opacity: 0.2;
|
||||
height: 200px;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 740px) {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.account-grid-card {
|
||||
box-sizing: border-box;
|
||||
width: 335px;
|
||||
background: $simple-background-color;
|
||||
border-radius: 4px;
|
||||
color: $inverted-text-color;
|
||||
margin: 0 5px 10px;
|
||||
position: relative;
|
||||
|
||||
@media screen and (max-width: 740px) {
|
||||
width: calc(100% - 10px);
|
||||
}
|
||||
|
||||
.account-grid-card__header {
|
||||
overflow: hidden;
|
||||
height: 100px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
background-color: lighten($inverted-text-color, 4%);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
background: rgba(darken($ui-base-color, 8%), 0.5);
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.account-grid-card__avatar {
|
||||
box-sizing: border-box;
|
||||
padding: 15px;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 100px - (40px + 2px);
|
||||
left: -2px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 80px;
|
||||
border: 2px solid $simple-background-color;
|
||||
background: $simple-background-color;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
padding: 15px;
|
||||
padding-top: 10px;
|
||||
padding-left: 15px + 80px + 15px;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
color: $inverted-text-color;
|
||||
text-decoration: none;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
.display_name {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.display_name {
|
||||
font-size: 16px;
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.username {
|
||||
color: $lighter-text-color;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.account__header__content {
|
||||
padding: 10px 15px;
|
||||
padding-top: 15px;
|
||||
color: $lighter-text-color;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
height: 5.5em;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
display: block;
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to bottom, rgba($simple-background-color, 0.01) 0%, rgba($simple-background-color, 1) 100%);
|
||||
left: 0;
|
||||
border-radius: 0 0 4px 4px;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nothing-here {
|
||||
width: 100%;
|
||||
display: block;
|
||||
color: $light-text-color;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
padding: 130px 0;
|
||||
padding-top: 125px;
|
||||
margin: 0 auto;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.account-card {
|
||||
border-radius: 4px;
|
||||
text-align: left;
|
||||
background: $ui-base-color;
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
background: $simple-background-color;
|
||||
|
||||
&__header {
|
||||
background: $base-shadow-color;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
height: 90px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
& > .detailed-status__display-name {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
& > div:first-child {
|
||||
flex: 0 0 auto;
|
||||
margin-right: 10px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.display-name {
|
||||
flex: 1 0 auto;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
cursor: default;
|
||||
|
||||
& > .detailed-status__display-name {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 500;
|
||||
color: $ui-base-color;
|
||||
|
||||
@each $lang in $cjk-langs {
|
||||
&:lang(#{$lang}) {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
color: $light-text-color;
|
||||
font-size: 14px;
|
||||
color: $light-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.display-name {
|
||||
strong {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.counter {
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 auto;
|
||||
color: $light-text-color;
|
||||
padding: 0 10px;
|
||||
cursor: default;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
line-height: 24px;
|
||||
|
||||
.counter-label {
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.counter-number {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: $inverted-text-color;
|
||||
font-family: 'mastodon-font-display', sans-serif;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.activity-stream-tabs {
|
||||
background: $simple-background-color;
|
||||
border-bottom: 1px solid $ui-secondary-color;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: 15px;
|
||||
text-decoration: none;
|
||||
color: $highlight-text-color;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: lighten($highlight-text-color, 8%);
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: $inverted-text-color;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -629,14 +220,14 @@
|
|||
padding: 0;
|
||||
margin: 15px -15px -15px;
|
||||
border: 0 none;
|
||||
border-top: 1px solid lighten($ui-base-color, 4%);
|
||||
border-bottom: 1px solid lighten($ui-base-color, 4%);
|
||||
border-top: 1px solid lighten($ui-base-color, 12%);
|
||||
border-bottom: 1px solid lighten($ui-base-color, 12%);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
|
||||
dl {
|
||||
display: flex;
|
||||
border-bottom: 1px solid lighten($ui-base-color, 4%);
|
||||
border-bottom: 1px solid lighten($ui-base-color, 12%);
|
||||
}
|
||||
|
||||
dt,
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
body {
|
||||
font-family: 'mastodon-font-sans-serif', sans-serif;
|
||||
background: $ui-base-color;
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
background: darken($ui-base-color, 8%);
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
font-weight: 400;
|
||||
color: $primary-text-color;
|
||||
padding-bottom: 20px;
|
||||
text-rendering: optimizelegibility;
|
||||
font-feature-settings: "kern";
|
||||
text-size-adjust: none;
|
||||
|
@ -35,16 +32,24 @@ body {
|
|||
height: 100%;
|
||||
padding: 0;
|
||||
background: $ui-base-color;
|
||||
|
||||
&.with-modals--active {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.about-body {
|
||||
background: darken($ui-base-color, 8%);
|
||||
padding-bottom: 0;
|
||||
&.lighter {
|
||||
background: $ui-base-color;
|
||||
}
|
||||
|
||||
&.tag-body {
|
||||
background: darken($ui-base-color, 8%);
|
||||
padding-bottom: 0;
|
||||
&.with-modals {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
&--active {
|
||||
overflow-y: hidden;
|
||||
margin-right: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
&.player {
|
||||
|
@ -52,7 +57,7 @@ body {
|
|||
}
|
||||
|
||||
&.embed {
|
||||
background: transparent;
|
||||
background: lighten($ui-base-color, 4%);
|
||||
margin: 0;
|
||||
padding-bottom: 0;
|
||||
|
||||
|
|
|
@ -946,6 +946,18 @@
|
|||
background: lighten($ui-base-color, 4%);
|
||||
padding: 14px 10px;
|
||||
|
||||
&--flex {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
.status__content,
|
||||
.detailed-status__meta {
|
||||
flex: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.status__content {
|
||||
font-size: 19px;
|
||||
line-height: 24px;
|
||||
|
@ -1224,7 +1236,6 @@ a .account__avatar {
|
|||
}
|
||||
|
||||
.account__action-bar-dropdown {
|
||||
flex: 0 1 calc(50% - 140px);
|
||||
padding: 10px;
|
||||
|
||||
.icon-button {
|
||||
|
@ -1256,9 +1267,9 @@ a .account__avatar {
|
|||
.account__action-bar__tab {
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
flex: 0 1 80px;
|
||||
flex: 0 1 100%;
|
||||
border-right: 1px solid lighten($ui-base-color, 8%);
|
||||
padding: 10px 5px;
|
||||
padding: 10px 0;
|
||||
|
||||
& > span {
|
||||
display: block;
|
||||
|
|
|
@ -60,10 +60,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.media-standalone__body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.account-header {
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
|
@ -118,3 +114,576 @@
|
|||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.public-layout {
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
padding-top: 48px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 960px;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
background: lighten($ui-base-color, 8%);
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
border-radius: 4px;
|
||||
height: 48px;
|
||||
margin: 10px 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
z-index: 110;
|
||||
}
|
||||
|
||||
& > div {
|
||||
flex: 1 1 33.3%;
|
||||
min-height: 1px;
|
||||
}
|
||||
|
||||
.nav-left {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.nav-center {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: flex-end;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: block;
|
||||
padding: 15px;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
height: 18px;
|
||||
width: auto;
|
||||
position: relative;
|
||||
bottom: -2px;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
background: lighten($ui-base-color, 12%);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
color: $darker-text-color;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
text-decoration: underline;
|
||||
color: $primary-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-button {
|
||||
background: lighten($ui-base-color, 16%);
|
||||
margin: 8px;
|
||||
margin-left: 0;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
text-decoration: none;
|
||||
background: lighten($ui-base-color, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$no-columns-breakpoint: 600px;
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-gap: 10px;
|
||||
grid-template-columns: minmax(300px, 3fr) minmax(298px, 1fr);
|
||||
grid-auto-columns: 25%;
|
||||
grid-auto-rows: max-content;
|
||||
|
||||
.column-0 {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.column-1 {
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-columns-breakpoint) {
|
||||
grid-template-columns: 100%;
|
||||
grid-gap: 0;
|
||||
|
||||
.column-1 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.public-account-header {
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
|
||||
&__image {
|
||||
border-radius: 4px 4px 0 0;
|
||||
overflow: hidden;
|
||||
height: 300px;
|
||||
position: relative;
|
||||
background: darken($ui-base-color, 12%);
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-shadow: inset 0 -1px 1px 1px rgba($base-shadow-color, 0.15);
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
margin-bottom: 0;
|
||||
box-shadow: none;
|
||||
|
||||
&__image::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__image,
|
||||
&__image img {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__bar {
|
||||
position: relative;
|
||||
margin-top: -80px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
background: lighten($ui-base-color, 4%);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 60px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: block;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
padding-left: 20px - 4px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
border-radius: 50%;
|
||||
border: 4px solid lighten($ui-base-color, 4%);
|
||||
background: darken($ui-base-color, 8%);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
margin-top: 0;
|
||||
background: lighten($ui-base-color, 4%);
|
||||
border-radius: 0 0 4px 4px;
|
||||
padding: 5px;
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
padding: 7px 0;
|
||||
padding-left: 10px;
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 360px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-columns-breakpoint) {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
&__tabs {
|
||||
flex: 1 1 auto;
|
||||
margin-left: 20px;
|
||||
|
||||
&__name {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 8px;
|
||||
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
line-height: 18px * 1.5;
|
||||
color: $primary-text-color;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
text-shadow: 1px 1px 1px $base-shadow-color;
|
||||
|
||||
small {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: $primary-text-color;
|
||||
font-weight: 400;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
margin-left: 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&__name {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
text-shadow: none;
|
||||
|
||||
small {
|
||||
color: $darker-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__tabs {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
height: 58px;
|
||||
|
||||
.details-counters {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-columns-breakpoint) {
|
||||
.details-counters {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.counter {
|
||||
width: 33.3%;
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 auto;
|
||||
color: $darker-text-color;
|
||||
padding: 10px;
|
||||
border-right: 1px solid lighten($ui-base-color, 4%);
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-bottom: 4px solid $ui-primary-color;
|
||||
opacity: 0.5;
|
||||
transition: all 400ms ease;
|
||||
}
|
||||
|
||||
&.active {
|
||||
&::after {
|
||||
border-bottom: 4px solid $highlight-text-color;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
opacity: 1;
|
||||
transition-duration: 100ms;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.counter-label {
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.counter-number {
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
margin-bottom: 5px;
|
||||
color: $primary-text-color;
|
||||
font-family: 'mastodon-font-display', sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex: 1 1 auto;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
padding: 7px 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__extra {
|
||||
display: none;
|
||||
margin-top: 4px;
|
||||
|
||||
.public-account-bio {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
margin: 0 -5px;
|
||||
|
||||
.account__header__fields {
|
||||
border-top: 1px solid lighten($ui-base-color, 12%);
|
||||
}
|
||||
|
||||
.roles {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__links {
|
||||
margin-top: -15px;
|
||||
font-size: 14px;
|
||||
color: $darker-text-color;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
color: $darker-text-color;
|
||||
text-decoration: none;
|
||||
padding: 15px;
|
||||
|
||||
strong {
|
||||
font-weight: 700;
|
||||
color: $primary-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-columns-breakpoint) {
|
||||
display: block;
|
||||
flex: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.account__section-headline {
|
||||
border-radius: 4px 4px 0 0;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.detailed-status__meta {
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.public-account-bio {
|
||||
background: lighten($ui-base-color, 8%);
|
||||
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) {
|
||||
box-shadow: none;
|
||||
margin-bottom: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.account__header__fields {
|
||||
margin: 0;
|
||||
border-top: 0;
|
||||
|
||||
a {
|
||||
color: lighten($ui-highlight-color, 8%);
|
||||
}
|
||||
}
|
||||
|
||||
.account__header__content {
|
||||
padding: 20px;
|
||||
padding-bottom: 0;
|
||||
color: $primary-text-color;
|
||||
}
|
||||
|
||||
&__extra,
|
||||
.roles {
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
color: $darker-text-color;
|
||||
}
|
||||
|
||||
.roles {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.static-icon-button {
|
||||
color: $action-button-color;
|
||||
font-size: 18px;
|
||||
|
||||
& > span {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
min-width: 100%;
|
||||
margin: 0 -5px;
|
||||
|
||||
& > div {
|
||||
box-sizing: border-box;
|
||||
flex: 1 0 auto;
|
||||
width: 300px;
|
||||
padding: 0 5px;
|
||||
margin-bottom: 10px;
|
||||
max-width: 33.333%;
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
margin: 0;
|
||||
border-top: 1px solid lighten($ui-base-color, 8%);
|
||||
|
||||
& > div {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.card__bar {
|
||||
background: $ui-base-color;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background: lighten($ui-base-color, 4%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,140 @@
|
|||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
.public-layout {
|
||||
.footer {
|
||||
text-align: left;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 60px;
|
||||
font-size: 12px;
|
||||
color: lighten($ui-base-color, 34%);
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-gap: 10px;
|
||||
grid-template-columns: 1fr 1fr 2fr 1fr 1fr;
|
||||
|
||||
.column-0 {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.column-1 {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.column-2 {
|
||||
grid-column: 3;
|
||||
grid-row: 1;
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
|
||||
h4 a {
|
||||
color: lighten($ui-base-color, 34%);
|
||||
}
|
||||
}
|
||||
|
||||
.column-3 {
|
||||
grid-column: 4;
|
||||
grid-row: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.column-4 {
|
||||
grid-column: 5;
|
||||
grid-row: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 690px) {
|
||||
grid-template-columns: 1fr 2fr 1fr;
|
||||
|
||||
.column-0,
|
||||
.column-1 {
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.column-1 {
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.column-2 {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.column-3,
|
||||
.column-4 {
|
||||
grid-column: 3;
|
||||
}
|
||||
|
||||
.column-4 {
|
||||
grid-row: 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.column-1 {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
.column-0,
|
||||
.column-1,
|
||||
.column-3,
|
||||
.column-4 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: $darker-text-color;
|
||||
|
||||
.footer__domain {
|
||||
font-weight: 500;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.powered-by,
|
||||
.single-user-login {
|
||||
font-weight: 400;
|
||||
ul a {
|
||||
text-decoration: none;
|
||||
color: lighten($ui-base-color, 34%);
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
text-decoration: underline;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
margin: 0 4px;
|
||||
position: relative;
|
||||
bottom: -1px;
|
||||
height: 18px;
|
||||
vertical-align: top;
|
||||
.brand {
|
||||
svg {
|
||||
display: block;
|
||||
height: 36px;
|
||||
width: auto;
|
||||
margin: 0 auto;
|
||||
|
||||
path {
|
||||
fill: lighten($ui-base-color, 34%);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
svg path {
|
||||
fill: lighten($ui-base-color, 38%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
.landing-strip,
|
||||
.memoriam-strip {
|
||||
background: rgba(darken($ui-base-color, 7%), 0.8);
|
||||
color: $darker-text-color;
|
||||
font-weight: 400;
|
||||
padding: 14px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
strong,
|
||||
a {
|
||||
font-weight: 500;
|
||||
|
||||
@each $lang in $cjk-langs {
|
||||
&:lang(#{$lang}) {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
flex: 0 0 auto;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 740px) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.memoriam-strip {
|
||||
background: rgba($base-shadow-color, 0.7);
|
||||
}
|
||||
|
||||
.moved-strip {
|
||||
padding: 14px;
|
||||
border-radius: 4px;
|
||||
background: rgba(darken($ui-base-color, 7%), 0.8);
|
||||
color: $secondary-text-color;
|
||||
font-weight: 400;
|
||||
margin-bottom: 20px;
|
||||
|
||||
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: $darker-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__card {
|
||||
.detailed-status__display-avatar {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.detailed-status__display-name {
|
||||
margin-bottom: 0;
|
||||
text-decoration: none;
|
||||
|
||||
span {
|
||||
color: $highlight-text-color;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,336 +1,79 @@
|
|||
.activity-stream {
|
||||
clear: both;
|
||||
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: $simple-background-color;
|
||||
background: $ui-base-color;
|
||||
|
||||
.detailed-status.light,
|
||||
.status.light,
|
||||
.more.light {
|
||||
border-bottom: 1px solid $ui-secondary-color;
|
||||
.detailed-status,
|
||||
.status,
|
||||
.load-more {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&,
|
||||
.detailed-status.light,
|
||||
.status.light {
|
||||
.detailed-status,
|
||||
.status {
|
||||
border-bottom: 0;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
&,
|
||||
.detailed-status.light,
|
||||
.status.light {
|
||||
.detailed-status,
|
||||
.status {
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&,
|
||||
.detailed-status.light,
|
||||
.status.light {
|
||||
.detailed-status,
|
||||
.status {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 740px) {
|
||||
&,
|
||||
.detailed-status.light,
|
||||
.status.light {
|
||||
.detailed-status,
|
||||
.status {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.with-header {
|
||||
.entry {
|
||||
&:first-child {
|
||||
&,
|
||||
.detailed-status.light,
|
||||
.status.light {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&,
|
||||
.detailed-status.light,
|
||||
.status.light {
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.media-gallery__gifv__label {
|
||||
bottom: 9px;
|
||||
}
|
||||
|
||||
.status.light {
|
||||
padding: 14px 14px 14px (48px + 14px * 2);
|
||||
position: relative;
|
||||
min-height: 48px;
|
||||
cursor: default;
|
||||
|
||||
.status__header {
|
||||
font-size: 15px;
|
||||
|
||||
.status__meta {
|
||||
float: right;
|
||||
font-size: 14px;
|
||||
|
||||
.status__relative-time {
|
||||
color: $lighter-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status__display-name {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
padding-right: 25px;
|
||||
color: $inverted-text-color;
|
||||
}
|
||||
|
||||
.status__avatar {
|
||||
position: absolute;
|
||||
left: 14px;
|
||||
top: 14px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
|
||||
& > div {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.display-name {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
strong {
|
||||
font-weight: 500;
|
||||
color: $inverted-text-color;
|
||||
|
||||
@each $lang in $cjk-langs {
|
||||
&:lang(#{$lang}) {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 14px;
|
||||
color: $light-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.status__content {
|
||||
color: $inverted-text-color;
|
||||
|
||||
a {
|
||||
color: $highlight-text-color;
|
||||
}
|
||||
|
||||
a.status__content__spoiler-link {
|
||||
color: $primary-text-color;
|
||||
background: $ui-base-color;
|
||||
|
||||
&:hover {
|
||||
background: lighten($ui-base-color, 8%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detailed-status.light {
|
||||
padding: 14px;
|
||||
background: $simple-background-color;
|
||||
cursor: default;
|
||||
|
||||
.detailed-status__display-name {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin-bottom: 15px;
|
||||
|
||||
& > div {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.display-name {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
strong {
|
||||
font-weight: 500;
|
||||
color: $inverted-text-color;
|
||||
|
||||
@each $lang in $cjk-langs {
|
||||
&:lang(#{$lang}) {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 14px;
|
||||
color: $light-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.status__content {
|
||||
color: $inverted-text-color;
|
||||
|
||||
a {
|
||||
color: $highlight-text-color;
|
||||
}
|
||||
|
||||
a.status__content__spoiler-link {
|
||||
color: $primary-text-color;
|
||||
background: $ui-base-color;
|
||||
|
||||
&:hover {
|
||||
background: lighten($ui-base-color, 8%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detailed-status__meta {
|
||||
margin-top: 15px;
|
||||
color: $light-text-color;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
span > span {
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
margin-left: 6px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.status-card {
|
||||
border-color: lighten($ui-secondary-color, 4%);
|
||||
color: $lighter-text-color;
|
||||
|
||||
&:hover {
|
||||
background: lighten($ui-secondary-color, 4%);
|
||||
}
|
||||
}
|
||||
|
||||
.status-card__title,
|
||||
.status-card__description {
|
||||
color: $inverted-text-color;
|
||||
}
|
||||
|
||||
.status-card__image {
|
||||
background: $ui-secondary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.media-spoiler {
|
||||
background: $ui-base-color;
|
||||
color: $darker-text-color;
|
||||
}
|
||||
|
||||
.pre-header {
|
||||
padding: 14px 0;
|
||||
padding-left: (48px + 14px * 2);
|
||||
padding-bottom: 0;
|
||||
margin-bottom: -4px;
|
||||
color: $light-text-color;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
|
||||
.pre-header__icon {
|
||||
position: absolute;
|
||||
left: (48px + 14px * 2 - 30px);
|
||||
}
|
||||
|
||||
.status__display-name.muted strong {
|
||||
color: $light-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.open-in-web-link {
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.more {
|
||||
color: $darker-text-color;
|
||||
display: block;
|
||||
padding: 14px;
|
||||
text-align: center;
|
||||
|
||||
&:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.embed {
|
||||
.activity-stream {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.entry {
|
||||
.detailed-status.light {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
.detailed-status__display-name {
|
||||
flex: 1;
|
||||
margin: 0 5px 15px 0;
|
||||
}
|
||||
|
||||
.button.button-secondary.logo-button {
|
||||
.button.logo-button {
|
||||
flex: 0 auto;
|
||||
font-size: 14px;
|
||||
background: $ui-highlight-color;
|
||||
color: $primary-text-color;
|
||||
text-transform: none;
|
||||
line-height: 36px;
|
||||
height: auto;
|
||||
padding: 3px 15px;
|
||||
border: 0;
|
||||
|
||||
svg {
|
||||
|
@ -357,11 +100,46 @@
|
|||
fill: lighten($ui-highlight-color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status__content,
|
||||
.detailed-status__meta {
|
||||
flex: 100%;
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,3 +46,5 @@ $cjk-langs: ja, ko, zh-CN, zh-HK, zh-TW;
|
|||
$media-modal-media-max-width: 100%;
|
||||
// put margins on top and bottom of image to avoid the screen covered by image.
|
||||
$media-modal-media-max-height: 80%;
|
||||
|
||||
$no-gap-breakpoint: 415px;
|
||||
|
|
161
app/javascript/styles/mastodon/widgets.scss
Normal file
161
app/javascript/styles/mastodon/widgets.scss
Normal file
|
@ -0,0 +1,161 @@
|
|||
.hero-widget {
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
|
||||
&__img {
|
||||
width: 100%;
|
||||
height: 167px;
|
||||
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: $ui-base-color;
|
||||
padding: 20px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
font-size: 15px;
|
||||
color: $darker-text-color;
|
||||
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: lighten($darker-text-color, 10%);
|
||||
}
|
||||
|
||||
a {
|
||||
color: $secondary-text-color;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.moved-account-widget {
|
||||
padding: 15px;
|
||||
padding-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
background: $ui-base-color;
|
||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||
color: $secondary-text-color;
|
||||
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: $darker-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__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: $darker-text-color;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.moved-account-widget,
|
||||
.memoriam-widget {
|
||||
@media screen and (max-width: $no-gap-breakpoint) {
|
||||
margin-bottom: 0;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
|
|||
{
|
||||
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
||||
'sensitive' => 'as:sensitive',
|
||||
'movedTo' => 'as:movedTo',
|
||||
'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' },
|
||||
'Hashtag' => 'as:Hashtag',
|
||||
'ostatus' => 'http://ostatus.org#',
|
||||
'atomUri' => 'ostatus:atomUri',
|
||||
|
@ -18,7 +18,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
|
|||
'toot' => 'http://joinmastodon.org/ns#',
|
||||
'Emoji' => 'toot:Emoji',
|
||||
'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' },
|
||||
'featured' => 'toot:featured',
|
||||
'featured' => { '@id' => 'toot:featured', '@type' => '@id' },
|
||||
'schema' => 'http://schema.org#',
|
||||
'PropertyValue' => 'schema:PropertyValue',
|
||||
'value' => 'schema:value',
|
||||
|
|
|
@ -70,6 +70,7 @@ class Account < ApplicationRecord
|
|||
|
||||
# Remote user validations
|
||||
validates :username, uniqueness: { scope: :domain, case_sensitive: true }, if: -> { !local? && will_save_change_to_username? }
|
||||
validates :username, format: { with: /\A#{USERNAME_RE}\z/i }, if: -> { !local? && will_save_change_to_username? }
|
||||
|
||||
# Local user validations
|
||||
validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? }
|
||||
|
|
|
@ -5,11 +5,12 @@ module AccountHeader
|
|||
|
||||
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
|
||||
LIMIT = 2.megabytes
|
||||
MAX_PIXELS = 750_000 # 1500x500px
|
||||
|
||||
class_methods do
|
||||
def header_styles(file)
|
||||
styles = { original: { geometry: '700x335#', file_geometry_parser: FastGeometryParser } }
|
||||
styles[:static] = { geometry: '700x335#', format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif'
|
||||
styles = { original: { pixels: MAX_PIXELS, file_geometry_parser: FastGeometryParser } }
|
||||
styles[:static] = { format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif'
|
||||
styles
|
||||
end
|
||||
|
||||
|
|
|
@ -25,11 +25,12 @@ class MediaAttachment < ApplicationRecord
|
|||
enum type: [:image, :gifv, :video, :audio, :unknown]
|
||||
|
||||
IMAGE_FILE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif'].freeze
|
||||
VIDEO_FILE_EXTENSIONS = ['.webm', '.mp4', '.m4v'].freeze
|
||||
VIDEO_FILE_EXTENSIONS = ['.webm', '.mp4', '.m4v', '.mov'].freeze
|
||||
AUDIO_FILE_EXTENSIONS = ['.mp3', '.m4a', '.wav', '.ogg'].freeze
|
||||
|
||||
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
|
||||
VIDEO_MIME_TYPES = ['video/webm', 'video/mp4'].freeze
|
||||
VIDEO_MIME_TYPES = ['video/webm', 'video/mp4', 'video/quicktime'].freeze
|
||||
VIDEO_CONVERTIBLE_MIME_TYPES = ['video/webm', 'video/quicktime'].freeze
|
||||
AUDIO_MIME_TYPES = ['audio/mpeg', 'audio/mp4', 'audio/vnd.wav', 'audio/wav', 'audio/x-wav', 'audio/x-wave', 'audio/ogg',].freeze
|
||||
|
||||
IMAGE_STYLES = {
|
||||
|
@ -72,7 +73,25 @@ class MediaAttachment < ApplicationRecord
|
|||
},
|
||||
}.freeze
|
||||
|
||||
LIMIT = 8.megabytes
|
||||
VIDEO_FORMAT = {
|
||||
format: 'mp4',
|
||||
convert_options: {
|
||||
output: {
|
||||
'movflags' => 'faststart',
|
||||
'pix_fmt' => 'yuv420p',
|
||||
'vf' => 'scale=\'trunc(iw/2)*2:trunc(ih/2)*2\'',
|
||||
'vsync' => 'cfr',
|
||||
'c:v' => 'h264',
|
||||
'b:v' => '500K',
|
||||
'maxrate' => '1300K',
|
||||
'bufsize' => '1300K',
|
||||
'crf' => 18,
|
||||
},
|
||||
},
|
||||
}.freeze
|
||||
|
||||
IMAGE_LIMIT = 8.megabytes
|
||||
VIDEO_LIMIT = 40.megabytes
|
||||
|
||||
belongs_to :account, inverse_of: :media_attachments, optional: true
|
||||
belongs_to :status, inverse_of: :media_attachments, optional: true
|
||||
|
@ -82,11 +101,10 @@ class MediaAttachment < ApplicationRecord
|
|||
processors: ->(f) { file_processors f },
|
||||
convert_options: { all: '-quality 90 -strip' }
|
||||
|
||||
include Remotable
|
||||
|
||||
validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES + AUDIO_MIME_TYPES
|
||||
validates_attachment_size :file, less_than: LIMIT
|
||||
remotable_attachment :file, LIMIT
|
||||
validates_attachment_size :file, less_than: IMAGE_LIMIT, unless: :video?
|
||||
validates_attachment_size :file, less_than: VIDEO_LIMIT, if: :video?
|
||||
remotable_attachment :file, VIDEO_LIMIT
|
||||
|
||||
include Attachmentable
|
||||
|
||||
|
@ -142,27 +160,17 @@ class MediaAttachment < ApplicationRecord
|
|||
if f.instance.file_content_type == 'image/gif'
|
||||
{
|
||||
small: IMAGE_STYLES[:small],
|
||||
original: {
|
||||
format: 'mp4',
|
||||
convert_options: {
|
||||
output: {
|
||||
'movflags' => 'faststart',
|
||||
'pix_fmt' => 'yuv420p',
|
||||
'vf' => 'scale=\'trunc(iw/2)*2:trunc(ih/2)*2\'',
|
||||
'vsync' => 'cfr',
|
||||
'c:v' => 'h264',
|
||||
'b:v' => '500K',
|
||||
'maxrate' => '1300K',
|
||||
'bufsize' => '1300K',
|
||||
'crf' => 18,
|
||||
},
|
||||
},
|
||||
},
|
||||
original: VIDEO_FORMAT,
|
||||
}
|
||||
elsif IMAGE_MIME_TYPES.include? f.instance.file_content_type
|
||||
IMAGE_STYLES
|
||||
elsif AUDIO_MIME_TYPES.include? f.instance.file_content_type
|
||||
AUDIO_STYLES
|
||||
elsif VIDEO_CONVERTIBLE_MIME_TYPES.include?(f.instance.file_content_type)
|
||||
{
|
||||
small: VIDEO_STYLES[:small],
|
||||
original: VIDEO_FORMAT,
|
||||
}
|
||||
else
|
||||
VIDEO_STYLES
|
||||
end
|
||||
|
|
|
@ -7,14 +7,14 @@ class ActivityPub::FetchRemoteAccountService < BaseService
|
|||
|
||||
# Should be called when uri has already been checked for locality
|
||||
# Does a WebFinger roundtrip on each call
|
||||
def call(uri, id: true, prefetched_body: nil)
|
||||
def call(uri, id: true, prefetched_body: nil, break_on_redirect: false)
|
||||
@json = if prefetched_body.nil?
|
||||
fetch_resource(uri, id)
|
||||
else
|
||||
body_to_json(prefetched_body)
|
||||
end
|
||||
|
||||
return unless supported_context? && expected_type?
|
||||
return if !supported_context? || !expected_type? || (break_on_redirect && @json['movedTo'].present?)
|
||||
|
||||
@uri = @json['id']
|
||||
@username = @json['preferredUsername']
|
||||
|
|
|
@ -175,7 +175,7 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||
|
||||
def moved_account
|
||||
account = ActivityPub::TagManager.instance.uri_to_resource(@json['movedTo'], Account)
|
||||
account ||= ActivityPub::FetchRemoteAccountService.new.call(@json['movedTo'], id: true)
|
||||
account ||= ActivityPub::FetchRemoteAccountService.new.call(@json['movedTo'], id: true, break_on_redirect: true)
|
||||
account
|
||||
end
|
||||
|
||||
|
|
15
app/views/accounts/_bio.html.haml
Normal file
15
app/views/accounts/_bio.html.haml
Normal file
|
@ -0,0 +1,15 @@
|
|||
.public-account-bio
|
||||
- unless account.fields.empty?
|
||||
.account__header__fields
|
||||
- account.fields.each do |field|
|
||||
%dl
|
||||
%dt.emojify{ title: field.name }= field.name
|
||||
%dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value, custom_emojify: true)
|
||||
|
||||
= account_badge(account)
|
||||
|
||||
- if account.note.present?
|
||||
.account__header__content.emojify= Formatter.instance.simplified_format(account, custom_emojify: true)
|
||||
|
||||
.public-account-bio__extra
|
||||
= t 'accounts.joined', date: l(account.created_at, format: :month)
|
|
@ -1,28 +0,0 @@
|
|||
- relationships ||= nil
|
||||
|
||||
- unless account.memorial? || account.moved?
|
||||
- if user_signed_in?
|
||||
- requested = relationships ? relationships.requested[account.id].present? : current_account.requested?(account)
|
||||
- following = relationships ? relationships.following[account.id].present? : current_account.following?(account)
|
||||
|
||||
- if user_signed_in? && current_account.id != account.id && !requested
|
||||
.controls
|
||||
- if following
|
||||
= link_to (account.local? ? account_unfollow_path(account) : remote_unfollow_path(acct: account.acct)), data: { method: :post }, class: 'icon-button' do
|
||||
= fa_icon 'user-times'
|
||||
= t('accounts.unfollow')
|
||||
- else
|
||||
= link_to (account.local? ? account_follow_path(account) : authorize_follow_path(acct: account.acct)), data: { method: :post }, class: 'icon-button' do
|
||||
= fa_icon 'user-plus'
|
||||
= t('accounts.follow')
|
||||
- elsif user_signed_in? && current_account.id == account.id
|
||||
.controls
|
||||
= link_to settings_profile_url, class: 'icon-button' do
|
||||
= fa_icon 'pencil'
|
||||
= t('settings.edit_profile')
|
||||
- elsif !user_signed_in?
|
||||
.controls
|
||||
.remote-follow
|
||||
= link_to (account.local? ? account_remote_follow_path(account) : "web+mastodon://follow?uri=#{account.uri}"), class: 'icon-button' do
|
||||
= fa_icon 'user-plus'
|
||||
= t('accounts.remote_follow')
|
|
@ -1,8 +0,0 @@
|
|||
.accounts-grid{ class: accounts.empty? ? 'empty' : '' }
|
||||
- if accounts.empty?
|
||||
= image_tag asset_pack_path('elephant_ui_greeting.svg'), alt: '', role: 'presentational'
|
||||
= render partial: 'accounts/nothing_here'
|
||||
- else
|
||||
= render partial: 'accounts/grid_card', collection: accounts, as: :account, cached: !user_signed_in?
|
||||
|
||||
= paginate follows
|
|
@ -1,3 +0,0 @@
|
|||
.accounts-grid.empty
|
||||
= image_tag asset_pack_path('elephant_ui_greeting.svg'), alt: '', role: 'presentational'
|
||||
%p.nothing-here= t('accounts.network_hidden')
|
|
@ -1,12 +0,0 @@
|
|||
.account-grid-card
|
||||
.account-grid-card__header{ style: "background-image: url(#{account.header.url(:original)})" }
|
||||
= render 'accounts/follow_button', account: account, relationships: @relationships
|
||||
.account-grid-card__avatar
|
||||
.avatar= image_tag account.avatar.url(:original)
|
||||
.name
|
||||
= link_to TagManager.instance.url_for(account) do
|
||||
%span.display_name.emojify= display_name(account, custom_emojify: true)
|
||||
%span.username
|
||||
@#{account.local? ? account.local_username_and_domain : account.acct}
|
||||
= fa_icon('lock') if account.locked?
|
||||
.account__header__content.p-note.emojify= Formatter.instance.simplified_format(account)
|
|
@ -1,39 +1,17 @@
|
|||
.card.h-card.p-author{ style: "background-image: url(#{account.header.url(:original)})" }
|
||||
.card__illustration
|
||||
= render 'accounts/follow_button', account: account
|
||||
.avatar= image_tag account.avatar.url(:original), class: 'u-photo'
|
||||
|
||||
.card__bio
|
||||
%h1.name
|
||||
%span.p-name.emojify= display_name(account, custom_emojify: true)
|
||||
%small<
|
||||
%span>< @#{account.local_username_and_domain}
|
||||
.public-account-header
|
||||
.public-account-header__image
|
||||
= image_tag account.header.url, class: 'parallax'
|
||||
.public-account-header__bar
|
||||
= link_to short_account_url(account), class: 'avatar' do
|
||||
= image_tag account.avatar.url
|
||||
.public-account-header__tabs
|
||||
.public-account-header__tabs__name
|
||||
%h1
|
||||
= display_name(account)
|
||||
%small
|
||||
= acct(account)
|
||||
= fa_icon('lock') if account.locked?
|
||||
|
||||
- if account.bot?
|
||||
.roles
|
||||
.account-role.bot
|
||||
= t 'accounts.roles.bot'
|
||||
- elsif Setting.show_staff_badge
|
||||
- if account.user_admin?
|
||||
.roles
|
||||
.account-role.admin
|
||||
= t 'accounts.roles.admin'
|
||||
- elsif account.user_moderator?
|
||||
.roles
|
||||
.account-role.moderator
|
||||
= t 'accounts.roles.moderator'
|
||||
|
||||
.bio
|
||||
.account__header__content.p-note.emojify= Formatter.instance.simplified_format(account, custom_emojify: true)
|
||||
|
||||
- unless account.fields.empty?
|
||||
.account__header__fields
|
||||
- account.fields.each do |field|
|
||||
%dl
|
||||
%dt.emojify{ title: field.name }= field.name
|
||||
%dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value, custom_emojify: true)
|
||||
|
||||
.public-account-header__tabs__tabs
|
||||
.details-counters
|
||||
.counter{ class: active_nav_class(short_account_url(account)) }
|
||||
= link_to short_account_url(account), class: 'u-url u-uid' do
|
||||
|
@ -49,3 +27,17 @@
|
|||
= link_to account_followers_url(account) do
|
||||
%span.counter-number= number_to_human account.followers_count, strip_insignificant_zeros: true
|
||||
%span.counter-label= t('accounts.followers')
|
||||
.spacer
|
||||
.public-account-header__tabs__tabs__buttons
|
||||
= account_action_button(account)
|
||||
|
||||
.public-account-header__extra
|
||||
= render 'accounts/bio', account: account
|
||||
|
||||
.public-account-header__extra__links
|
||||
= link_to account_following_index_url(account) do
|
||||
%strong= number_to_human account.following_count, strip_insignificant_zeros: true
|
||||
= t('accounts.following')
|
||||
= link_to account_followers_url(account) do
|
||||
%strong= number_to_human account.followers_count, strip_insignificant_zeros: true
|
||||
= t('accounts.followers')
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
- moved_to_account = account.moved_to_account
|
||||
|
||||
.moved-strip
|
||||
.moved-strip__message
|
||||
.moved-account-widget
|
||||
.moved-account-widget__message
|
||||
= fa_icon 'suitcase'
|
||||
= t('accounts.moved_html', name: content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention'))
|
||||
= t('accounts.moved_html', name: content_tag(:bdi, content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify)), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention'))
|
||||
|
||||
.moved-strip__card
|
||||
.moved-account-widget__card
|
||||
= link_to TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
|
||||
.detailed-status__display-avatar
|
||||
.account__avatar-overlay
|
||||
|
@ -13,5 +13,6 @@
|
|||
.account__avatar-overlay-overlay{ style: "background-image: url('#{account.avatar.url(:original)}')" }
|
||||
|
||||
%span.display-name
|
||||
%bdi
|
||||
%strong.emojify= display_name(moved_to_account, custom_emojify: true)
|
||||
%span @#{moved_to_account.acct}
|
|
@ -1 +0,0 @@
|
|||
%p.nothing-here= t('accounts.nothing_here')
|
|
@ -20,36 +20,39 @@
|
|||
= opengraph 'og:type', 'profile'
|
||||
= render 'og', account: @account, url: short_account_url(@account, only_path: false)
|
||||
|
||||
- if @account.memorial?
|
||||
.memoriam-strip= t('in_memoriam_html')
|
||||
- elsif @account.moved?
|
||||
= render partial: 'moved_strip', locals: { account: @account }
|
||||
- elsif show_landing_strip?
|
||||
= render partial: 'shared/landing_strip', locals: { account: @account }
|
||||
|
||||
.h-feed
|
||||
= render 'header', account: @account, with_bio: true
|
||||
|
||||
.grid
|
||||
.column-0
|
||||
.h-feed
|
||||
%data.p-name{ value: "#{@account.username} on #{site_hostname}" }/
|
||||
|
||||
= render 'header', account: @account
|
||||
|
||||
.activity-stream-tabs
|
||||
.account__section-headline
|
||||
= active_link_to t('accounts.posts'), short_account_url(@account)
|
||||
= active_link_to t('accounts.posts_with_replies'), short_account_with_replies_url(@account)
|
||||
= active_link_to t('accounts.media'), short_account_media_url(@account)
|
||||
|
||||
- if @statuses.empty?
|
||||
.accounts-grid
|
||||
= render 'nothing_here'
|
||||
= nothing_here 'nothing-here--under-tabs'
|
||||
- else
|
||||
.activity-stream.with-header
|
||||
.activity-stream
|
||||
- if params[:page].to_i.zero?
|
||||
= render partial: 'stream_entries/status', collection: @pinned_statuses, as: :status, locals: { pinned: true }
|
||||
|
||||
- if @newer_url
|
||||
.entry= link_to_more @newer_url
|
||||
|
||||
= render partial: 'stream_entries/status', collection: @statuses, as: :status
|
||||
|
||||
- if @newer_url || @older_url
|
||||
.pagination
|
||||
- if @older_url
|
||||
= link_to safe_join([fa_icon('chevron-left'), t('pagination.older')], ' '), @older_url, class: 'older', rel: 'next'
|
||||
- if @newer_url
|
||||
= link_to safe_join([t('pagination.newer'), fa_icon('chevron-right')], ' '), @newer_url, class: 'newer', rel: 'prev'
|
||||
.entry= link_to_more @older_url
|
||||
|
||||
.column-1
|
||||
- if @account.memorial?
|
||||
.memoriam-widget= t('in_memoriam_html')
|
||||
- elsif @account.moved?
|
||||
= render 'moved', account: @account
|
||||
|
||||
= render 'bio', account: @account
|
||||
= render 'application/sidebar'
|
||||
|
|
16
app/views/application/_card.html.haml
Normal file
16
app/views/application/_card.html.haml
Normal file
|
@ -0,0 +1,16 @@
|
|||
- account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
|
||||
|
||||
.card.h-card
|
||||
= link_to account_url, target: '_blank', rel: 'noopener' do
|
||||
.card__img
|
||||
= image_tag account.header.url, alt: ''
|
||||
.card__bar
|
||||
.avatar
|
||||
= image_tag account.avatar.url, alt: '', width: 48, height: 48, class: 'u-photo'
|
||||
|
||||
.display-name
|
||||
%bdi
|
||||
%strong.emojify.p-name= display_name(account, custom_emojify: true)
|
||||
%span
|
||||
= acct(account)
|
||||
= fa_icon('lock') if account.locked?
|
6
app/views/application/_sidebar.html.haml
Normal file
6
app/views/application/_sidebar.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
|||
.hero-widget
|
||||
.hero-widget__img
|
||||
= image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title
|
||||
|
||||
.hero-widget__text
|
||||
%p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname)
|
|
@ -10,7 +10,7 @@
|
|||
- if @invite.present? && @invite.autofollow?
|
||||
.fields-group{ style: 'margin-bottom: 30px' }
|
||||
%p.hint{ style: 'text-align: center' }= t('invites.invited_by')
|
||||
= render 'authorize_follows/card', account: @invite.user.account
|
||||
= render 'application/card', account: @invite.user.account
|
||||
|
||||
= f.simple_fields_for :account do |ff|
|
||||
.input-with-append
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
.account-card
|
||||
.account-card__header{ style: "background-image: url(#{account.header.url(:original)})" }
|
||||
.detailed-status__display-name
|
||||
%div
|
||||
= image_tag account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar'
|
||||
|
||||
%span.display-name
|
||||
- account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
|
||||
= link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
|
||||
%strong.emojify= display_name(account, custom_emojify: true)
|
||||
%span @#{account.acct}
|
||||
|
||||
.counter
|
||||
%span.counter-number= number_to_human account.statuses_count, strip_insignificant_zeros: true
|
||||
%span.counter-label= t('accounts.posts')
|
||||
|
||||
.counter
|
||||
%span.counter-number= number_to_human account.following_count, strip_insignificant_zeros: true
|
||||
%span.counter-label= t('accounts.following')
|
||||
|
||||
.counter
|
||||
%span.counter-number= number_to_human account.followers_count, strip_insignificant_zeros: true
|
||||
%span.counter-label= t('accounts.followers')
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
.form-container
|
||||
.follow-prompt
|
||||
= render 'card', account: @account
|
||||
= render 'application/card', account: @account
|
||||
|
||||
- if current_account.following?(@account)
|
||||
.flash-message
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
- else
|
||||
%h2= t('authorize_follow.following')
|
||||
|
||||
= render 'card', account: @account
|
||||
= render 'application/card', account: @account
|
||||
|
||||
= render 'post_follow_actions'
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
= render 'accounts/header', account: @account
|
||||
|
||||
- if @account.user_hides_network?
|
||||
= render 'accounts/follow_grid_hidden'
|
||||
.nothing-here= t('accounts.network_hidden')
|
||||
- elsif @follows.empty?
|
||||
= nothing_here
|
||||
- else
|
||||
= render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:account)
|
||||
.card-grid
|
||||
= render partial: 'application/card', collection: @follows.map(&:account), as: :account
|
||||
|
||||
= paginate @follows
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
= render 'accounts/header', account: @account
|
||||
|
||||
- if @account.user_hides_network?
|
||||
= render 'accounts/follow_grid_hidden'
|
||||
.nothing-here= t('accounts.network_hidden')
|
||||
- elsif @follows.empty?
|
||||
= nothing_here
|
||||
- else
|
||||
= render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:target_account)
|
||||
.card-grid
|
||||
= render partial: 'application/card', collection: @follows.map(&:target_account), as: :account
|
||||
|
||||
= paginate @follows
|
||||
|
|
|
@ -1,14 +1,47 @@
|
|||
- content_for :content do
|
||||
.container-alt= yield
|
||||
.footer
|
||||
- if !user_signed_in? && single_user_mode?
|
||||
%span.single-user-login
|
||||
= link_to t('auth.login'), new_user_session_path
|
||||
—
|
||||
%span.footer__domain= link_to site_hostname, about_path
|
||||
.public-layout
|
||||
.container
|
||||
%nav.header
|
||||
.nav-left
|
||||
= link_to root_url, class: 'brand' do
|
||||
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
|
||||
.nav-center
|
||||
.nav-right
|
||||
- if user_signed_in?
|
||||
= link_to t('settings.back'), root_url, class: 'nav-link nav-button webapp-btn'
|
||||
- else
|
||||
%span.footer__domain= link_to site_hostname, root_path
|
||||
%span.powered-by
|
||||
!= t('generic.powered_by', link: link_to('https://joinmastodon.org') { image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon' })
|
||||
= link_to t('auth.login'), new_user_session_path, class: 'webapp-btn nav-link nav-button'
|
||||
= link_to t('auth.register'), new_user_registration_path, class: 'webapp-btn nav-link nav-button'
|
||||
|
||||
.container= yield
|
||||
|
||||
.container
|
||||
.footer
|
||||
.grid
|
||||
.column-0
|
||||
%h4= t 'footer.resources'
|
||||
%ul
|
||||
%li= link_to t('about.terms'), terms_path
|
||||
%li= link_to t('about.privacy_policy'), terms_path
|
||||
.column-1
|
||||
%h4= t 'footer.developers'
|
||||
%ul
|
||||
%li= link_to t('about.documentation'), 'https://github.com/tootsuite/documentation'
|
||||
%li= link_to t('about.api'), 'https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md'
|
||||
.column-2
|
||||
%h4= link_to t('about.what_is_mastodon'), 'https://joinmastodon.org/'
|
||||
|
||||
= link_to root_url, class: 'brand' do
|
||||
= render file: Rails.root.join('app', 'javascript', 'images', 'logo_transparent.svg')
|
||||
.column-3
|
||||
%h4= site_hostname
|
||||
%ul
|
||||
%li= link_to t('about.about_this'), about_more_path
|
||||
%li= "v#{Mastodon::Version.to_s}"
|
||||
.column-4
|
||||
%h4= t 'footer.more'
|
||||
%ul
|
||||
%li= link_to t('about.source_code'), Mastodon::Version.source_url
|
||||
%li= link_to 'joinmastodon.org', 'https://joinmastodon.org'
|
||||
|
||||
= render template: 'layouts/application'
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
.follow-prompt
|
||||
%h2= t('remote_follow.prompt')
|
||||
|
||||
= render partial: 'authorize_follows/card', locals: { account: @account }
|
||||
= render partial: 'application/card', locals: { account: @account }
|
||||
|
||||
= simple_form_for @remote_follow, as: :remote_follow, url: account_remote_follow_path(@account) do |f|
|
||||
= render 'shared/error_messages', object: @remote_follow
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
.follow-prompt
|
||||
%h2= t('remote_unfollow.unfollowed')
|
||||
|
||||
= render 'card', account: @account
|
||||
= render 'application/card', account: @account
|
||||
|
||||
= render 'post_follow_actions'
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
%p.hint= t('migrations.currently_redirecting')
|
||||
|
||||
.fields-group
|
||||
= render partial: 'authorize_follows/card', locals: { account: @migration.account }
|
||||
= render partial: 'application/card', locals: { account: @migration.account }
|
||||
|
||||
= render 'shared/error_messages', object: @migration
|
||||
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
= f.input :display_name, placeholder: t('simple_form.labels.defaults.display_name'), hint: t('simple_form.hints.defaults.display_name', count: 30 - @account.display_name.size).html_safe
|
||||
= f.input :note, placeholder: t('simple_form.labels.defaults.note'), hint: t('simple_form.hints.defaults.note', count: 500 - @account.note.size).html_safe
|
||||
|
||||
.card.compact{ style: "background-image: url(#{@account.header.url(:original)})", data: { original_src: @account.header.url(:original) } }
|
||||
.avatar= image_tag @account.avatar.url(:original), data: { original_src: @account.avatar.url(:original) }
|
||||
= render 'application/card', account: @account
|
||||
|
||||
.fields-group
|
||||
= f.input :avatar, wrapper: :with_label, input_html: { accept: AccountAvatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar')
|
||||
= f.input :avatar, wrapper: :with_label, input_html: { accept: AccountAvatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(AccountAvatar::LIMIT))
|
||||
|
||||
= f.input :header, wrapper: :with_label, input_html: { accept: AccountHeader::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header')
|
||||
= f.input :header, wrapper: :with_label, input_html: { accept: AccountHeader::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(AccountHeader::LIMIT))
|
||||
|
||||
.fields-group
|
||||
= f.input :locked, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.locked')
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
.landing-strip
|
||||
= image_tag asset_pack_path('logo.svg'), class: 'logo'
|
||||
|
||||
%div
|
||||
= t('landing_strip_html', name: content_tag(:span, display_name(account, custom_emojify: true), class: :emojify), link_to_root_path: link_to(content_tag(:strong, site_hostname), root_path))
|
||||
= t('landing_strip_signup_html', sign_up_path: open_registrations? ? new_user_registration_path : 'https://joinmastodon.org/#getting-started')
|
|
@ -1,7 +0,0 @@
|
|||
.media-spoiler-wrapper{ class: sensitive == false && 'media-spoiler-wrapper__visible' }><
|
||||
.spoiler-button
|
||||
.icon-button.overlayed
|
||||
%i.fa.fa-fw.fa-eye
|
||||
.media-spoiler
|
||||
%span= t('stream_entries.sensitive_content')
|
||||
%span= t('stream_entries.click_to_show')
|
|
@ -1,16 +1,15 @@
|
|||
.detailed-status.light
|
||||
.detailed-status.detailed-status--flex
|
||||
= link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do
|
||||
%div
|
||||
.avatar
|
||||
= image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'u-photo'
|
||||
.detailed-status__display-avatar
|
||||
= image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'account__avatar u-photo'
|
||||
%span.display-name
|
||||
%strong.p-name.emojify= display_name(status.account, custom_emojify: true)
|
||||
%span= acct(status.account)
|
||||
%bdi
|
||||
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true)
|
||||
%span.display-name__account
|
||||
= acct(status.account)
|
||||
= fa_icon('lock') if status.account.locked?
|
||||
|
||||
- if !user_signed_in? || embedded_view?
|
||||
= link_to account_remote_follow_path(status.account), class: 'button button-secondary logo-button', target: '_new' do
|
||||
= render file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')
|
||||
= t('accounts.follow')
|
||||
= account_action_button(status.account)
|
||||
|
||||
.status__content.emojify<
|
||||
- if status.spoiler_text?
|
||||
|
@ -30,6 +29,7 @@
|
|||
|
||||
.detailed-status__meta
|
||||
%data.dt-published{ value: status.created_at.to_time.iso8601 }
|
||||
|
||||
= link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener' do
|
||||
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
||||
·
|
||||
|
@ -40,20 +40,20 @@
|
|||
= link_to status.application.name, status.application.website, class: 'detailed-status__application', target: '_blank', rel: 'noopener'
|
||||
·
|
||||
- if status.direct_visibility?
|
||||
%span<
|
||||
%span.detailed-status__link<
|
||||
= fa_icon('envelope')
|
||||
- elsif status.private_visibility?
|
||||
%span<
|
||||
%span.detailed-status__link<
|
||||
= fa_icon('lock')
|
||||
- else
|
||||
%span<
|
||||
%span.detailed-status__link<
|
||||
= fa_icon('retweet')
|
||||
%span= status.reblogs_count
|
||||
%span.detailed-status__reblogs= number_to_human status.reblogs_count, strip_insignificant_zeros: true
|
||||
·
|
||||
%span<
|
||||
%span.detailed-status__link<
|
||||
= fa_icon('star')
|
||||
%span= status.favourites_count
|
||||
%span.detailed-status__favorites= number_to_human status.favourites_count, strip_insignificant_zeros: true
|
||||
|
||||
- if user_signed_in?
|
||||
·
|
||||
= link_to t('statuses.open_in_web'), web_url("statuses/#{status.id}"), class: 'open-in-web-link', target: '_blank'
|
||||
= link_to t('statuses.open_in_web'), web_url("statuses/#{status.id}"), class: 'detailed-status__application', target: '_blank'
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
.media-item><
|
||||
= link_to media.remote_url.blank? ? media.file.url(:original) : media.remote_url, style: media.image? ? "background-image: url(#{media.file.url(:original)})" : '', target: '_blank', rel: 'noopener', class: "u-#{media.video? || media.gifv? ? 'video' : 'photo'}" do
|
||||
- unless media.image?
|
||||
%video{ src: media.file.url(:original), autoplay: true, loop: true }/
|
|
@ -1,2 +0,0 @@
|
|||
= link_to url, class: 'more light' do
|
||||
= t('statuses.show_more')
|
|
@ -1,6 +1,5 @@
|
|||
.status.light
|
||||
.status__header
|
||||
.status__meta
|
||||
.status
|
||||
.status__info
|
||||
= link_to TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener' do
|
||||
%time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
||||
%data.dt-published{ value: status.created_at.to_time.iso8601 }
|
||||
|
@ -8,11 +7,13 @@
|
|||
= link_to TagManager.instance.url_for(status.account), class: 'status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do
|
||||
.status__avatar
|
||||
%div
|
||||
= image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo'
|
||||
= image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo account__avatar'
|
||||
%span.display-name
|
||||
%strong.p-name.emojify= display_name(status.account, custom_emojify: true)
|
||||
%span= acct(status.account)
|
||||
|
||||
%bdi
|
||||
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true)
|
||||
%span.display-name__account
|
||||
= acct(status.account)
|
||||
= fa_icon('lock') if status.account.locked?
|
||||
.status__content.emojify<
|
||||
- if status.spoiler_text?
|
||||
%p{ style: 'margin-bottom: 0' }<
|
||||
|
@ -27,3 +28,16 @@
|
|||
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343, inline: true
|
||||
- else
|
||||
= react_component :media_gallery, height: 343, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
|
||||
|
||||
.status__action-bar
|
||||
.status__action-bar-button.static-icon-button<
|
||||
- if status.public_visibility? || status.unlisted_visibility?
|
||||
= fa_icon 'retweet fw'
|
||||
%span.detailed-status__reblogs= number_to_human status.reblogs_count, strip_insignificant_zeros: true
|
||||
- elsif status.private_visibility?
|
||||
= fa_icon 'lock fw'
|
||||
- else
|
||||
= fa_icon 'envelope fw'
|
||||
.status__action-bar-button.static-icon-button<
|
||||
= fa_icon 'star fw'
|
||||
%span.detailed-status__favorites= number_to_human status.favourites_count, strip_insignificant_zeros: true
|
||||
|
|
|
@ -16,24 +16,25 @@
|
|||
- if status.reply? && include_threads
|
||||
- if @next_ancestor
|
||||
.entry{ class: entry_classes }
|
||||
= render 'stream_entries/more', url: TagManager.instance.url_for(@next_ancestor)
|
||||
= link_to_more TagManager.instance.url_for(@next_ancestor)
|
||||
|
||||
= render partial: 'stream_entries/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }
|
||||
|
||||
.entry{ class: entry_classes }
|
||||
|
||||
- if status.reblog?
|
||||
.pre-header
|
||||
.pre-header__icon
|
||||
= fa_icon('retweet fw')
|
||||
.status__prepend
|
||||
.status__prepend-icon-wrapper
|
||||
%i.status__prepend-icon.fa.fa-fw.fa-retweet
|
||||
%span
|
||||
= link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do
|
||||
%bdi
|
||||
%strong.emojify= display_name(status.account, custom_emojify: true)
|
||||
= t('stream_entries.reblogged')
|
||||
- elsif pinned
|
||||
.pre-header
|
||||
.pre-header__icon
|
||||
= fa_icon('thumb-tack fw')
|
||||
.status__prepend
|
||||
.status__prepend-icon-wrapper
|
||||
%i.status__prepend-icon.fa.fa-fw.fa-thumb-tack
|
||||
%span
|
||||
= t('stream_entries.pinned')
|
||||
|
||||
|
@ -42,13 +43,13 @@
|
|||
- if include_threads
|
||||
- if @since_descendant_thread_id
|
||||
.entry{ class: entry_classes }
|
||||
= render 'stream_entries/more', url: short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1)
|
||||
= link_to_more short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1)
|
||||
- @descendant_threads.each do |thread|
|
||||
= render partial: 'stream_entries/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }
|
||||
|
||||
- if thread[:next_status]
|
||||
.entry{ class: entry_classes }
|
||||
= render 'stream_entries/more', url: TagManager.instance.url_for(thread[:next_status])
|
||||
= link_to_more TagManager.instance.url_for(thread[:next_status])
|
||||
- if @next_descendant_thread
|
||||
.entry{ class: entry_classes }
|
||||
= render 'stream_entries/more', url: short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1)
|
||||
= link_to_more short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
- cache @stream_entry.activity do
|
||||
.activity-stream.activity-stream-headless
|
||||
.activity-stream.activity-stream--headless
|
||||
= render "stream_entries/#{@type}", @type.to_sym => @stream_entry.activity, centered: true
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
= render 'stream_entries/og_description', activity: @stream_entry.activity
|
||||
= render 'stream_entries/og_image', activity: @stream_entry.activity, account: @account
|
||||
|
||||
- if show_landing_strip?
|
||||
= render partial: 'shared/landing_strip', locals: { account: @stream_entry.account }
|
||||
|
||||
.activity-stream.activity-stream-headless.h-entry
|
||||
.grid
|
||||
.column-0
|
||||
.activity-stream.activity-stream-headless.h-entry
|
||||
= render partial: "stream_entries/#{@type}", locals: { @type.to_sym => @stream_entry.activity, include_threads: true }
|
||||
.column-1
|
||||
= render 'application/sidebar'
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
{}
|
||||
---
|
||||
ast:
|
||||
|
|
|
@ -46,7 +46,6 @@ ar:
|
|||
people_who_follow: الأشخاص الذين يتبعون %{name}
|
||||
posts: منشورات
|
||||
posts_with_replies: التبويقات و الردود
|
||||
remote_follow: إتبع عن بعد
|
||||
reserved_username: إسم المستخدم محجوز
|
||||
roles:
|
||||
admin: المدير
|
||||
|
@ -516,7 +515,6 @@ ar:
|
|||
unlocked_warning_title: إنّ حسابك غير مقفل
|
||||
generic:
|
||||
changes_saved_msg: تم حفظ التعديلات بنجاح !
|
||||
powered_by: مدعوم بـ %{link}
|
||||
save_changes: حفظ التغييرات
|
||||
validation_errors:
|
||||
one: لا يزال هناك خلل ما إلى حد الآن. يُرجى إعادة النظر في الخطأ أسفله
|
||||
|
@ -551,8 +549,6 @@ ar:
|
|||
expires_at: تنتهي مدة صلاحيتها في
|
||||
uses: يستخدِم
|
||||
title: دعوة أشخاص
|
||||
landing_strip_html: "<strong>%{name}</strong> هو أحد مُستخدِمي %{link_to_root_path}. بإمكانك متابعته أو التواصل معه إن كنت تملك حسابًا أيا كان على البيئة الموحَّدة فيديفرس."
|
||||
landing_strip_signup_html: إن كنت لا تملك واحدا، يمكنك <a href="%{sign_up_path}">التسجيل مِن هنا</a>.
|
||||
lists:
|
||||
errors:
|
||||
limit: لقد بلغت الحد الأقصى للقوائم
|
||||
|
@ -720,7 +716,6 @@ ar:
|
|||
unlisted: غير مُدرَج
|
||||
unlisted_long: يُمكن لأيٍ كان رُؤيتَه و لكن لن يُعرَض على الخيوط العامة
|
||||
stream_entries:
|
||||
click_to_show: إضغط للعرض
|
||||
pinned: تبويق مثبّت
|
||||
reblogged: رقى
|
||||
sensitive_content: محتوى حساس
|
||||
|
|
|
@ -96,8 +96,6 @@ ast:
|
|||
followers:
|
||||
domain: Dominiu
|
||||
followers_count: Númberu de siguidores
|
||||
generic:
|
||||
powered_by: cola potencia de %{link}
|
||||
invites:
|
||||
expires_in:
|
||||
'1800': 30 minutos
|
||||
|
@ -183,7 +181,6 @@ ast:
|
|||
other: "%{count} vídeos"
|
||||
title: "%{name}: «%{quote}»"
|
||||
stream_entries:
|
||||
click_to_show: Primi p'amosar
|
||||
sensitive_content: Conteníu sensible
|
||||
themes:
|
||||
default: Mastodon
|
||||
|
|
|
@ -22,7 +22,6 @@ bg:
|
|||
people_followed_by: Хора, които %{name} следва
|
||||
people_who_follow: Хора, които следват %{name}
|
||||
posts: Публикации
|
||||
remote_follow: Последвай
|
||||
unfollow: Не следвай
|
||||
application_mailer:
|
||||
settings: 'Промяна на предпочитанията за e-mail: %{link}'
|
||||
|
@ -64,7 +63,6 @@ bg:
|
|||
storage: Съхранение на мултимедия
|
||||
generic:
|
||||
changes_saved_msg: Успешно запазване на промените!
|
||||
powered_by: поддържано от %{link}
|
||||
save_changes: Запази промените
|
||||
validation_errors:
|
||||
one: Нещо все още не е наред! Моля, прегледай грешката по-долу
|
||||
|
@ -76,8 +74,6 @@ bg:
|
|||
blocking: Списък на блокираните
|
||||
following: Списък на последователите
|
||||
upload: Качване
|
||||
landing_strip_html: "<strong>%{name}</strong> е потребител от %{link_to_root_path}. Можеш да ги следваш, или да контактуваш с тях, ако имаш акаунт където и да е из федерираната вселена на Mastodon."
|
||||
landing_strip_signup_html: Ако нямаш акаунт, можеш да си <a href="%{sign_up_path}">създадеш ето тук</a>.
|
||||
media_attachments:
|
||||
validations:
|
||||
images_and_video: Не мога да прикача видеоклип към публикация, която вече съдържа изображения
|
||||
|
@ -144,7 +140,6 @@ bg:
|
|||
public: Публично
|
||||
unlisted: Публично, но не показвай в публичния канал
|
||||
stream_entries:
|
||||
click_to_show: Покажи
|
||||
reblogged: споделено
|
||||
sensitive_content: Деликатно съдържание
|
||||
time:
|
||||
|
|
|
@ -46,7 +46,6 @@ ca:
|
|||
people_who_follow: Usuaris que segueixen %{name}
|
||||
posts: Toots
|
||||
posts_with_replies: Toots i respostes
|
||||
remote_follow: Seguiment remot
|
||||
reserved_username: El nom d'usuari està reservat
|
||||
roles:
|
||||
admin: Administrador
|
||||
|
@ -504,7 +503,6 @@ ca:
|
|||
unlocked_warning_title: El teu compte no està blocat
|
||||
generic:
|
||||
changes_saved_msg: Els canvis s'han desat correctament!
|
||||
powered_by: amb tecnologia %{link}
|
||||
save_changes: Desa els canvis
|
||||
validation_errors:
|
||||
one: Alguna cosa no va bé! Si us plau, revisa l'error
|
||||
|
@ -540,8 +538,6 @@ ca:
|
|||
expires_at: Caduca
|
||||
uses: Usos
|
||||
title: Convida persones
|
||||
landing_strip_html: "<strong>%{name}</strong> és un usuari/a de %{link_to_root_path}. Pots seguir-lo/la o interactuar amb ell/a si tens un compte a qualsevol node del fediverse."
|
||||
landing_strip_signup_html: Si no en tens, pots <a href="%{sign_up_path}">registrar-te aquí</a>.
|
||||
lists:
|
||||
errors:
|
||||
limit: Has assolit la quantitat màxima de llistes
|
||||
|
@ -710,7 +706,6 @@ ca:
|
|||
unlisted: No llistat
|
||||
unlisted_long: Tothom ho pot veure, però no es mostra en la història federada
|
||||
stream_entries:
|
||||
click_to_show: Clic per mostrar
|
||||
pinned: Toot fixat
|
||||
reblogged: ha impulsat
|
||||
sensitive_content: Contingut sensible
|
||||
|
|
|
@ -46,7 +46,6 @@ co:
|
|||
people_who_follow: Seguitanu %{name}
|
||||
posts: Statuti
|
||||
posts_with_replies: Statuti è risposte
|
||||
remote_follow: Siguità d’altrò
|
||||
reserved_username: Stu cugnome hè riservatu
|
||||
roles:
|
||||
admin: Amministratore
|
||||
|
@ -488,7 +487,6 @@ co:
|
|||
unlocked_warning_title: U vostru contu hè pubblicu
|
||||
generic:
|
||||
changes_saved_msg: Cambiamenti salvati!
|
||||
powered_by: mossu da %{link}
|
||||
save_changes: Salvà e mudificazione
|
||||
validation_errors:
|
||||
one: Qualcosa ùn và bè! Verificate u prublemu quì sottu
|
||||
|
@ -523,8 +521,6 @@ co:
|
|||
expires_at: Spira
|
||||
uses: Utiliza
|
||||
title: Invità ghjente
|
||||
landing_strip_html: "<strong>%{name}</strong> hè nant’à %{link_to_root_path}. Pudete seguitallu·a o cumunicà cù ellu·a cù un contu in qualche parte di u fediverse."
|
||||
landing_strip_signup_html: Pudete ancu <a href="%{sign_up_path}">arrigistravi quì</a>.
|
||||
lists:
|
||||
errors:
|
||||
limit: Ùn pudete più creà altre liste
|
||||
|
@ -691,7 +687,6 @@ co:
|
|||
unlisted: Micca listatu
|
||||
unlisted_long: Tuttu u mondu pò vede, mà micca indè e linee pubbliche
|
||||
stream_entries:
|
||||
click_to_show: Cliccà per vede
|
||||
pinned: Statutu puntarulatu
|
||||
reblogged: spartutu
|
||||
sensitive_content: Cuntenutu sensibile
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
cs:
|
||||
about:
|
||||
about_hashtag_html: Toto jsou veřejné tooty označené jako <strong>#%{hashtag}</strong>. Pokud máte účet kdekoliv na fediverse, můžete s nimi interagovat.
|
||||
about_hashtag_html: Toto jsou veřejné tooty označené hashtagem<strong>#%{hashtag}</strong>. Pokud máte účet kdekoliv na fediverse, můžete s nimi interagovat.
|
||||
about_mastodon_html: Mastodon je sociální síť založená na otevřených webových protokolech a svobodném, otevřeném softwaru. Je decentrovalizovaná jako e-mail.
|
||||
about_this: O této instanci
|
||||
administered_by: 'Server spravuje:'
|
||||
|
@ -18,14 +18,21 @@ cs:
|
|||
features:
|
||||
humane_approach_body: Mastodon, poučen z chyb jiných sociálních sítí, se snaží bojovat se zneužíváním sociálních sítí vytvářením etických možností.
|
||||
humane_approach_title: Lidštější přístup
|
||||
not_a_product_body: Mastodon není komerční síť. Žádné reklamy, žádné dolování dat, žádné hranice. Žádná centrální autorita.
|
||||
not_a_product_title: Jste osoba, ne produkt
|
||||
real_conversation_body: S 500 znaky k vaší dispozici a podporou pro varování o obsahu a médiích se můžete vyjadřovat tak, jak chcete.
|
||||
real_conversation_title: Vytvořen pro opravdovou konverzaci
|
||||
within_reach_body: Několik aplikací pro iOS, Android a jiné platformy vám díky jednoduchému API ekosystému dovolují držet krok s vašimi přáteli, ať už jste kdekoliv.
|
||||
within_reach_title: Vždy v dosahu
|
||||
generic_description: "%{domain} je jedním serverem v síti"
|
||||
hosted_on: Mastodon hostovaný na %{domain}
|
||||
learn_more: Zjistit více
|
||||
other_instances: Seznam instancí
|
||||
source_code: Zdrojový kód
|
||||
status_count_after: příspěvků
|
||||
status_count_before: Kdo je autorem
|
||||
status_count_before: Kteří napsali
|
||||
user_count_after: uživatelů
|
||||
user_count_before: Domov pro
|
||||
user_count_before: Domov
|
||||
what_is_mastodon: Co je Mastodon?
|
||||
accounts:
|
||||
follow: Sledovat
|
||||
|
@ -35,10 +42,836 @@ cs:
|
|||
moved_html: 'Účet %{name} byl přesunut na %{new_profile_link}:'
|
||||
network_hidden: Tato informace není k dispozici
|
||||
nothing_here: Tady nic není!
|
||||
people_followed_by: Lidé, které %{name} sleduje
|
||||
people_who_follow: Lidé, kteří sledují uživatele %{name}
|
||||
posts: Tooty
|
||||
posts_with_replies: Tooty s odpověďmi
|
||||
reserved_username: Toto uživatelské jméno je rezervováno
|
||||
roles:
|
||||
admin: Administrátor
|
||||
bot: Robot
|
||||
moderator: Moderátor
|
||||
unfollow: Přestat sledovat
|
||||
admin:
|
||||
account_moderation_notes:
|
||||
create: Zanechat poznámku
|
||||
created_msg: Poznámka moderátora byla úspěšně vytvořena!
|
||||
delete: Smazat
|
||||
destroyed_msg: Poznámka moderátora byla úspěšně zničena!
|
||||
accounts:
|
||||
are_you_sure: Jste si jistý/á?
|
||||
avatar: Avatar
|
||||
by_domain: Doména
|
||||
change_email:
|
||||
changed_msg: E-mail k tomuto účtu byl úspěšně změněn!
|
||||
current_email: Současný e-mail
|
||||
label: Změnit e-mail
|
||||
new_email: Nový e-mail
|
||||
submit: Změnit e-mail
|
||||
title: Změnit e-mail pro uživatele %{username}
|
||||
confirm: Potvrdit
|
||||
confirmed: Potvrzeno
|
||||
confirming: Potvrzující
|
||||
demote: Degradovat
|
||||
disable: Zablokovat
|
||||
disable_two_factor_authentication: Zakázat 2FA
|
||||
disabled: Blokováno
|
||||
display_name: Zobrazované jméno
|
||||
domain: Doména
|
||||
edit: Upravit
|
||||
email: E-mail
|
||||
email_status: Stav e-mailu
|
||||
enable: Povolit
|
||||
enabled: Povoleno
|
||||
feed_url: URL proudu
|
||||
followers: Sledovatelé
|
||||
followers_url: URL sledovatelů
|
||||
follows: Sleduje
|
||||
inbox_url: URL přijatých zpráv
|
||||
ip: IP
|
||||
location:
|
||||
all: Vše
|
||||
local: Místní
|
||||
remote: Vzdálené
|
||||
title: Umístění
|
||||
login_status: Stav přihlášení
|
||||
media_attachments: Mediální přílohy
|
||||
memorialize: Změnit na "in memoriam"
|
||||
moderation:
|
||||
all: Vše
|
||||
silenced: Utišen
|
||||
suspended: Suspendován
|
||||
title: Moderace
|
||||
moderation_notes: Moderační poznámky
|
||||
most_recent_activity: Nejnovější aktivita
|
||||
most_recent_ip: Nejnovější IP
|
||||
not_subscribed: Neodebírá
|
||||
order:
|
||||
alphabetic: Abecedně
|
||||
most_recent: Nejnovější
|
||||
title: Pořadí
|
||||
outbox_url: URL odchozích zpráv
|
||||
perform_full_suspension: Provést plnou suspenzaci
|
||||
profile_url: URL profilu
|
||||
promote: Povýšit
|
||||
protocol: Protokol
|
||||
public: Veřejný
|
||||
push_subscription_expires: Odebírání PuSH expiruje
|
||||
redownload: Obnovit avatar
|
||||
remove_avatar: Odstranit avatar
|
||||
resend_confirmation:
|
||||
already_confirmed: Tento uživatel je již potvrzen
|
||||
send: Znovu odeslat potvrzovací e-mail
|
||||
success: Potvrzovací e-mail byl úspěšně odeslán!
|
||||
reset: Resetovat
|
||||
reset_password: Obnovit heslo
|
||||
resubscribe: Znovu odebírat
|
||||
role: Oprávnění
|
||||
roles:
|
||||
admin: Administrátor
|
||||
moderator: Moderátor
|
||||
staff: Personál
|
||||
user: Uživatel
|
||||
salmon_url: URL Salmon
|
||||
search: Hledat
|
||||
shared_inbox_url: URL sdílené schránky
|
||||
show:
|
||||
created_reports: Nahlášení vytvořené z tohoto účtu
|
||||
report: nahlášení
|
||||
targeted_reports: Nahlášení vytvořena o tomto účtu
|
||||
silence: Utišit
|
||||
statuses: Statusy
|
||||
subscribe: Odebírat
|
||||
title: Účty
|
||||
unconfirmed_email: Nepotvrzený e-mail
|
||||
undo_silenced: Zrušit utišení
|
||||
undo_suspension: Zrušit suspenzaci
|
||||
unsubscribe: Přestat odebírat
|
||||
username: Uživatelské jméno
|
||||
web: Web
|
||||
action_logs:
|
||||
actions:
|
||||
assigned_to_self_report: "%{name} přidělil/a hlášení %{target} sobě"
|
||||
change_email_user: "%{name} změnil/a e-mailovou adresu uživatele %{target}"
|
||||
confirm_user: "%{name} potvrdil/a e-mailovou adresu uživatele %{target}"
|
||||
create_custom_emoji: "%{name} nahrál/a nové emoji %{target}"
|
||||
create_domain_block: "%{name} zablokoval/a doménu %{target}"
|
||||
create_email_domain_block: "%{name} přidal/a e-mailovou doménu %{target} na černou listinu"
|
||||
demote_user: "%{name} degradoval/a uživatele %{target}"
|
||||
destroy_domain_block: "%{name} odblokoval/a doménu %{target}"
|
||||
destroy_email_domain_block: "%{name} odebral/a e-mailovou doménu %{target} z černé listiny"
|
||||
destroy_status: "%{name} odstranil/a status uživatele %{target}"
|
||||
disable_2fa_user: "%{name} vypnul/a požadavek pro dvoufaktorovou autentikaci pro uživatele %{target}"
|
||||
disable_custom_emoji: "%{name} zakázal/a emoji %{target}"
|
||||
disable_user: "%{name} zakázal/a přihlašování pro uživatele %{target}"
|
||||
enable_custom_emoji: "%{name} povolil/a emoji %{target}"
|
||||
enable_user: "%{name} povolil/a přihlašování pro uživatele %{target}"
|
||||
memorialize_account: '%{name} změnil/a účet %{target} na stránku "in memoriam"'
|
||||
promote_user: "%{name} povýšil/a uživatele %{target}"
|
||||
remove_avatar_user: "%{name} odstranil/a avatar uživatele %{target}"
|
||||
reopen_report: "%{name} znovuotevřel/a nahlášení %{target}"
|
||||
reset_password_user: "%{name} resetoval/a heslo uživatele %{target}"
|
||||
resolve_report: "%{name} vyřešil/a nahlášení %{target}"
|
||||
silence_account: "%{name} utišil/a účet uživatele %{target}"
|
||||
suspend_account: "%{name} suspendoval/a účet uživatele %{target}"
|
||||
unassigned_report: "%{name} odebral/a nahlášení %{target}"
|
||||
unsilence_account: "%{name} odtišil/a účet uživatele %{target}"
|
||||
unsuspend_account: "%{name} zrušil/a suspenzaci účtu uživatele %{target}"
|
||||
update_custom_emoji: "%{name} aktualizoval/a emoji %{target}"
|
||||
update_status: "%{name} aktualizoval/a status uživatele %{target}"
|
||||
title: Záznam auditu
|
||||
custom_emojis:
|
||||
by_domain: Doména
|
||||
copied_msg: Místní kopie emoji byla úspěšně vytvořena
|
||||
copy: Kopírovat
|
||||
copy_failed_msg: Nebylo možné vytvořit místní kopii tohoto emoji
|
||||
created_msg: Emoji úspěšně vytvořeno!
|
||||
delete: Smazat
|
||||
destroyed_msg: Emoji úspěšně zničeno!
|
||||
disable: Zakázat
|
||||
disabled_msg: Emoji bylo úspěšně zakázáno
|
||||
emoji: Emoji
|
||||
enable: Povolit
|
||||
enabled_msg: Emoji bylo úspěšně povoleno
|
||||
image_hint: PNG až do 50KB
|
||||
listed: Uvedené
|
||||
new:
|
||||
title: Přidat nové vlastní emoji
|
||||
overwrite: Přepsat
|
||||
shortcode: Zkratka
|
||||
shortcode_hint: Alespoň 2 znaky, pouze alfanumerické znaky a podtržítka
|
||||
title: Vlastní emoji
|
||||
unlisted: Neuvedené
|
||||
update_failed_msg: Nebylo možné aktualizovat toto emoji
|
||||
updated_msg: Emoji úspěšně aktualizováno!
|
||||
upload: Nahrát
|
||||
dashboard:
|
||||
backlog: opožděné úlohy
|
||||
config: Konfigurace
|
||||
feature_deletions: Smazání účtů
|
||||
feature_invites: Pozvánky
|
||||
feature_registrations: Registrace
|
||||
feature_relay: Federovací most
|
||||
features: Vlastnosti
|
||||
hidden_service: Federace se skrytými službami
|
||||
open_reports: otevřená hlášení
|
||||
recent_users: Nedávní uživatelé
|
||||
search: Fulltextové vyhledávání
|
||||
single_user_mode: Režim jednoho uživatele
|
||||
software: Software
|
||||
space: Využití prostoru
|
||||
title: Přehled
|
||||
total_users: uživatelů celkem
|
||||
trends: Trendy
|
||||
week_interactions: interakcí tento týden
|
||||
week_users_active: aktivních tento týden
|
||||
week_users_new: uživatelů tento týden
|
||||
domain_blocks:
|
||||
add_new: Přidat nové
|
||||
created_msg: Blokace domény se právě vyřizuje
|
||||
destroyed_msg: Blokace domény byla zrušena
|
||||
domain: Doména
|
||||
new:
|
||||
create: Vytvořit blokaci
|
||||
hint: Blokace domény nezakáže vytváření účtových záznamů v databázi, ale bude na tyto účty zpětně a automaticky aplikovat specifické metody moderace.
|
||||
severity:
|
||||
desc_html: Funkce <strong>Utišit</strong> zneviditelní příspěvky z účtu komukoliv, kdo jej nesleduje. Funkce <strong>Suspendovat</strong> odstraní všechen obsah, média a profilová data účtu. Pro pouhé odmítnutí mediálních souborů použijte funkci <strong>Žádné</strong>.
|
||||
noop: Žádné
|
||||
silence: Utišit
|
||||
suspend: Suspendovat
|
||||
title: Nová doménová blokace
|
||||
reject_media: Odmítat mediální soubory
|
||||
reject_media_hint: Odstraní lokálně uložené soubory a odmítne jejich stažení v budoucnosti. Irelevantní pro suspenzace
|
||||
severities:
|
||||
noop: Žádné
|
||||
silence: Utišit
|
||||
suspend: Suspendovat
|
||||
severity: Přísnost
|
||||
show:
|
||||
affected_accounts:
|
||||
one: Jeden účet v databázi byl ovlivněn
|
||||
other: "%{count} účtů v databázi byl ovlivněn"
|
||||
retroactive:
|
||||
silence: Odtišit všechny existující účty z této domény
|
||||
suspend: Zrušit suspenzaci všech existujících účtů z této domény
|
||||
title: Zrušit blokaci domény %{domain}
|
||||
undo: Odvolat
|
||||
title: Doménové blokace
|
||||
undo: Odvolat
|
||||
email_domain_blocks:
|
||||
add_new: Přidat nový
|
||||
created_msg: E-mailová doména úspěšně přidána na černou listinu
|
||||
delete: Smazat
|
||||
destroyed_msg: E-mailová doména úspěšně odstraněna z černé listiny
|
||||
domain: Doména
|
||||
new:
|
||||
create: Přidat doménu
|
||||
title: Nový e-mail pro zablokování
|
||||
title: Černá listina e-mailů
|
||||
instances:
|
||||
account_count: Známé účty
|
||||
domain_name: Doména
|
||||
reset: Resetovat
|
||||
search: Hledat
|
||||
title: Známé instance
|
||||
invites:
|
||||
filter:
|
||||
all: Vše
|
||||
available: Dostupné
|
||||
expired: Vypršelé
|
||||
title: Filtrovat
|
||||
title: Pozvánky
|
||||
relays:
|
||||
add_new: Přidat nový most
|
||||
description_html: "<strong>Federovací most</strong> je přechodný server, který vyměňuje velká množství veřejných tootů mezi servery, které z něj odebírají a poblikují na něj. <strong>Může pomoci malým a středně velkým serverům objevovat obsah z fediverse</strong>, což by jinak vyžadovalo, aby místní uživatelé manuálně sledovali jiné lidi na vzdálených serverech."
|
||||
enable_hint: Je-li tohle povoleno, začne váš server odebírat všechny veřejné tooty z tohoto mostu a odesílat na něj své vlastní veřejné tooty.
|
||||
inbox_url: URL mostu
|
||||
setup: Nastavit připojení k mostu
|
||||
status: Stav
|
||||
title: Mosty
|
||||
report_notes:
|
||||
created_msg: Poznámka o nahlášení úspěšně vytvořena!
|
||||
destroyed_msg: Poznámka o nahlášení úspěšně smazána!
|
||||
reports:
|
||||
account:
|
||||
note: poznámka
|
||||
report: nahlášení
|
||||
action_taken_by: Akci vykonal/a
|
||||
are_you_sure: Jste si jistý/á?
|
||||
assign_to_self: Přidělit ke mně
|
||||
assigned: Přiřazený moderátor
|
||||
comment:
|
||||
none: Žádné
|
||||
created_at: Nahlášené
|
||||
id: ID
|
||||
mark_as_resolved: Označit jako vyřešené
|
||||
mark_as_unresolved: Označit jako nevyřešené
|
||||
notes:
|
||||
create: Přidat poznámku
|
||||
create_and_resolve: Vyřešit s poznámkou
|
||||
create_and_unresolve: Znovu otevřít s poznámkou
|
||||
delete: Smazat
|
||||
placeholder: Popište, jaké akce byly vykonány, nebo jakékoliv jiné související aktuality...
|
||||
reopen: Znovu otevřít nahlášení
|
||||
report: 'Nahlásit #%{id}'
|
||||
report_contents: Obsah
|
||||
reported_account: Nahlášený účet
|
||||
reported_by: Nahlášeno uživatelem
|
||||
resolved: Vyřešeno
|
||||
resolved_msg: Nahlášení úspěšně vyřešeno!
|
||||
silence_account: Utišit účet
|
||||
status: Stav
|
||||
suspend_account: Suspendovat účet
|
||||
target: Cíl
|
||||
title: Nahlášení
|
||||
unassign: Odebrat
|
||||
unresolved: Nevyřešeno
|
||||
updated_at: Aktualizováno
|
||||
view: Zobrazit
|
||||
settings:
|
||||
activity_api_enabled:
|
||||
desc_html: Počty lokálně publikovaných statusů, aktivních uživatelů a nových registrací, v týdenních intervalech
|
||||
title: Publikovat hromadné statistiky o uživatelské aktivitě
|
||||
bootstrap_timeline_accounts:
|
||||
desc_html: Je-li uživatelskch jmen více, oddělujte je čárkami. Lze zadat pouze místní a odemknuté účty. Je-li tohle prázdné, jsou výchozí hodnotou všichni místní administrátoři.
|
||||
title: Výchozí sledování pro nové uživatele
|
||||
contact_information:
|
||||
email: Pracovní e-mail
|
||||
username: Uživatelské jméno kontaktu
|
||||
hero:
|
||||
desc_html: Zobrazuje se na hlavní stránce. Doporučuje se rozlišení alespoň 600x100px. Pokud toto není nastavené, bude zobrazena miniatura instance
|
||||
title: Hlavní obrázek
|
||||
peers_api_enabled:
|
||||
desc_html: Domény, na které tato instanve narazila ve fediverse
|
||||
title: Zveřejnit seznam objevených instancí
|
||||
preview_sensitive_media:
|
||||
desc_html: Náhledy odkazů na jiných stránkách budou zobrazeny i pokud jsou media označena jako citlivá
|
||||
title: Zobrazovat v náhledech OpenGraph i citlivá média
|
||||
registrations:
|
||||
closed_message:
|
||||
desc_html: Zobrazí se na hlavní stránce, jsou-li registrace uzavřeny. Můžete použít i HTML značky
|
||||
title: Zpráva o uzavřených registracích
|
||||
deletion:
|
||||
desc_html: Dovolit každému smazání svého účtu
|
||||
title: Zpřístupnit smazání účtu
|
||||
min_invite_role:
|
||||
disabled: Nikdo
|
||||
title: Povolit pozvánky od
|
||||
open:
|
||||
desc_html: Povolit každému vytvořit si účet
|
||||
title: Zpřístupnit registraci
|
||||
show_known_fediverse_at_about_page:
|
||||
desc_html: Je-li toto zapnuto, zobrazí se v náhledu tooty ze všech známých serverů na fediverse. Jinak budou zobrazeny pouze místní tooty.
|
||||
title: Zobrazit celou známou fediverse na náhledu časové osy
|
||||
show_staff_badge:
|
||||
desc_html: Zobrazit na stránce uživatele odznak člena personálu
|
||||
title: Zobrazit odznak personálu
|
||||
site_description:
|
||||
desc_html: Úvodní odstavec na hlavní straně a v meta značkách. Můžete zde používat HTML značky, hlavně <code><a></code> a <code><em></code>.
|
||||
title: Popis instance
|
||||
site_description_extended:
|
||||
desc_html: Dobré místo pro vaše pravidla, pokyny a jiné věci, které vaši instanci odlišují od ostatních. Lze použít HTML značky
|
||||
title: Vlastní doplňujísí informace
|
||||
site_terms:
|
||||
desc_html: Můžete si napsat vlastní zásady soukromí, podmínky používání či jiné legality. Můžete použít HTML značky
|
||||
title: Vlastní podmínky používání
|
||||
site_title: Název instance
|
||||
thumbnail:
|
||||
desc_html: Používáno pro náhledy přes OpenGraph a API. Doporučuje se rozlišení 1200x630px
|
||||
title: Miniatura instance
|
||||
timeline_preview:
|
||||
desc_html: Zobrazit na hlavní straně veřejnou časovou osu
|
||||
title: Náhled časové osy
|
||||
title: Nastavení stránky
|
||||
statuses:
|
||||
back_to_account: Zpět na stránku účtu
|
||||
batch:
|
||||
delete: Vymazat
|
||||
nsfw_off: Označit, že není citlivý
|
||||
nsfw_on: Označit jako citlivý
|
||||
failed_to_execute: Nepodařilo se vykonat
|
||||
media:
|
||||
title: Média
|
||||
no_media: Žádná média
|
||||
title: Statusy účtů
|
||||
with_media: S médii
|
||||
subscriptions:
|
||||
callback_url: Zpáteční URL
|
||||
confirmed: Potvrzeno
|
||||
expires_in: Vyprší v
|
||||
last_delivery: Poslední doručení
|
||||
title: WebSub
|
||||
topic: Téma
|
||||
title: Administrace
|
||||
admin_mailer:
|
||||
new_report:
|
||||
body: "%{reporter} nahlásil/a uživatele %{target}"
|
||||
body_remote: Někdo z %{domain} nahlásil uživatele %{target}
|
||||
subject: Nové nahlášení pro %{instance} (#%{id})
|
||||
application_mailer:
|
||||
notification_preferences: Změnit volby e-mailu
|
||||
salutation: "%{name},"
|
||||
settings: 'Změnit volby e-mailu: %{link}'
|
||||
view: 'Zobrazit:'
|
||||
view_profile: Zobrazit profil
|
||||
view_status: Zobrazit status
|
||||
applications:
|
||||
created: Aplikace úspěšně vytvořena
|
||||
destroyed: Aplikace úspěšně smazána
|
||||
invalid_url: Zadaná adresa URL je neplatná
|
||||
regenerate_token: Znovu vygenerovat přístupový token
|
||||
token_regenerated: Přístupový token byl úspěšně vygenerován
|
||||
warning: Buďte s těmito daty velmi opatrní. Nikdy je s nikým nesdílejte!
|
||||
your_token: Váš přístupový token
|
||||
auth:
|
||||
agreement_html: Registrací souhlasíte s následováním <a href="%{rules_path}">pravidel této instance</a> a <a href="%{terms_path}">našich podmínek používání</a>.
|
||||
change_password: Heslo
|
||||
confirm_email: Potvrdit e-mail
|
||||
delete_account: Odstranit účet
|
||||
delete_account_html: Chcete-li odstranit svůj účet, <a href="%{path}">pokračujte zde</a>. Budete požádán/a o potvrzení.
|
||||
didnt_get_confirmation: Neobdržel/a jste pokyny pro potvrzení?
|
||||
forgot_password: Zapomněl/a jste heslo?
|
||||
invalid_reset_password_token: Token na obnovu hesla je buď neplatný, nebo vypršel. Prosím vyžádejte si nový.
|
||||
login: Přihlásit
|
||||
logout: Odhlásit
|
||||
migrate_account: Přesunout se na jiný účet
|
||||
migrate_account_html: Chcete-li přesměrovat tento účet na jiný, můžete to <a href="%{path}">nastavit zde</a>.
|
||||
or: nebo
|
||||
or_log_in_with: Nebo se přihlaste pomocí
|
||||
providers:
|
||||
cas: CAS
|
||||
saml: SAML
|
||||
register: Registrovat
|
||||
register_elsewhere: Registrovat na jiném serveru
|
||||
resend_confirmation: Znovu odeslat pokyny pro potvrzení
|
||||
reset_password: Obnovit heslo
|
||||
security: Zabezpečení
|
||||
set_new_password: Nastavit nové heslo
|
||||
authorize_follow:
|
||||
already_following: Tento účet již sledujete
|
||||
error: Při hledání vzdáleného účtu bohužel nastala chyba
|
||||
follow: Sledovat
|
||||
follow_request: 'Poslal/a jste žádost o sledování uživateli:'
|
||||
following: 'Podařilo se! Nyní sledujete uživatele:'
|
||||
post_follow:
|
||||
close: Nebo můžete toto okno klidně zavřít.
|
||||
return: Zobrazit profil uživatele
|
||||
web: Přejít na web
|
||||
title: Sledovat uživatele %{acct}
|
||||
datetime:
|
||||
distance_in_words:
|
||||
about_x_hours: "%{count} hod"
|
||||
about_x_months: "%{count} měsíců"
|
||||
about_x_years: "%{count} let"
|
||||
almost_x_years: "%{count} let"
|
||||
half_a_minute: Právě teď
|
||||
less_than_x_minutes: "%{count} min"
|
||||
less_than_x_seconds: Právě teď
|
||||
over_x_years: "%{count} let"
|
||||
x_days: "%{count} dní"
|
||||
x_minutes: "%{count} min"
|
||||
x_months: "%{count} mesíců"
|
||||
x_seconds: "%{count} s"
|
||||
deletes:
|
||||
bad_password_msg: Dobrý pokus, hackeři! Nesprávné heslo
|
||||
confirm_password: Zadejte svoje současné heslo pro ověření vaší identity
|
||||
description_html: Tímto <strong>trvale a nenávratně</strong> odstraníte obsah z vašeho účtu a deaktivuje ho. Vaše uživatelské jméno zůstane rezervované pro zabránění budoucím napodobováním.
|
||||
proceed: Odstranit účet
|
||||
success_msg: Váš účet byl úspěšně odstraněn
|
||||
warning_html: Pouze vymazání obsahu z této konkrétní instance je zaručeno. Obsah, který byl široce sdílen, po sobě pravděpodobně zanechá stopy. U offline serverů a serverů, které vaše aktualizace již neodebírají, nebudou databáze aktualizovány.
|
||||
warning_title: Dostupnost rozšířeného obsahu
|
||||
errors:
|
||||
'403': Nemáte povolení zobrazit tuto stránku.
|
||||
'404': Stránka, kterou hledáte, neexistuje.
|
||||
'410': Stránka, kterou hledáte, již neexistuje.
|
||||
'422':
|
||||
content: Bezpečnostní ověření selhalo. Neblokujete cookoes?
|
||||
title: Bezpečnostní ověření selhalo
|
||||
'429': Příliš mnoho požadavků
|
||||
'500':
|
||||
content: Omlouváme se, ale něco se pokazilo u nás.
|
||||
title: Tato stránka není správná
|
||||
noscript_html: Pro použití webové aplikace Mastodon prosím povolte JavaScript. Nebo zkuste jednu z <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">nativních aplikací</a> pro Mastodon pro vaši platformu.
|
||||
exports:
|
||||
archive_takeout:
|
||||
date: Datum
|
||||
download: Stáhnout svůj archiv
|
||||
hint_html: Můžete si vyžádat archiv vašich <strong>tootů a nahraných médií</strong>. Exportovaná data budou ve formátu ActivityPub a budou čitelné kterýmkoliv kompatibilním softwarem. Archiv si můžete vyžádat každých 7 dní.
|
||||
in_progress: Kompiluji váš archiv...
|
||||
request: Vyžádat svůj archiv
|
||||
size: Velikost
|
||||
blocks: Blokujete
|
||||
csv: CSV
|
||||
follows: Sledujete
|
||||
mutes: Ignorujete
|
||||
storage: Úložisko médií
|
||||
filters:
|
||||
contexts:
|
||||
home: Domovská časová osa
|
||||
notifications: Oznámení
|
||||
public: Veřejný časové osy
|
||||
thread: Konverzace
|
||||
edit:
|
||||
title: Upravit filtr
|
||||
errors:
|
||||
invalid_context: Nebylo poskytnuto nic, nebo má neplatný kontext
|
||||
invalid_irreversible: Nezvratné filtrování funguje pouze v souvislosti s domovskou osou či oznámeními
|
||||
index:
|
||||
delete: Smazat
|
||||
title: Filtry
|
||||
new:
|
||||
title: Přidat nový filtr
|
||||
followers:
|
||||
domain: Doména
|
||||
explanation_html: Chcete-li zaručit soukromí vašich statusů, musíte mít na vědomí, kdo vás sleduje. <strong>Vaše soukromé statusy jsou doručeny na všechny instance, kde máte sledovatele</strong>. Nejspíš si je budete chtít zkontrolovat a odstranit sledovatele na instancích, jejichž personálu či softwaru nedůvěřujete s respektováním vašeho soukromí.
|
||||
followers_count: Počet sledovatelů
|
||||
lock_link: Zamkněte svůj účet
|
||||
purge: Odstranit ze sledovatelů
|
||||
success:
|
||||
one: V průběhu utišování sledovatelů z jedné domény...
|
||||
other: V průběhu utišování sledovatelů z %{count} domén...
|
||||
true_privacy_html: Berte prosím na vědomí, že <strong>skutečného soukromí se dá dosáhnout pouze za pomoci end-to-end šifrování</strong>.
|
||||
unlocked_warning_html: Kdokoliv vás může sledovat a okamžitě vidět vaše soukromé statusy. %{lock_link}, abyste mohl/a zkontrolovat a odmítnout sledovatele.
|
||||
unlocked_warning_title: Váš účet není zamknutý
|
||||
generic:
|
||||
changes_saved_msg: Změny byly úspěšně uloženy!
|
||||
save_changes: Uložit změny
|
||||
validation_errors:
|
||||
one: Něco ještě není úplně v pořádku! Prosím zkontrolujte chybu níže
|
||||
other: Něco ještě není úplně v pořádku! Prosím zkontrolujte %{count} chyb níže
|
||||
imports:
|
||||
preface: Můžete importovat data, která jste exportoval/a z jiné instance, jako například seznam lidí, které sledujete či blokujete.
|
||||
success: Vaše data byla úspěšně nahrána a nyní budou zpracována v daný čas
|
||||
types:
|
||||
blocking: Seznam blokovaných
|
||||
following: Seznam sledovaných
|
||||
muting: Seznam ignorovaných
|
||||
upload: Nahrát
|
||||
in_memoriam_html: Navždy budeme vzpomínat.
|
||||
invites:
|
||||
delete: Deaktivovat
|
||||
expired: Vypršelé
|
||||
expires_in:
|
||||
'1800': 30 minut
|
||||
'21600': 6 hodin
|
||||
'3600': 1 hodina
|
||||
'43200': 12 hodin
|
||||
'604800': 1 týden
|
||||
'86400': 1 den
|
||||
expires_in_prompt: Nikdy
|
||||
generate: Vygenerovat
|
||||
invited_by: 'Byl/a jste pozván/a uživatelem:'
|
||||
max_uses:
|
||||
one: 1 použití
|
||||
other: "%{count} použití"
|
||||
max_uses_prompt: Bez limitu
|
||||
prompt: Vygenerujte a sdílejte s ostatními odkazy a umožněte jim přístup na tuto instanci
|
||||
table:
|
||||
expires_at: Vyprší
|
||||
uses: Použití
|
||||
title: Pozvěte lidi
|
||||
lists:
|
||||
errors:
|
||||
limit: Dosáhl/a jste maximálního počtu seznamů
|
||||
media_attachments:
|
||||
validations:
|
||||
images_and_video: Ke statusu, který již obsahuje obrázky, nelze připojit video
|
||||
too_many: Nelze připojit více než 4 soubory
|
||||
migrations:
|
||||
acct: přezdívka@doména nového účtu
|
||||
currently_redirecting: 'Váš profil má nastaveno přesměrování na:'
|
||||
proceed: Uložit
|
||||
updated_msg: Vaše nastavení migrace účtu bylo úspěšně aktualizováno!
|
||||
moderation:
|
||||
title: Moderace
|
||||
notification_mailer:
|
||||
digest:
|
||||
action: Zobrazit všechna oznámení
|
||||
body: Zde najdete stručný souhrn zpráv, které jste zmeškal/a od vaší poslední návštěvy %{since}
|
||||
mention: "%{name} vás zmínil/a v:"
|
||||
new_followers_summary:
|
||||
one: Navíc jste získal/a jednoho nového sledovatele, zatímco jste byl/a pryč! Hurá!
|
||||
other: Navíc jste získal/a %{count} nových sledovatelů, zatímco jste byl/a pryč! Hurá!
|
||||
subject:
|
||||
one: "Jedno nové oznámení od vaší poslední návštěvy \U0001F418"
|
||||
other: "%{count} nových oznámení od vaší poslední návštěvy \U0001F418"
|
||||
title: Ve vaší absenci...
|
||||
favourite:
|
||||
body: 'Váš status si oblíbil/a %{name}:'
|
||||
subject: "%{name} si oblíbil/a váš status"
|
||||
title: Nové oblíbení
|
||||
follow:
|
||||
body: "%{name} vás nyní sleduje!"
|
||||
subject: "%{name} vás nyní sleduje"
|
||||
title: Nový sledovatel
|
||||
follow_request:
|
||||
action: Spravovat žádosti o sledování
|
||||
body: "%{name} žádá o povolení vás následovat"
|
||||
subject: 'Čekající sledovatel: %{name}'
|
||||
title: Nová žádost o sledování
|
||||
mention:
|
||||
action: Odpovědět
|
||||
body: 'Byl/a jste zmíněn/a uživatelem %{name} v:'
|
||||
subject: Byl/a jste zmíněn/a uživatelem %{name}
|
||||
title: Nová zmínka
|
||||
reblog:
|
||||
body: 'Váš status byl boostnutý uživatelem %{name}:'
|
||||
subject: "%{name} boostnul/a váš status"
|
||||
title: Nové boostnutí
|
||||
number:
|
||||
human:
|
||||
decimal_units:
|
||||
format: "%n %u"
|
||||
units:
|
||||
billion: mld
|
||||
million: mil
|
||||
quadrillion: bld
|
||||
thousand: tis
|
||||
trillion: T
|
||||
pagination:
|
||||
newer: Novější
|
||||
next: Starší
|
||||
older: Starší
|
||||
prev: Před
|
||||
truncate: "…"
|
||||
preferences:
|
||||
languages: Jazyky
|
||||
other: Ostatní
|
||||
publishing: Publikování
|
||||
web: Web
|
||||
remote_follow:
|
||||
acct: Napište svou přezdívku@doménu, ze které chcete sledovat
|
||||
missing_resource: Nemůžeme najít požadované přesměrovací URL pro váš účet
|
||||
no_account_html: Ještě nemáte účet? Můžete se <a href='%{sign_up_path}' target='_blank'>registrovat zde</a>
|
||||
proceed: Pokračujte pro sledování
|
||||
prompt: 'Budete sledovat:'
|
||||
remote_unfollow:
|
||||
error: Chyba
|
||||
title: Nadpis
|
||||
unfollowed: Už nesledujete
|
||||
sessions:
|
||||
activity: Nejnovější aktivita
|
||||
browser: Prohlížeč
|
||||
browsers:
|
||||
alipay: Alipay
|
||||
blackberry: Blackberry
|
||||
chrome: Chrome
|
||||
edge: Microsoft Edge
|
||||
electron: Electron
|
||||
firefox: Firefox
|
||||
generic: Neznámý prohlížeč
|
||||
ie: Internet Explorer
|
||||
micro_messenger: MicroMessenger
|
||||
nokia: Nokia S40 Ovi Browser
|
||||
opera: Opera
|
||||
otter: Otter
|
||||
phantom_js: PhantomJS
|
||||
qq: QQ Browser
|
||||
safari: Safari
|
||||
uc_browser: UCBrowser
|
||||
weibo: Weibo
|
||||
current_session: Aktuální relace
|
||||
description: "%{browser} na %{platform}"
|
||||
explanation: Toto jsou webové prohlížeče aktuálně přihlášené na váš účet Mastodon.
|
||||
ip: IP
|
||||
platforms:
|
||||
adobe_air: Adobe Air
|
||||
android: Android
|
||||
blackberry: Blackberry
|
||||
chrome_os: Chrome OS
|
||||
firefox_os: Firefox OS
|
||||
ios: iOS
|
||||
linux: Linux
|
||||
mac: Mac
|
||||
other: neznámé platformě
|
||||
windows: Windows
|
||||
windows_mobile: Windows Mobile
|
||||
windows_phone: Windows Phone
|
||||
revoke: Zamítnout
|
||||
revoke_success: Relace úspěšně zamítnuta
|
||||
title: Relace
|
||||
settings:
|
||||
authorized_apps: Autorizované aplikace
|
||||
back: Zpět na Mastodon
|
||||
delete: Smazání účtu
|
||||
development: Vývoj
|
||||
edit_profile: Upravit profil
|
||||
export: Export dat
|
||||
followers: Autorizovaní sledovatelé
|
||||
import: Import
|
||||
migrate: Přesunutí účtu
|
||||
notifications: Oznámení
|
||||
preferences: Předvolby
|
||||
settings: Nastavení
|
||||
two_factor_authentication: Dvoufaktorové ověřování
|
||||
your_apps: Vaše aplikace
|
||||
statuses:
|
||||
attached:
|
||||
description: 'Přiloženo: %{attached}'
|
||||
image:
|
||||
one: "%{count} obrázek"
|
||||
other: "%{count} obrázků"
|
||||
video:
|
||||
one: "%{count} video"
|
||||
other: "%{count} videí"
|
||||
boosted_from_html: Boostnuto z %{acct_link}
|
||||
content_warning: 'Varování o obsahu: %{warning}'
|
||||
disallowed_hashtags:
|
||||
one: 'obsahuje nepovolený hashtag: %{tags}'
|
||||
other: 'obsahuje nepovolené hashtagy: %{tags}'
|
||||
language_detection: Zjistit jazyk automaticky
|
||||
open_in_web: Otevřít na webu
|
||||
over_character_limit: limit %{max} znaků byl překročen
|
||||
pin_errors:
|
||||
limit: Už jste si připnul/a maximální počet tootů
|
||||
ownership: Nelže připnout toot někoho jiného
|
||||
private: Nelze připnout neveřejné tooty
|
||||
reblog: Nelze připnout boostnutí
|
||||
show_more: Zobrazit více
|
||||
title: '%{name}: "%{quote}"'
|
||||
visibilities:
|
||||
private: Pouze pro sledovatele
|
||||
private_long: Zobrazit pouze sledovatelům
|
||||
public: Veřejné
|
||||
public_long: Všichni mohou vidět
|
||||
unlisted: Neuvedené
|
||||
unlisted_long: Všichni mohou vidět, ale není zahrnut ve veřejných časových osách
|
||||
stream_entries:
|
||||
pinned: Připnutý toot
|
||||
reblogged: boostnutý
|
||||
sensitive_content: CItlivý obsah
|
||||
terms:
|
||||
body_html: |
|
||||
<h2>Zásady soukromí</h2>
|
||||
<h3 id="collect">Jaké informace sbíráme?</h3>
|
||||
|
||||
<ul>
|
||||
<li><em>Základní informace o účtu</em>: Pokud se na tomto serveru zaregistrujete, můžeme vás požádat o zadání uživatelského jména, e-mailové adresy a hesla. Můžete také zadat dodatečné profilové informace, jako například zobrazované jméno a krátký životopis, a nahrát si profilovou fotografii a hlavičkový obrázek. Uživatelské i zobrazované jméno, životopis, profilová fotografie a hlavičkový obrázek jsou vždy uvedeny veřejně.</li>
|
||||
<li><em>Příspěvky, sledovatelé a další veřejné informace</em>: Seznam lidí, které sledujete, je uveden veřejně, totéž platí i pro vaše sledovatele. Když sem nahrajete zprávu, bude uloženo datum a čas, společně s aplikací, ze které jste zprávu odeslali. Zprávy mohou obsahovat mediální přílohy, jako jsou obrázky a videa. Veřejné a nezobrazované příspěvky jsou dostupné veřejně. Pokud na vašem profilu uvedete příspěvek, je to také veřejně dostupná informace. Vaše příspěvky jsou doručeny vašim sledovatelům, což v některých případech znamená, že budou doručeny na různé servery, na kterých budou ukládány kopie. Pokud příspěvky smažete, bude tohle taktéž doručeno vašim sledovatelům. Akce znovusdílení nebo oblíbení jiného příspěvku je vždy veřejná.</li>
|
||||
<li><em>Příspěvky přímé a pouze pro sledovatele</em>: Všechny příspěvky jsou uloženy a zpracovány na serveru. Příspěvky pouze pro sledovatele jsou doručeny vašim sledovatelům a uživateům v nich zmíněných a přímé příspěvky jsou doručeny pouze uživatelům v nich zmíněných. V některých případech tohle znamená, že budou doručeny na různé servery, na kterých budou ukládány kopie. Snažíme se omezit přístup k těmto příspěvkům pouze na autorizované uživatele, ovšem jiné servery tak nemusejí učinit. Proto je důležité posoudit servery, ke kterým vaši sledovatelé patří. V nastavení si můžete zapnout volbu pro manuální schvalování či odmítnutí nových sledovatelů. <em>Prosím mějte na paměti, že operátoři tohoto serveru a kteréhokoliv přijímacího serveru mohou tyto zprávy vidět</em> a příjemci mohou vytvořit jejich snímek, zkopírovat je, nebo je jinak sdílet. <em>Nesdílejte přes Mastodon jakékoliv nebezpečné informace.</em></li>
|
||||
<li><em>IP adresy a další metadata</em>: Když se přihlásíte, zaznamenáváme IP adresu, ze které se přihlašujete, jakožto i název vašeho webového prohlížeče. Všechny vaše webové relace jsou v nastavení přístupné k vašemu posouzení a odvolání. Nejpozdější IP adresa použita je uložena maximálně do 12 měsíců. Můžeme také uchovávat serverové záznamy, které obsahují IP adresy každého požadavku odeslaného na náš server.</li>
|
||||
</ul>
|
||||
|
||||
<hr class="spacer" />
|
||||
|
||||
<h3 id="use">Na co používáme vaše informace?</h3>
|
||||
|
||||
<p>Jakékoliv informace, které sbíráme, mohou být použity následujícími způsoby:</p>
|
||||
|
||||
<ul>
|
||||
<li>K poskytnutí základních funkcí Mastodonu. Interagovat s obsahem od jiných lidí a přispívat svým vlastním obsahem můžete pouze, pokud jste přihlášeni. Můžete například sledovat jiné lidi a zobrazit si jejich kombinované příspěvky ve vaší vlastní personalizované časové ose.</li>
|
||||
<li>Pro pomoc moderaci komunity, například porovnáním vaší IP adresy s dalšími známými adresami pro určení vyhýbání se zákazům či jiných přestupků.</li>
|
||||
<li>E-mailová adresa, kterou nám poskytnete, může být použita pro zasílání informací, oznámení o interakcích jiných uživatelů s vaším obsahem nebo přijatých zprávách a k odpovědím na dotazy a/nebo další požadavky či otázky.</li>
|
||||
</ul>
|
||||
|
||||
<hr class="spacer" />
|
||||
|
||||
<h3 id="protect">Jak vaše informace chráníme?</h3>
|
||||
|
||||
<p>Implenentujeme různá bezpečnostní opatření pro udržování bezpečnosti vašich osobních dat, když zadáváte, odesíláte, či přistupujete k vašim osobním datům. Mimo jiné je vaše relace v prohlížeči, jakož i provoz mezi vašimi aplikacemi a API, zabezpečena pomocí SSL, a vaše heslo je hashováno pomocí silného jednosměrného algoritmu. Pro větší zabezpečení vašeho účtu můžete povolit dvoufaktorovou autentikaci.</p>
|
||||
|
||||
<hr class="spacer" />
|
||||
|
||||
<h3 id="data-retention">Jaké jsou naše zásady o uchovávání údajů?</h3>
|
||||
|
||||
<p>Budeme se snažit:</p>
|
||||
|
||||
<ul>
|
||||
<li>Uchovávat serverové záznamy obsahující IP adresy všech požadavků pro tento server, pokud se takové záznamy uchovávají, maximálně 90 dní.</li>
|
||||
<li>Uchovávat IP adresy související s registrovanými uživateli maximálně 12 měsíců.</li>
|
||||
</ul>
|
||||
|
||||
<p>Kdykoliv si můžete vyžádat a stáhnout archiv vašeho obsahu, včetně vašich příspěvků, mediálních příloh, profilové fotografie a hlavičkového obrázku.</p>
|
||||
|
||||
<p>Kdykoliv můžete nenávratně smazat váš účet.</p>
|
||||
|
||||
<hr class="spacer"/>
|
||||
|
||||
<h3 id="cookies">Používáme cookies?</h3>
|
||||
|
||||
<p>Ano. Cookies jsou malé soubory, které stránka nebo její poskytovatel uloží na pevný disk vašeho počítače (pokud to dovolíte). Tyto cookies umožňují stránce rozpoznat váš prohlížeč a, pokud máte registrovaný účet, přidružit ho s vaším registrovaným účtem.</p>
|
||||
|
||||
<p>POužíváme cookies pro pochopení a ukládání vašich předvoleb pro budoucí návštěvy.</p>
|
||||
|
||||
<hr class="spacer" />
|
||||
|
||||
<h3 id="disclose">Zveřejňujeme jakékoliv informace třetím stranám?</h3>
|
||||
|
||||
<p>Vaše osobně identifikovatelné informace neprodáváme, neobchodujeme s nimi, ani je nijak nepřenášíme vnějším stranám. Do tohoto se nepočítají důvěryhodné třetí strany, které nám pomáhají provozovat naši stránku, podnikat, nebo vás obsluhovat, pokud tyto strany souhlasí se zachováním důvěrnosti těchto informací. Můžeme také uvolnit vaše informace, pokud věříme, že je to nutné pro soulad se zákonem, prosazování našich zásad, nebo ochranu práv, majetku, či bezpečnost nás či ostatních.</p>
|
||||
|
||||
<p>Váš veřejný obsah může být stažen jinými servery na síti. Vaše příspěvky veřejné a pouze pro sledovatele budou doručeny na servery vašich sledovatelů a přímé zprávy budou doručeny na servery příjemců, pokud jsou tito sledovatelé nebo příjemci zaregistrováni na jiném serveru, než je tento.</p>
|
||||
|
||||
<p>Když autorizujete aplikaci, aby používala váš účet, může, v závislosti na rozsahu oprávnění, které jí udělíte, přistupovat k vašim veřejným profilovým informacím, seznamu lidí, které sledujete, vašim sledovatelům, vašim seznamům, všem vašim příspěvkům a příspěvkům, které jste si oblíbili. Aplikace nikdy nemohou získat vaši e-mailovou adresu či heslo.</p>
|
||||
|
||||
<hr class="spacer" />
|
||||
|
||||
<h3 id="children">Používání stránky dětmi</h3>
|
||||
|
||||
<p>Pokud se tento server nachází v EU nebo EHP: Naše stránka, produkty a služby jsou všechny směřovány na lidi, kterým je alespoň 16 let. Pokud je vám méně než 16, dle požadavků nařízení GDPR (<a href="https://cs.wikipedia.org/wiki/Obecn%C3%A9_na%C5%99%C3%ADzen%C3%AD_o_ochran%C4%9B_osobn%C3%ADch_%C3%BAdaj%C5%AF">Obecné nařízení o ochě sobních údajů</a>) </p>
|
||||
|
||||
<p>Pokud se tento server nachází v USA: Naše stránka, produkty a služby jsou všechny směřovány na lidi, kterým je alespoň 13 let. Pokud je vám méně než 13, dle požadavků zákona COPPA (<a href="https://cs.wikipedia.org/wiki/Children%27s_online_privacy_protection_act">Children's Online Privacy Protection Act</a>) tuto stránku nepoužívejte.</p>
|
||||
|
||||
<p>Právní požadavky mohou být jiné, pokud se tento server nachází v jiné jurisdikci.</p>
|
||||
|
||||
<hr class="spacer" />
|
||||
|
||||
<h3 id="changes">Změny v našich zásadách soukromí</h3>
|
||||
|
||||
<p>Rozhodneme-li se naše zásady soukromí změnit, zveřejníme tyto změny na této stránce.</p>
|
||||
|
||||
<p>Tento dokument je dostupný pod licencí CC-BY-SA. Byl naposledy aktualizován 7 března 2018.</p>
|
||||
|
||||
<p>Původně adaptováno ze <a href="https://github.com/discourse/discourse">zásad soukromí Discourse</a>.</p>
|
||||
title: Podmínky používání a zásady soukromí %{instance}
|
||||
themes:
|
||||
contrast: Vysoký kontrast
|
||||
default: Mastodon
|
||||
mastodon-light: Mastodon (světlý)
|
||||
time:
|
||||
formats:
|
||||
default: "%d. %b %Y, %H:%M"
|
||||
two_factor_authentication:
|
||||
code_hint: Pro potvrzení zadejte kód vygenerovaný vaší autentikační aplikací
|
||||
description_html: Povolíte-li <strong>dvoufaktorové ověřování</strong>, budete při přihlášení potřebovat telefon, který vám vygeneruje přístupové tokeny, které musíte zadat.
|
||||
disable: Zakázat
|
||||
enable: Povolit
|
||||
enabled: Dvoufaktorové ověřování je povoleno
|
||||
enabled_success: Dvoufaktorové ověřování bylo úspěšně povoleno
|
||||
generate_recovery_codes: Vygenerovat záložní kódy
|
||||
instructions_html: "<strong>Naskenujte tento QR kód Google Authenticatorem nebo jinou TOTP aplikací na vašem telefonu</strong>. Od teď bude tato aplikace generovat tokeny, které budete muset zadat při přihlášení."
|
||||
lost_recovery_codes: Záložní kódy vám dovolí dostat se k vašemu účtu, pokud ztratíte telefon. Ztratíte-li záložní kódy, můžete je zde znovu vygenerovat. Vaše staré záložní kódy budou zneplatněny.
|
||||
manual_instructions: 'Nemůžete-li oskenovat QR kód a je potřebovat ho zadat ručně, zde je tajemství v prostém textu:'
|
||||
recovery_codes: Záložní kódy pro obnovu
|
||||
recovery_codes_regenerated: Záložní kódy byly úspěšně znovu vygenerované
|
||||
recovery_instructions_html: Ztratíte-li někdy přístup k vašemu telefonu, můžete k získání přístupu k účtu použít jeden ze záložních kódů. <strong>Uchovávejte tyto kódy v bezpečí</strong>. Můžete si je například vytisknout a uložit je mezi jiné důležité dokumenty.
|
||||
setup: Nastavit
|
||||
wrong_code: Zadaný kód byl neplatný! Je serverový čas a čas na zařízení správný?
|
||||
user_mailer:
|
||||
backup_ready:
|
||||
explanation: Vyžádal/a jste si úplnou zálohu svého účtu Mastodon. Nyní je připravena ke stažení!
|
||||
subject: Váš archiv je připraven ke stažení
|
||||
title: Stažení archivu
|
||||
welcome:
|
||||
edit_profile_action: Nastavit profil
|
||||
edit_profile_step: Můžete si přizpůsobit svůj profil nahráním avataru a obrázku na hlavičce, změnou zobrazovaného jména a dalších. Chcete-li posoudit nové sledovatele předtím, než vás mohou sledovat, můžete svůj účet uzamknout.
|
||||
explanation: Zde je pár tipů na začátek
|
||||
final_action: Začněte přispívat
|
||||
final_step: 'Začněte psát! I když nemáte sledovatele, mohou vaše zprávy vidět jiní lidé, například na místní časové ose a mezi hashtagy. Můžete se ostatním představit pomocí hashtagu #introductions.'
|
||||
full_handle: Vaše celá adresa profilu
|
||||
full_handle_hint: Tohle je, co byste řekl/a svým přátelům, aby vám mohli posílat zprávy nebo vás sledovat z jiné instance.
|
||||
review_preferences_action: Změnit nastavení
|
||||
review_preferences_step: Nezapomeňte si nastavit své volby, například jaké e-maily chcete přijímat či jak soukromé mají být vaše příspěvky ve výchozím stavu. Nemáte-li epilepsii, můžete si nastavit automatické přehrávání obrázků GIF.
|
||||
subject: Vítejte na Mastodonu
|
||||
tip_bridge_html: Pokud přicházíte z Twitteru, můžete najít vaše přátele na Mastodonu pomocí <a href="%{bridge_url}">mostové aplikace</a>. Funguje ovšem pouze, pokud ji oni někdy také použili!
|
||||
tip_federated_timeline: Federovaná časová osa je náhled celé sítě Mastodon. Zahrnuje ovšem pouze lidi, které sledují vaši sousedé, takže není úplná.
|
||||
tip_following: Administrátora/y serveru sledujete automaticky. Chcete-li najít další zajímavé lidi, podívejte se na místní a federované časové osy.
|
||||
tip_local_timeline: Místní časová osa je náhled lidí na %{instance}. Toto jsou vaši nejbližší sousedé!
|
||||
tip_mobile_webapp: Pokud vám váš mobilní prohlížeč nabídne přidat si Mastodon na vaši domovskou obrazovku, můžete dostávat oznámení. V mnoha ohledech to funguje jako nativní aplikace!
|
||||
tips: Tipy
|
||||
title: Vítejte na palubě, %{name}!
|
||||
users:
|
||||
invalid_email: E-mailová adresa je neplatná
|
||||
invalid_otp_token: Neplatný kód pro dvoufaktorovou autentikaci
|
||||
otp_lost_help_html: Pokud jste ztratil/a přístup k oběma, můžete se spojit %{email}
|
||||
seamless_external_login: Jste přihlášen/a přes externí službu, nastavení hesla a e-mailu proto nejsou dostupná.
|
||||
signed_in_as: 'Přihlášen/a jako:'
|
||||
|
|
|
@ -46,7 +46,6 @@ da:
|
|||
people_who_follow: Folk der følger %{name}
|
||||
posts: Dyt
|
||||
posts_with_replies: Toots og svar
|
||||
remote_follow: Følg fra andre instanser
|
||||
reserved_username: Brugernavnet er reserveret
|
||||
roles:
|
||||
admin: Administrator
|
||||
|
@ -464,7 +463,6 @@ da:
|
|||
unlocked_warning_title: Din konto er ikke låst
|
||||
generic:
|
||||
changes_saved_msg: Ændringerne blev gemt!
|
||||
powered_by: drevet af %{link}
|
||||
save_changes: Gem ændringer
|
||||
imports:
|
||||
types:
|
||||
|
@ -511,6 +509,9 @@ da:
|
|||
action: Se alle notifikationer
|
||||
mention: "%{name} nævnte dig i:"
|
||||
title: Mens du var væk...
|
||||
favourite:
|
||||
body: 'Din status blev favoriseret af %{name}:'
|
||||
subject: "%{name} favoriserede din status"
|
||||
follow:
|
||||
body: "%{name} følger dig nu!"
|
||||
subject: "%{name} følger dig nu"
|
||||
|
@ -538,18 +539,22 @@ da:
|
|||
preferences:
|
||||
languages: Sprog
|
||||
other: Andet
|
||||
publishing: Offentligører
|
||||
web: Web
|
||||
remote_unfollow:
|
||||
error: Fejl
|
||||
title: Titel
|
||||
unfollowed: Følger ikke længere
|
||||
sessions:
|
||||
activity: Sidste aktivitet
|
||||
browser: Browser
|
||||
browsers:
|
||||
blackberry: Blackberry OS
|
||||
chrome: Google Chrome
|
||||
firefox: Mozilla Firefox
|
||||
generic: Ukendt browser
|
||||
ie: IE
|
||||
safari: Apple Safari
|
||||
description: "%{browser} på %{platform}"
|
||||
ip: IP
|
||||
platforms:
|
||||
|
@ -583,7 +588,9 @@ da:
|
|||
content_warning: 'Advarsel om indhold: %{warning}'
|
||||
language_detection: Opfang automatisk sprog
|
||||
pin_errors:
|
||||
limit: Du har allerede fastgjort det maksimale antal trut
|
||||
ownership: Dun kan ikke fastgøre en anden persons toot
|
||||
private: Ikke offentlige trut kan ikke blive fastgjort
|
||||
show_more: Vis mere
|
||||
title: '%{name}: "%{quote}"'
|
||||
visibilities:
|
||||
|
@ -593,7 +600,6 @@ da:
|
|||
public_long: Alle kan se
|
||||
unlisted: Ikke listet
|
||||
stream_entries:
|
||||
click_to_show: Tryk for at vise
|
||||
pinned: Fastgjort toot
|
||||
sensitive_content: Følsomt indhold
|
||||
themes:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue