Merge pull request #2449 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes up to 9a3d047f3e
main
commit
59893a4eab
|
@ -236,7 +236,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
// Common React utilities
|
// Common React utilities
|
||||||
{
|
{
|
||||||
pattern: '{classnames,react-helmet,react-router-dom}',
|
pattern: '{classnames,react-helmet,react-router,react-router-dom}',
|
||||||
group: 'external',
|
group: 'external',
|
||||||
position: 'before',
|
position: 'before',
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
name: 'Setup Javascript'
|
||||||
|
description: 'Setup a Javascript environment ready to run the Mastodon code'
|
||||||
|
inputs:
|
||||||
|
onlyProduction:
|
||||||
|
description: Only install production dependencies
|
||||||
|
default: 'false'
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
cache: yarn
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
|
||||||
|
- name: Install all yarn packages
|
||||||
|
shell: bash
|
||||||
|
run: yarn --frozen-lockfile ${{ inputs.onlyProduction != 'false' && '--production' || '' }}
|
|
@ -0,0 +1,23 @@
|
||||||
|
name: 'Setup RUby'
|
||||||
|
description: 'Setup a Ruby environment ready to run the Mastodon code'
|
||||||
|
inputs:
|
||||||
|
ruby-version:
|
||||||
|
description: The Ruby version to install
|
||||||
|
default: '.ruby-version'
|
||||||
|
additional-system-dependencies:
|
||||||
|
description: 'Additional packages to install'
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: Install system dependencies
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libicu-dev libidn11-dev ${{ inputs.additional-system-dependencies }}
|
||||||
|
|
||||||
|
- name: Set up Ruby
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: ${{ inputs.ruby-version }}
|
||||||
|
bundler-cache: true
|
|
@ -3,7 +3,6 @@
|
||||||
extends: [
|
extends: [
|
||||||
'config:recommended',
|
'config:recommended',
|
||||||
':labels(dependencies)',
|
':labels(dependencies)',
|
||||||
':maintainLockFilesMonthly', // update non-direct dependencies monthly
|
|
||||||
':prConcurrentLimitNone', // Remove limit for open PRs at any time.
|
':prConcurrentLimitNone', // Remove limit for open PRs at any time.
|
||||||
':prHourlyLimit2', // Rate limit PR creation to a maximum of two per hour.
|
':prHourlyLimit2', // Rate limit PR creation to a maximum of two per hour.
|
||||||
],
|
],
|
||||||
|
|
|
@ -27,14 +27,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
- name: Set up Ruby environment
|
||||||
run: sudo apt-get install -y libicu-dev libidn11-dev
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
- name: Set up Ruby
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: .ruby-version
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Run bundler-audit
|
- name: Run bundler-audit
|
||||||
run: bundle exec bundler-audit
|
run: bundle exec bundler-audit
|
||||||
|
|
|
@ -19,25 +19,11 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install system dependencies
|
- name: Set up Ruby environment
|
||||||
run: |
|
uses: ./.github/actions/setup-ruby
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libicu-dev libidn11-dev
|
|
||||||
|
|
||||||
- name: Set up Ruby
|
- name: Set up Javascript environment
|
||||||
uses: ruby/setup-ruby@v1
|
uses: ./.github/actions/setup-javascript
|
||||||
with:
|
|
||||||
ruby-version: .ruby-version
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install all yarn packages
|
|
||||||
run: yarn --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Check for missing strings in English JSON
|
- name: Check for missing strings in English JSON
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -45,14 +45,8 @@ jobs:
|
||||||
run: sudo chown -R runner:docker .
|
run: sudo chown -R runner:docker .
|
||||||
|
|
||||||
# This is needed to run the normalize step
|
# This is needed to run the normalize step
|
||||||
- name: Install native Ruby dependencies
|
- name: Set up Ruby environment
|
||||||
run: sudo apt-get install -y libicu-dev libidn11-dev
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
- name: Set up Ruby
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: .ruby-version
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Run i18n normalize task
|
- name: Run i18n normalize task
|
||||||
run: bundle exec i18n-tasks normalize
|
run: bundle exec i18n-tasks normalize
|
||||||
|
|
|
@ -35,14 +35,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Javascript environment
|
||||||
uses: actions/setup-node@v3
|
uses: ./.github/actions/setup-javascript
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install all yarn packages
|
|
||||||
run: yarn --frozen-lockfile
|
|
||||||
|
|
||||||
- uses: xt0rted/stylelint-problem-matcher@v1
|
- uses: xt0rted/stylelint-problem-matcher@v1
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
- name: Set up Ruby environment
|
||||||
run: |
|
uses: ./.github/actions/setup-ruby
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libicu-dev libidn11-dev
|
|
||||||
|
|
||||||
- name: Set up Ruby
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: .ruby-version
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Run haml-lint
|
- name: Run haml-lint
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -39,14 +39,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Javascript environment
|
||||||
uses: actions/setup-node@v3
|
uses: ./.github/actions/setup-javascript
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install all yarn packages
|
|
||||||
run: yarn --frozen-lockfile
|
|
||||||
|
|
||||||
- name: ESLint
|
- name: ESLint
|
||||||
run: yarn lint:js --max-warnings 0
|
run: yarn lint:js --max-warnings 0
|
||||||
|
|
|
@ -31,14 +31,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Javascript environment
|
||||||
uses: actions/setup-node@v3
|
uses: ./.github/actions/setup-javascript
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install all yarn packages
|
|
||||||
run: yarn --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Prettier
|
- name: Prettier
|
||||||
run: yarn lint:json
|
run: yarn lint:json
|
||||||
|
|
|
@ -31,14 +31,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Javascript environment
|
||||||
uses: actions/setup-node@v3
|
uses: ./.github/actions/setup-javascript
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install all yarn packages
|
|
||||||
run: yarn --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Prettier
|
- name: Prettier
|
||||||
run: yarn lint:md
|
run: yarn lint:md
|
||||||
|
|
|
@ -31,14 +31,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
- name: Set up Ruby environment
|
||||||
run: sudo apt-get install -y libicu-dev libidn11-dev
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
- name: Set up Ruby
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: .ruby-version
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Set-up RuboCop Problem Matcher
|
- name: Set-up RuboCop Problem Matcher
|
||||||
uses: r7kamura/rubocop-problem-matchers-action@v1
|
uses: r7kamura/rubocop-problem-matchers-action@v1
|
||||||
|
|
|
@ -33,14 +33,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Javascript environment
|
||||||
uses: actions/setup-node@v3
|
uses: ./.github/actions/setup-javascript
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install all yarn packages
|
|
||||||
run: yarn --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Prettier
|
- name: Prettier
|
||||||
run: yarn lint:yml
|
run: yarn lint:yml
|
||||||
|
|
|
@ -35,14 +35,8 @@ jobs:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Javascript environment
|
||||||
uses: actions/setup-node@v3
|
uses: ./.github/actions/setup-javascript
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install all yarn packages
|
|
||||||
run: yarn --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Jest testing
|
- name: Jest testing
|
||||||
run: yarn jest --reporters github-actions summary
|
run: yarn jest --reporters github-actions summary
|
||||||
|
|
|
@ -72,16 +72,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
- name: Set up Ruby environment
|
||||||
run: |
|
uses: ./.github/actions/setup-ruby
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libicu-dev libidn11-dev
|
|
||||||
|
|
||||||
- name: Set up bundler cache
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: .ruby-version
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Create database
|
- name: Create database
|
||||||
run: './bin/rails db:create'
|
run: './bin/rails db:create'
|
||||||
|
|
|
@ -71,16 +71,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
- name: Set up Ruby environment
|
||||||
run: |
|
uses: ./.github/actions/setup-ruby
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libicu-dev libidn11-dev
|
|
||||||
|
|
||||||
- name: Set up bundler cache
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: .ruby-version
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- name: Create database
|
- name: Create database
|
||||||
run: './bin/rails db:create'
|
run: './bin/rails db:create'
|
||||||
|
|
|
@ -34,24 +34,14 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Ruby environment
|
||||||
uses: actions/setup-node@v3
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
|
- name: Set up Javascript environment
|
||||||
|
uses: ./.github/actions/setup-javascript
|
||||||
with:
|
with:
|
||||||
cache: yarn
|
onlyProduction: 'true'
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libicu-dev libidn11-dev
|
|
||||||
|
|
||||||
- name: Set up bundler cache
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
|
||||||
ruby-version: .ruby-version
|
|
||||||
bundler-cache: true
|
|
||||||
|
|
||||||
- run: yarn --frozen-lockfile --production
|
|
||||||
- name: Precompile assets
|
- name: Precompile assets
|
||||||
# Previously had set this, but it's not supported
|
# Previously had set this, but it's not supported
|
||||||
# export NODE_OPTIONS=--openssl-legacy-provider
|
# export NODE_OPTIONS=--openssl-legacy-provider
|
||||||
|
@ -135,20 +125,11 @@ jobs:
|
||||||
path: './public'
|
path: './public'
|
||||||
name: ${{ github.sha }}
|
name: ${{ github.sha }}
|
||||||
|
|
||||||
- name: Update package index
|
- name: Set up Ruby environment
|
||||||
run: sudo apt-get update
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
|
||||||
run: sudo apt-get install -y libicu-dev libidn11-dev
|
|
||||||
|
|
||||||
- name: Install additional system dependencies
|
|
||||||
run: sudo apt-get install -y ffmpeg imagemagick libpam-dev
|
|
||||||
|
|
||||||
- name: Set up bundler cache
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
with:
|
||||||
ruby-version: ${{ matrix.ruby-version}}
|
ruby-version: ${{ matrix.ruby-version}}
|
||||||
bundler-cache: true
|
additional-system-dependencies: ffmpeg imagemagick libpam-dev
|
||||||
|
|
||||||
- name: Load database schema
|
- name: Load database schema
|
||||||
run: './bin/rails db:create db:schema:load db:seed'
|
run: './bin/rails db:create db:schema:load db:seed'
|
||||||
|
@ -210,28 +191,14 @@ jobs:
|
||||||
path: './public'
|
path: './public'
|
||||||
name: ${{ github.sha }}
|
name: ${{ github.sha }}
|
||||||
|
|
||||||
- name: Update package index
|
- name: Set up Ruby environment
|
||||||
run: sudo apt-get update
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
|
||||||
run: sudo apt-get install -y libicu-dev libidn11-dev
|
|
||||||
|
|
||||||
- name: Install additional system dependencies
|
|
||||||
run: sudo apt-get install -y ffmpeg imagemagick
|
|
||||||
|
|
||||||
- name: Set up bundler cache
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
with:
|
||||||
ruby-version: ${{ matrix.ruby-version}}
|
ruby-version: ${{ matrix.ruby-version}}
|
||||||
bundler-cache: true
|
additional-system-dependencies: ffmpeg imagemagick
|
||||||
|
|
||||||
- run: yarn --frozen-lockfile
|
- name: Set up Javascript environment
|
||||||
|
uses: ./.github/actions/setup-javascript
|
||||||
|
|
||||||
- name: Load database schema
|
- name: Load database schema
|
||||||
run: './bin/rails db:create db:schema:load db:seed'
|
run: './bin/rails db:create db:schema:load db:seed'
|
||||||
|
@ -328,28 +295,14 @@ jobs:
|
||||||
path: './public'
|
path: './public'
|
||||||
name: ${{ github.sha }}
|
name: ${{ github.sha }}
|
||||||
|
|
||||||
- name: Update package index
|
- name: Set up Ruby environment
|
||||||
run: sudo apt-get update
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
cache: yarn
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install native Ruby dependencies
|
|
||||||
run: sudo apt-get install -y libicu-dev libidn11-dev
|
|
||||||
|
|
||||||
- name: Install additional system dependencies
|
|
||||||
run: sudo apt-get install -y ffmpeg imagemagick
|
|
||||||
|
|
||||||
- name: Set up bundler cache
|
|
||||||
uses: ruby/setup-ruby@v1
|
|
||||||
with:
|
with:
|
||||||
ruby-version: ${{ matrix.ruby-version}}
|
ruby-version: ${{ matrix.ruby-version}}
|
||||||
bundler-cache: true
|
additional-system-dependencies: ffmpeg imagemagick
|
||||||
|
|
||||||
- run: yarn --frozen-lockfile
|
- name: Set up Javascript environment
|
||||||
|
uses: ./.github/actions/setup-javascript
|
||||||
|
|
||||||
- name: Load database schema
|
- name: Load database schema
|
||||||
run: './bin/rails db:create db:schema:load db:seed'
|
run: './bin/rails db:create db:schema:load db:seed'
|
||||||
|
|
|
@ -1,33 +1,21 @@
|
||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `haml-lint --auto-gen-config`
|
# `haml-lint --auto-gen-config`
|
||||||
# on 2023-10-11 11:31:24 -0400 using Haml-Lint version 0.51.0.
|
# on 2023-10-25 08:29:48 -0400 using Haml-Lint version 0.51.0.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the lints are removed from the code base.
|
# one by one as the lints are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
# versions of Haml-Lint, may require this file to be generated again.
|
# versions of Haml-Lint, may require this file to be generated again.
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
# Offense count: 946
|
# Offense count: 945
|
||||||
LineLength:
|
LineLength:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
# Offense count: 22
|
# Offense count: 10
|
||||||
UnnecessaryStringOutput:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
# Offense count: 44
|
|
||||||
RuboCop:
|
RuboCop:
|
||||||
enabled: false
|
|
||||||
|
|
||||||
# Offense count: 3
|
|
||||||
ViewLength:
|
|
||||||
exclude:
|
exclude:
|
||||||
- 'app/views/admin/accounts/show.html.haml'
|
- 'app/views/admin/accounts/_buttons.html.haml'
|
||||||
- 'app/views/admin/reports/show.html.haml'
|
- 'app/views/admin/accounts/_local_account.html.haml'
|
||||||
- 'app/views/disputes/strikes/show.html.haml'
|
- 'app/views/admin/accounts/index.html.haml'
|
||||||
|
- 'app/views/admin/roles/_form.html.haml'
|
||||||
# Offense count: 2
|
- 'app/views/layouts/application.html.haml'
|
||||||
IdNames:
|
|
||||||
exclude:
|
|
||||||
- 'app/views/oauth/authorizations/error.html.haml'
|
|
||||||
- 'app/views/shared/_error_messages.html.haml'
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp`
|
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp`
|
||||||
# using RuboCop version 1.56.1.
|
# using RuboCop version 1.57.1.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the offenses are removed from the code base.
|
# one by one as the offenses are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
|
@ -80,7 +80,6 @@ RSpec/AnyInstance:
|
||||||
- 'spec/controllers/admin/accounts_controller_spec.rb'
|
- 'spec/controllers/admin/accounts_controller_spec.rb'
|
||||||
- 'spec/controllers/admin/resets_controller_spec.rb'
|
- 'spec/controllers/admin/resets_controller_spec.rb'
|
||||||
- 'spec/controllers/admin/settings/branding_controller_spec.rb'
|
- 'spec/controllers/admin/settings/branding_controller_spec.rb'
|
||||||
- 'spec/controllers/api/v1/media_controller_spec.rb'
|
|
||||||
- 'spec/controllers/auth/sessions_controller_spec.rb'
|
- 'spec/controllers/auth/sessions_controller_spec.rb'
|
||||||
- 'spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb'
|
- 'spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb'
|
||||||
- 'spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb'
|
- 'spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb'
|
||||||
|
@ -180,7 +179,6 @@ RSpec/LetSetup:
|
||||||
|
|
||||||
RSpec/MessageChain:
|
RSpec/MessageChain:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'spec/controllers/api/v1/media_controller_spec.rb'
|
|
||||||
- 'spec/models/concerns/remotable_spec.rb'
|
- 'spec/models/concerns/remotable_spec.rb'
|
||||||
- 'spec/models/session_activation_spec.rb'
|
- 'spec/models/session_activation_spec.rb'
|
||||||
- 'spec/models/setting_spec.rb'
|
- 'spec/models/setting_spec.rb'
|
||||||
|
@ -219,19 +217,6 @@ Rails/ApplicationController:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/health_controller.rb'
|
- 'app/controllers/health_controller.rb'
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
|
||||||
# Include: db/**/*.rb
|
|
||||||
Rails/CreateTableWithTimestamps:
|
|
||||||
Exclude:
|
|
||||||
- 'db/migrate/20170508230434_create_conversation_mutes.rb'
|
|
||||||
- 'db/migrate/20170823162448_create_status_pins.rb'
|
|
||||||
- 'db/migrate/20171116161857_create_list_accounts.rb'
|
|
||||||
- 'db/migrate/20180929222014_create_account_conversations.rb'
|
|
||||||
- 'db/migrate/20181007025445_create_pghero_space_stats.rb'
|
|
||||||
- 'db/migrate/20190103124649_create_scheduled_statuses.rb'
|
|
||||||
- 'db/migrate/20220824233535_create_status_trends.rb'
|
|
||||||
- 'db/migrate/20221006061337_create_preview_card_trends.rb'
|
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: Severity.
|
# Configuration parameters: Severity.
|
||||||
Rails/DuplicateAssociation:
|
Rails/DuplicateAssociation:
|
||||||
|
@ -273,7 +258,6 @@ Rails/LexicallyScopedActionFilter:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/auth/passwords_controller.rb'
|
- 'app/controllers/auth/passwords_controller.rb'
|
||||||
- 'app/controllers/auth/registrations_controller.rb'
|
- 'app/controllers/auth/registrations_controller.rb'
|
||||||
- 'app/controllers/auth/sessions_controller.rb'
|
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
Rails/NegateInclude:
|
Rails/NegateInclude:
|
||||||
|
@ -289,7 +273,6 @@ Rails/NegateInclude:
|
||||||
- 'app/models/custom_filter.rb'
|
- 'app/models/custom_filter.rb'
|
||||||
- 'app/services/activitypub/process_status_update_service.rb'
|
- 'app/services/activitypub/process_status_update_service.rb'
|
||||||
- 'app/services/fetch_link_card_service.rb'
|
- 'app/services/fetch_link_card_service.rb'
|
||||||
- 'app/services/search_service.rb'
|
|
||||||
- 'app/workers/web/push_notification_worker.rb'
|
- 'app/workers/web/push_notification_worker.rb'
|
||||||
- 'lib/paperclip/color_extractor.rb'
|
- 'lib/paperclip/color_extractor.rb'
|
||||||
|
|
||||||
|
@ -309,24 +292,6 @@ Rails/RakeEnvironment:
|
||||||
- 'lib/tasks/repo.rake'
|
- 'lib/tasks/repo.rake'
|
||||||
- 'lib/tasks/statistics.rake'
|
- 'lib/tasks/statistics.rake'
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
|
||||||
# Include: db/**/*.rb
|
|
||||||
Rails/ReversibleMigration:
|
|
||||||
Exclude:
|
|
||||||
- 'db/migrate/20160223164502_make_uris_nullable_in_statuses.rb'
|
|
||||||
- 'db/migrate/20161122163057_remove_unneeded_indexes.rb'
|
|
||||||
- 'db/migrate/20170205175257_remove_devices.rb'
|
|
||||||
- 'db/migrate/20170322143850_change_primary_key_to_bigint_on_statuses.rb'
|
|
||||||
- 'db/migrate/20170520145338_change_language_filter_to_opt_out.rb'
|
|
||||||
- 'db/migrate/20170609145826_remove_default_language_from_statuses.rb'
|
|
||||||
- 'db/migrate/20170711225116_fix_null_booleans.rb'
|
|
||||||
- 'db/migrate/20171129172043_add_index_on_stream_entries.rb'
|
|
||||||
- 'db/migrate/20171212195226_remove_duplicate_indexes_in_lists.rb'
|
|
||||||
- 'db/migrate/20171226094803_more_faster_index_on_notifications.rb'
|
|
||||||
- 'db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb'
|
|
||||||
- 'db/migrate/20180617162849_remove_unused_indexes.rb'
|
|
||||||
- 'db/migrate/20220827195229_change_canonical_email_blocks_nullable.rb'
|
|
||||||
|
|
||||||
# Configuration parameters: ForbiddenMethods, AllowedMethods.
|
# Configuration parameters: ForbiddenMethods, AllowedMethods.
|
||||||
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
|
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
|
||||||
Rails/SkipsModelValidations:
|
Rails/SkipsModelValidations:
|
||||||
|
@ -379,31 +344,6 @@ Rails/SkipsModelValidations:
|
||||||
- 'spec/services/follow_service_spec.rb'
|
- 'spec/services/follow_service_spec.rb'
|
||||||
- 'spec/services/update_account_service_spec.rb'
|
- 'spec/services/update_account_service_spec.rb'
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
|
||||||
# Include: db/**/*.rb
|
|
||||||
Rails/ThreeStateBooleanColumn:
|
|
||||||
Exclude:
|
|
||||||
- 'db/migrate/20160325130944_add_admin_to_users.rb'
|
|
||||||
- 'db/migrate/20161123093447_add_sensitive_to_statuses.rb'
|
|
||||||
- 'db/migrate/20170123203248_add_reject_media_to_domain_blocks.rb'
|
|
||||||
- 'db/migrate/20170127165745_add_devise_two_factor_to_users.rb'
|
|
||||||
- 'db/migrate/20170209184350_add_reply_to_statuses.rb'
|
|
||||||
- 'db/migrate/20170330163835_create_imports.rb'
|
|
||||||
- 'db/migrate/20170905165803_add_local_to_statuses.rb'
|
|
||||||
- 'db/migrate/20171210213213_add_local_only_flag_to_statuses.rb'
|
|
||||||
- 'db/migrate/20181203021853_add_discoverable_to_accounts.rb'
|
|
||||||
- 'db/migrate/20190509164208_add_by_moderator_to_tombstone.rb'
|
|
||||||
- 'db/migrate/20190805123746_add_capabilities_to_tags.rb'
|
|
||||||
- 'db/migrate/20191212163405_add_hide_collections_to_accounts.rb'
|
|
||||||
- 'db/migrate/20200309150742_add_forwarded_to_reports.rb'
|
|
||||||
- 'db/migrate/20210609202149_create_login_activities.rb'
|
|
||||||
- 'db/migrate/20210621221010_add_skip_sign_in_token_to_users.rb'
|
|
||||||
- 'db/migrate/20211031031021_create_preview_card_providers.rb'
|
|
||||||
- 'db/migrate/20211115032527_add_trendable_to_preview_cards.rb'
|
|
||||||
- 'db/migrate/20220202200743_add_trendable_to_accounts.rb'
|
|
||||||
- 'db/migrate/20220202200926_add_trendable_to_statuses.rb'
|
|
||||||
- 'db/migrate/20220303000827_add_ordered_media_attachment_ids_to_status_edits.rb'
|
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
# Configuration parameters: Include.
|
||||||
# Include: app/models/**/*.rb
|
# Include: app/models/**/*.rb
|
||||||
Rails/UniqueValidationWithoutIndex:
|
Rails/UniqueValidationWithoutIndex:
|
||||||
|
@ -467,7 +407,7 @@ Style/CaseEquality:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'config/initializers/trusted_proxies.rb'
|
- 'config/initializers/trusted_proxies.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
||||||
# AllowedMethods: ==, equal?, eql?
|
# AllowedMethods: ==, equal?, eql?
|
||||||
Style/ClassEqualityComparison:
|
Style/ClassEqualityComparison:
|
||||||
|
@ -675,7 +615,6 @@ Style/RedundantReturn:
|
||||||
Style/SafeNavigation:
|
Style/SafeNavigation:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/concerns/account_finder_concern.rb'
|
- 'app/models/concerns/account_finder_concern.rb'
|
||||||
- 'app/models/status.rb'
|
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
|
|
2329
CHANGELOG.md
2329
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
|
@ -28,7 +28,7 @@ RUN apt-get update && \
|
||||||
libgdbm-dev \
|
libgdbm-dev \
|
||||||
libgmp-dev \
|
libgmp-dev \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libyaml-0-2 \
|
libyaml-dev \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
libreadline8 \
|
libreadline8 \
|
||||||
python3 \
|
python3 \
|
||||||
|
|
2
Gemfile
2
Gemfile
|
@ -4,7 +4,7 @@ source 'https://rubygems.org'
|
||||||
ruby '>= 3.0.0'
|
ruby '>= 3.0.0'
|
||||||
|
|
||||||
gem 'puma', '~> 6.3'
|
gem 'puma', '~> 6.3'
|
||||||
gem 'rails', '~> 7.0'
|
gem 'rails', '~> 7.1.1'
|
||||||
gem 'sprockets', '~> 3.7.2'
|
gem 'sprockets', '~> 3.7.2'
|
||||||
gem 'thor', '~> 1.2'
|
gem 'thor', '~> 1.2'
|
||||||
gem 'rack', '~> 2.2.7'
|
gem 'rack', '~> 2.2.7'
|
||||||
|
|
173
Gemfile.lock
173
Gemfile.lock
|
@ -39,75 +39,83 @@ GIT
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (7.0.8)
|
actioncable (7.1.1)
|
||||||
actionpack (= 7.0.8)
|
actionpack (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailbox (7.0.8)
|
zeitwerk (~> 2.6)
|
||||||
actionpack (= 7.0.8)
|
actionmailbox (7.1.1)
|
||||||
activejob (= 7.0.8)
|
actionpack (= 7.1.1)
|
||||||
activerecord (= 7.0.8)
|
activejob (= 7.1.1)
|
||||||
activestorage (= 7.0.8)
|
activerecord (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activestorage (= 7.1.1)
|
||||||
|
activesupport (= 7.1.1)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
net-imap
|
net-imap
|
||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
actionmailer (7.0.8)
|
actionmailer (7.1.1)
|
||||||
actionpack (= 7.0.8)
|
actionpack (= 7.1.1)
|
||||||
actionview (= 7.0.8)
|
actionview (= 7.1.1)
|
||||||
activejob (= 7.0.8)
|
activejob (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
net-imap
|
net-imap
|
||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.2)
|
||||||
actionpack (7.0.8)
|
actionpack (7.1.1)
|
||||||
actionview (= 7.0.8)
|
actionview (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
rack (~> 2.0, >= 2.2.4)
|
nokogiri (>= 1.8.5)
|
||||||
|
rack (>= 2.2.4)
|
||||||
|
rack-session (>= 1.0.1)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
rails-html-sanitizer (~> 1.6)
|
||||||
actiontext (7.0.8)
|
actiontext (7.1.1)
|
||||||
actionpack (= 7.0.8)
|
actionpack (= 7.1.1)
|
||||||
activerecord (= 7.0.8)
|
activerecord (= 7.1.1)
|
||||||
activestorage (= 7.0.8)
|
activestorage (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
globalid (>= 0.6.0)
|
globalid (>= 0.6.0)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (7.0.8)
|
actionview (7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.11)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
rails-html-sanitizer (~> 1.6)
|
||||||
active_model_serializers (0.10.14)
|
active_model_serializers (0.10.14)
|
||||||
actionpack (>= 4.1)
|
actionpack (>= 4.1)
|
||||||
activemodel (>= 4.1)
|
activemodel (>= 4.1)
|
||||||
case_transform (>= 0.2)
|
case_transform (>= 0.2)
|
||||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||||
activejob (7.0.8)
|
activejob (7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (7.0.8)
|
activemodel (7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
activerecord (7.0.8)
|
activerecord (7.1.1)
|
||||||
activemodel (= 7.0.8)
|
activemodel (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
activestorage (7.0.8)
|
timeout (>= 0.4.0)
|
||||||
actionpack (= 7.0.8)
|
activestorage (7.1.1)
|
||||||
activejob (= 7.0.8)
|
actionpack (= 7.1.1)
|
||||||
activerecord (= 7.0.8)
|
activejob (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activerecord (= 7.1.1)
|
||||||
|
activesupport (= 7.1.1)
|
||||||
marcel (~> 1.0)
|
marcel (~> 1.0)
|
||||||
mini_mime (>= 1.1.0)
|
activesupport (7.1.1)
|
||||||
activesupport (7.0.8)
|
base64
|
||||||
|
bigdecimal
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
|
connection_pool (>= 2.2.5)
|
||||||
|
drb
|
||||||
i18n (>= 1.6, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
|
mutex_m
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
addressable (2.8.5)
|
addressable (2.8.5)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
public_suffix (>= 2.0.2, < 6.0)
|
||||||
|
@ -158,6 +166,7 @@ GEM
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
parser (>= 2.4)
|
parser (>= 2.4)
|
||||||
smart_properties
|
smart_properties
|
||||||
|
bigdecimal (3.1.4)
|
||||||
bindata (2.4.15)
|
bindata (2.4.15)
|
||||||
binding_of_caller (1.0.0)
|
binding_of_caller (1.0.0)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
|
@ -237,6 +246,8 @@ GEM
|
||||||
dotenv-rails (2.8.1)
|
dotenv-rails (2.8.1)
|
||||||
dotenv (= 2.8.1)
|
dotenv (= 2.8.1)
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
|
drb (2.1.1)
|
||||||
|
ruby2_keywords
|
||||||
ed25519 (1.3.0)
|
ed25519 (1.3.0)
|
||||||
elasticsearch (7.13.3)
|
elasticsearch (7.13.3)
|
||||||
elasticsearch-api (= 7.13.3)
|
elasticsearch-api (= 7.13.3)
|
||||||
|
@ -305,8 +316,8 @@ GEM
|
||||||
fuubar (2.5.1)
|
fuubar (2.5.1)
|
||||||
rspec-core (~> 3.0)
|
rspec-core (~> 3.0)
|
||||||
ruby-progressbar (~> 1.4)
|
ruby-progressbar (~> 1.4)
|
||||||
globalid (1.1.0)
|
globalid (1.2.1)
|
||||||
activesupport (>= 5.0)
|
activesupport (>= 6.1)
|
||||||
haml (6.2.0)
|
haml (6.2.0)
|
||||||
temple (>= 0.8.2)
|
temple (>= 0.8.2)
|
||||||
thor
|
thor
|
||||||
|
@ -357,7 +368,11 @@ GEM
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
terminal-table (>= 1.5.1)
|
terminal-table (>= 1.5.1)
|
||||||
idn-ruby (0.1.5)
|
idn-ruby (0.1.5)
|
||||||
|
io-console (0.6.0)
|
||||||
ipaddress (0.8.3)
|
ipaddress (0.8.3)
|
||||||
|
irb (1.8.1)
|
||||||
|
rdoc
|
||||||
|
reline (>= 0.3.8)
|
||||||
jmespath (1.6.2)
|
jmespath (1.6.2)
|
||||||
json (2.6.3)
|
json (2.6.3)
|
||||||
json-canonicalization (0.3.2)
|
json-canonicalization (0.3.2)
|
||||||
|
@ -434,7 +449,6 @@ GEM
|
||||||
azure-storage-blob (~> 2.0.1)
|
azure-storage-blob (~> 2.0.1)
|
||||||
hashie (~> 5.0)
|
hashie (~> 5.0)
|
||||||
memory_profiler (1.0.1)
|
memory_profiler (1.0.1)
|
||||||
method_source (1.0.0)
|
|
||||||
mime-types (3.5.1)
|
mime-types (3.5.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2023.0808)
|
mime-types-data (3.2023.0808)
|
||||||
|
@ -444,11 +458,12 @@ GEM
|
||||||
msgpack (1.7.1)
|
msgpack (1.7.1)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
multipart-post (2.3.0)
|
multipart-post (2.3.0)
|
||||||
|
mutex_m (0.1.2)
|
||||||
net-http (0.3.2)
|
net-http (0.3.2)
|
||||||
uri
|
uri
|
||||||
net-http-persistent (4.0.2)
|
net-http-persistent (4.0.2)
|
||||||
connection_pool (~> 2.2)
|
connection_pool (~> 2.2)
|
||||||
net-imap (0.3.7)
|
net-imap (0.4.1)
|
||||||
date
|
date
|
||||||
net-protocol
|
net-protocol
|
||||||
net-ldap (0.18.0)
|
net-ldap (0.18.0)
|
||||||
|
@ -456,7 +471,7 @@ GEM
|
||||||
net-protocol
|
net-protocol
|
||||||
net-protocol (0.2.1)
|
net-protocol (0.2.1)
|
||||||
timeout
|
timeout
|
||||||
net-smtp (0.3.3)
|
net-smtp (0.4.0)
|
||||||
net-protocol
|
net-protocol
|
||||||
nio4r (2.5.9)
|
nio4r (2.5.9)
|
||||||
nokogiri (1.15.4)
|
nokogiri (1.15.4)
|
||||||
|
@ -512,6 +527,8 @@ GEM
|
||||||
net-smtp
|
net-smtp
|
||||||
premailer (~> 1.7, >= 1.7.9)
|
premailer (~> 1.7, >= 1.7.9)
|
||||||
private_address_check (0.5.0)
|
private_address_check (0.5.0)
|
||||||
|
psych (5.1.1)
|
||||||
|
stringio
|
||||||
public_suffix (5.0.3)
|
public_suffix (5.0.3)
|
||||||
puma (6.4.0)
|
puma (6.4.0)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
|
@ -534,22 +551,27 @@ GEM
|
||||||
rack
|
rack
|
||||||
rack-proxy (0.7.6)
|
rack-proxy (0.7.6)
|
||||||
rack
|
rack
|
||||||
|
rack-session (1.0.1)
|
||||||
|
rack (< 3)
|
||||||
rack-test (2.1.0)
|
rack-test (2.1.0)
|
||||||
rack (>= 1.3)
|
rack (>= 1.3)
|
||||||
rails (7.0.8)
|
rackup (1.0.0)
|
||||||
actioncable (= 7.0.8)
|
rack (< 3)
|
||||||
actionmailbox (= 7.0.8)
|
webrick
|
||||||
actionmailer (= 7.0.8)
|
rails (7.1.1)
|
||||||
actionpack (= 7.0.8)
|
actioncable (= 7.1.1)
|
||||||
actiontext (= 7.0.8)
|
actionmailbox (= 7.1.1)
|
||||||
actionview (= 7.0.8)
|
actionmailer (= 7.1.1)
|
||||||
activejob (= 7.0.8)
|
actionpack (= 7.1.1)
|
||||||
activemodel (= 7.0.8)
|
actiontext (= 7.1.1)
|
||||||
activerecord (= 7.0.8)
|
actionview (= 7.1.1)
|
||||||
activestorage (= 7.0.8)
|
activejob (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activemodel (= 7.1.1)
|
||||||
|
activerecord (= 7.1.1)
|
||||||
|
activestorage (= 7.1.1)
|
||||||
|
activesupport (= 7.1.1)
|
||||||
bundler (>= 1.15.0)
|
bundler (>= 1.15.0)
|
||||||
railties (= 7.0.8)
|
railties (= 7.1.1)
|
||||||
rails-controller-testing (1.0.5)
|
rails-controller-testing (1.0.5)
|
||||||
actionpack (>= 5.0.1.rc1)
|
actionpack (>= 5.0.1.rc1)
|
||||||
actionview (>= 5.0.1.rc1)
|
actionview (>= 5.0.1.rc1)
|
||||||
|
@ -564,19 +586,22 @@ GEM
|
||||||
rails-i18n (7.0.8)
|
rails-i18n (7.0.8)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
railties (>= 6.0.0, < 8)
|
railties (>= 6.0.0, < 8)
|
||||||
railties (7.0.8)
|
railties (7.1.1)
|
||||||
actionpack (= 7.0.8)
|
actionpack (= 7.1.1)
|
||||||
activesupport (= 7.0.8)
|
activesupport (= 7.1.1)
|
||||||
method_source
|
irb
|
||||||
|
rackup (>= 1.0.0)
|
||||||
rake (>= 12.2)
|
rake (>= 12.2)
|
||||||
thor (~> 1.0)
|
thor (~> 1.0, >= 1.2.2)
|
||||||
zeitwerk (~> 2.5)
|
zeitwerk (~> 2.6)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.0.6)
|
rake (13.0.6)
|
||||||
rdf (3.2.11)
|
rdf (3.2.11)
|
||||||
link_header (~> 0.0, >= 0.0.8)
|
link_header (~> 0.0, >= 0.0.8)
|
||||||
rdf-normalize (0.6.1)
|
rdf-normalize (0.6.1)
|
||||||
rdf (~> 3.2)
|
rdf (~> 3.2)
|
||||||
|
rdoc (6.5.0)
|
||||||
|
psych (>= 4.0.0)
|
||||||
redcarpet (3.6.0)
|
redcarpet (3.6.0)
|
||||||
redis (4.8.1)
|
redis (4.8.1)
|
||||||
redis-namespace (1.11.0)
|
redis-namespace (1.11.0)
|
||||||
|
@ -584,13 +609,15 @@ GEM
|
||||||
redlock (1.3.2)
|
redlock (1.3.2)
|
||||||
redis (>= 3.0.0, < 6.0)
|
redis (>= 3.0.0, < 6.0)
|
||||||
regexp_parser (2.8.2)
|
regexp_parser (2.8.2)
|
||||||
|
reline (0.3.9)
|
||||||
|
io-console (~> 0.5)
|
||||||
request_store (1.5.1)
|
request_store (1.5.1)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
responders (3.1.1)
|
responders (3.1.1)
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
rexml (3.2.6)
|
rexml (3.2.6)
|
||||||
rotp (6.2.2)
|
rotp (6.3.0)
|
||||||
rouge (4.1.2)
|
rouge (4.1.2)
|
||||||
rpam2 (4.0.2)
|
rpam2 (4.0.2)
|
||||||
rqrcode (2.2.0)
|
rqrcode (2.2.0)
|
||||||
|
@ -712,6 +739,7 @@ GEM
|
||||||
statsd-ruby (1.5.0)
|
statsd-ruby (1.5.0)
|
||||||
stoplight (3.0.2)
|
stoplight (3.0.2)
|
||||||
redlock (~> 1.0)
|
redlock (~> 1.0)
|
||||||
|
stringio (3.0.8)
|
||||||
strong_migrations (0.8.0)
|
strong_migrations (0.8.0)
|
||||||
activerecord (>= 5.2)
|
activerecord (>= 5.2)
|
||||||
swd (1.3.0)
|
swd (1.3.0)
|
||||||
|
@ -783,6 +811,7 @@ GEM
|
||||||
rack-proxy (>= 0.6.1)
|
rack-proxy (>= 0.6.1)
|
||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
semantic_range (>= 2.3.0)
|
semantic_range (>= 2.3.0)
|
||||||
|
webrick (1.8.1)
|
||||||
websocket (1.2.10)
|
websocket (1.2.10)
|
||||||
websocket-driver (0.7.6)
|
websocket-driver (0.7.6)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
|
@ -878,7 +907,7 @@ DEPENDENCIES
|
||||||
rack-attack (~> 6.6)
|
rack-attack (~> 6.6)
|
||||||
rack-cors (~> 2.0)
|
rack-cors (~> 2.0)
|
||||||
rack-test (~> 2.1)
|
rack-test (~> 2.1)
|
||||||
rails (~> 7.0)
|
rails (~> 7.1.1)
|
||||||
rails-controller-testing (~> 1.0)
|
rails-controller-testing (~> 1.0)
|
||||||
rails-i18n (~> 7.0)
|
rails-i18n (~> 7.0)
|
||||||
rails-settings-cached (~> 0.6)!
|
rails-settings-cached (~> 0.6)!
|
||||||
|
@ -929,4 +958,4 @@ RUBY VERSION
|
||||||
ruby 3.2.2p53
|
ruby 3.2.2p53
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.4.13
|
2.4.20
|
||||||
|
|
|
@ -49,7 +49,7 @@ module Admin
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_instance
|
def set_instance
|
||||||
@instance = Instance.find(TagManager.instance.normalize_domain(params[:id]&.strip))
|
@instance = Instance.find_or_initialize_by(domain: TagManager.instance.normalize_domain(params[:id]&.strip))
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_instances
|
def set_instances
|
||||||
|
|
|
@ -13,6 +13,7 @@ class ApplicationController < ActionController::Base
|
||||||
include ThemingConcern
|
include ThemingConcern
|
||||||
include DatabaseHelper
|
include DatabaseHelper
|
||||||
include AuthorizedFetchHelper
|
include AuthorizedFetchHelper
|
||||||
|
include SelfDestructHelper
|
||||||
|
|
||||||
helper_method :current_account
|
helper_method :current_account
|
||||||
helper_method :current_session
|
helper_method :current_session
|
||||||
|
@ -41,6 +42,8 @@ class ApplicationController < ActionController::Base
|
||||||
service_unavailable
|
service_unavailable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
before_action :check_self_destruct!
|
||||||
|
|
||||||
before_action :store_referrer, except: :raise_not_found, if: :devise_controller?
|
before_action :store_referrer, except: :raise_not_found, if: :devise_controller?
|
||||||
before_action :require_functional!, if: :user_signed_in?
|
before_action :require_functional!, if: :user_signed_in?
|
||||||
|
|
||||||
|
@ -169,6 +172,15 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_self_destruct!
|
||||||
|
return unless self_destruct?
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.any { render 'errors/self_destruct', layout: 'auth', status: 410, formats: [:html] }
|
||||||
|
format.json { render json: { error: Rack::Utils::HTTP_STATUS_CODES[410] }, status: code }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def set_cache_control_defaults
|
def set_cache_control_defaults
|
||||||
response.cache_control.replace(private: true, no_store: true)
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Auth::ChallengesController < ApplicationController
|
||||||
before_action :set_pack
|
before_action :set_pack
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
|
|
@ -13,6 +13,7 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
|
||||||
before_action :extend_csp_for_captcha!, only: [:show, :confirm_captcha]
|
before_action :extend_csp_for_captcha!, only: [:show, :confirm_captcha]
|
||||||
before_action :require_captcha_if_needed!, only: [:show]
|
before_action :require_captcha_if_needed!, only: [:show]
|
||||||
|
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :verify_authenticity_token
|
skip_before_action :verify_authenticity_token
|
||||||
|
|
||||||
def self.provides_callback_for(provider)
|
def self.provides_callback_for(provider)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Auth::PasswordsController < Devise::PasswordsController
|
class Auth::PasswordsController < Devise::PasswordsController
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
before_action :check_validity_of_reset_password_token, only: :edit
|
before_action :check_validity_of_reset_password_token, only: :edit
|
||||||
before_action :set_pack
|
before_action :set_pack
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
|
|
@ -18,6 +18,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
||||||
before_action :require_rules_acceptance!, only: :new
|
before_action :require_rules_acceptance!, only: :new
|
||||||
before_action :set_registration_form_time, only: :new
|
before_action :set_registration_form_time, only: :new
|
||||||
|
|
||||||
|
skip_before_action :check_self_destruct!, only: [:edit, :update]
|
||||||
skip_before_action :require_functional!, only: [:edit, :update]
|
skip_before_action :require_functional!, only: [:edit, :update]
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
class Auth::SessionsController < Devise::SessionsController
|
class Auth::SessionsController < Devise::SessionsController
|
||||||
layout 'auth'
|
layout 'auth'
|
||||||
|
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :require_no_authentication, only: [:create]
|
skip_before_action :require_no_authentication, only: [:create]
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
skip_before_action :update_user_sign_in
|
skip_before_action :update_user_sign_in
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
class BackupsController < ApplicationController
|
class BackupsController < ApplicationController
|
||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
|
|
@ -7,6 +7,7 @@ module ExportControllerConcern
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :load_export
|
before_action :load_export
|
||||||
|
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Settings::ExportsController < Settings::BaseController
|
||||||
include Redisable
|
include Redisable
|
||||||
include Lockable
|
include Lockable
|
||||||
|
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Settings::LoginActivitiesController < Settings::BaseController
|
class Settings::LoginActivitiesController < Settings::BaseController
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@login_activities = LoginActivity.where(user: current_user).order(id: :desc).page(params[:page])
|
@login_activities = LoginActivity.where(user: current_user).order(id: :desc).page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
module Settings
|
module Settings
|
||||||
module TwoFactorAuthentication
|
module TwoFactorAuthentication
|
||||||
class WebauthnCredentialsController < BaseController
|
class WebauthnCredentialsController < BaseController
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
before_action :require_otp_enabled
|
before_action :require_otp_enabled
|
||||||
|
|
|
@ -4,6 +4,7 @@ module Settings
|
||||||
class TwoFactorAuthenticationMethodsController < BaseController
|
class TwoFactorAuthenticationMethodsController < BaseController
|
||||||
include ChallengableConcern
|
include ChallengableConcern
|
||||||
|
|
||||||
|
skip_before_action :check_self_destruct!
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
before_action :require_challenge!, only: :disable
|
before_action :require_challenge!, only: :disable
|
||||||
|
|
|
@ -9,6 +9,10 @@ module FormattingHelper
|
||||||
TextFormatter.new(text, options).to_s
|
TextFormatter.new(text, options).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def url_for_preview_card(preview_card)
|
||||||
|
preview_card.url
|
||||||
|
end
|
||||||
|
|
||||||
def extract_status_plain_text(status)
|
def extract_status_plain_text(status)
|
||||||
PlainTextFormatter.new(status.text, status.local?).to_s
|
PlainTextFormatter.new(status.text, status.local?).to_s
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module SelfDestructHelper
|
||||||
|
def self.self_destruct?
|
||||||
|
value = ENV.fetch('SELF_DESTRUCT', nil)
|
||||||
|
value.present? && Rails.application.message_verifier('self-destruct').verify(value) == ENV['LOCAL_DOMAIN']
|
||||||
|
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def self_destruct?
|
||||||
|
SelfDestructHelper.self_destruct?
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
// eslint-disable-next-line import/no-anonymous-default-export
|
||||||
|
export default 'SvgrURL';
|
||||||
|
export const ReactComponent = 'div';
|
|
@ -1,7 +1,7 @@
|
||||||
// This file will be loaded on admin pages, regardless of theme.
|
// This file will be loaded on admin pages, regardless of theme.
|
||||||
|
|
||||||
import 'packs/public-path';
|
import 'packs/public-path';
|
||||||
import { delegate } from '@rails/ujs';
|
import Rails from '@rails/ujs';
|
||||||
|
|
||||||
import ready from '../mastodon/ready';
|
import ready from '../mastodon/ready';
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ const setAnnouncementEndsAttributes = (target) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
delegate(document, 'input[type="datetime-local"]#announcement_starts_at', 'change', ({ target }) => {
|
Rails.delegate(document, 'input[type="datetime-local"]#announcement_starts_at', 'change', ({ target }) => {
|
||||||
setAnnouncementEndsAttributes(target);
|
setAnnouncementEndsAttributes(target);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ const hideSelectAll = () => {
|
||||||
hiddenField.value = '0';
|
hiddenField.value = '0';
|
||||||
};
|
};
|
||||||
|
|
||||||
delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
|
Rails.delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
|
||||||
const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
|
const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
|
||||||
|
|
||||||
[].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => {
|
[].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => {
|
||||||
|
@ -58,7 +58,7 @@ delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '.batch-table__select-all button', 'click', () => {
|
Rails.delegate(document, '.batch-table__select-all button', 'click', () => {
|
||||||
const hiddenField = document.querySelector('#select_all_matching');
|
const hiddenField = document.querySelector('#select_all_matching');
|
||||||
const active = hiddenField.value === '1';
|
const active = hiddenField.value === '1';
|
||||||
const selectedMsg = document.querySelector('.batch-table__select-all .selected');
|
const selectedMsg = document.querySelector('.batch-table__select-all .selected');
|
||||||
|
@ -75,7 +75,7 @@ delegate(document, '.batch-table__select-all button', 'click', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, batchCheckboxClassName, 'change', () => {
|
Rails.delegate(document, batchCheckboxClassName, 'change', () => {
|
||||||
const checkAllElement = document.querySelector('#batch_checkbox_all');
|
const checkAllElement = document.querySelector('#batch_checkbox_all');
|
||||||
const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
|
const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
|
||||||
|
|
||||||
|
@ -93,19 +93,19 @@ delegate(document, batchCheckboxClassName, 'change', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '.media-spoiler-show-button', 'click', () => {
|
Rails.delegate(document, '.media-spoiler-show-button', 'click', () => {
|
||||||
[].forEach.call(document.querySelectorAll('button.media-spoiler'), (element) => {
|
[].forEach.call(document.querySelectorAll('button.media-spoiler'), (element) => {
|
||||||
element.click();
|
element.click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '.media-spoiler-hide-button', 'click', () => {
|
Rails.delegate(document, '.media-spoiler-hide-button', 'click', () => {
|
||||||
[].forEach.call(document.querySelectorAll('.spoiler-button.spoiler-button--visible button'), (element) => {
|
[].forEach.call(document.querySelectorAll('.spoiler-button.spoiler-button--visible button'), (element) => {
|
||||||
element.click();
|
element.click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '.filter-subset--with-select select', 'change', ({ target }) => {
|
Rails.delegate(document, '.filter-subset--with-select select', 'change', ({ target }) => {
|
||||||
target.form.submit();
|
target.form.submit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ const onDomainBlockSeverityChange = (target) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
delegate(document, '#domain_block_severity', 'change', ({ target }) => onDomainBlockSeverityChange(target));
|
Rails.delegate(document, '#domain_block_severity', 'change', ({ target }) => onDomainBlockSeverityChange(target));
|
||||||
|
|
||||||
const onEnableBootstrapTimelineAccountsChange = (target) => {
|
const onEnableBootstrapTimelineAccountsChange = (target) => {
|
||||||
const bootstrapTimelineAccountsField = document.querySelector('#form_admin_settings_bootstrap_timeline_accounts');
|
const bootstrapTimelineAccountsField = document.querySelector('#form_admin_settings_bootstrap_timeline_accounts');
|
||||||
|
@ -139,7 +139,7 @@ const onEnableBootstrapTimelineAccountsChange = (target) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target));
|
Rails.delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target));
|
||||||
|
|
||||||
const onChangeRegistrationMode = (target) => {
|
const onChangeRegistrationMode = (target) => {
|
||||||
const enabled = target.value === 'approved';
|
const enabled = target.value === 'approved';
|
||||||
|
@ -176,7 +176,7 @@ const convertLocalDatetimeToUTC = (value) => {
|
||||||
return fullISO8601.slice(0, fullISO8601.indexOf('T') + 6);
|
return fullISO8601.slice(0, fullISO8601.indexOf('T') + 6);
|
||||||
};
|
};
|
||||||
|
|
||||||
delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target));
|
Rails.delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target));
|
||||||
|
|
||||||
ready(() => {
|
ready(() => {
|
||||||
const domainBlockSeverityInput = document.getElementById('domain_block_severity');
|
const domainBlockSeverityInput = document.getElementById('domain_block_severity');
|
||||||
|
@ -213,7 +213,7 @@ ready(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, 'form', 'submit', ({ target }) => {
|
Rails.delegate(document, 'form', 'submit', ({ target }) => {
|
||||||
[].forEach.call(target.querySelectorAll('input[type="datetime-local"]'), element => {
|
[].forEach.call(target.querySelectorAll('input[type="datetime-local"]'), element => {
|
||||||
if (element.value && element.validity.valid) {
|
if (element.value && element.validity.valid) {
|
||||||
element.value = convertLocalDatetimeToUTC(element.value);
|
element.value = convertLocalDatetimeToUTC(element.value);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// This file will be loaded on settings pages, regardless of theme.
|
// This file will be loaded on settings pages, regardless of theme.
|
||||||
|
|
||||||
import 'packs/public-path';
|
import 'packs/public-path';
|
||||||
import { delegate } from '@rails/ujs';
|
import Rails from '@rails/ujs';
|
||||||
|
|
||||||
delegate(document, '#edit_profile input[type=file]', 'change', ({ target }) => {
|
Rails.delegate(document, '#edit_profile input[type=file]', 'change', ({ target }) => {
|
||||||
const avatar = document.getElementById(target.id + '-preview');
|
const avatar = document.getElementById(target.id + '-preview');
|
||||||
const [file] = target.files || [];
|
const [file] = target.files || [];
|
||||||
const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
|
const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
|
||||||
|
@ -11,13 +11,13 @@ delegate(document, '#edit_profile input[type=file]', 'change', ({ target }) => {
|
||||||
avatar.src = url;
|
avatar.src = url;
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '.input-copy input', 'click', ({ target }) => {
|
Rails.delegate(document, '.input-copy input', 'click', ({ target }) => {
|
||||||
target.focus();
|
target.focus();
|
||||||
target.select();
|
target.select();
|
||||||
target.setSelectionRange(0, target.value.length);
|
target.setSelectionRange(0, target.value.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '.input-copy button', 'click', ({ target }) => {
|
Rails.delegate(document, '.input-copy button', 'click', ({ target }) => {
|
||||||
const input = target.parentNode.querySelector('.input-copy__wrapper input');
|
const input = target.parentNode.querySelector('.input-copy__wrapper input');
|
||||||
|
|
||||||
const oldReadOnly = input.readonly;
|
const oldReadOnly = input.readonly;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
|
|
||||||
import unicodeMapping from 'flavours/glitch/features/emoji/emoji_unicode_mapping_light';
|
import { unicodeMapping } from 'flavours/glitch/features/emoji/emoji_unicode_mapping_light';
|
||||||
import { assetHost } from 'flavours/glitch/utils/config';
|
import { assetHost } from 'flavours/glitch/utils/config';
|
||||||
|
|
||||||
export default class AutosuggestEmoji extends PureComponent {
|
export default class AutosuggestEmoji extends PureComponent {
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { PureComponent } from 'react';
|
|
||||||
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
export default class Button extends PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
text: PropTypes.node,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
disabled: PropTypes.bool,
|
|
||||||
block: PropTypes.bool,
|
|
||||||
secondary: PropTypes.bool,
|
|
||||||
className: PropTypes.string,
|
|
||||||
title: PropTypes.string,
|
|
||||||
children: PropTypes.node,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleClick = (e) => {
|
|
||||||
if (!this.props.disabled) {
|
|
||||||
this.props.onClick(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setRef = (c) => {
|
|
||||||
this.node = c;
|
|
||||||
};
|
|
||||||
|
|
||||||
focus() {
|
|
||||||
this.node.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
let attrs = {
|
|
||||||
className: classNames('button', this.props.className, {
|
|
||||||
'button-secondary': this.props.secondary,
|
|
||||||
'button--block': this.props.block,
|
|
||||||
}),
|
|
||||||
disabled: this.props.disabled,
|
|
||||||
onClick: this.handleClick,
|
|
||||||
ref: this.setRef,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.props.title) attrs.title = this.props.title;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button {...attrs}>
|
|
||||||
{this.props.text || this.props.children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface BaseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
|
block?: boolean;
|
||||||
|
secondary?: boolean;
|
||||||
|
text?: JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PropsWithChildren extends BaseProps {
|
||||||
|
text?: never;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PropsWithText extends BaseProps {
|
||||||
|
text: JSX.Element;
|
||||||
|
children: never;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = PropsWithText | PropsWithChildren;
|
||||||
|
|
||||||
|
export const Button: React.FC<Props> = ({
|
||||||
|
text,
|
||||||
|
type = 'button',
|
||||||
|
onClick,
|
||||||
|
disabled,
|
||||||
|
block,
|
||||||
|
secondary,
|
||||||
|
className,
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const handleClick = useCallback<React.MouseEventHandler<HTMLButtonElement>>(
|
||||||
|
(e) => {
|
||||||
|
if (!disabled && onClick) {
|
||||||
|
onClick(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[disabled, onClick],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={classNames('button', className, {
|
||||||
|
'button-secondary': secondary,
|
||||||
|
'button--block': block,
|
||||||
|
})}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={handleClick}
|
||||||
|
title={title}
|
||||||
|
type={type}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{text ?? children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
|
@ -24,12 +24,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) {
|
||||||
|
|
|
@ -4,26 +4,25 @@ import { createPortal } from 'react-dom';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
export default class ColumnBackButton extends PureComponent {
|
export class ColumnBackButton extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
const { router } = this.context;
|
const { history } = this.props;
|
||||||
|
|
||||||
if (router.history.location?.state?.fromMastodon) {
|
if (history.location?.state?.fromMastodon) {
|
||||||
router.history.goBack();
|
history.goBack();
|
||||||
} else {
|
} else {
|
||||||
router.history.push('/');
|
history.push('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,3 +56,5 @@ export default class ColumnBackButton extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(ColumnBackButton);
|
||||||
|
|
|
@ -1,25 +1,27 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
export default class ColumnBackButtonSlim extends PureComponent {
|
class ColumnBackButtonSlim extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static propTypes = {
|
||||||
router: PropTypes.object,
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
const { router } = this.context;
|
const { location, history } = this.props;
|
||||||
|
|
||||||
// Check if there is a previous page in the app to go back to per https://stackoverflow.com/a/70532858/9703201
|
// Check if there is a previous page in the app to go back to per https://stackoverflow.com/a/70532858/9703201
|
||||||
// When upgrading to V6, check `location.key !== 'default'` instead per https://github.com/remix-run/history/blob/main/docs/api-reference.md#location
|
// When upgrading to V6, check `location.key !== 'default'` instead per https://github.com/remix-run/history/blob/main/docs/api-reference.md#location
|
||||||
if (router.route.location.key) {
|
if (location.key) {
|
||||||
router.history.goBack();
|
history.goBack();
|
||||||
} else {
|
} else {
|
||||||
router.history.push('/');
|
history.push('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,5 +35,6 @@ export default class ColumnBackButtonSlim extends PureComponent {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(ColumnBackButtonSlim);
|
||||||
|
|
|
@ -5,8 +5,10 @@ import { createPortal } from 'react-dom';
|
||||||
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
||||||
|
@ -18,7 +20,6 @@ const messages = defineMessages({
|
||||||
class ColumnHeader extends PureComponent {
|
class ColumnHeader extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ class ColumnHeader extends PureComponent {
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
appendContent: PropTypes.node,
|
appendContent: PropTypes.node,
|
||||||
collapseIssues: PropTypes.bool,
|
collapseIssues: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -63,12 +65,12 @@ class ColumnHeader extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleBackClick = () => {
|
handleBackClick = () => {
|
||||||
const { router } = this.context;
|
const { history } = this.props;
|
||||||
|
|
||||||
if (router.history.location?.state?.fromMastodon) {
|
if (history.location?.state?.fromMastodon) {
|
||||||
router.history.goBack();
|
history.goBack();
|
||||||
} else {
|
} else {
|
||||||
router.history.push('/');
|
history.push('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,15 +80,14 @@ class ColumnHeader extends PureComponent {
|
||||||
|
|
||||||
handlePin = () => {
|
handlePin = () => {
|
||||||
if (!this.props.pinned) {
|
if (!this.props.pinned) {
|
||||||
this.context.router.history.replace('/');
|
this.props.history.replace('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.onPin();
|
this.props.onPin();
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { router } = this.context;
|
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues, history } = this.props;
|
||||||
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props;
|
|
||||||
const { collapsed, animating } = this.state;
|
const { collapsed, animating } = this.state;
|
||||||
|
|
||||||
const wrapperClassName = classNames('column-header__wrapper', {
|
const wrapperClassName = classNames('column-header__wrapper', {
|
||||||
|
@ -129,7 +130,7 @@ class ColumnHeader extends PureComponent {
|
||||||
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>;
|
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pinned && ((multiColumn && router.history.location?.state?.fromMastodon) || showBackButton)) {
|
if (!pinned && ((multiColumn && history.location?.state?.fromMastodon) || showBackButton)) {
|
||||||
backButton = (
|
backButton = (
|
||||||
<button onClick={this.handleBackClick} className='column-header__back-button'>
|
<button onClick={this.handleBackClick} className='column-header__back-button'>
|
||||||
<Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
|
<Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
|
||||||
|
@ -215,4 +216,4 @@ class ColumnHeader extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(ColumnHeader);
|
export default injectIntl(withRouter(ColumnHeader));
|
||||||
|
|
|
@ -2,13 +2,16 @@ import PropTypes from 'prop-types';
|
||||||
import { PureComponent, cloneElement, Children } from 'react';
|
import { PureComponent, cloneElement, Children } from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
||||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import Overlay from 'react-overlays/Overlay';
|
import Overlay from 'react-overlays/Overlay';
|
||||||
|
|
||||||
import { CircularProgress } from "./circular_progress";
|
import { CircularProgress } from 'flavours/glitch/components/circular_progress';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import { IconButton } from './icon_button';
|
import { IconButton } from './icon_button';
|
||||||
|
|
||||||
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
|
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
|
||||||
|
@ -16,10 +19,6 @@ let id = 0;
|
||||||
|
|
||||||
class DropdownMenu extends PureComponent {
|
class DropdownMenu extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
items: PropTypes.oneOfType([PropTypes.array, ImmutablePropTypes.list]).isRequired,
|
items: PropTypes.oneOfType([PropTypes.array, ImmutablePropTypes.list]).isRequired,
|
||||||
loading: PropTypes.bool,
|
loading: PropTypes.bool,
|
||||||
|
@ -159,11 +158,7 @@ class DropdownMenu extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Dropdown extends PureComponent {
|
class Dropdown extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
|
@ -183,6 +178,7 @@ export default class Dropdown extends PureComponent {
|
||||||
renderItem: PropTypes.func,
|
renderItem: PropTypes.func,
|
||||||
renderHeader: PropTypes.func,
|
renderHeader: PropTypes.func,
|
||||||
onItemClick: PropTypes.func,
|
onItemClick: PropTypes.func,
|
||||||
|
...WithRouterPropTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -250,7 +246,7 @@ export default class Dropdown extends PureComponent {
|
||||||
item.action();
|
item.action();
|
||||||
} else if (item && item.to) {
|
} else if (item && item.to) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.context.router.history.push(item.to);
|
this.props.history.push(item.to);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -338,3 +334,5 @@ export default class Dropdown extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(Dropdown);
|
||||||
|
|
|
@ -2,14 +2,13 @@ import PropTypes from 'prop-types';
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
|
|
||||||
import 'wicg-inert';
|
import 'wicg-inert';
|
||||||
|
|
||||||
import { multiply } from 'color-blend';
|
import { multiply } from 'color-blend';
|
||||||
import { createBrowserHistory } from 'history';
|
import { createBrowserHistory } from 'history';
|
||||||
|
|
||||||
export default class ModalRoot extends PureComponent {
|
import { WithOptionalRouterPropTypes, withOptionalRouter } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
static contextTypes = {
|
class ModalRoot extends PureComponent {
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
|
@ -21,6 +20,7 @@ export default class ModalRoot extends PureComponent {
|
||||||
}),
|
}),
|
||||||
noEsc: PropTypes.bool,
|
noEsc: PropTypes.bool,
|
||||||
ignoreFocus: PropTypes.bool,
|
ignoreFocus: PropTypes.bool,
|
||||||
|
...WithOptionalRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
activeElement = this.props.children ? document.activeElement : null;
|
activeElement = this.props.children ? document.activeElement : null;
|
||||||
|
@ -56,7 +56,7 @@ export default class ModalRoot extends PureComponent {
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
window.addEventListener('keyup', this.handleKeyUp, false);
|
window.addEventListener('keyup', this.handleKeyUp, false);
|
||||||
window.addEventListener('keydown', this.handleKeyDown, false);
|
window.addEventListener('keydown', this.handleKeyDown, false);
|
||||||
this.history = this.context.router ? this.context.router.history : createBrowserHistory();
|
this.history = this.props.history || createBrowserHistory();
|
||||||
|
|
||||||
if (this.props.children) {
|
if (this.props.children) {
|
||||||
this._handleModalOpen();
|
this._handleModalOpen();
|
||||||
|
@ -160,3 +160,5 @@ export default class ModalRoot extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withOptionalRouter(ModalRoot);
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import { PureComponent } from 'react';
|
|
||||||
|
|
||||||
import { Switch, Route, withRouter } from 'react-router-dom';
|
|
||||||
|
|
||||||
import AccountNavigation from 'flavours/glitch/features/account/navigation';
|
|
||||||
import Trends from 'flavours/glitch/features/getting_started/containers/trends_container';
|
|
||||||
import { showTrends } from 'flavours/glitch/initial_state';
|
|
||||||
|
|
||||||
const DefaultNavigation = () => (
|
|
||||||
showTrends ? (
|
|
||||||
<>
|
|
||||||
<div className='flex-spacer' />
|
|
||||||
<Trends />
|
|
||||||
</>
|
|
||||||
) : null
|
|
||||||
);
|
|
||||||
|
|
||||||
class NavigationPortal extends PureComponent {
|
|
||||||
|
|
||||||
render () {
|
|
||||||
return (
|
|
||||||
<Switch>
|
|
||||||
<Route path='/@:acct' exact component={AccountNavigation} />
|
|
||||||
<Route path='/@:acct/tagged/:tagged?' exact component={AccountNavigation} />
|
|
||||||
<Route path='/@:acct/with_replies' exact component={AccountNavigation} />
|
|
||||||
<Route path='/@:acct/followers' exact component={AccountNavigation} />
|
|
||||||
<Route path='/@:acct/following' exact component={AccountNavigation} />
|
|
||||||
<Route path='/@:acct/media' exact component={AccountNavigation} />
|
|
||||||
<Route component={DefaultNavigation} />
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withRouter(NavigationPortal);
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Switch, Route } from 'react-router-dom';
|
||||||
|
|
||||||
|
import AccountNavigation from 'flavours/glitch/features/account/navigation';
|
||||||
|
import Trends from 'flavours/glitch/features/getting_started/containers/trends_container';
|
||||||
|
import { showTrends } from 'flavours/glitch/initial_state';
|
||||||
|
|
||||||
|
const DefaultNavigation: React.FC = () =>
|
||||||
|
showTrends ? (
|
||||||
|
<>
|
||||||
|
<div className='flex-spacer' />
|
||||||
|
<Trends />
|
||||||
|
</>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
export const NavigationPortal: React.FC = () => (
|
||||||
|
<Switch>
|
||||||
|
<Route path='/@:acct' exact component={AccountNavigation} />
|
||||||
|
<Route path='/@:acct/tagged/:tagged?' exact component={AccountNavigation} />
|
||||||
|
<Route path='/@:acct/with_replies' exact component={AccountNavigation} />
|
||||||
|
<Route path='/@:acct/followers' exact component={AccountNavigation} />
|
||||||
|
<Route path='/@:acct/following' exact component={AccountNavigation} />
|
||||||
|
<Route path='/@:acct/media' exact component={AccountNavigation} />
|
||||||
|
<Route component={DefaultNavigation} />
|
||||||
|
</Switch>
|
||||||
|
);
|
|
@ -1,11 +1,9 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
|
|
||||||
export default class Permalink extends PureComponent {
|
import { withOptionalRouter, WithOptionalRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
static contextTypes = {
|
class Permalink extends PureComponent {
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
|
@ -13,6 +11,7 @@ export default class Permalink extends PureComponent {
|
||||||
to: PropTypes.string.isRequired,
|
to: PropTypes.string.isRequired,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
onInterceptClick: PropTypes.func,
|
onInterceptClick: PropTypes.func,
|
||||||
|
...WithOptionalRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = (e) => {
|
handleClick = (e) => {
|
||||||
|
@ -22,9 +21,9 @@ export default class Permalink extends PureComponent {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.context.router) {
|
if (this.props.history) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.context.router.history.push(this.props.to);
|
this.props.history.push(this.props.to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -47,3 +46,5 @@ export default class Permalink extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withOptionalRouter(Permalink);
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { createBrowserHistory } from 'history';
|
|
||||||
import { Router as OriginalRouter } from 'react-router';
|
import { Router as OriginalRouter } from 'react-router';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
LocationDescriptor,
|
||||||
|
LocationDescriptorObject,
|
||||||
|
Path,
|
||||||
|
} from 'history';
|
||||||
|
import { createBrowserHistory } from 'history';
|
||||||
|
|
||||||
import { layoutFromWindow } from 'flavours/glitch/is_mobile';
|
import { layoutFromWindow } from 'flavours/glitch/is_mobile';
|
||||||
|
|
||||||
interface MastodonLocationState {
|
interface MastodonLocationState {
|
||||||
fromMastodon?: boolean;
|
fromMastodon?: boolean;
|
||||||
mastodonModalKey?: string;
|
mastodonModalKey?: string;
|
||||||
}
|
}
|
||||||
|
type HistoryPath = Path | LocationDescriptor<MastodonLocationState>;
|
||||||
|
|
||||||
const browserHistory = createBrowserHistory<
|
const browserHistory = createBrowserHistory<
|
||||||
MastodonLocationState | undefined
|
MastodonLocationState | undefined
|
||||||
|
@ -17,28 +24,55 @@ const browserHistory = createBrowserHistory<
|
||||||
const originalPush = browserHistory.push.bind(browserHistory);
|
const originalPush = browserHistory.push.bind(browserHistory);
|
||||||
const originalReplace = browserHistory.replace.bind(browserHistory);
|
const originalReplace = browserHistory.replace.bind(browserHistory);
|
||||||
|
|
||||||
browserHistory.push = (path: string, state?: MastodonLocationState) => {
|
function normalizePath(
|
||||||
state = state ?? {};
|
path: HistoryPath,
|
||||||
state.fromMastodon = true;
|
state?: MastodonLocationState,
|
||||||
|
): LocationDescriptorObject<MastodonLocationState> {
|
||||||
|
const location = typeof path === 'string' ? { pathname: path } : { ...path };
|
||||||
|
|
||||||
if (layoutFromWindow() === 'multi-column' && !path.startsWith('/deck')) {
|
if (location.state === undefined && state !== undefined) {
|
||||||
originalPush(`/deck${path}`, state);
|
location.state = state;
|
||||||
} else {
|
} else if (
|
||||||
originalPush(path, state);
|
location.state !== undefined &&
|
||||||
|
state !== undefined &&
|
||||||
|
process.env.NODE_ENV === 'development'
|
||||||
|
) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(
|
||||||
|
'You should avoid providing a 2nd state argument to push when the 1st argument is a location-like object that already has state; it is ignored',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
layoutFromWindow() === 'multi-column' &&
|
||||||
|
!location.pathname?.startsWith('/deck')
|
||||||
|
) {
|
||||||
|
location.pathname = `/deck${location.pathname}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
browserHistory.push = (path: HistoryPath, state?: MastodonLocationState) => {
|
||||||
|
const location = normalizePath(path, state);
|
||||||
|
|
||||||
|
location.state = location.state ?? {};
|
||||||
|
location.state.fromMastodon = true;
|
||||||
|
|
||||||
|
originalPush(location);
|
||||||
};
|
};
|
||||||
|
|
||||||
browserHistory.replace = (path: string, state?: MastodonLocationState) => {
|
browserHistory.replace = (path: HistoryPath, state?: MastodonLocationState) => {
|
||||||
|
const location = normalizePath(path, state);
|
||||||
|
|
||||||
|
if (!location.pathname) return;
|
||||||
|
|
||||||
if (browserHistory.location.state?.fromMastodon) {
|
if (browserHistory.location.state?.fromMastodon) {
|
||||||
state = state ?? {};
|
location.state = location.state ?? {};
|
||||||
state.fromMastodon = true;
|
location.state.fromMastodon = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layoutFromWindow() === 'multi-column' && !path.startsWith('/deck')) {
|
originalReplace(location);
|
||||||
originalReplace(`/deck${path}`, state);
|
|
||||||
} else {
|
|
||||||
originalReplace(path, state);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Router: React.FC<PropsWithChildren> = ({ children }) => {
|
export const Router: React.FC<PropsWithChildren> = ({ children }) => {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
||||||
import { Children, cloneElement, PureComponent } from 'react';
|
import { Children, cloneElement, PureComponent } from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -34,11 +35,32 @@ const mapStateToProps = (state, { scrollKey }) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScrollableList extends PureComponent {
|
// This component only exists to be able to call useLocation()
|
||||||
|
const IOArticleContainerWrapper = ({id, index, listLength, intersectionObserverWrapper, trackScroll, scrollKey, children}) => {
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
static contextTypes = {
|
return (<IntersectionObserverArticleContainer
|
||||||
router: PropTypes.object,
|
id={id}
|
||||||
};
|
index={index}
|
||||||
|
listLength={listLength}
|
||||||
|
intersectionObserverWrapper={intersectionObserverWrapper}
|
||||||
|
saveHeightKey={trackScroll ? `${location.key}:${scrollKey}` : null}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</IntersectionObserverArticleContainer>);
|
||||||
|
};
|
||||||
|
|
||||||
|
IOArticleContainerWrapper.propTypes = {
|
||||||
|
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
index: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
listLength: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
scrollKey: PropTypes.string.isRequired,
|
||||||
|
intersectionObserverWrapper: PropTypes.object.isRequired,
|
||||||
|
trackScroll: PropTypes.bool.isRequired,
|
||||||
|
children: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScrollableList extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
scrollKey: PropTypes.string.isRequired,
|
scrollKey: PropTypes.string.isRequired,
|
||||||
|
@ -331,13 +353,14 @@ class ScrollableList extends PureComponent {
|
||||||
{loadPending}
|
{loadPending}
|
||||||
|
|
||||||
{Children.map(this.props.children, (child, index) => (
|
{Children.map(this.props.children, (child, index) => (
|
||||||
<IntersectionObserverArticleContainer
|
<IOArticleContainerWrapper
|
||||||
key={child.key}
|
key={child.key}
|
||||||
id={child.key}
|
id={child.key}
|
||||||
index={index}
|
index={index}
|
||||||
listLength={childrenCount}
|
listLength={childrenCount}
|
||||||
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
||||||
saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null}
|
trackScroll={trackScroll}
|
||||||
|
scrollKey={scrollKey}
|
||||||
>
|
>
|
||||||
{cloneElement(child, {
|
{cloneElement(child, {
|
||||||
getScrollPosition: this.getScrollPosition,
|
getScrollPosition: this.getScrollPosition,
|
||||||
|
@ -345,7 +368,7 @@ class ScrollableList extends PureComponent {
|
||||||
cachedMediaWidth: this.state.cachedMediaWidth,
|
cachedMediaWidth: this.state.cachedMediaWidth,
|
||||||
cacheMediaWidth: this.cacheMediaWidth,
|
cacheMediaWidth: this.cacheMediaWidth,
|
||||||
})}
|
})}
|
||||||
</IntersectionObserverArticleContainer>
|
</IOArticleContainerWrapper>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{loadMore}
|
{loadMore}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import PollContainer from 'flavours/glitch/containers/poll_container';
|
||||||
import NotificationOverlayContainer from 'flavours/glitch/features/notifications/containers/overlay_container';
|
import NotificationOverlayContainer from 'flavours/glitch/features/notifications/containers/overlay_container';
|
||||||
import { displayMedia } from 'flavours/glitch/initial_state';
|
import { displayMedia } from 'flavours/glitch/initial_state';
|
||||||
import { autoUnfoldCW } from 'flavours/glitch/utils/content_warning';
|
import { autoUnfoldCW } from 'flavours/glitch/utils/content_warning';
|
||||||
|
import { withOptionalRouter, WithOptionalRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import Card from '../features/status/components/card';
|
import Card from '../features/status/components/card';
|
||||||
import Bundle from '../features/ui/components/bundle';
|
import Bundle from '../features/ui/components/bundle';
|
||||||
|
@ -67,10 +68,6 @@ export const defaultMediaVisibility = (status, settings) => {
|
||||||
|
|
||||||
class Status extends ImmutablePureComponent {
|
class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
containerId: PropTypes.string,
|
containerId: PropTypes.string,
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
|
@ -117,6 +114,7 @@ class Status extends ImmutablePureComponent {
|
||||||
inUse: PropTypes.bool,
|
inUse: PropTypes.bool,
|
||||||
available: PropTypes.bool,
|
available: PropTypes.bool,
|
||||||
}),
|
}),
|
||||||
|
...WithOptionalRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -356,10 +354,9 @@ class Status extends ImmutablePureComponent {
|
||||||
// Otherwise, we open the url handed to us in `destination`, if
|
// Otherwise, we open the url handed to us in `destination`, if
|
||||||
// applicable.
|
// applicable.
|
||||||
parseClick = (e, destination) => {
|
parseClick = (e, destination) => {
|
||||||
const { router } = this.context;
|
const { status, history } = this.props;
|
||||||
const { status } = this.props;
|
|
||||||
const { isCollapsed } = this.state;
|
const { isCollapsed } = this.state;
|
||||||
if (!router) return;
|
if (!history) return;
|
||||||
|
|
||||||
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) {
|
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) {
|
||||||
if (isCollapsed) this.setCollapsed(false);
|
if (isCollapsed) this.setCollapsed(false);
|
||||||
|
@ -377,7 +374,7 @@ class Status extends ImmutablePureComponent {
|
||||||
status.getIn(['reblog', 'id'], status.get('id'))
|
status.getIn(['reblog', 'id'], status.get('id'))
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
router.history.push(destination);
|
history.push(destination);
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
@ -431,7 +428,7 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleHotkeyReply = e => {
|
handleHotkeyReply = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.onReply(this.props.status, this.context.router.history);
|
this.props.onReply(this.props.status, this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyFavourite = (e) => {
|
handleHotkeyFavourite = (e) => {
|
||||||
|
@ -448,16 +445,16 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleHotkeyMention = e => {
|
handleHotkeyMention = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.onMention(this.props.status.get('account'), this.context.router.history);
|
this.props.onMention(this.props.status.get('account'), this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyOpen = () => {
|
handleHotkeyOpen = () => {
|
||||||
const status = this.props.status;
|
const status = this.props.status;
|
||||||
this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
|
this.props.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyOpenProfile = () => {
|
handleHotkeyOpenProfile = () => {
|
||||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyMoveUp = e => {
|
handleHotkeyMoveUp = e => {
|
||||||
|
@ -514,7 +511,6 @@ class Status extends ImmutablePureComponent {
|
||||||
parseClick,
|
parseClick,
|
||||||
setCollapsed,
|
setCollapsed,
|
||||||
} = this;
|
} = this;
|
||||||
const { router } = this.context;
|
|
||||||
const {
|
const {
|
||||||
intl,
|
intl,
|
||||||
status,
|
status,
|
||||||
|
@ -533,6 +529,7 @@ class Status extends ImmutablePureComponent {
|
||||||
previousId,
|
previousId,
|
||||||
nextInReplyToId,
|
nextInReplyToId,
|
||||||
rootId,
|
rootId,
|
||||||
|
history,
|
||||||
...other
|
...other
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { isCollapsed } = this.state;
|
const { isCollapsed } = this.state;
|
||||||
|
@ -828,7 +825,7 @@ class Status extends ImmutablePureComponent {
|
||||||
onExpandedToggle={this.handleExpandedToggle}
|
onExpandedToggle={this.handleExpandedToggle}
|
||||||
onTranslate={this.handleTranslate}
|
onTranslate={this.handleTranslate}
|
||||||
parseClick={parseClick}
|
parseClick={parseClick}
|
||||||
disabled={!router}
|
disabled={!history}
|
||||||
tagLinks={settings.get('tag_misleading_links')}
|
tagLinks={settings.get('tag_misleading_links')}
|
||||||
rewriteMentions={settings.get('rewrite_mentions')}
|
rewriteMentions={settings.get('rewrite_mentions')}
|
||||||
/>
|
/>
|
||||||
|
@ -854,4 +851,4 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Status);
|
export default withOptionalRouter(injectIntl(Status));
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
@ -11,6 +12,7 @@ import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_cont
|
||||||
import { me } from 'flavours/glitch/initial_state';
|
import { me } from 'flavours/glitch/initial_state';
|
||||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions';
|
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions';
|
||||||
import { accountAdminLink, statusAdminLink } from 'flavours/glitch/utils/backend_links';
|
import { accountAdminLink, statusAdminLink } from 'flavours/glitch/utils/backend_links';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import { IconButton } from './icon_button';
|
import { IconButton } from './icon_button';
|
||||||
import { RelativeTimestamp } from './relative_timestamp';
|
import { RelativeTimestamp } from './relative_timestamp';
|
||||||
|
@ -53,7 +55,6 @@ const messages = defineMessages({
|
||||||
class StatusActionBar extends ImmutablePureComponent {
|
class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,6 +81,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
showReplyCount: PropTypes.bool,
|
showReplyCount: PropTypes.bool,
|
||||||
scrollKey: PropTypes.string,
|
scrollKey: PropTypes.string,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Avoid checking props that are functions (and whose equality will always
|
// Avoid checking props that are functions (and whose equality will always
|
||||||
|
@ -95,7 +97,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
const { signedIn } = this.context.identity;
|
const { signedIn } = this.context.identity;
|
||||||
|
|
||||||
if (signedIn) {
|
if (signedIn) {
|
||||||
this.props.onReply(this.props.status, this.context.router.history);
|
this.props.onReply(this.props.status, this.props.history);
|
||||||
} else {
|
} else {
|
||||||
this.props.onInteractionModal('reply', this.props.status);
|
this.props.onInteractionModal('reply', this.props.status);
|
||||||
}
|
}
|
||||||
|
@ -132,15 +134,15 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDeleteClick = () => {
|
handleDeleteClick = () => {
|
||||||
this.props.onDelete(this.props.status, this.context.router.history);
|
this.props.onDelete(this.props.status, this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleRedraftClick = () => {
|
handleRedraftClick = () => {
|
||||||
this.props.onDelete(this.props.status, this.context.router.history, true);
|
this.props.onDelete(this.props.status, this.props.history, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEditClick = () => {
|
handleEditClick = () => {
|
||||||
this.props.onEdit(this.props.status, this.context.router.history);
|
this.props.onEdit(this.props.status, this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePinClick = () => {
|
handlePinClick = () => {
|
||||||
|
@ -148,11 +150,11 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMentionClick = () => {
|
handleMentionClick = () => {
|
||||||
this.props.onMention(this.props.status.get('account'), this.context.router.history);
|
this.props.onMention(this.props.status.get('account'), this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDirectClick = () => {
|
handleDirectClick = () => {
|
||||||
this.props.onDirect(this.props.status.get('account'), this.context.router.history);
|
this.props.onDirect(this.props.status.get('account'), this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMuteClick = () => {
|
handleMuteClick = () => {
|
||||||
|
@ -164,12 +166,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpen = () => {
|
handleOpen = () => {
|
||||||
let state = { ...this.context.router.history.location.state };
|
this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
|
||||||
if (state.mastodonModalKey) {
|
|
||||||
this.context.router.history.replace(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
|
|
||||||
} else {
|
|
||||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEmbed = () => {
|
handleEmbed = () => {
|
||||||
|
@ -340,4 +337,4 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(StatusActionBar);
|
export default withRouter(injectIntl(StatusActionBar));
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { PureComponent } from 'react';
|
||||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -131,6 +132,10 @@ class StatusContent extends PureComponent {
|
||||||
rewriteMentions: PropTypes.string,
|
rewriteMentions: PropTypes.string,
|
||||||
languages: ImmutablePropTypes.map,
|
languages: ImmutablePropTypes.map,
|
||||||
intl: PropTypes.object,
|
intl: PropTypes.object,
|
||||||
|
// from react-router
|
||||||
|
match: PropTypes.object.isRequired,
|
||||||
|
location: PropTypes.object.isRequired,
|
||||||
|
history: PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -472,4 +477,4 @@ class StatusContent extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(injectIntl(StatusContent));
|
export default withRouter(connect(mapStateToProps)(injectIntl(StatusContent)));
|
||||||
|
|
|
@ -14,10 +14,6 @@ const messages = defineMessages({
|
||||||
|
|
||||||
class FeaturedTags extends ImmutablePureComponent {
|
class FeaturedTags extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
featuredTags: ImmutablePropTypes.list,
|
featuredTags: ImmutablePropTypes.list,
|
||||||
|
|
|
@ -4,18 +4,20 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||||
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
|
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
|
||||||
import { autoPlayGif, me, domain } from 'flavours/glitch/initial_state';
|
import { autoPlayGif, me, domain } from 'flavours/glitch/initial_state';
|
||||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions';
|
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions';
|
||||||
import { preferencesLink, profileLink, accountAdminLink } from 'flavours/glitch/utils/backend_links';
|
import { preferencesLink, profileLink, accountAdminLink } from 'flavours/glitch/utils/backend_links';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import AccountNoteContainer from '../containers/account_note_container';
|
import AccountNoteContainer from '../containers/account_note_container';
|
||||||
import FollowRequestNoteContainer from '../containers/follow_request_note_container';
|
import FollowRequestNoteContainer from '../containers/follow_request_note_container';
|
||||||
|
@ -81,10 +83,6 @@ const dateFormatOptions = {
|
||||||
|
|
||||||
class Header extends ImmutablePureComponent {
|
class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
identity: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
identity_props: ImmutablePropTypes.list,
|
identity_props: ImmutablePropTypes.list,
|
||||||
|
@ -107,6 +105,11 @@ class Header extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
domain: PropTypes.string.isRequired,
|
domain: PropTypes.string.isRequired,
|
||||||
hidden: PropTypes.bool,
|
hidden: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
|
};
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
openEditProfile = () => {
|
openEditProfile = () => {
|
||||||
|
@ -406,4 +409,4 @@ class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Header);
|
export default withRouter(injectIntl(Header));
|
||||||
|
|
|
@ -2,18 +2,19 @@ import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink, withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import ActionBar from 'flavours/glitch/features/account/components/action_bar';
|
import ActionBar from 'flavours/glitch/features/account/components/action_bar';
|
||||||
import InnerHeader from 'flavours/glitch/features/account/components/header';
|
import InnerHeader from 'flavours/glitch/features/account/components/header';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import MemorialNote from './memorial_note';
|
import MemorialNote from './memorial_note';
|
||||||
import MovedNote from './moved_note';
|
import MovedNote from './moved_note';
|
||||||
|
|
||||||
export default class Header extends ImmutablePureComponent {
|
class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
|
@ -34,10 +35,7 @@ export default class Header extends ImmutablePureComponent {
|
||||||
hideTabs: PropTypes.bool,
|
hideTabs: PropTypes.bool,
|
||||||
domain: PropTypes.string.isRequired,
|
domain: PropTypes.string.isRequired,
|
||||||
hidden: PropTypes.bool,
|
hidden: PropTypes.bool,
|
||||||
};
|
...WithRouterPropTypes,
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleFollow = () => {
|
handleFollow = () => {
|
||||||
|
@ -49,11 +47,11 @@ export default class Header extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMention = () => {
|
handleMention = () => {
|
||||||
this.props.onMention(this.props.account, this.context.router.history);
|
this.props.onMention(this.props.account, this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDirect = () => {
|
handleDirect = () => {
|
||||||
this.props.onDirect(this.props.account, this.context.router.history);
|
this.props.onDirect(this.props.account, this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleReport = () => {
|
handleReport = () => {
|
||||||
|
@ -162,3 +160,5 @@ export default class Header extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(Header);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { revealAccount } from 'flavours/glitch/actions/accounts';
|
import { revealAccount } from 'flavours/glitch/actions/accounts';
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { domain } from 'flavours/glitch/initial_state';
|
import { domain } from 'flavours/glitch/initial_state';
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { accountId }) => ({
|
const mapDispatchToProps = (dispatch, { accountId }) => ({
|
||||||
|
|
|
@ -1,30 +1,28 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import AvatarOverlay from '../../../components/avatar_overlay';
|
import AvatarOverlay from '../../../components/avatar_overlay';
|
||||||
import { DisplayName } from '../../../components/display_name';
|
import { DisplayName } from '../../../components/display_name';
|
||||||
|
|
||||||
export default class MovedNote extends ImmutablePureComponent {
|
class MovedNote extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
from: ImmutablePropTypes.map.isRequired,
|
from: ImmutablePropTypes.map.isRequired,
|
||||||
to: ImmutablePropTypes.map.isRequired,
|
to: ImmutablePropTypes.map.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleAccountClick = e => {
|
handleAccountClick = e => {
|
||||||
if (e.button === 0) {
|
if (e.button === 0) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.context.router.history.push(`/@${this.props.to.get('acct')}`);
|
this.props.history.push(`/@${this.props.to.get('acct')}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -50,3 +48,5 @@ export default class MovedNote extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(MovedNote);
|
||||||
|
|
|
@ -44,7 +44,6 @@ class CommunityTimeline extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { length } from 'stringz';
|
||||||
|
|
||||||
import { maxChars } from 'flavours/glitch/initial_state';
|
import { maxChars } from 'flavours/glitch/initial_state';
|
||||||
import { isMobile } from 'flavours/glitch/is_mobile';
|
import { isMobile } from 'flavours/glitch/is_mobile';
|
||||||
|
import { WithOptionalRouterPropTypes, withOptionalRouter } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import AutosuggestInput from '../../../components/autosuggest_input';
|
import AutosuggestInput from '../../../components/autosuggest_input';
|
||||||
import AutosuggestTextarea from '../../../components/autosuggest_textarea';
|
import AutosuggestTextarea from '../../../components/autosuggest_textarea';
|
||||||
|
@ -38,11 +39,6 @@ const messages = defineMessages({
|
||||||
});
|
});
|
||||||
|
|
||||||
class ComposeForm extends ImmutablePureComponent {
|
class ComposeForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
text: PropTypes.string,
|
text: PropTypes.string,
|
||||||
|
@ -70,7 +66,6 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
isInReply: PropTypes.bool,
|
isInReply: PropTypes.bool,
|
||||||
singleColumn: PropTypes.bool,
|
singleColumn: PropTypes.bool,
|
||||||
lang: PropTypes.string,
|
lang: PropTypes.string,
|
||||||
|
|
||||||
advancedOptions: ImmutablePropTypes.map,
|
advancedOptions: ImmutablePropTypes.map,
|
||||||
layout: PropTypes.string,
|
layout: PropTypes.string,
|
||||||
media: ImmutablePropTypes.list,
|
media: ImmutablePropTypes.list,
|
||||||
|
@ -82,6 +77,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
onChangeSpoilerness: PropTypes.func,
|
onChangeSpoilerness: PropTypes.func,
|
||||||
onChangeVisibility: PropTypes.func,
|
onChangeVisibility: PropTypes.func,
|
||||||
onMediaDescriptionConfirm: PropTypes.func,
|
onMediaDescriptionConfirm: PropTypes.func,
|
||||||
|
...WithOptionalRouterPropTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -129,12 +125,12 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
// Submit unless there are media with missing descriptions
|
// Submit unless there are media with missing descriptions
|
||||||
if (mediaDescriptionConfirmation && onMediaDescriptionConfirm && media && media.some(item => !item.get('description'))) {
|
if (mediaDescriptionConfirmation && onMediaDescriptionConfirm && media && media.some(item => !item.get('description'))) {
|
||||||
const firstWithoutDescription = media.find(item => !item.get('description'));
|
const firstWithoutDescription = media.find(item => !item.get('description'));
|
||||||
onMediaDescriptionConfirm(this.context.router ? this.context.router.history : null, firstWithoutDescription.get('id'), overriddenVisibility);
|
onMediaDescriptionConfirm(this.props.history || null, firstWithoutDescription.get('id'), overriddenVisibility);
|
||||||
} else if (onSubmit) {
|
} else if (onSubmit) {
|
||||||
if (onChangeVisibility && overriddenVisibility) {
|
if (onChangeVisibility && overriddenVisibility) {
|
||||||
onChangeVisibility(overriddenVisibility);
|
onChangeVisibility(overriddenVisibility);
|
||||||
}
|
}
|
||||||
onSubmit(this.context.router ? this.context.router.history : null);
|
onSubmit(this.props.history || null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -390,4 +386,4 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(ComposeForm);
|
export default withOptionalRouter(injectIntl(ComposeForm));
|
||||||
|
|
|
@ -8,7 +8,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
|
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import { maxChars } from 'flavours/glitch/initial_state';
|
import { maxChars } from 'flavours/glitch/initial_state';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// Package imports.
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
@ -6,18 +5,13 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
// Components.
|
|
||||||
import AttachmentList from 'flavours/glitch/components/attachment_list';
|
import AttachmentList from 'flavours/glitch/components/attachment_list';
|
||||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||||
import AccountContainer from 'flavours/glitch/containers/account_container';
|
import AccountContainer from 'flavours/glitch/containers/account_container';
|
||||||
// Messages.
|
|
||||||
const messages = defineMessages({
|
|
||||||
cancel: {
|
|
||||||
defaultMessage: 'Cancel',
|
|
||||||
id: 'reply_indicator.cancel',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
|
||||||
|
});
|
||||||
|
|
||||||
class ReplyIndicator extends ImmutablePureComponent {
|
class ReplyIndicator extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,14 @@ import { PureComponent } from 'react';
|
||||||
import { defineMessages, injectIntl, FormattedMessage, FormattedList } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage, FormattedList } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
||||||
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
|
||||||
import { domain, searchEnabled } from 'flavours/glitch/initial_state';
|
import { domain, searchEnabled } from 'flavours/glitch/initial_state';
|
||||||
import { focusRoot } from 'flavours/glitch/utils/dom_helpers';
|
|
||||||
import { HASHTAG_REGEX } from 'flavours/glitch/utils/hashtags';
|
import { HASHTAG_REGEX } from 'flavours/glitch/utils/hashtags';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
|
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
|
||||||
|
@ -32,7 +32,6 @@ const labelForRecentSearch = search => {
|
||||||
class Search extends PureComponent {
|
class Search extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object.isRequired,
|
|
||||||
identity: PropTypes.object.isRequired,
|
identity: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,6 +49,7 @@ class Search extends PureComponent {
|
||||||
openInRoute: PropTypes.bool,
|
openInRoute: PropTypes.bool,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
singleColumn: PropTypes.bool,
|
singleColumn: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -122,8 +122,7 @@ class Search extends PureComponent {
|
||||||
switch(e.key) {
|
switch(e.key) {
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
this._unfocus();
|
||||||
focusRoot();
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'ArrowDown':
|
case 'ArrowDown':
|
||||||
|
@ -170,32 +169,29 @@ class Search extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHashtagClick = () => {
|
handleHashtagClick = () => {
|
||||||
const { router } = this.context;
|
const { value, onClickSearchResult, history } = this.props;
|
||||||
const { value, onClickSearchResult } = this.props;
|
|
||||||
|
|
||||||
const query = value.trim().replace(/^#/, '');
|
const query = value.trim().replace(/^#/, '');
|
||||||
|
|
||||||
router.history.push(`/tags/${query}`);
|
history.push(`/tags/${query}`);
|
||||||
onClickSearchResult(query, 'hashtag');
|
onClickSearchResult(query, 'hashtag');
|
||||||
this._unfocus();
|
this._unfocus();
|
||||||
};
|
};
|
||||||
|
|
||||||
handleAccountClick = () => {
|
handleAccountClick = () => {
|
||||||
const { router } = this.context;
|
const { value, onClickSearchResult, history } = this.props;
|
||||||
const { value, onClickSearchResult } = this.props;
|
|
||||||
|
|
||||||
const query = value.trim().replace(/^@/, '');
|
const query = value.trim().replace(/^@/, '');
|
||||||
|
|
||||||
router.history.push(`/@${query}`);
|
history.push(`/@${query}`);
|
||||||
onClickSearchResult(query, 'account');
|
onClickSearchResult(query, 'account');
|
||||||
this._unfocus();
|
this._unfocus();
|
||||||
};
|
};
|
||||||
|
|
||||||
handleURLClick = () => {
|
handleURLClick = () => {
|
||||||
const { router } = this.context;
|
const { onOpenURL, history } = this.props;
|
||||||
const { onOpenURL } = this.props;
|
|
||||||
|
|
||||||
onOpenURL(router.history);
|
onOpenURL(history);
|
||||||
this._unfocus();
|
this._unfocus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -208,13 +204,12 @@ class Search extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleRecentSearchClick = search => {
|
handleRecentSearchClick = search => {
|
||||||
const { onChange } = this.props;
|
const { onChange, history } = this.props;
|
||||||
const { router } = this.context;
|
|
||||||
|
|
||||||
if (search.get('type') === 'account') {
|
if (search.get('type') === 'account') {
|
||||||
router.history.push(`/@${search.get('q')}`);
|
history.push(`/@${search.get('q')}`);
|
||||||
} else if (search.get('type') === 'hashtag') {
|
} else if (search.get('type') === 'hashtag') {
|
||||||
router.history.push(`/tags/${search.get('q')}`);
|
history.push(`/tags/${search.get('q')}`);
|
||||||
} else {
|
} else {
|
||||||
onChange(search.get('q'));
|
onChange(search.get('q'));
|
||||||
this._submit(search.get('type'));
|
this._submit(search.get('type'));
|
||||||
|
@ -246,8 +241,7 @@ class Search extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
_submit (type) {
|
_submit (type) {
|
||||||
const { onSubmit, openInRoute, value, onClickSearchResult } = this.props;
|
const { onSubmit, openInRoute, value, onClickSearchResult, history } = this.props;
|
||||||
const { router } = this.context;
|
|
||||||
|
|
||||||
onSubmit(type);
|
onSubmit(type);
|
||||||
|
|
||||||
|
@ -256,7 +250,7 @@ class Search extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openInRoute) {
|
if (openInRoute) {
|
||||||
router.history.push('/search');
|
history.push('/search');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._unfocus();
|
this._unfocus();
|
||||||
|
@ -403,4 +397,4 @@ class Search extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Search);
|
export default withRouter(injectIntl(Search));
|
||||||
|
|
|
@ -13,10 +13,6 @@ import Motion from '../../ui/util/optional_motion';
|
||||||
|
|
||||||
export default class Upload extends ImmutablePureComponent {
|
export default class Upload extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
media: ImmutablePropTypes.map.isRequired,
|
media: ImmutablePropTypes.map.isRequired,
|
||||||
onUndo: PropTypes.func.isRequired,
|
onUndo: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
@ -17,6 +18,7 @@ import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp
|
||||||
import StatusContent from 'flavours/glitch/components/status_content';
|
import StatusContent from 'flavours/glitch/components/status_content';
|
||||||
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
|
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
|
||||||
import { autoPlayGif } from 'flavours/glitch/initial_state';
|
import { autoPlayGif } from 'flavours/glitch/initial_state';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
more: { id: 'status.more', defaultMessage: 'More' },
|
more: { id: 'status.more', defaultMessage: 'More' },
|
||||||
|
@ -30,10 +32,6 @@ const messages = defineMessages({
|
||||||
|
|
||||||
class Conversation extends ImmutablePureComponent {
|
class Conversation extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
conversationId: PropTypes.string.isRequired,
|
conversationId: PropTypes.string.isRequired,
|
||||||
accounts: ImmutablePropTypes.list.isRequired,
|
accounts: ImmutablePropTypes.list.isRequired,
|
||||||
|
@ -45,6 +43,7 @@ class Conversation extends ImmutablePureComponent {
|
||||||
markRead: PropTypes.func.isRequired,
|
markRead: PropTypes.func.isRequired,
|
||||||
delete: PropTypes.func.isRequired,
|
delete: PropTypes.func.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -52,9 +51,8 @@ class Conversation extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
parseClick = (e, destination) => {
|
parseClick = (e, destination) => {
|
||||||
const { router } = this.context;
|
const { history, lastStatus, unread, markRead } = this.props;
|
||||||
const { lastStatus, unread, markRead } = this.props;
|
if (!history) return;
|
||||||
if (!router) return;
|
|
||||||
|
|
||||||
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) {
|
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) {
|
||||||
if (destination === undefined) {
|
if (destination === undefined) {
|
||||||
|
@ -63,7 +61,7 @@ class Conversation extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
destination = `/statuses/${lastStatus.get('id')}`;
|
destination = `/statuses/${lastStatus.get('id')}`;
|
||||||
}
|
}
|
||||||
router.history.push(destination);
|
history.push(destination);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -95,7 +93,7 @@ class Conversation extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
if (!this.context.router) {
|
if (!this.props.history) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +103,7 @@ class Conversation extends ImmutablePureComponent {
|
||||||
markRead();
|
markRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.context.router.history.push(`/@${lastStatus.getIn(['account', 'acct'])}/${lastStatus.get('id')}`);
|
this.props.history.push(`/@${lastStatus.getIn(['account', 'acct'])}/${lastStatus.get('id')}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMarkAsRead = () => {
|
handleMarkAsRead = () => {
|
||||||
|
@ -113,7 +111,7 @@ class Conversation extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleReply = () => {
|
handleReply = () => {
|
||||||
this.props.reply(this.props.lastStatus, this.context.router.history);
|
this.props.reply(this.props.lastStatus, this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDelete = () => {
|
handleDelete = () => {
|
||||||
|
@ -232,4 +230,4 @@ class Conversation extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Conversation);
|
export default withRouter(injectIntl(Conversation));
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
} from 'flavours/glitch/actions/accounts';
|
} from 'flavours/glitch/actions/accounts';
|
||||||
import { openModal } from 'flavours/glitch/actions/modal';
|
import { openModal } from 'flavours/glitch/actions/modal';
|
||||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||||
import Permalink from 'flavours/glitch/components/permalink';
|
import Permalink from 'flavours/glitch/components/permalink';
|
||||||
|
|
|
@ -36,10 +36,6 @@ const mapStateToProps = state => ({
|
||||||
|
|
||||||
class Directory extends PureComponent {
|
class Directory extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
accountIds: ImmutablePropTypes.list.isRequired,
|
accountIds: ImmutablePropTypes.list.isRequired,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import Trie from 'substring-trie';
|
||||||
import { autoPlayGif, useSystemEmojiFont } from 'flavours/glitch/initial_state';
|
import { autoPlayGif, useSystemEmojiFont } from 'flavours/glitch/initial_state';
|
||||||
import { assetHost } from 'flavours/glitch/utils/config';
|
import { assetHost } from 'flavours/glitch/utils/config';
|
||||||
|
|
||||||
import unicodeMapping from './emoji_unicode_mapping_light';
|
import { unicodeMapping } from './emoji_unicode_mapping_light';
|
||||||
|
|
||||||
const trie = new Trie(Object.keys(unicodeMapping));
|
const trie = new Trie(Object.keys(unicodeMapping));
|
||||||
|
|
||||||
|
|
|
@ -13,15 +13,20 @@ export type Search = string;
|
||||||
* This could be a potential area of refactoring or error handling.
|
* This could be a potential area of refactoring or error handling.
|
||||||
* The non-existence of 'skins' property is evident at [this location]{@link app/javascript/flavours/glitch/features/emoji/emoji_compressed.js:121}.
|
* The non-existence of 'skins' property is evident at [this location]{@link app/javascript/flavours/glitch/features/emoji/emoji_compressed.js:121}.
|
||||||
*/
|
*/
|
||||||
export type Skins = null;
|
type Skins = null;
|
||||||
|
|
||||||
export type FilenameData = string[] | string[][];
|
type Filename = string;
|
||||||
|
type UnicodeFilename = string;
|
||||||
|
export type FilenameData = [
|
||||||
|
filename: Filename,
|
||||||
|
unicodeFilename?: UnicodeFilename,
|
||||||
|
][];
|
||||||
export type ShortCodesToEmojiDataKey =
|
export type ShortCodesToEmojiDataKey =
|
||||||
| EmojiData['id']
|
| EmojiData['id']
|
||||||
| BaseEmoji['native']
|
| BaseEmoji['native']
|
||||||
| keyof NimbleEmojiIndex['emojis'];
|
| keyof NimbleEmojiIndex['emojis'];
|
||||||
|
|
||||||
export type SearchData = [
|
type SearchData = [
|
||||||
BaseEmoji['native'],
|
BaseEmoji['native'],
|
||||||
Emoji['short_names'],
|
Emoji['short_names'],
|
||||||
Search,
|
Search,
|
||||||
|
@ -32,9 +37,9 @@ export type ShortCodesToEmojiData = Record<
|
||||||
ShortCodesToEmojiDataKey,
|
ShortCodesToEmojiDataKey,
|
||||||
[FilenameData, SearchData]
|
[FilenameData, SearchData]
|
||||||
>;
|
>;
|
||||||
export type EmojisWithoutShortCodes = FilenameData[];
|
type EmojisWithoutShortCodes = FilenameData;
|
||||||
|
|
||||||
export type EmojiCompressed = [
|
type EmojiCompressed = [
|
||||||
ShortCodesToEmojiData,
|
ShortCodesToEmojiData,
|
||||||
Skins,
|
Skins,
|
||||||
Category[],
|
Category[],
|
||||||
|
|
|
@ -30,22 +30,13 @@ const emojis: Emojis = {};
|
||||||
// decompress
|
// decompress
|
||||||
Object.keys(shortCodesToEmojiData).forEach((shortCode) => {
|
Object.keys(shortCodesToEmojiData).forEach((shortCode) => {
|
||||||
const [_filenameData, searchData] = shortCodesToEmojiData[shortCode];
|
const [_filenameData, searchData] = shortCodesToEmojiData[shortCode];
|
||||||
const native = searchData[0];
|
const [native, short_names, search, unified] = searchData;
|
||||||
let short_names = searchData[1];
|
|
||||||
const search = searchData[2];
|
|
||||||
let unified = searchData[3];
|
|
||||||
|
|
||||||
if (!unified) {
|
|
||||||
// unified name can be derived from unicodeToUnifiedName
|
|
||||||
unified = unicodeToUnifiedName(native);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (short_names) short_names = [shortCode].concat(short_names);
|
|
||||||
emojis[shortCode] = {
|
emojis[shortCode] = {
|
||||||
native,
|
native,
|
||||||
search,
|
search,
|
||||||
short_names,
|
short_names: short_names ? [shortCode].concat(short_names) : undefined,
|
||||||
unified,
|
unified: unified ?? unicodeToUnifiedName(native),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
// A mapping of unicode strings to an object containing the filename
|
|
||||||
// (i.e. the svg filename) and a shortCode intended to be shown
|
|
||||||
// as a "title" attribute in an HTML element (aka tooltip).
|
|
||||||
|
|
||||||
import emojiCompressed from './emoji_compressed';
|
|
||||||
import { unicodeToFilename } from './unicode_to_filename';
|
|
||||||
|
|
||||||
const [
|
|
||||||
shortCodesToEmojiData,
|
|
||||||
_skins,
|
|
||||||
_categories,
|
|
||||||
_short_names,
|
|
||||||
emojisWithoutShortCodes,
|
|
||||||
] = emojiCompressed;
|
|
||||||
|
|
||||||
// decompress
|
|
||||||
const unicodeMapping = {};
|
|
||||||
|
|
||||||
function processEmojiMapData(emojiMapData, shortCode) {
|
|
||||||
let [ native, filename ] = emojiMapData;
|
|
||||||
if (!filename) {
|
|
||||||
// filename name can be derived from unicodeToFilename
|
|
||||||
filename = unicodeToFilename(native);
|
|
||||||
}
|
|
||||||
unicodeMapping[native] = {
|
|
||||||
shortCode: shortCode,
|
|
||||||
filename: filename,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(shortCodesToEmojiData).forEach((shortCode) => {
|
|
||||||
let [ filenameData ] = shortCodesToEmojiData[shortCode];
|
|
||||||
filenameData.forEach(emojiMapData => processEmojiMapData(emojiMapData, shortCode));
|
|
||||||
});
|
|
||||||
emojisWithoutShortCodes.forEach(emojiMapData => processEmojiMapData(emojiMapData));
|
|
||||||
|
|
||||||
export default unicodeMapping;
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
// A mapping of unicode strings to an object containing the filename
|
||||||
|
// (i.e. the svg filename) and a shortCode intended to be shown
|
||||||
|
// as a "title" attribute in an HTML element (aka tooltip).
|
||||||
|
|
||||||
|
import type {
|
||||||
|
FilenameData,
|
||||||
|
ShortCodesToEmojiDataKey,
|
||||||
|
} from './emoji_compressed';
|
||||||
|
import emojiCompressed from './emoji_compressed';
|
||||||
|
import { unicodeToFilename } from './unicode_to_filename';
|
||||||
|
|
||||||
|
type UnicodeMapping = {
|
||||||
|
[key in FilenameData[number][0]]: {
|
||||||
|
shortCode: ShortCodesToEmojiDataKey;
|
||||||
|
filename: FilenameData[number][number];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const [
|
||||||
|
shortCodesToEmojiData,
|
||||||
|
_skins,
|
||||||
|
_categories,
|
||||||
|
_short_names,
|
||||||
|
emojisWithoutShortCodes,
|
||||||
|
] = emojiCompressed;
|
||||||
|
|
||||||
|
// decompress
|
||||||
|
const unicodeMapping: UnicodeMapping = {};
|
||||||
|
|
||||||
|
function processEmojiMapData(
|
||||||
|
emojiMapData: FilenameData[number],
|
||||||
|
shortCode?: ShortCodesToEmojiDataKey,
|
||||||
|
) {
|
||||||
|
const [native, _filename] = emojiMapData;
|
||||||
|
let filename = emojiMapData[1];
|
||||||
|
if (!filename) {
|
||||||
|
// filename name can be derived from unicodeToFilename
|
||||||
|
filename = unicodeToFilename(native);
|
||||||
|
}
|
||||||
|
unicodeMapping[native] = {
|
||||||
|
shortCode,
|
||||||
|
filename,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(shortCodesToEmojiData).forEach(
|
||||||
|
(shortCode: ShortCodesToEmojiDataKey) => {
|
||||||
|
if (shortCode === undefined) return;
|
||||||
|
const [filenameData, _searchData] = shortCodesToEmojiData[shortCode];
|
||||||
|
filenameData.forEach((emojiMapData) => {
|
||||||
|
processEmojiMapData(emojiMapData, shortCode);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
emojisWithoutShortCodes.forEach((emojiMapData) => {
|
||||||
|
processEmojiMapData(emojiMapData);
|
||||||
|
});
|
||||||
|
|
||||||
|
export { unicodeMapping };
|
|
@ -34,7 +34,6 @@ const mapStateToProps = state => ({
|
||||||
class Explore extends PureComponent {
|
class Explore extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,47 +68,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'>
|
<NavLink exact to='/explore/links'>
|
||||||
<FormattedMessage tagName='div' id='explore.trending_tags' defaultMessage='Hashtags' />
|
<FormattedMessage tagName='div' id='explore.trending_links' defaultMessage='News' />
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
{signedIn && (
|
<Switch>
|
||||||
<NavLink exact to='/explore/suggestions'>
|
<Route path='/explore/tags' component={Tags} />
|
||||||
<FormattedMessage tagName='div' id='explore.suggested_follows' defaultMessage='People' />
|
<Route path='/explore/links' component={Links} />
|
||||||
</NavLink>
|
<Route path='/explore/suggestions' component={Suggestions} />
|
||||||
)}
|
<Route exact path={['/explore', '/explore/posts', '/search']}>
|
||||||
|
<Statuses multiColumn={multiColumn} />
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
|
||||||
<NavLink exact to='/explore/links'>
|
<Helmet>
|
||||||
<FormattedMessage tagName='div' id='explore.trending_links' defaultMessage='News' />
|
<title>{intl.formatMessage(messages.title)}</title>
|
||||||
</NavLink>
|
<meta name='robots' content={isSearching ? 'noindex' : 'all'} />
|
||||||
</div>
|
</Helmet>
|
||||||
|
</>
|
||||||
<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>
|
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,15 @@ import { PureComponent } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { fetchTrendingLinks } from 'flavours/glitch/actions/trends';
|
import { fetchTrendingLinks } from 'flavours/glitch/actions/trends';
|
||||||
import { DismissableBanner } from 'flavours/glitch/components/dismissable_banner';
|
import { DismissableBanner } from 'flavours/glitch/components/dismissable_banner';
|
||||||
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import Story from './components/story';
|
import Story from './components/story';
|
||||||
|
|
||||||
|
@ -23,10 +26,17 @@ class Links extends PureComponent {
|
||||||
links: ImmutablePropTypes.list,
|
links: ImmutablePropTypes.list,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { dispatch } = this.props;
|
const { dispatch, links, history } = this.props;
|
||||||
|
|
||||||
|
// If we're navigating back to the screen, do not trigger a reload
|
||||||
|
if (history.action === 'POP' && links.size > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(fetchTrendingLinks());
|
dispatch(fetchTrendingLinks());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +62,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) => (
|
||||||
|
@ -77,4 +87,4 @@ class Links extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(Links);
|
export default connect(mapStateToProps)(withRouter(Links));
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -3,15 +3,19 @@ import { PureComponent } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
|
|
||||||
import { fetchTrendingStatuses, expandTrendingStatuses } from 'flavours/glitch/actions/trends';
|
import { fetchTrendingStatuses, expandTrendingStatuses } from 'flavours/glitch/actions/trends';
|
||||||
import { DismissableBanner } from 'flavours/glitch/components/dismissable_banner';
|
import { DismissableBanner } from 'flavours/glitch/components/dismissable_banner';
|
||||||
import StatusList from 'flavours/glitch/components/status_list';
|
import StatusList from 'flavours/glitch/components/status_list';
|
||||||
import { getStatusList } from 'flavours/glitch/selectors';
|
import { getStatusList } from 'flavours/glitch/selectors';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
statusIds: getStatusList(state, 'trending'),
|
statusIds: getStatusList(state, 'trending'),
|
||||||
|
@ -27,10 +31,17 @@ class Statuses extends PureComponent {
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { dispatch } = this.props;
|
const { dispatch, statusIds, history } = this.props;
|
||||||
|
|
||||||
|
// If we're navigating back to the screen, do not trigger a reload
|
||||||
|
if (history.action === 'POP' && statusIds.size > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(fetchTrendingStatuses());
|
dispatch(fetchTrendingStatuses());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,27 +56,23 @@ class Statuses extends PureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />;
|
const emptyMessage = <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<StatusList
|
||||||
<DismissableBanner id='explore/statuses'>
|
trackScroll
|
||||||
<FormattedMessage id='dismissable_banner.explore_statuses' defaultMessage='These are posts from across the social web that are gaining traction today. Newer posts with more boosts and favorites are ranked higher.' />
|
prepend={<DismissableBanner id='explore/statuses'><FormattedMessage id='dismissable_banner.explore_statuses' defaultMessage='These are posts from across the social web that are gaining traction today. Newer posts with more boosts and favorites are ranked higher.' /></DismissableBanner>}
|
||||||
</DismissableBanner>
|
alwaysPrepend
|
||||||
|
timelineId='explore'
|
||||||
<StatusList
|
statusIds={statusIds}
|
||||||
trackScroll
|
scrollKey='explore-statuses'
|
||||||
timelineId='explore'
|
hasMore={hasMore}
|
||||||
statusIds={statusIds}
|
isLoading={isLoading}
|
||||||
scrollKey='explore-statuses'
|
onLoadMore={this.handleLoadMore}
|
||||||
hasMore={hasMore}
|
emptyMessage={emptyMessage}
|
||||||
isLoading={isLoading}
|
bindToDocument={!multiColumn}
|
||||||
onLoadMore={this.handleLoadMore}
|
withCounters
|
||||||
emptyMessage={emptyMessage}
|
/>
|
||||||
bindToDocument={!multiColumn}
|
|
||||||
withCounters
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(Statuses);
|
export default connect(mapStateToProps)(withRouter(Statuses));
|
||||||
|
|
|
@ -3,12 +3,15 @@ import { PureComponent } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { fetchSuggestions, dismissSuggestion } from 'flavours/glitch/actions/suggestions';
|
import { fetchSuggestions, dismissSuggestion } from 'flavours/glitch/actions/suggestions';
|
||||||
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
||||||
import AccountCard from 'flavours/glitch/features/directory/components/account_card';
|
import AccountCard from 'flavours/glitch/features/directory/components/account_card';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
suggestions: state.getIn(['suggestions', 'items']),
|
suggestions: state.getIn(['suggestions', 'items']),
|
||||||
|
@ -21,10 +24,17 @@ class Suggestions extends PureComponent {
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
suggestions: ImmutablePropTypes.list,
|
suggestions: ImmutablePropTypes.list,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { dispatch } = this.props;
|
const { dispatch, suggestions, history } = this.props;
|
||||||
|
|
||||||
|
// If we're navigating back to the screen, do not trigger a reload
|
||||||
|
if (history.action === 'POP' && suggestions.size > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(fetchSuggestions(true));
|
dispatch(fetchSuggestions(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +57,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')} onDismiss={suggestion.get('source') === 'past_interactions' ? this.handleDismiss : null} />
|
<AccountCard key={suggestion.get('account')} id={suggestion.get('account')} onDismiss={suggestion.get('source') === 'past_interactions' ? this.handleDismiss : null} />
|
||||||
))}
|
))}
|
||||||
|
@ -57,4 +67,4 @@ class Suggestions extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(Suggestions);
|
export default connect(mapStateToProps)(withRouter(Suggestions));
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { PureComponent } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
@ -10,6 +12,7 @@ import { fetchTrendingHashtags } from 'flavours/glitch/actions/trends';
|
||||||
import { DismissableBanner } from 'flavours/glitch/components/dismissable_banner';
|
import { DismissableBanner } from 'flavours/glitch/components/dismissable_banner';
|
||||||
import { ImmutableHashtag as Hashtag } from 'flavours/glitch/components/hashtag';
|
import { ImmutableHashtag as Hashtag } from 'flavours/glitch/components/hashtag';
|
||||||
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,10 +27,17 @@ class Tags extends PureComponent {
|
||||||
hashtags: ImmutablePropTypes.list,
|
hashtags: ImmutablePropTypes.list,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { dispatch } = this.props;
|
const { dispatch, history, hashtags } = this.props;
|
||||||
|
|
||||||
|
// If we're navigating back to the screen, do not trigger a reload
|
||||||
|
if (history.action === 'POP' && hashtags.size > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(fetchTrendingHashtags());
|
dispatch(fetchTrendingHashtags());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +63,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 => (
|
||||||
|
@ -65,4 +75,4 @@ class Tags extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(Tags);
|
export default connect(mapStateToProps)(withRouter(Tags));
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { toServerSideType } from 'flavours/glitch/utils/filters';
|
import { toServerSideType } from 'flavours/glitch/utils/filters';
|
||||||
|
|
||||||
const mapStateToProps = (state, { filterId }) => ({
|
const mapStateToProps = (state, { filterId }) => ({
|
||||||
|
|
|
@ -188,33 +188,31 @@ 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}${feedType === 'public' && allowLocalOnly ? ':allow_local_only' : ''}${onlyMedia ? ':media' : ''}`}
|
|
||||||
onLoadMore={handleLoadMore}
|
|
||||||
trackScroll
|
|
||||||
scrollKey='firehose'
|
|
||||||
emptyMessage={emptyMessage}
|
|
||||||
bindToDocument={!multiColumn}
|
|
||||||
regex={regex}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<StatusListContainer
|
||||||
|
prepend={prependBanner}
|
||||||
|
timelineId={`${feedType}${feedType === 'public' && allowLocalOnly ? ':allow_local_only' : ''}${onlyMedia ? ':media' : ''}`}
|
||||||
|
onLoadMore={handleLoadMore}
|
||||||
|
trackScroll
|
||||||
|
scrollKey='firehose'
|
||||||
|
emptyMessage={emptyMessage}
|
||||||
|
bindToDocument={!multiColumn}
|
||||||
|
regex={regex}
|
||||||
|
/>
|
||||||
|
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{intl.formatMessage(messages.title)}</title>
|
<title>{intl.formatMessage(messages.title)}</title>
|
||||||
<meta name='robots' content='noindex' />
|
<meta name='robots' content='noindex' />
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
@ -12,8 +13,9 @@ import { requestBrowserPermission } from 'flavours/glitch/actions/notifications'
|
||||||
import { changeSetting, saveSettings } from 'flavours/glitch/actions/settings';
|
import { changeSetting, saveSettings } from 'flavours/glitch/actions/settings';
|
||||||
import { fetchSuggestions } from 'flavours/glitch/actions/suggestions';
|
import { fetchSuggestions } from 'flavours/glitch/actions/suggestions';
|
||||||
import { markAsPartial } from 'flavours/glitch/actions/timelines';
|
import { markAsPartial } from 'flavours/glitch/actions/timelines';
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import Column from 'flavours/glitch/features/ui/components/column';
|
import Column from 'flavours/glitch/features/ui/components/column';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg';
|
import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg';
|
||||||
|
|
||||||
import Account from './components/account';
|
import Account from './components/account';
|
||||||
|
@ -25,14 +27,11 @@ const mapStateToProps = state => ({
|
||||||
|
|
||||||
class FollowRecommendations extends ImmutablePureComponent {
|
class FollowRecommendations extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
suggestions: ImmutablePropTypes.list,
|
suggestions: ImmutablePropTypes.list,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
|
@ -56,8 +55,7 @@ class FollowRecommendations extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDone = () => {
|
handleDone = () => {
|
||||||
const { dispatch } = this.props;
|
const { history, dispatch } = this.props;
|
||||||
const { router } = this.context;
|
|
||||||
|
|
||||||
dispatch(requestBrowserPermission((permission) => {
|
dispatch(requestBrowserPermission((permission) => {
|
||||||
if (permission === 'granted') {
|
if (permission === 'granted') {
|
||||||
|
@ -71,7 +69,7 @@ class FollowRecommendations extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
router.history.push('/home');
|
history.push('/home');
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
@ -118,4 +116,4 @@ class FollowRecommendations extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(FollowRecommendations);
|
export default withRouter(connect(mapStateToProps)(FollowRecommendations));
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { PureComponent } from 'react';
|
||||||
import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
@ -16,27 +17,22 @@ import { AnimatedNumber } from 'flavours/glitch/components/animated_number';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||||
import EmojiPickerDropdown from 'flavours/glitch/features/compose/containers/emoji_picker_dropdown_container';
|
import EmojiPickerDropdown from 'flavours/glitch/features/compose/containers/emoji_picker_dropdown_container';
|
||||||
import unicodeMapping from 'flavours/glitch/features/emoji/emoji_unicode_mapping_light';
|
import { unicodeMapping } from 'flavours/glitch/features/emoji/emoji_unicode_mapping_light';
|
||||||
import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'flavours/glitch/initial_state';
|
import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'flavours/glitch/initial_state';
|
||||||
import { assetHost } from 'flavours/glitch/utils/config';
|
import { assetHost } from 'flavours/glitch/utils/config';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg';
|
import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
|
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
|
||||||
next: { id: 'lightbox.next', defaultMessage: 'Next' },
|
next: { id: 'lightbox.next', defaultMessage: 'Next' },
|
||||||
});
|
});
|
||||||
|
|
||||||
class Content extends ImmutablePureComponent {
|
class ContentWithRouter extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
announcement: ImmutablePropTypes.map.isRequired,
|
announcement: ImmutablePropTypes.map.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
|
@ -91,25 +87,25 @@ class Content extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMentionClick = (mention, e) => {
|
onMentionClick = (mention, e) => {
|
||||||
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.context.router.history.push(`/@${mention.get('acct')}`);
|
this.props.history.push(`/@${mention.get('acct')}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onHashtagClick = (hashtag, e) => {
|
onHashtagClick = (hashtag, e) => {
|
||||||
hashtag = hashtag.replace(/^#/, '');
|
hashtag = hashtag.replace(/^#/, '');
|
||||||
|
|
||||||
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
if (this.props.history&& e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.context.router.history.push(`/tags/${hashtag}`);
|
this.props.history.push(`/tags/${hashtag}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onStatusClick = (status, e) => {
|
onStatusClick = (status, e) => {
|
||||||
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
|
this.props.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -155,6 +151,8 @@ class Content extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Content = withRouter(ContentWithRouter);
|
||||||
|
|
||||||
class Emoji extends PureComponent {
|
class Emoji extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -88,7 +88,6 @@ const badgeDisplay = (number, limit) => {
|
||||||
class GettingStarted extends ImmutablePureComponent {
|
class GettingStarted extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object.isRequired,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ const messages = defineMessages({
|
||||||
class GettingStartedMisc extends ImmutablePureComponent {
|
class GettingStartedMisc extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object.isRequired,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { ShortNumber } from 'flavours/glitch/components/short_number';
|
import { ShortNumber } from 'flavours/glitch/components/short_number';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { throttle, escapeRegExp } from 'lodash';
|
||||||
|
|
||||||
import { openModal, closeModal } from 'flavours/glitch/actions/modal';
|
import { openModal, closeModal } from 'flavours/glitch/actions/modal';
|
||||||
import api from 'flavours/glitch/api';
|
import api from 'flavours/glitch/api';
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import { registrationsOpen, sso_redirect } from 'flavours/glitch/initial_state';
|
import { registrationsOpen, sso_redirect } from 'flavours/glitch/initial_state';
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { PureComponent } from 'react';
|
||||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -22,6 +23,7 @@ import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
||||||
import { RadioButton } from 'flavours/glitch/components/radio_button';
|
import { RadioButton } from 'flavours/glitch/components/radio_button';
|
||||||
import BundleColumnError from 'flavours/glitch/features/ui/components/bundle_column_error';
|
import BundleColumnError from 'flavours/glitch/features/ui/components/bundle_column_error';
|
||||||
import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
|
import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
||||||
|
@ -38,10 +40,6 @@ const mapStateToProps = (state, props) => ({
|
||||||
|
|
||||||
class ListTimeline extends PureComponent {
|
class ListTimeline extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
params: PropTypes.object.isRequired,
|
params: PropTypes.object.isRequired,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
@ -50,6 +48,7 @@ class ListTimeline extends PureComponent {
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
list: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
|
list: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePin = () => {
|
handlePin = () => {
|
||||||
|
@ -59,7 +58,7 @@ class ListTimeline extends PureComponent {
|
||||||
dispatch(removeColumn(columnId));
|
dispatch(removeColumn(columnId));
|
||||||
} else {
|
} else {
|
||||||
dispatch(addColumn('LIST', { id: this.props.params.id }));
|
dispatch(addColumn('LIST', { id: this.props.params.id }));
|
||||||
this.context.router.history.push('/');
|
this.props.history.push('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,7 +136,7 @@ class ListTimeline extends PureComponent {
|
||||||
if (columnId) {
|
if (columnId) {
|
||||||
dispatch(removeColumn(columnId));
|
dispatch(removeColumn(columnId));
|
||||||
} else {
|
} else {
|
||||||
this.context.router.history.push('/lists');
|
this.props.history.push('/lists');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -242,4 +241,4 @@ class ListTimeline extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(injectIntl(ListTimeline));
|
export default withRouter(connect(mapStateToProps)(injectIntl(ListTimeline)));
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
// Package imports.
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import { HotKeys } from 'react-hotkeys';
|
import { HotKeys } from 'react-hotkeys';
|
||||||
|
|
||||||
|
|
||||||
// Our imports.
|
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import Permalink from 'flavours/glitch/components/permalink';
|
import Permalink from 'flavours/glitch/components/permalink';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import NotificationOverlayContainer from '../containers/overlay_container';
|
import NotificationOverlayContainer from '../containers/overlay_container';
|
||||||
|
|
||||||
import Report from './report';
|
import Report from './report';
|
||||||
|
|
||||||
export default class AdminReport extends ImmutablePureComponent {
|
class AdminReport extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
hidden: PropTypes.bool,
|
hidden: PropTypes.bool,
|
||||||
|
@ -28,6 +27,7 @@ export default class AdminReport extends ImmutablePureComponent {
|
||||||
notification: ImmutablePropTypes.map.isRequired,
|
notification: ImmutablePropTypes.map.isRequired,
|
||||||
unread: PropTypes.bool,
|
unread: PropTypes.bool,
|
||||||
report: ImmutablePropTypes.map.isRequired,
|
report: ImmutablePropTypes.map.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMoveUp = () => {
|
handleMoveUp = () => {
|
||||||
|
@ -45,15 +45,15 @@ export default class AdminReport extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpenProfile = () => {
|
handleOpenProfile = () => {
|
||||||
const { notification } = this.props;
|
const { history, notification } = this.props;
|
||||||
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMention = e => {
|
handleMention = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { notification, onMention } = this.props;
|
const { history, notification, onMention } = this.props;
|
||||||
onMention(notification.get('account'), this.context.router.history);
|
onMention(notification.get('account'), history);
|
||||||
};
|
};
|
||||||
|
|
||||||
getHandlers () {
|
getHandlers () {
|
||||||
|
@ -111,3 +111,5 @@ export default class AdminReport extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(AdminReport);
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
// Package imports.
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import { HotKeys } from 'react-hotkeys';
|
import { HotKeys } from 'react-hotkeys';
|
||||||
|
|
||||||
|
|
||||||
// Our imports.
|
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import Permalink from 'flavours/glitch/components/permalink';
|
import Permalink from 'flavours/glitch/components/permalink';
|
||||||
import AccountContainer from 'flavours/glitch/containers/account_container';
|
import AccountContainer from 'flavours/glitch/containers/account_container';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import NotificationOverlayContainer from '../containers/overlay_container';
|
import NotificationOverlayContainer from '../containers/overlay_container';
|
||||||
|
|
||||||
export default class NotificationFollow extends ImmutablePureComponent {
|
class NotificationAdminSignup extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
hidden: PropTypes.bool,
|
hidden: PropTypes.bool,
|
||||||
|
@ -26,6 +25,7 @@ export default class NotificationFollow extends ImmutablePureComponent {
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
notification: ImmutablePropTypes.map.isRequired,
|
notification: ImmutablePropTypes.map.isRequired,
|
||||||
unread: PropTypes.bool,
|
unread: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMoveUp = () => {
|
handleMoveUp = () => {
|
||||||
|
@ -43,15 +43,15 @@ export default class NotificationFollow extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpenProfile = () => {
|
handleOpenProfile = () => {
|
||||||
const { notification } = this.props;
|
const { history, notification } = this.props;
|
||||||
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMention = e => {
|
handleMention = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { notification, onMention } = this.props;
|
const { history, notification, onMention } = this.props;
|
||||||
onMention(notification.get('account'), this.context.router.history);
|
onMention(notification.get('account'), history);
|
||||||
};
|
};
|
||||||
|
|
||||||
getHandlers () {
|
getHandlers () {
|
||||||
|
@ -104,3 +104,5 @@ export default class NotificationFollow extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(NotificationAdminSignup);
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
// Package imports.
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import { HotKeys } from 'react-hotkeys';
|
import { HotKeys } from 'react-hotkeys';
|
||||||
|
|
||||||
|
|
||||||
// Our imports.
|
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import Permalink from 'flavours/glitch/components/permalink';
|
import Permalink from 'flavours/glitch/components/permalink';
|
||||||
import AccountContainer from 'flavours/glitch/containers/account_container';
|
import AccountContainer from 'flavours/glitch/containers/account_container';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import NotificationOverlayContainer from '../containers/overlay_container';
|
import NotificationOverlayContainer from '../containers/overlay_container';
|
||||||
|
|
||||||
export default class NotificationFollow extends ImmutablePureComponent {
|
class NotificationFollow extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
hidden: PropTypes.bool,
|
hidden: PropTypes.bool,
|
||||||
|
@ -26,6 +25,7 @@ export default class NotificationFollow extends ImmutablePureComponent {
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
notification: ImmutablePropTypes.map.isRequired,
|
notification: ImmutablePropTypes.map.isRequired,
|
||||||
unread: PropTypes.bool,
|
unread: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMoveUp = () => {
|
handleMoveUp = () => {
|
||||||
|
@ -43,15 +43,15 @@ export default class NotificationFollow extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpenProfile = () => {
|
handleOpenProfile = () => {
|
||||||
const { notification } = this.props;
|
const { history, notification } = this.props;
|
||||||
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMention = e => {
|
handleMention = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { notification, onMention } = this.props;
|
const { history, notification, onMention } = this.props;
|
||||||
onMention(notification.get('account'), this.context.router.history);
|
onMention(notification.get('account'), history);
|
||||||
};
|
};
|
||||||
|
|
||||||
getHandlers () {
|
getHandlers () {
|
||||||
|
@ -104,3 +104,5 @@ export default class NotificationFollow extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(NotificationFollow);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
@ -14,6 +15,7 @@ import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||||
import Permalink from 'flavours/glitch/components/permalink';
|
import Permalink from 'flavours/glitch/components/permalink';
|
||||||
|
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
|
||||||
|
|
||||||
import NotificationOverlayContainer from '../containers/overlay_container';
|
import NotificationOverlayContainer from '../containers/overlay_container';
|
||||||
|
|
||||||
|
@ -31,6 +33,7 @@ class FollowRequest extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
notification: ImmutablePropTypes.map.isRequired,
|
notification: ImmutablePropTypes.map.isRequired,
|
||||||
unread: PropTypes.bool,
|
unread: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMoveUp = () => {
|
handleMoveUp = () => {
|
||||||
|
@ -48,15 +51,15 @@ class FollowRequest extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpenProfile = () => {
|
handleOpenProfile = () => {
|
||||||
const { notification } = this.props;
|
const { history, notification } = this.props;
|
||||||
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMention = e => {
|
handleMention = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { notification, onMention } = this.props;
|
const { history, notification, onMention } = this.props;
|
||||||
onMention(notification.get('account'), this.context.router.history);
|
onMention(notification.get('account'), history);
|
||||||
};
|
};
|
||||||
|
|
||||||
getHandlers () {
|
getHandlers () {
|
||||||
|
@ -135,4 +138,4 @@ class FollowRequest extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(FollowRequest);
|
export default withRouter(injectIntl(FollowRequest));
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { requestBrowserPermission } from 'flavours/glitch/actions/notifications';
|
import { requestBrowserPermission } from 'flavours/glitch/actions/notifications';
|
||||||
import { changeSetting } from 'flavours/glitch/actions/settings';
|
import { changeSetting } from 'flavours/glitch/actions/settings';
|
||||||
import Button from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue