Merge commit '37bbd3c1064380a756b4e821655d7697105f99f5' into glitch-soc/merge-upstream

local
Claire 7 months ago
commit 74c27e33e3
  1. 6
      app/javascript/mastodon/components/column.jsx
  2. 78
      app/javascript/mastodon/features/explore/index.jsx
  3. 2
      app/javascript/mastodon/features/explore/links.jsx
  4. 2
      app/javascript/mastodon/features/explore/results.jsx
  5. 2
      app/javascript/mastodon/features/explore/suggestions.jsx
  6. 2
      app/javascript/mastodon/features/explore/tags.jsx
  7. 46
      app/javascript/mastodon/features/firehose/index.jsx
  8. 3
      app/javascript/styles/mastodon/components.scss
  9. 6
      app/lib/account_statuses_filter.rb
  10. 2
      app/workers/scheduler/trends/refresh_scheduler.rb
  11. 16
      spec/lib/account_statuses_filter_spec.rb

@ -22,12 +22,6 @@ export default class Column extends PureComponent {
scrollable = document.scrollingElement; scrollable = document.scrollingElement;
} else { } else {
scrollable = this.node.querySelector('.scrollable'); scrollable = this.node.querySelector('.scrollable');
// Some columns have nested `.scrollable` containers, with the outer one
// being a wrapper while the actual scrollable content is deeper.
if (scrollable.classList.contains('scrollable--flex')) {
scrollable = scrollable?.querySelector('.scrollable') || scrollable;
}
} }
if (!scrollable) { if (!scrollable) {

@ -67,47 +67,45 @@ class Explore extends PureComponent {
<Search /> <Search />
</div> </div>
<div className='scrollable scrollable--flex' data-nosnippet> {isSearching ? (
{isSearching ? ( <SearchResults />
<SearchResults /> ) : (
) : ( <>
<> <div className='account__section-headline'>
<div className='account__section-headline'> <NavLink exact to='/explore'>
<NavLink exact to='/explore'> <FormattedMessage tagName='div' id='explore.trending_statuses' defaultMessage='Posts' />
<FormattedMessage tagName='div' id='explore.trending_statuses' defaultMessage='Posts' /> </NavLink>
<NavLink exact to='/explore/tags'>
<FormattedMessage tagName='div' id='explore.trending_tags' defaultMessage='Hashtags' />
</NavLink>
{signedIn && (
<NavLink exact to='/explore/suggestions'>
<FormattedMessage tagName='div' id='explore.suggested_follows' defaultMessage='People' />
</NavLink> </NavLink>
)}
<NavLink exact to='/explore/tags'>
<FormattedMessage tagName='div' id='explore.trending_tags' defaultMessage='Hashtags' /> <NavLink exact to='/explore/links'>
</NavLink> <FormattedMessage tagName='div' id='explore.trending_links' defaultMessage='News' />
</NavLink>
{signedIn && ( </div>
<NavLink exact to='/explore/suggestions'>
<FormattedMessage tagName='div' id='explore.suggested_follows' defaultMessage='People' /> <Switch>
</NavLink> <Route path='/explore/tags' component={Tags} />
)} <Route path='/explore/links' component={Links} />
<Route path='/explore/suggestions' component={Suggestions} />
<NavLink exact to='/explore/links'> <Route exact path={['/explore', '/explore/posts', '/search']}>
<FormattedMessage tagName='div' id='explore.trending_links' defaultMessage='News' /> <Statuses multiColumn={multiColumn} />
</NavLink> </Route>
</div> </Switch>
<Switch> <Helmet>
<Route path='/explore/tags' component={Tags} /> <title>{intl.formatMessage(messages.title)}</title>
<Route path='/explore/links' component={Links} /> <meta name='robots' content={isSearching ? 'noindex' : 'all'} />
<Route path='/explore/suggestions' component={Suggestions} /> </Helmet>
<Route exact path={['/explore', '/explore/posts', '/search']}> </>
<Statuses multiColumn={multiColumn} /> )}
</Route>
</Switch>
<Helmet>
<title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content={isSearching ? 'noindex' : 'all'} />
</Helmet>
</>
)}
</div>
</Column> </Column>
); );
} }

@ -52,7 +52,7 @@ class Links extends PureComponent {
} }
return ( return (
<div className='explore__links'> <div className='explore__links scrollable' data-nosnippet>
{banner} {banner}
{isLoading ? (<LoadingIndicator />) : links.map((link, i) => ( {isLoading ? (<LoadingIndicator />) : links.map((link, i) => (

@ -204,7 +204,7 @@ class Results extends PureComponent {
<button onClick={this.handleSelectStatuses} className={type === 'statuses' ? 'active' : undefined}><FormattedMessage id='search_results.statuses' defaultMessage='Posts' /></button> <button onClick={this.handleSelectStatuses} className={type === 'statuses' ? 'active' : undefined}><FormattedMessage id='search_results.statuses' defaultMessage='Posts' /></button>
</div> </div>
<div className='explore__search-results'> <div className='explore__search-results' data-nosnippet>
<ScrollableList <ScrollableList
scrollKey='search-results' scrollKey='search-results'
isLoading={isLoading} isLoading={isLoading}

@ -42,7 +42,7 @@ class Suggestions extends PureComponent {
} }
return ( return (
<div className='explore__suggestions'> <div className='explore__suggestions scrollable' data-nosnippet>
{isLoading ? <LoadingIndicator /> : suggestions.map(suggestion => ( {isLoading ? <LoadingIndicator /> : suggestions.map(suggestion => (
<AccountCard key={suggestion.get('account')} id={suggestion.get('account')} /> <AccountCard key={suggestion.get('account')} id={suggestion.get('account')} />
))} ))}

@ -51,7 +51,7 @@ class Tags extends PureComponent {
} }
return ( return (
<div className='explore__links'> <div className='scrollable explore__links' data-nosnippet>
{banner} {banner}
{isLoading ? (<LoadingIndicator />) : hashtags.map(hashtag => ( {isLoading ? (<LoadingIndicator />) : hashtags.map(hashtag => (

@ -169,32 +169,30 @@ const Firehose = ({ feedType, multiColumn }) => {
<ColumnSettings /> <ColumnSettings />
</ColumnHeader> </ColumnHeader>
<div className='scrollable scrollable--flex'> <div className='account__section-headline'>
<div className='account__section-headline'> <NavLink exact to='/public/local'>
<NavLink exact to='/public/local'> <FormattedMessage tagName='div' id='firehose.local' defaultMessage='This server' />
<FormattedMessage tagName='div' id='firehose.local' defaultMessage='This server' /> </NavLink>
</NavLink>
<NavLink exact to='/public/remote'>
<NavLink exact to='/public/remote'> <FormattedMessage tagName='div' id='firehose.remote' defaultMessage='Other servers' />
<FormattedMessage tagName='div' id='firehose.remote' defaultMessage='Other servers' /> </NavLink>
</NavLink>
<NavLink exact to='/public'>
<NavLink exact to='/public'> <FormattedMessage tagName='div' id='firehose.all' defaultMessage='All' />
<FormattedMessage tagName='div' id='firehose.all' defaultMessage='All' /> </NavLink>
</NavLink>
</div>
<StatusListContainer
prepend={prependBanner}
timelineId={`${feedType}${onlyMedia ? ':media' : ''}`}
onLoadMore={handleLoadMore}
trackScroll
scrollKey='firehose'
emptyMessage={emptyMessage}
bindToDocument={!multiColumn}
/>
</div> </div>
<StatusListContainer
prepend={prependBanner}
timelineId={`${feedType}${onlyMedia ? ':media' : ''}`}
onLoadMore={handleLoadMore}
trackScroll
scrollKey='firehose'
emptyMessage={emptyMessage}
bindToDocument={!multiColumn}
/>
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='noindex' /> <meta name='robots' content='noindex' />

@ -8279,6 +8279,9 @@ noscript {
flex: 1 1 auto; flex: 1 1 auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: $ui-base-color;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
} }
.story { .story {

@ -60,8 +60,12 @@ class AccountStatusesFilter
.where(reblog_of_id: nil) .where(reblog_of_id: nil)
.or( .or(
scope scope
# This is basically `Status.not_domain_blocked_by_account(current_account)`
# and `Status.not_excluded_by_account(current_account)` but on the
# `reblog` association. Unfortunately, there seem to be no clean way
# to re-use those scopes in our case.
.where(reblog: { accounts: { domain: nil } }).or(scope.where.not(reblog: { accounts: { domain: current_account.excluded_from_timeline_domains } }))
.where.not(reblog: { account_id: current_account.excluded_from_timeline_account_ids }) .where.not(reblog: { account_id: current_account.excluded_from_timeline_account_ids })
.where.not(reblog: { accounts: { domain: current_account.excluded_from_timeline_domains } })
) )
end end

@ -3,7 +3,7 @@
class Scheduler::Trends::RefreshScheduler class Scheduler::Trends::RefreshScheduler
include Sidekiq::Worker include Sidekiq::Worker
sidekiq_options retry: 0 sidekiq_options retry: 0, lock: :until_executed, lock_ttl: 30.minutes.to_i
def perform def perform
Trends.refresh! Trends.refresh!

@ -202,7 +202,7 @@ RSpec.describe AccountStatusesFilter do
context 'when blocking a reblogged domain' do context 'when blocking a reblogged domain' do
let(:other_account) { Fabricate(:account, domain: 'example.com') } let(:other_account) { Fabricate(:account, domain: 'example.com') }
let(:reblogging_status) { Fabricate(:status, account: other_account) } let(:reblogging_status) { Fabricate(:status, account: other_account) }
let(:reblog) { Fabricate(:status, account: account, visibility: 'public', reblog: reblogging_status) } let!(:reblog) { Fabricate(:status, account: account, visibility: 'public', reblog: reblogging_status) }
before do before do
current_account.block_domain!(other_account.domain) current_account.block_domain!(other_account.domain)
@ -213,6 +213,20 @@ RSpec.describe AccountStatusesFilter do
end end
end end
context 'when blocking an unrelated domain' do
let(:other_account) { Fabricate(:account, domain: nil) }
let(:reblogging_status) { Fabricate(:status, account: other_account, visibility: 'public') }
let!(:reblog) { Fabricate(:status, account: account, visibility: 'public', reblog: reblogging_status) }
before do
current_account.block_domain!('example.com')
end
it 'returns the reblog from the non-blocked domain' do
expect(subject.results.pluck(:id)).to include(reblog.id)
end
end
context 'when muting a reblogged account' do context 'when muting a reblogged account' do
let(:reblog) { status_with_reblog!('public') } let(:reblog) { status_with_reblog!('public') }
Loading…
Cancel
Save