~cytrogen/masto-fe

74c27e33e3f8dcdc7e002037e90cd819dadf553a — Claire 2 years ago 8eb09c6 + 37bbd3c
Merge commit '37bbd3c1064380a756b4e821655d7697105f99f5' into glitch-soc/merge-upstream
M app/javascript/mastodon/components/column.jsx => app/javascript/mastodon/components/column.jsx +0 -6
@@ 22,12 22,6 @@ export default class Column extends PureComponent {
      scrollable = document.scrollingElement;
    } else {
      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) {

M app/javascript/mastodon/features/explore/index.jsx => app/javascript/mastodon/features/explore/index.jsx +38 -40
@@ 67,47 67,45 @@ class Explore extends PureComponent {
          <Search />
        </div>

        <div className='scrollable scrollable--flex' data-nosnippet>
          {isSearching ? (
            <SearchResults />
          ) : (
            <>
              <div className='account__section-headline'>
                <NavLink exact to='/explore'>
                  <FormattedMessage tagName='div' id='explore.trending_statuses' defaultMessage='Posts' />
        {isSearching ? (
          <SearchResults />
        ) : (
          <>
            <div className='account__section-headline'>
              <NavLink exact to='/explore'>
                <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 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 exact to='/explore/links'>
                  <FormattedMessage tagName='div' id='explore.trending_links' defaultMessage='News' />
                </NavLink>
              </div>

              <Switch>
                <Route path='/explore/tags' component={Tags} />
                <Route path='/explore/links' component={Links} />
                <Route path='/explore/suggestions' component={Suggestions} />
                <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>
              )}

              <NavLink exact to='/explore/links'>
                <FormattedMessage tagName='div' id='explore.trending_links' defaultMessage='News' />
              </NavLink>
            </div>

            <Switch>
              <Route path='/explore/tags' component={Tags} />
              <Route path='/explore/links' component={Links} />
              <Route path='/explore/suggestions' component={Suggestions} />
              <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>
          </>
        )}
      </Column>
    );
  }

M app/javascript/mastodon/features/explore/links.jsx => app/javascript/mastodon/features/explore/links.jsx +1 -1
@@ 52,7 52,7 @@ class Links extends PureComponent {
    }

    return (
      <div className='explore__links'>
      <div className='explore__links scrollable' data-nosnippet>
        {banner}

        {isLoading ? (<LoadingIndicator />) : links.map((link, i) => (

M app/javascript/mastodon/features/explore/results.jsx => app/javascript/mastodon/features/explore/results.jsx +1 -1
@@ 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>
        </div>

        <div className='explore__search-results'>
        <div className='explore__search-results' data-nosnippet>
          <ScrollableList
            scrollKey='search-results'
            isLoading={isLoading}

M app/javascript/mastodon/features/explore/suggestions.jsx => app/javascript/mastodon/features/explore/suggestions.jsx +1 -1
@@ 42,7 42,7 @@ class Suggestions extends PureComponent {
    }

    return (
      <div className='explore__suggestions'>
      <div className='explore__suggestions scrollable' data-nosnippet>
        {isLoading ? <LoadingIndicator /> : suggestions.map(suggestion => (
          <AccountCard key={suggestion.get('account')} id={suggestion.get('account')} />
        ))}

M app/javascript/mastodon/features/explore/tags.jsx => app/javascript/mastodon/features/explore/tags.jsx +1 -1
@@ 51,7 51,7 @@ class Tags extends PureComponent {
    }

    return (
      <div className='explore__links'>
      <div className='scrollable explore__links' data-nosnippet>
        {banner}

        {isLoading ? (<LoadingIndicator />) : hashtags.map(hashtag => (

M app/javascript/mastodon/features/firehose/index.jsx => app/javascript/mastodon/features/firehose/index.jsx +22 -24
@@ 169,32 169,30 @@ const Firehose = ({ feedType, multiColumn }) => {
        <ColumnSettings />
      </ColumnHeader>

      <div className='scrollable scrollable--flex'>
        <div className='account__section-headline'>
          <NavLink exact to='/public/local'>
            <FormattedMessage tagName='div' id='firehose.local' defaultMessage='This server' />
          </NavLink>

          <NavLink exact to='/public/remote'>
            <FormattedMessage tagName='div' id='firehose.remote' defaultMessage='Other servers' />
          </NavLink>

          <NavLink exact to='/public'>
            <FormattedMessage tagName='div' id='firehose.all' defaultMessage='All' />
          </NavLink>
        </div>

        <StatusListContainer
          prepend={prependBanner}
          timelineId={`${feedType}${onlyMedia ? ':media' : ''}`}
          onLoadMore={handleLoadMore}
          trackScroll
          scrollKey='firehose'
          emptyMessage={emptyMessage}
          bindToDocument={!multiColumn}
        />
      <div className='account__section-headline'>
        <NavLink exact to='/public/local'>
          <FormattedMessage tagName='div' id='firehose.local' defaultMessage='This server' />
        </NavLink>

        <NavLink exact to='/public/remote'>
          <FormattedMessage tagName='div' id='firehose.remote' defaultMessage='Other servers' />
        </NavLink>

        <NavLink exact to='/public'>
          <FormattedMessage tagName='div' id='firehose.all' defaultMessage='All' />
        </NavLink>
      </div>

      <StatusListContainer
        prepend={prependBanner}
        timelineId={`${feedType}${onlyMedia ? ':media' : ''}`}
        onLoadMore={handleLoadMore}
        trackScroll
        scrollKey='firehose'
        emptyMessage={emptyMessage}
        bindToDocument={!multiColumn}
      />

      <Helmet>
        <title>{intl.formatMessage(messages.title)}</title>
        <meta name='robots' content='noindex' />

M app/javascript/styles/mastodon/components.scss => app/javascript/styles/mastodon/components.scss +3 -0
@@ 8279,6 8279,9 @@ noscript {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  background: $ui-base-color;
  border-bottom-left-radius: 4px;
  border-bottom-right-radius: 4px;
}

.story {

M app/lib/account_statuses_filter.rb => app/lib/account_statuses_filter.rb +5 -1
@@ 60,8 60,12 @@ class AccountStatusesFilter
      .where(reblog_of_id: nil)
      .or(
        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: { accounts: { domain: current_account.excluded_from_timeline_domains } })
      )
  end


M app/workers/scheduler/trends/refresh_scheduler.rb => app/workers/scheduler/trends/refresh_scheduler.rb +1 -1
@@ 3,7 3,7 @@
class Scheduler::Trends::RefreshScheduler
  include Sidekiq::Worker

  sidekiq_options retry: 0
  sidekiq_options retry: 0, lock: :until_executed, lock_ttl: 30.minutes.to_i

  def perform
    Trends.refresh!

R spec/models/account_statuses_filter_spec.rb => spec/lib/account_statuses_filter_spec.rb +15 -1
@@ 202,7 202,7 @@ RSpec.describe AccountStatusesFilter do
      context 'when blocking a reblogged domain' do
        let(:other_account) { Fabricate(:account, domain: 'example.com') }
        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
          current_account.block_domain!(other_account.domain)


@@ 213,6 213,20 @@ RSpec.describe AccountStatusesFilter do
        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
        let(:reblog) { status_with_reblog!('public') }