Remove code for rendering public and hashtag timelines outside the web UI (#19257)
This commit is contained in:
parent
e2b561e3a5
commit
02ba9cfa35
|
@ -1,32 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class DirectoriesController < ApplicationController
|
|
||||||
layout 'public'
|
|
||||||
|
|
||||||
before_action :authenticate_user!, if: :whitelist_mode?
|
|
||||||
before_action :require_enabled!
|
|
||||||
before_action :set_instance_presenter
|
|
||||||
before_action :set_accounts
|
|
||||||
|
|
||||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
|
||||||
|
|
||||||
def index
|
|
||||||
render :index
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def require_enabled!
|
|
||||||
return not_found unless Setting.profile_directory
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_accounts
|
|
||||||
@accounts = Account.local.discoverable.by_recent_status.page(params[:page]).per(20).tap do |query|
|
|
||||||
query.merge!(Account.not_excluded_by_account(current_account)) if current_account
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_instance_presenter
|
|
||||||
@instance_presenter = InstancePresenter.new
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,26 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class PublicTimelinesController < ApplicationController
|
|
||||||
layout 'public'
|
|
||||||
|
|
||||||
before_action :authenticate_user!, if: :whitelist_mode?
|
|
||||||
before_action :require_enabled!
|
|
||||||
before_action :set_body_classes
|
|
||||||
before_action :set_instance_presenter
|
|
||||||
|
|
||||||
def show; end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def require_enabled!
|
|
||||||
not_found unless Setting.timeline_preview
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_body_classes
|
|
||||||
@body_classes = 'with-modals'
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_instance_presenter
|
|
||||||
@instance_presenter = InstancePresenter.new
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -21,7 +21,7 @@ class TagsController < ApplicationController
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
expires_in 0, public: true
|
redirect_to web_path("tags/#{@tag.name}")
|
||||||
end
|
end
|
||||||
|
|
||||||
format.rss do
|
format.rss do
|
||||||
|
|
|
@ -198,10 +198,7 @@ module ApplicationHelper
|
||||||
|
|
||||||
def render_initial_state
|
def render_initial_state
|
||||||
state_params = {
|
state_params = {
|
||||||
settings: {
|
settings: {},
|
||||||
known_fediverse: Setting.show_known_fediverse_at_about_page,
|
|
||||||
},
|
|
||||||
|
|
||||||
text: [params[:title], params[:text], params[:url]].compact.join(' '),
|
text: [params[:title], params[:text], params[:url]].compact.join(' '),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import { expandHashtagTimeline } from 'mastodon/actions/timelines';
|
|
||||||
import Masonry from 'react-masonry-infinite';
|
|
||||||
import { List as ImmutableList } from 'immutable';
|
|
||||||
import DetailedStatusContainer from 'mastodon/features/status/containers/detailed_status_container';
|
|
||||||
import { debounce } from 'lodash';
|
|
||||||
import LoadingIndicator from 'mastodon/components/loading_indicator';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { hashtag }) => ({
|
|
||||||
statusIds: state.getIn(['timelines', `hashtag:${hashtag}`, 'items'], ImmutableList()),
|
|
||||||
isLoading: state.getIn(['timelines', `hashtag:${hashtag}`, 'isLoading'], false),
|
|
||||||
hasMore: state.getIn(['timelines', `hashtag:${hashtag}`, 'hasMore'], false),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
|
||||||
class HashtagTimeline extends React.PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
dispatch: PropTypes.func.isRequired,
|
|
||||||
statusIds: ImmutablePropTypes.list.isRequired,
|
|
||||||
isLoading: PropTypes.bool.isRequired,
|
|
||||||
hasMore: PropTypes.bool.isRequired,
|
|
||||||
hashtag: PropTypes.string.isRequired,
|
|
||||||
local: PropTypes.bool.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
local: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
const { dispatch, hashtag, local } = this.props;
|
|
||||||
|
|
||||||
dispatch(expandHashtagTimeline(hashtag, { local }));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLoadMore = () => {
|
|
||||||
const { dispatch, hashtag, local, statusIds } = this.props;
|
|
||||||
const maxId = statusIds.last();
|
|
||||||
|
|
||||||
if (maxId) {
|
|
||||||
dispatch(expandHashtagTimeline(hashtag, { maxId, local }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setRef = c => {
|
|
||||||
this.masonry = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleHeightChange = debounce(() => {
|
|
||||||
if (!this.masonry) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.masonry.forcePack();
|
|
||||||
}, 50)
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { statusIds, hasMore, isLoading } = this.props;
|
|
||||||
|
|
||||||
const sizes = [
|
|
||||||
{ columns: 1, gutter: 0 },
|
|
||||||
{ mq: '415px', columns: 1, gutter: 10 },
|
|
||||||
{ mq: '640px', columns: 2, gutter: 10 },
|
|
||||||
{ mq: '960px', columns: 3, gutter: 10 },
|
|
||||||
{ mq: '1255px', columns: 3, gutter: 10 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const loader = (isLoading && statusIds.isEmpty()) ? <LoadingIndicator key={0} /> : undefined;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Masonry ref={this.setRef} className='statuses-grid' hasMore={hasMore} loadMore={this.handleLoadMore} sizes={sizes} loader={loader}>
|
|
||||||
{statusIds.map(statusId => (
|
|
||||||
<div className='statuses-grid__item' key={statusId}>
|
|
||||||
<DetailedStatusContainer
|
|
||||||
id={statusId}
|
|
||||||
compact
|
|
||||||
measureHeight
|
|
||||||
onHeightChange={this.handleHeightChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)).toArray()}
|
|
||||||
</Masonry>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import { expandPublicTimeline, expandCommunityTimeline } from 'mastodon/actions/timelines';
|
|
||||||
import Masonry from 'react-masonry-infinite';
|
|
||||||
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
|
||||||
import DetailedStatusContainer from 'mastodon/features/status/containers/detailed_status_container';
|
|
||||||
import { debounce } from 'lodash';
|
|
||||||
import LoadingIndicator from 'mastodon/components/loading_indicator';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { local }) => {
|
|
||||||
const timeline = state.getIn(['timelines', local ? 'community' : 'public'], ImmutableMap());
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusIds: timeline.get('items', ImmutableList()),
|
|
||||||
isLoading: timeline.get('isLoading', false),
|
|
||||||
hasMore: timeline.get('hasMore', false),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
|
||||||
class PublicTimeline extends React.PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
dispatch: PropTypes.func.isRequired,
|
|
||||||
statusIds: ImmutablePropTypes.list.isRequired,
|
|
||||||
isLoading: PropTypes.bool.isRequired,
|
|
||||||
hasMore: PropTypes.bool.isRequired,
|
|
||||||
local: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
this._connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
|
||||||
if (prevProps.local !== this.props.local) {
|
|
||||||
this._connect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_connect () {
|
|
||||||
const { dispatch, local } = this.props;
|
|
||||||
|
|
||||||
dispatch(local ? expandCommunityTimeline() : expandPublicTimeline());
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLoadMore = () => {
|
|
||||||
const { dispatch, statusIds, local } = this.props;
|
|
||||||
const maxId = statusIds.last();
|
|
||||||
|
|
||||||
if (maxId) {
|
|
||||||
dispatch(local ? expandCommunityTimeline({ maxId }) : expandPublicTimeline({ maxId }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setRef = c => {
|
|
||||||
this.masonry = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleHeightChange = debounce(() => {
|
|
||||||
if (!this.masonry) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.masonry.forcePack();
|
|
||||||
}, 50)
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { statusIds, hasMore, isLoading } = this.props;
|
|
||||||
|
|
||||||
const sizes = [
|
|
||||||
{ columns: 1, gutter: 0 },
|
|
||||||
{ mq: '415px', columns: 1, gutter: 10 },
|
|
||||||
{ mq: '640px', columns: 2, gutter: 10 },
|
|
||||||
{ mq: '960px', columns: 3, gutter: 10 },
|
|
||||||
{ mq: '1255px', columns: 3, gutter: 10 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const loader = (isLoading && statusIds.isEmpty()) ? <LoadingIndicator key={0} /> : undefined;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Masonry ref={this.setRef} className='statuses-grid' hasMore={hasMore} loadMore={this.handleLoadMore} sizes={sizes} loader={loader}>
|
|
||||||
{statusIds.map(statusId => (
|
|
||||||
<div className='statuses-grid__item' key={statusId}>
|
|
||||||
<DetailedStatusContainer
|
|
||||||
id={statusId}
|
|
||||||
compact
|
|
||||||
measureHeight
|
|
||||||
onHeightChange={this.handleHeightChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)).toArray()}
|
|
||||||
</Masonry>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
import './public-path';
|
|
||||||
import loadPolyfills from '../mastodon/load_polyfills';
|
|
||||||
import { start } from '../mastodon/common';
|
|
||||||
|
|
||||||
start();
|
|
||||||
|
|
||||||
function loaded() {
|
|
||||||
const TimelineContainer = require('../mastodon/containers/timeline_container').default;
|
|
||||||
const React = require('react');
|
|
||||||
const ReactDOM = require('react-dom');
|
|
||||||
const mountNode = document.getElementById('mastodon-timeline');
|
|
||||||
|
|
||||||
if (mountNode !== null) {
|
|
||||||
const props = JSON.parse(mountNode.getAttribute('data-props'));
|
|
||||||
ReactDOM.render(<TimelineContainer {...props} />, mountNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
const ready = require('../mastodon/ready').default;
|
|
||||||
ready(loaded);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadPolyfills().then(main).catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
|
@ -19,7 +19,6 @@ class Form::AdminSettings
|
||||||
theme
|
theme
|
||||||
activity_api_enabled
|
activity_api_enabled
|
||||||
peers_api_enabled
|
peers_api_enabled
|
||||||
show_known_fediverse_at_about_page
|
|
||||||
preview_sensitive_media
|
preview_sensitive_media
|
||||||
custom_css
|
custom_css
|
||||||
profile_directory
|
profile_directory
|
||||||
|
@ -42,7 +41,6 @@ class Form::AdminSettings
|
||||||
timeline_preview
|
timeline_preview
|
||||||
activity_api_enabled
|
activity_api_enabled
|
||||||
peers_api_enabled
|
peers_api_enabled
|
||||||
show_known_fediverse_at_about_page
|
|
||||||
preview_sensitive_media
|
preview_sensitive_media
|
||||||
profile_directory
|
profile_directory
|
||||||
trends
|
trends
|
||||||
|
|
|
@ -17,25 +17,12 @@
|
||||||
= render 'registration'
|
= render 'registration'
|
||||||
|
|
||||||
.directory
|
.directory
|
||||||
- if Setting.profile_directory
|
.directory__tag
|
||||||
.directory__tag
|
= link_to web_path do
|
||||||
= optional_link_to Setting.profile_directory, explore_path do
|
%h4
|
||||||
%h4
|
= fa_icon 'globe fw'
|
||||||
= fa_icon 'address-book fw'
|
= t('about.see_whats_happening')
|
||||||
= t('about.discover_users')
|
%small= t('about.browse_public_posts')
|
||||||
%small= t('about.browse_directory')
|
|
||||||
|
|
||||||
.avatar-stack
|
|
||||||
- @instance_presenter.sample_accounts.each do |account|
|
|
||||||
= image_tag current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url, alt: '', class: 'account__avatar'
|
|
||||||
|
|
||||||
- if Setting.timeline_preview
|
|
||||||
.directory__tag
|
|
||||||
= optional_link_to Setting.timeline_preview, public_timeline_path do
|
|
||||||
%h4
|
|
||||||
= fa_icon 'globe fw'
|
|
||||||
= t('about.see_whats_happening')
|
|
||||||
%small= t('about.browse_public_posts')
|
|
||||||
|
|
||||||
.directory__tag
|
.directory__tag
|
||||||
= link_to 'https://joinmastodon.org/apps', target: '_blank', rel: 'noopener noreferrer' do
|
= link_to 'https://joinmastodon.org/apps', target: '_blank', rel: 'noopener noreferrer' do
|
||||||
|
|
|
@ -57,9 +57,6 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html')
|
= f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html')
|
||||||
|
|
||||||
.fields-group
|
|
||||||
= f.input :show_known_fediverse_at_about_page, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_known_fediverse_at_about_page.title'), hint: t('admin.settings.show_known_fediverse_at_about_page.desc_html')
|
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :open_deletion, as: :boolean, wrapper: :with_label, label: t('admin.settings.registrations.deletion.title'), hint: t('admin.settings.registrations.deletion.desc_html')
|
= f.input :open_deletion, as: :boolean, wrapper: :with_label, label: t('admin.settings.registrations.deletion.title'), hint: t('admin.settings.registrations.deletion.desc_html')
|
||||||
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
- content_for :page_title do
|
|
||||||
= t('directories.explore_mastodon', title: site_title)
|
|
||||||
|
|
||||||
- content_for :header_tags do
|
|
||||||
%meta{ name: 'description', content: t('directories.explanation') }
|
|
||||||
|
|
||||||
= opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname)
|
|
||||||
= opengraph 'og:type', 'website'
|
|
||||||
= opengraph 'og:title', t('directories.explore_mastodon', title: site_title)
|
|
||||||
= opengraph 'og:description', t('directories.explanation')
|
|
||||||
= opengraph 'og:image', File.join(root_url, 'android-chrome-192x192.png')
|
|
||||||
|
|
||||||
.page-header
|
|
||||||
%h1= t('directories.explore_mastodon', title: site_title)
|
|
||||||
%p= t('directories.explanation')
|
|
||||||
|
|
||||||
- if @accounts.empty?
|
|
||||||
= nothing_here
|
|
||||||
- else
|
|
||||||
.directory__list
|
|
||||||
- @accounts.each do |account|
|
|
||||||
.account-card
|
|
||||||
= link_to TagManager.instance.url_for(account), class: 'account-card__permalink' do
|
|
||||||
.account-card__header
|
|
||||||
= image_tag account.header.url, alt: ''
|
|
||||||
.account-card__title
|
|
||||||
.account-card__title__avatar
|
|
||||||
= image_tag account.avatar.url, alt: ''
|
|
||||||
.display-name
|
|
||||||
%bdi
|
|
||||||
%strong.emojify.p-name= display_name(account, custom_emojify: true)
|
|
||||||
%span
|
|
||||||
= acct(account)
|
|
||||||
= fa_icon('lock') if account.locked?
|
|
||||||
- if account.note.present?
|
|
||||||
.account-card__bio.emojify
|
|
||||||
= prerender_custom_emojis(account_bio_format(account), account.emojis)
|
|
||||||
- else
|
|
||||||
.flex-spacer
|
|
||||||
.account-card__actions
|
|
||||||
.account-card__counters
|
|
||||||
.account-card__counters__item
|
|
||||||
= friendly_number_to_human account.statuses_count
|
|
||||||
%small= t('accounts.posts', count: account.statuses_count).downcase
|
|
||||||
.account-card__counters__item
|
|
||||||
= friendly_number_to_human account.followers_count
|
|
||||||
%small= t('accounts.followers', count: account.followers_count).downcase
|
|
||||||
.account-card__counters__item
|
|
||||||
= friendly_number_to_human account.following_count
|
|
||||||
%small= t('accounts.following', count: account.following_count).downcase
|
|
||||||
.account-card__actions__button
|
|
||||||
= account_action_button(account)
|
|
||||||
|
|
||||||
= paginate @accounts
|
|
|
@ -12,7 +12,6 @@
|
||||||
= logo_as_symbol(:wordmark)
|
= logo_as_symbol(:wordmark)
|
||||||
|
|
||||||
- unless whitelist_mode?
|
- unless whitelist_mode?
|
||||||
= link_to t('directories.directory'), explore_path, class: 'nav-link optional' if Setting.profile_directory
|
|
||||||
= link_to t('about.about_this'), about_more_path, class: 'nav-link optional'
|
= link_to t('about.about_this'), about_more_path, class: 'nav-link optional'
|
||||||
= link_to t('about.apps'), 'https://joinmastodon.org/apps', class: 'nav-link optional'
|
= link_to t('about.apps'), 'https://joinmastodon.org/apps', class: 'nav-link optional'
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
- content_for :page_title do
|
|
||||||
= t('about.see_whats_happening')
|
|
||||||
|
|
||||||
- content_for :header_tags do
|
|
||||||
%meta{ name: 'robots', content: 'noindex' }/
|
|
||||||
= javascript_pack_tag 'about', crossorigin: 'anonymous'
|
|
||||||
|
|
||||||
.page-header
|
|
||||||
%h1= t('about.see_whats_happening')
|
|
||||||
|
|
||||||
- if Setting.show_known_fediverse_at_about_page
|
|
||||||
%p= t('about.browse_public_posts')
|
|
||||||
- else
|
|
||||||
%p= t('about.browse_local_posts')
|
|
||||||
|
|
||||||
#mastodon-timeline{ data: { props: Oj.dump(default_props.merge(local: !Setting.show_known_fediverse_at_about_page)) }}
|
|
||||||
.notranslate#modal-container
|
|
|
@ -1,6 +0,0 @@
|
||||||
= opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname)
|
|
||||||
= opengraph 'og:url', tag_url(@tag)
|
|
||||||
= opengraph 'og:type', 'website'
|
|
||||||
= opengraph 'og:title', "##{@tag.display_name}"
|
|
||||||
= opengraph 'og:description', strip_tags(t('about.about_hashtag_html', hashtag: @tag.display_name))
|
|
||||||
= opengraph 'twitter:card', 'summary'
|
|
|
@ -1,16 +0,0 @@
|
||||||
- content_for :page_title do
|
|
||||||
= "##{@tag.display_name}"
|
|
||||||
|
|
||||||
- content_for :header_tags do
|
|
||||||
%meta{ name: 'robots', content: 'noindex' }/
|
|
||||||
%link{ rel: 'alternate', type: 'application/rss+xml', href: tag_url(@tag, format: 'rss') }/
|
|
||||||
|
|
||||||
= javascript_pack_tag 'about', crossorigin: 'anonymous'
|
|
||||||
= render 'og'
|
|
||||||
|
|
||||||
.page-header
|
|
||||||
%h1= "##{@tag.display_name}"
|
|
||||||
%p= t('about.about_hashtag_html', hashtag: @tag.display_name)
|
|
||||||
|
|
||||||
#mastodon-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name, local: @local)) }}
|
|
||||||
.notranslate#modal-container
|
|
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
en:
|
en:
|
||||||
about:
|
about:
|
||||||
about_hashtag_html: These are public posts tagged with <strong>#%{hashtag}</strong>. You can interact with them if you have an account anywhere in the fediverse.
|
|
||||||
about_mastodon_html: 'The social network of the future: No ads, no corporate surveillance, ethical design, and decentralization! Own your data with Mastodon!'
|
about_mastodon_html: 'The social network of the future: No ads, no corporate surveillance, ethical design, and decentralization! Own your data with Mastodon!'
|
||||||
about_this: About
|
about_this: About
|
||||||
active_count_after: active
|
active_count_after: active
|
||||||
|
@ -10,14 +9,11 @@ en:
|
||||||
api: API
|
api: API
|
||||||
apps: Mobile apps
|
apps: Mobile apps
|
||||||
apps_platforms: Use Mastodon from iOS, Android and other platforms
|
apps_platforms: Use Mastodon from iOS, Android and other platforms
|
||||||
browse_directory: Browse a profile directory and filter by interests
|
|
||||||
browse_local_posts: Browse a live stream of public posts from this server
|
|
||||||
browse_public_posts: Browse a live stream of public posts on Mastodon
|
browse_public_posts: Browse a live stream of public posts on Mastodon
|
||||||
contact: Contact
|
contact: Contact
|
||||||
contact_missing: Not set
|
contact_missing: Not set
|
||||||
contact_unavailable: N/A
|
contact_unavailable: N/A
|
||||||
continue_to_web: Continue to web app
|
continue_to_web: Continue to web app
|
||||||
discover_users: Discover users
|
|
||||||
documentation: Documentation
|
documentation: Documentation
|
||||||
federation_hint_html: With an account on %{instance} you'll be able to follow people on any Mastodon server and beyond.
|
federation_hint_html: With an account on %{instance} you'll be able to follow people on any Mastodon server and beyond.
|
||||||
get_apps: Try a mobile app
|
get_apps: Try a mobile app
|
||||||
|
@ -783,9 +779,6 @@ en:
|
||||||
none: Nobody can sign up
|
none: Nobody can sign up
|
||||||
open: Anyone can sign up
|
open: Anyone can sign up
|
||||||
title: Registrations mode
|
title: Registrations mode
|
||||||
show_known_fediverse_at_about_page:
|
|
||||||
desc_html: When disabled, restricts the public timeline linked from the landing page to showing only local content
|
|
||||||
title: Include federated content on unauthenticated public timeline page
|
|
||||||
site_description:
|
site_description:
|
||||||
desc_html: Introductory paragraph on the API. Describe what makes this Mastodon server special and anything else important. You can use HTML tags, in particular <code><a></code> and <code><em></code>.
|
desc_html: Introductory paragraph on the API. Describe what makes this Mastodon server special and anything else important. You can use HTML tags, in particular <code><a></code> and <code><em></code>.
|
||||||
title: Server description
|
title: Server description
|
||||||
|
@ -1109,10 +1102,6 @@ en:
|
||||||
more_details_html: For more details, see the <a href="%{terms_path}">privacy policy</a>.
|
more_details_html: For more details, see the <a href="%{terms_path}">privacy policy</a>.
|
||||||
username_available: Your username will become available again
|
username_available: Your username will become available again
|
||||||
username_unavailable: Your username will remain unavailable
|
username_unavailable: Your username will remain unavailable
|
||||||
directories:
|
|
||||||
directory: Profile directory
|
|
||||||
explanation: Discover users based on their interests
|
|
||||||
explore_mastodon: Explore %{title}
|
|
||||||
disputes:
|
disputes:
|
||||||
strikes:
|
strikes:
|
||||||
action_taken: Action taken
|
action_taken: Action taken
|
||||||
|
|
|
@ -95,7 +95,6 @@ Rails.application.routes.draw do
|
||||||
get '/interact/:id', to: 'remote_interaction#new', as: :remote_interaction
|
get '/interact/:id', to: 'remote_interaction#new', as: :remote_interaction
|
||||||
post '/interact/:id', to: 'remote_interaction#create'
|
post '/interact/:id', to: 'remote_interaction#create'
|
||||||
|
|
||||||
get '/explore', to: 'directories#index', as: :explore
|
|
||||||
get '/settings', to: redirect('/settings/profile')
|
get '/settings', to: redirect('/settings/profile')
|
||||||
|
|
||||||
namespace :settings do
|
namespace :settings do
|
||||||
|
@ -188,7 +187,9 @@ Rails.application.routes.draw do
|
||||||
resource :relationships, only: [:show, :update]
|
resource :relationships, only: [:show, :update]
|
||||||
resource :statuses_cleanup, controller: :statuses_cleanup, only: [:show, :update]
|
resource :statuses_cleanup, controller: :statuses_cleanup, only: [:show, :update]
|
||||||
|
|
||||||
get '/public', to: 'public_timelines#show', as: :public_timeline
|
get '/explore', to: redirect('/web/explore')
|
||||||
|
get '/public', to: redirect('/web/public')
|
||||||
|
get '/public/local', to: redirect('/web/public/local')
|
||||||
get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy
|
get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy
|
||||||
|
|
||||||
resource :authorize_interaction, only: [:show, :create]
|
resource :authorize_interaction, only: [:show, :create]
|
||||||
|
|
|
@ -66,7 +66,6 @@ defaults: &defaults
|
||||||
bootstrap_timeline_accounts: ''
|
bootstrap_timeline_accounts: ''
|
||||||
activity_api_enabled: true
|
activity_api_enabled: true
|
||||||
peers_api_enabled: true
|
peers_api_enabled: true
|
||||||
show_known_fediverse_at_about_page: true
|
|
||||||
show_domain_blocks: 'disabled'
|
show_domain_blocks: 'disabled'
|
||||||
show_domain_blocks_rationale: 'disabled'
|
show_domain_blocks_rationale: 'disabled'
|
||||||
require_invite_text: false
|
require_invite_text: false
|
||||||
|
|
|
@ -97,7 +97,6 @@
|
||||||
"react-immutable-proptypes": "^2.2.0",
|
"react-immutable-proptypes": "^2.2.0",
|
||||||
"react-immutable-pure-component": "^2.2.2",
|
"react-immutable-pure-component": "^2.2.2",
|
||||||
"react-intl": "^2.9.0",
|
"react-intl": "^2.9.0",
|
||||||
"react-masonry-infinite": "^1.2.2",
|
|
||||||
"react-motion": "^0.5.2",
|
"react-motion": "^0.5.2",
|
||||||
"react-notification": "^6.8.5",
|
"react-notification": "^6.8.5",
|
||||||
"react-overlays": "^0.9.3",
|
"react-overlays": "^0.9.3",
|
||||||
|
|
|
@ -10,14 +10,9 @@ RSpec.describe TagsController, type: :controller do
|
||||||
let!(:late) { Fabricate(:status, tags: [tag], text: 'late #test') }
|
let!(:late) { Fabricate(:status, tags: [tag], text: 'late #test') }
|
||||||
|
|
||||||
context 'when tag exists' do
|
context 'when tag exists' do
|
||||||
it 'returns http success' do
|
it 'redirects to web version' do
|
||||||
get :show, params: { id: 'test', max_id: late.id }
|
get :show, params: { id: 'test', max_id: late.id }
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to redirect_to('/web/tags/test')
|
||||||
end
|
|
||||||
|
|
||||||
it 'renders application layout' do
|
|
||||||
get :show, params: { id: 'test', max_id: late.id }
|
|
||||||
expect(response).to render_template layout: 'public'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
28
yarn.lock
28
yarn.lock
|
@ -2934,13 +2934,6 @@ braces@^3.0.2, braces@~3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.0.1"
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
bricks.js@^1.7.0:
|
|
||||||
version "1.8.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/bricks.js/-/bricks.js-1.8.0.tgz#8fdeb3c0226af251f4d5727a7df7f9ac0092b4b2"
|
|
||||||
integrity sha1-j96zwCJq8lH01XJ6fff5rACStLI=
|
|
||||||
dependencies:
|
|
||||||
knot.js "^1.1.5"
|
|
||||||
|
|
||||||
brorand@^1.0.1, brorand@^1.1.0:
|
brorand@^1.0.1, brorand@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
||||||
|
@ -7110,11 +7103,6 @@ klona@^2.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0"
|
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0"
|
||||||
integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
|
integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
|
||||||
|
|
||||||
knot.js@^1.1.5:
|
|
||||||
version "1.1.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/knot.js/-/knot.js-1.1.5.tgz#28e72522f703f50fe98812fde224dd72728fef5d"
|
|
||||||
integrity sha1-KOclIvcD9Q/piBL94iTdcnKP710=
|
|
||||||
|
|
||||||
known-css-properties@^0.25.0:
|
known-css-properties@^0.25.0:
|
||||||
version "0.25.0"
|
version "0.25.0"
|
||||||
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.25.0.tgz#6ebc4d4b412f602e5cfbeb4086bd544e34c0a776"
|
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.25.0.tgz#6ebc4d4b412f602e5cfbeb4086bd544e34c0a776"
|
||||||
|
@ -9226,13 +9214,6 @@ react-immutable-pure-component@^2.2.2:
|
||||||
resolved "https://registry.yarnpkg.com/react-immutable-pure-component/-/react-immutable-pure-component-2.2.2.tgz#3014d3e20cd5a7a4db73b81f1f1464f4d351684b"
|
resolved "https://registry.yarnpkg.com/react-immutable-pure-component/-/react-immutable-pure-component-2.2.2.tgz#3014d3e20cd5a7a4db73b81f1f1464f4d351684b"
|
||||||
integrity sha512-vkgoMJUDqHZfXXnjVlG3keCxSO/U6WeDQ5/Sl0GK2cH8TOxEzQ5jXqDXHEL/jqk6fsNxV05oH5kD7VNMUE2k+A==
|
integrity sha512-vkgoMJUDqHZfXXnjVlG3keCxSO/U6WeDQ5/Sl0GK2cH8TOxEzQ5jXqDXHEL/jqk6fsNxV05oH5kD7VNMUE2k+A==
|
||||||
|
|
||||||
react-infinite-scroller@^1.0.12:
|
|
||||||
version "1.2.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-infinite-scroller/-/react-infinite-scroller-1.2.4.tgz#f67eaec4940a4ce6417bebdd6e3433bfc38826e9"
|
|
||||||
integrity sha512-/oOa0QhZjXPqaD6sictN2edFMsd3kkMiE19Vcz5JDgHpzEJVqYcmq+V3mkwO88087kvKGe1URNksHEOt839Ubw==
|
|
||||||
dependencies:
|
|
||||||
prop-types "^15.5.8"
|
|
||||||
|
|
||||||
react-intl-translations-manager@^5.0.3:
|
react-intl-translations-manager@^5.0.3:
|
||||||
version "5.0.3"
|
version "5.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-intl-translations-manager/-/react-intl-translations-manager-5.0.3.tgz#aee010ecf35975673e033ca5d7d3f4147894324d"
|
resolved "https://registry.yarnpkg.com/react-intl-translations-manager/-/react-intl-translations-manager-5.0.3.tgz#aee010ecf35975673e033ca5d7d3f4147894324d"
|
||||||
|
@ -9274,15 +9255,6 @@ react-lifecycles-compat@^3.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||||
|
|
||||||
react-masonry-infinite@^1.2.2:
|
|
||||||
version "1.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-masonry-infinite/-/react-masonry-infinite-1.2.2.tgz#20c1386f9ccdda9747527c8f42bc2c02dd2e7951"
|
|
||||||
integrity sha1-IME4b5zN2pdHUnyPQrwsAt0ueVE=
|
|
||||||
dependencies:
|
|
||||||
bricks.js "^1.7.0"
|
|
||||||
prop-types "^15.5.10"
|
|
||||||
react-infinite-scroller "^1.0.12"
|
|
||||||
|
|
||||||
react-motion@^0.5.2:
|
react-motion@^0.5.2:
|
||||||
version "0.5.2"
|
version "0.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316"
|
resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316"
|
||||||
|
|
Reference in New Issue