Merge branch 'main' into glitch-soc/merge-upstream
Conflicts: - `.github/workflows/build-image.yml`: Upstream updated `docker/build-push-action`, and we a different config for `docker/metadata-action` so the lines directly above were different, but it's not a real conflict. Upgraded `docker/build-push-action` as upstream did. - `app/javascript/mastodon/features/compose/components/compose_form.js`: Upstream changed the codestyle near a line we had modified to accommodate configurable character count. Kept our change.
This commit is contained in:
		
						commit
						aeacebb3d7
					
				
					 249 changed files with 4854 additions and 3174 deletions
				
			
		
							
								
								
									
										87
									
								
								.eslintrc.js
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								.eslintrc.js
									
									
									
									
									
								
							|  | @ -3,6 +3,8 @@ module.exports = { | ||||||
| 
 | 
 | ||||||
|   extends: [ |   extends: [ | ||||||
|     'eslint:recommended', |     'eslint:recommended', | ||||||
|  |     'plugin:react/recommended', | ||||||
|  |     'plugin:jsx-a11y/recommended', | ||||||
|   ], |   ], | ||||||
| 
 | 
 | ||||||
|   env: { |   env: { | ||||||
|  | @ -80,8 +82,6 @@ module.exports = { | ||||||
|       }, |       }, | ||||||
|     ], |     ], | ||||||
|     'no-empty': 'off', |     'no-empty': 'off', | ||||||
|     'no-nested-ternary': 'warn', |  | ||||||
|     'no-prototype-builtins': 'off', |  | ||||||
|     'no-restricted-properties': [ |     'no-restricted-properties': [ | ||||||
|       'error', |       'error', | ||||||
|       { property: 'substring', message: 'Use .slice instead of .substring.' }, |       { property: 'substring', message: 'Use .slice instead of .substring.' }, | ||||||
|  | @ -113,55 +113,42 @@ module.exports = { | ||||||
|     'react/jsx-boolean-value': 'error', |     'react/jsx-boolean-value': 'error', | ||||||
|     'react/jsx-closing-bracket-location': ['error', 'line-aligned'], |     'react/jsx-closing-bracket-location': ['error', 'line-aligned'], | ||||||
|     'react/jsx-curly-spacing': 'error', |     'react/jsx-curly-spacing': 'error', | ||||||
|  |     'react/display-name': 'off', | ||||||
|     'react/jsx-equals-spacing': 'error', |     'react/jsx-equals-spacing': 'error', | ||||||
|     'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], |     'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], | ||||||
|     'react/jsx-indent': ['error', 2], |     'react/jsx-indent': ['error', 2], | ||||||
|     'react/jsx-no-bind': 'error', |     'react/jsx-no-bind': 'error', | ||||||
|     'react/jsx-no-duplicate-props': 'error', |     'react/jsx-no-target-blank': 'off', | ||||||
|     'react/jsx-no-undef': 'error', |  | ||||||
|     'react/jsx-tag-spacing': 'error', |     'react/jsx-tag-spacing': 'error', | ||||||
|     'react/jsx-uses-react': 'error', |  | ||||||
|     'react/jsx-uses-vars': 'error', |  | ||||||
|     'react/jsx-wrap-multilines': 'error', |     'react/jsx-wrap-multilines': 'error', | ||||||
|     'react/no-multi-comp': 'off', |     'react/no-deprecated': 'off', | ||||||
|     'react/no-string-refs': 'error', |     'react/no-unknown-property': 'off', | ||||||
|     'react/prop-types': 'error', |  | ||||||
|     'react/self-closing-comp': 'error', |     'react/self-closing-comp': 'error', | ||||||
| 
 | 
 | ||||||
|  |     // recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/index.js
 | ||||||
|     'jsx-a11y/accessible-emoji': 'warn', |     'jsx-a11y/accessible-emoji': 'warn', | ||||||
|     'jsx-a11y/alt-text': 'warn', |     'jsx-a11y/click-events-have-key-events': 'off', | ||||||
|     'jsx-a11y/anchor-has-content': 'warn', |     'jsx-a11y/label-has-associated-control': 'off', | ||||||
|     'jsx-a11y/anchor-is-valid': [ |     'jsx-a11y/media-has-caption': 'off', | ||||||
|       'warn', |     'jsx-a11y/no-autofocus': 'off', | ||||||
|       { |     // recommended rule is:
 | ||||||
|         components: [ |     // 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
 | ||||||
|           'Link', |     //   'error',
 | ||||||
|           'NavLink', |     //   {
 | ||||||
|         ], |     //     tr: ['none', 'presentation'],
 | ||||||
|         specialLink: [ |     //     canvas: ['img'],
 | ||||||
|           'to', |     //   },
 | ||||||
|         ], |     // ],
 | ||||||
|         aspect: [ |     'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off', | ||||||
|           'noHref', |     // recommended rule is:
 | ||||||
|           'invalidHref', |     // 'jsx-a11y/no-noninteractive-element-interactions': [
 | ||||||
|           'preferButton', |     //   'error',
 | ||||||
|         ], |     //   {
 | ||||||
|       }, |     //     body: ['onError', 'onLoad'],
 | ||||||
|     ], |     //     iframe: ['onError', 'onLoad'],
 | ||||||
|     'jsx-a11y/aria-activedescendant-has-tabindex': 'warn', |     //     img: ['onError', 'onLoad'],
 | ||||||
|     'jsx-a11y/aria-props': 'warn', |     //   },
 | ||||||
|     'jsx-a11y/aria-proptypes': 'warn', |     // ],
 | ||||||
|     'jsx-a11y/aria-role': 'warn', |  | ||||||
|     'jsx-a11y/aria-unsupported-elements': 'warn', |  | ||||||
|     'jsx-a11y/heading-has-content': 'warn', |  | ||||||
|     'jsx-a11y/html-has-lang': 'warn', |  | ||||||
|     'jsx-a11y/iframe-has-title': 'warn', |  | ||||||
|     'jsx-a11y/img-redundant-alt': 'warn', |  | ||||||
|     'jsx-a11y/interactive-supports-focus': 'warn', |  | ||||||
|     'jsx-a11y/label-has-for': 'off', |  | ||||||
|     'jsx-a11y/mouse-events-have-key-events': 'warn', |  | ||||||
|     'jsx-a11y/no-access-key': 'warn', |  | ||||||
|     'jsx-a11y/no-distracting-elements': 'warn', |  | ||||||
|     'jsx-a11y/no-noninteractive-element-interactions': [ |     'jsx-a11y/no-noninteractive-element-interactions': [ | ||||||
|       'warn', |       'warn', | ||||||
|       { |       { | ||||||
|  | @ -170,8 +157,18 @@ module.exports = { | ||||||
|         ], |         ], | ||||||
|       }, |       }, | ||||||
|     ], |     ], | ||||||
|  |     // recommended rule is:
 | ||||||
|  |     // 'jsx-a11y/no-noninteractive-tabindex': [
 | ||||||
|  |     //   'error',
 | ||||||
|  |     //   {
 | ||||||
|  |     //     tags: [],
 | ||||||
|  |     //     roles: ['tabpanel'],
 | ||||||
|  |     //     allowExpressionValues: true,
 | ||||||
|  |     //   },
 | ||||||
|  |     // ],
 | ||||||
|  |     'jsx-a11y/no-noninteractive-tabindex': 'off', | ||||||
|     'jsx-a11y/no-onchange': 'warn', |     'jsx-a11y/no-onchange': 'warn', | ||||||
|     'jsx-a11y/no-redundant-roles': 'warn', |     // recommended is full 'error'
 | ||||||
|     'jsx-a11y/no-static-element-interactions': [ |     'jsx-a11y/no-static-element-interactions': [ | ||||||
|       'warn', |       'warn', | ||||||
|       { |       { | ||||||
|  | @ -180,10 +177,6 @@ module.exports = { | ||||||
|         ], |         ], | ||||||
|       }, |       }, | ||||||
|     ], |     ], | ||||||
|     'jsx-a11y/role-has-required-aria-props': 'warn', |  | ||||||
|     'jsx-a11y/role-supports-aria-props': 'off', |  | ||||||
|     'jsx-a11y/scope': 'warn', |  | ||||||
|     'jsx-a11y/tabindex-no-positive': 'warn', |  | ||||||
| 
 | 
 | ||||||
|     'import/extensions': [ |     'import/extensions': [ | ||||||
|       'error', |       'error', | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								.github/workflows/build-image.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/build-image.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -15,6 +15,11 @@ permissions: | ||||||
| jobs: | jobs: | ||||||
|   build-image: |   build-image: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|  | 
 | ||||||
|  |     concurrency: | ||||||
|  |       group: ${{ github.ref }} | ||||||
|  |       cancel-in-progress: true | ||||||
|  | 
 | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v3 |       - uses: actions/checkout@v3 | ||||||
|       - uses: hadolint/hadolint-action@v3.1.0 |       - uses: hadolint/hadolint-action@v3.1.0 | ||||||
|  | @ -34,10 +39,11 @@ jobs: | ||||||
|             type=raw,value=latest,enable={{is_default_branch}} |             type=raw,value=latest,enable={{is_default_branch}} | ||||||
|             type=edge,branch=main |             type=edge,branch=main | ||||||
|             type=sha,prefix=,format=long |             type=sha,prefix=,format=long | ||||||
|       - uses: docker/build-push-action@v3 |       - uses: docker/build-push-action@v4 | ||||||
|         with: |         with: | ||||||
|           context: . |           context: . | ||||||
|           platforms: linux/amd64,linux/arm64 |           platforms: linux/amd64,linux/arm64 | ||||||
|  |           provenance: false | ||||||
|           builder: ${{ steps.buildx.outputs.name }} |           builder: ${{ steps.buildx.outputs.name }} | ||||||
|           push: ${{ github.event_name != 'pull_request' }} |           push: ${{ github.event_name != 'pull_request' }} | ||||||
|           tags: ${{ steps.meta.outputs.tags }} |           tags: ${{ steps.meta.outputs.tags }} | ||||||
|  |  | ||||||
							
								
								
									
										48
									
								
								.github/workflows/lint-css.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/lint-css.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | name: CSS Linting | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches-ignore: | ||||||
|  |       - 'dependabot/**' | ||||||
|  |     paths: | ||||||
|  |       - 'package.json' | ||||||
|  |       - 'yarn.lock' | ||||||
|  |       - '.prettier*' | ||||||
|  |       - 'stylelint.config.js' | ||||||
|  |       - '**/*.css' | ||||||
|  |       - '**/*.scss' | ||||||
|  |       - '.github/workflows/lint-css.yml' | ||||||
|  |       - '.github/stylelint-matcher.json' | ||||||
|  | 
 | ||||||
|  |   pull_request: | ||||||
|  |     paths: | ||||||
|  |       - 'package.json' | ||||||
|  |       - 'yarn.lock' | ||||||
|  |       - '.prettier*' | ||||||
|  |       - 'stylelint.config.js' | ||||||
|  |       - '**/*.css' | ||||||
|  |       - '**/*.scss' | ||||||
|  |       - '.github/workflows/lint-css.yml' | ||||||
|  |       - '.github/stylelint-matcher.json' | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   lint: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  | 
 | ||||||
|  |     steps: | ||||||
|  |       - name: Clone repository | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  | 
 | ||||||
|  |       - name: Set up Node.js | ||||||
|  |         uses: actions/setup-node@v3 | ||||||
|  |         with: | ||||||
|  |           cache: yarn | ||||||
|  | 
 | ||||||
|  |       - name: Install all yarn packages | ||||||
|  |         run: yarn --frozen-lockfile | ||||||
|  | 
 | ||||||
|  |       - uses: xt0rted/stylelint-problem-matcher@v1 | ||||||
|  | 
 | ||||||
|  |       - run: echo "::add-matcher::.github/stylelint-matcher.json" | ||||||
|  | 
 | ||||||
|  |       - name: Stylelint | ||||||
|  |         run: yarn test:lint:sass | ||||||
							
								
								
									
										40
									
								
								.github/workflows/lint-js.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								.github/workflows/lint-js.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | name: JavaScript Linting | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches-ignore: | ||||||
|  |       - 'dependabot/**' | ||||||
|  |     paths: | ||||||
|  |       - 'package.json' | ||||||
|  |       - 'yarn.lock' | ||||||
|  |       - '.prettier*' | ||||||
|  |       - '.eslint*' | ||||||
|  |       - '**/*.js' | ||||||
|  |       - '.github/workflows/lint-js.yml' | ||||||
|  | 
 | ||||||
|  |   pull_request: | ||||||
|  |     paths: | ||||||
|  |       - 'package.json' | ||||||
|  |       - 'yarn.lock' | ||||||
|  |       - '.prettier*' | ||||||
|  |       - '.eslint*' | ||||||
|  |       - '**/*.js' | ||||||
|  |       - '.github/workflows/lint-js.yml' | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   lint: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  | 
 | ||||||
|  |     steps: | ||||||
|  |       - name: Clone repository | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  | 
 | ||||||
|  |       - name: Set up Node.js | ||||||
|  |         uses: actions/setup-node@v3 | ||||||
|  |         with: | ||||||
|  |           cache: yarn | ||||||
|  | 
 | ||||||
|  |       - name: Install all yarn packages | ||||||
|  |         run: yarn --frozen-lockfile | ||||||
|  | 
 | ||||||
|  |       - name: ESLint | ||||||
|  |         run: yarn test:lint:js | ||||||
							
								
								
									
										2
									
								
								.github/workflows/lint-json.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/lint-json.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -9,6 +9,7 @@ on: | ||||||
|       - '.prettier*' |       - '.prettier*' | ||||||
|       - '**/*.json' |       - '**/*.json' | ||||||
|       - '.github/workflows/lint-json.yml' |       - '.github/workflows/lint-json.yml' | ||||||
|  |       - '!app/javascript/mastodon/locales/*.json' | ||||||
| 
 | 
 | ||||||
|   pull_request: |   pull_request: | ||||||
|     paths: |     paths: | ||||||
|  | @ -17,6 +18,7 @@ on: | ||||||
|       - '.prettier*' |       - '.prettier*' | ||||||
|       - '**/*.json' |       - '**/*.json' | ||||||
|       - '.github/workflows/lint-json.yml' |       - '.github/workflows/lint-json.yml' | ||||||
|  |       - '!app/javascript/mastodon/locales/*.json' | ||||||
| 
 | 
 | ||||||
| jobs: | jobs: | ||||||
|   lint: |   lint: | ||||||
|  |  | ||||||
							
								
								
									
										41
									
								
								.github/workflows/lint-ruby.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								.github/workflows/lint-ruby.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | ||||||
|  | name: Ruby Linting | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches-ignore: | ||||||
|  |       - 'dependabot/**' | ||||||
|  |     paths: | ||||||
|  |       - 'Gemfile*' | ||||||
|  |       - '.rubocop.yml' | ||||||
|  |       - '**/*.rb' | ||||||
|  |       - '**/*.rake' | ||||||
|  |       - '.github/workflows/lint-ruby.yml' | ||||||
|  | 
 | ||||||
|  |   pull_request: | ||||||
|  |     paths: | ||||||
|  |       - 'Gemfile*' | ||||||
|  |       - '.rubocop.yml' | ||||||
|  |       - '**/*.rb' | ||||||
|  |       - '**/*.rake' | ||||||
|  |       - '.github/workflows/lint-ruby.yml' | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   lint: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout Code | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  |         with: | ||||||
|  |           fetch-depth: 0 | ||||||
|  | 
 | ||||||
|  |       - name: Set-up RuboCop Problem Mathcher | ||||||
|  |         uses: r7kamura/rubocop-problem-matchers-action@v1 | ||||||
|  | 
 | ||||||
|  |       - name: Run rubocop | ||||||
|  |         uses: github/super-linter@v4 | ||||||
|  |         env: | ||||||
|  |           DEFAULT_BRANCH: main | ||||||
|  |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |           LINTER_RULES_PATH: . | ||||||
|  |           RUBY_CONFIG_FILE: .rubocop.yml | ||||||
|  |           VALIDATE_ALL_CODEBASE: false | ||||||
|  |           VALIDATE_RUBY: true | ||||||
							
								
								
									
										2
									
								
								.github/workflows/lint-yml.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/lint-yml.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -10,6 +10,7 @@ on: | ||||||
|       - '**/*.yaml' |       - '**/*.yaml' | ||||||
|       - '**/*.yml' |       - '**/*.yml' | ||||||
|       - '.github/workflows/lint-yml.yml' |       - '.github/workflows/lint-yml.yml' | ||||||
|  |       - '!config/locales/*.yml' | ||||||
| 
 | 
 | ||||||
|   pull_request: |   pull_request: | ||||||
|     paths: |     paths: | ||||||
|  | @ -19,6 +20,7 @@ on: | ||||||
|       - '**/*.yaml' |       - '**/*.yaml' | ||||||
|       - '**/*.yml' |       - '**/*.yml' | ||||||
|       - '.github/workflows/lint-yml.yml' |       - '.github/workflows/lint-yml.yml' | ||||||
|  |       - '!config/locales/*.yml' | ||||||
| 
 | 
 | ||||||
| jobs: | jobs: | ||||||
|   lint: |   lint: | ||||||
|  |  | ||||||
							
								
								
									
										83
									
								
								.github/workflows/linter.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								.github/workflows/linter.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -1,83 +0,0 @@ | ||||||
| --- |  | ||||||
| ################################# |  | ||||||
| ################################# |  | ||||||
| ## Super Linter GitHub Actions ## |  | ||||||
| ################################# |  | ||||||
| ################################# |  | ||||||
| name: Lint Code Base |  | ||||||
| 
 |  | ||||||
| # |  | ||||||
| # Documentation: |  | ||||||
| # https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions |  | ||||||
| # |  | ||||||
| 
 |  | ||||||
| ############################# |  | ||||||
| # Start the job on all push # |  | ||||||
| ############################# |  | ||||||
| on: |  | ||||||
|   push: |  | ||||||
|     branches-ignore: [main] |  | ||||||
|     # Remove the line above to run when pushing to master |  | ||||||
|   pull_request: |  | ||||||
|     branches: [main] |  | ||||||
| 
 |  | ||||||
| ############### |  | ||||||
| # Set the Job # |  | ||||||
| ############### |  | ||||||
| permissions: |  | ||||||
|   checks: write |  | ||||||
|   contents: read |  | ||||||
|   pull-requests: write |  | ||||||
|   statuses: write |  | ||||||
| 
 |  | ||||||
| jobs: |  | ||||||
|   build: |  | ||||||
|     # Name the Job |  | ||||||
|     name: Lint Code Base |  | ||||||
|     # Set the agent to run on |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
| 
 |  | ||||||
|     ################## |  | ||||||
|     # Load all steps # |  | ||||||
|     ################## |  | ||||||
|     steps: |  | ||||||
|       ########################## |  | ||||||
|       # Checkout the code base # |  | ||||||
|       ########################## |  | ||||||
|       - name: Checkout Code |  | ||||||
|         uses: actions/checkout@v3 |  | ||||||
|         with: |  | ||||||
|           # Full git history is needed to get a proper list of changed files within `super-linter` |  | ||||||
|           fetch-depth: 0 |  | ||||||
| 
 |  | ||||||
|       - name: Set-up Node.js |  | ||||||
|         uses: actions/setup-node@v3 |  | ||||||
|         with: |  | ||||||
|           node-version-file: .nvmrc |  | ||||||
|           cache: yarn |  | ||||||
|       - name: Install dependencies |  | ||||||
|         run: yarn install --frozen-lockfile |  | ||||||
|       - name: Set-up RuboCop Problem Mathcher |  | ||||||
|         uses: r7kamura/rubocop-problem-matchers-action@v1 |  | ||||||
|       - name: Set-up Stylelint Problem Matcher |  | ||||||
|         uses: xt0rted/stylelint-problem-matcher@v1 |  | ||||||
|       # https://github.com/xt0rted/stylelint-problem-matcher/issues/360 |  | ||||||
|       - run: echo "::add-matcher::.github/stylelint-matcher.json" |  | ||||||
| 
 |  | ||||||
|       ################################ |  | ||||||
|       # Run Linter against code base # |  | ||||||
|       ################################ |  | ||||||
|       - name: Lint Code Base |  | ||||||
|         uses: github/super-linter@v4 |  | ||||||
|         env: |  | ||||||
|           CSS_FILE_NAME: stylelint.config.js |  | ||||||
|           DEFAULT_BRANCH: main |  | ||||||
|           NO_COLOR: 1 # https://github.com/xt0rted/stylelint-problem-matcher/issues/360 |  | ||||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |  | ||||||
|           JAVASCRIPT_ES_CONFIG_FILE: .eslintrc.js |  | ||||||
|           LINTER_RULES_PATH: . |  | ||||||
|           RUBY_CONFIG_FILE: .rubocop.yml |  | ||||||
|           VALIDATE_ALL_CODEBASE: false |  | ||||||
|           VALIDATE_CSS: true |  | ||||||
|           VALIDATE_JAVASCRIPT_ES: true |  | ||||||
|           VALIDATE_RUBY: true |  | ||||||
							
								
								
									
										13
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								CHANGELOG.md
									
									
									
									
									
								
							|  | @ -38,8 +38,10 @@ All notable changes to this project will be documented in this file. | ||||||
| - Add brotli compression to `assets:precompile` ([Izorkin](https://github.com/mastodon/mastodon/pull/19025)) | - Add brotli compression to `assets:precompile` ([Izorkin](https://github.com/mastodon/mastodon/pull/19025)) | ||||||
| - Add “disabled” account filter to the `/admin/accounts` UI ([tribela](https://github.com/mastodon/mastodon/pull/21282)) | - Add “disabled” account filter to the `/admin/accounts` UI ([tribela](https://github.com/mastodon/mastodon/pull/21282)) | ||||||
| - Add transparency to modal background for accessibility ([edent](https://github.com/mastodon/mastodon/pull/18081)) | - Add transparency to modal background for accessibility ([edent](https://github.com/mastodon/mastodon/pull/18081)) | ||||||
|  | - Add `lang` attribute to image description textarea and poll option field ([c960657](https://github.com/mastodon/mastodon/pull/23293)) | ||||||
| - Add `title` attribute to video elements in media attachments ([bramus](https://github.com/mastodon/mastodon/pull/21420)) | - Add `title` attribute to video elements in media attachments ([bramus](https://github.com/mastodon/mastodon/pull/21420)) | ||||||
| - Add left and right margins to emojis ([dsblank](https://github.com/mastodon/mastodon/pull/20464)) | - Add left and right margins to emojis ([dsblank](https://github.com/mastodon/mastodon/pull/20464)) | ||||||
|  | - Add `roles` attribute to `Account` entities in REST API ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23255)) | ||||||
| - Add `reading:autoplay:gifs` to `/api/v1/preferences` ([j-f1](https://github.com/mastodon/mastodon/pull/22706)) | - Add `reading:autoplay:gifs` to `/api/v1/preferences` ([j-f1](https://github.com/mastodon/mastodon/pull/22706)) | ||||||
| - Add `hide_collections` parameter to `/api/v1/accounts/credentials` ([CarlSchwan](https://github.com/mastodon/mastodon/pull/22790)) | - Add `hide_collections` parameter to `/api/v1/accounts/credentials` ([CarlSchwan](https://github.com/mastodon/mastodon/pull/22790)) | ||||||
| - Add `policy` attribute to web push subscription objects in `/api/v1/push/subscriptions` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23210)) | - Add `policy` attribute to web push subscription objects in `/api/v1/push/subscriptions` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23210)) | ||||||
|  | @ -67,8 +69,13 @@ All notable changes to this project will be documented in this file. | ||||||
| - Change confirm prompts for relationships management ([tribela](https://github.com/mastodon/mastodon/pull/19411)) | - Change confirm prompts for relationships management ([tribela](https://github.com/mastodon/mastodon/pull/19411)) | ||||||
| - Change language surrounding disability in prompts for media descriptions ([hs4man21](https://github.com/mastodon/mastodon/pull/20923)) | - Change language surrounding disability in prompts for media descriptions ([hs4man21](https://github.com/mastodon/mastodon/pull/20923)) | ||||||
| - Change confusing wording in the sign in banner ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22490)) | - Change confusing wording in the sign in banner ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22490)) | ||||||
|  | - Change `POST /settings/applications/:id` to regenerate token on scopes change ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23359)) | ||||||
| - Change account moderation notes to make links clickable ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22553)) | - Change account moderation notes to make links clickable ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22553)) | ||||||
|  | - Change link previews for statuses to never use avatar as fallback ([Gargron](https://github.com/mastodon/mastodon/pull/23376)) | ||||||
| - Change email address input to be read-only for logged-in users when requesting a new confirmation e-mail ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23247)) | - Change email address input to be read-only for logged-in users when requesting a new confirmation e-mail ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23247)) | ||||||
|  | - Change notifications per page from 15 to 40 in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/23348)) | ||||||
|  | - Change number of stored items in home feed from 400 to 800 ([Gargron](https://github.com/mastodon/mastodon/pull/23349)) | ||||||
|  | - Change API rate limits from 300/5min per user to 1500/5min per user, 300/5min per app ([Gargron](https://github.com/mastodon/mastodon/pull/23347)) | ||||||
| - Save avatar or header correctly even if the other one fails ([tribela](https://github.com/mastodon/mastodon/pull/18465)) | - Save avatar or header correctly even if the other one fails ([tribela](https://github.com/mastodon/mastodon/pull/18465)) | ||||||
| - Change `referrer-policy` to `same-origin` application-wide ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23014), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/23037)) | - Change `referrer-policy` to `same-origin` application-wide ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23014), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/23037)) | ||||||
| - Add 'private' to `Cache-Control`, match Rails expectations ([daxtens](https://github.com/mastodon/mastodon/pull/20608)) | - Add 'private' to `Cache-Control`, match Rails expectations ([daxtens](https://github.com/mastodon/mastodon/pull/20608)) | ||||||
|  | @ -88,7 +95,7 @@ All notable changes to this project will be documented in this file. | ||||||
| - Allow adding relays in secure mode and limited federation mode ([ineffyble](https://github.com/mastodon/mastodon/pull/22324)) | - Allow adding relays in secure mode and limited federation mode ([ineffyble](https://github.com/mastodon/mastodon/pull/22324)) | ||||||
| - Change timestamps to be displayed using the user's timezone throughout the moderation interface ([FrancisMurillo](https://github.com/mastodon/mastodon/pull/21878), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/22555)) | - Change timestamps to be displayed using the user's timezone throughout the moderation interface ([FrancisMurillo](https://github.com/mastodon/mastodon/pull/21878), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/22555)) | ||||||
| - Change CSP directives on API to be tight and concise ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20960)) | - Change CSP directives on API to be tight and concise ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20960)) | ||||||
| - Change web UI to not autofocus the compose form ([raboof](https://github.com/mastodon/mastodon/pull/16517)) | - Change web UI to not autofocus the compose form ([raboof](https://github.com/mastodon/mastodon/pull/16517), [Akkiesoft](https://github.com/mastodon/mastodon/pull/23094)) | ||||||
| - Change idempotency key handling for posting when database access is slow ([lambda](https://github.com/mastodon/mastodon/pull/21840)) | - Change idempotency key handling for posting when database access is slow ([lambda](https://github.com/mastodon/mastodon/pull/21840)) | ||||||
| - Change remote media files to be downloaded outside of transactions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21796)) | - Change remote media files to be downloaded outside of transactions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21796)) | ||||||
| - Improve contrast of charts in “poll has ended” notifications ([j-f1](https://github.com/mastodon/mastodon/pull/22575)) | - Improve contrast of charts in “poll has ended” notifications ([j-f1](https://github.com/mastodon/mastodon/pull/22575)) | ||||||
|  | @ -101,6 +108,7 @@ All notable changes to this project will be documented in this file. | ||||||
| 
 | 
 | ||||||
| - Officially remove support for Ruby 2.6 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21477)) | - Officially remove support for Ruby 2.6 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21477)) | ||||||
| - Remove `object-fit` polyfill used for old versions of Microsoft Edge ([shuuji3](https://github.com/mastodon/mastodon/pull/22693)) | - Remove `object-fit` polyfill used for old versions of Microsoft Edge ([shuuji3](https://github.com/mastodon/mastodon/pull/22693)) | ||||||
|  | - Remove `intersection-observer` polyfill for old Safari support ([shuuji3](https://github.com/mastodon/mastodon/pull/23284)) | ||||||
| - Remove empty `title` tag from mailer layout ([nametoolong](https://github.com/mastodon/mastodon/pull/23078)) | - Remove empty `title` tag from mailer layout ([nametoolong](https://github.com/mastodon/mastodon/pull/23078)) | ||||||
| 
 | 
 | ||||||
| ### Fixed | ### Fixed | ||||||
|  | @ -110,6 +118,7 @@ All notable changes to this project will be documented in this file. | ||||||
| - Fix possible race conditions when suspending/unsuspending accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22363)) | - Fix possible race conditions when suspending/unsuspending accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22363)) | ||||||
| - Fix being stuck in edit mode when deleting the edited status ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22126)) | - Fix being stuck in edit mode when deleting the edited status ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22126)) | ||||||
| - Fix filters not being applied to some notification types ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23211)) | - Fix filters not being applied to some notification types ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23211)) | ||||||
|  | - Fix incorrect link in push notifications for some event types ([elizabeth-dev](https://github.com/mastodon/mastodon/pull/23286)) | ||||||
| - Fix some performance issues with `/admin/instances` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21907)) | - Fix some performance issues with `/admin/instances` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21907)) | ||||||
| - Fix some pre-4.0 admin audit logs ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22091)) | - Fix some pre-4.0 admin audit logs ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22091)) | ||||||
| - Fix moderation audit log items for warnings having incorrect links ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23242)) | - Fix moderation audit log items for warnings having incorrect links ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23242)) | ||||||
|  | @ -126,6 +135,7 @@ All notable changes to this project will be documented in this file. | ||||||
| - Fix wrong padding in RTL layout ([Gargron](https://github.com/mastodon/mastodon/pull/23157)) | - Fix wrong padding in RTL layout ([Gargron](https://github.com/mastodon/mastodon/pull/23157)) | ||||||
| - Fix drag & drop upload area display in single-column mode ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23217)) | - Fix drag & drop upload area display in single-column mode ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23217)) | ||||||
| - Fix being unable to get a single EmailDomainBlock from the admin API ([trwnh](https://github.com/mastodon/mastodon/pull/20846)) | - Fix being unable to get a single EmailDomainBlock from the admin API ([trwnh](https://github.com/mastodon/mastodon/pull/20846)) | ||||||
|  | - Fix unserialized `role` on account entities in admin API ([Gargron](https://github.com/mastodon/mastodon/pull/23290)) | ||||||
| - Fix pagination of followed tags ([trwnh](https://github.com/mastodon/mastodon/pull/20861)) | - Fix pagination of followed tags ([trwnh](https://github.com/mastodon/mastodon/pull/20861)) | ||||||
| - Fix dropdown menu positions when scrolling ([sidp](https://github.com/mastodon/mastodon/pull/22916), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/23062)) | - Fix dropdown menu positions when scrolling ([sidp](https://github.com/mastodon/mastodon/pull/22916), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/23062)) | ||||||
| - Fix email with empty domain name labels passing validation ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23246)) | - Fix email with empty domain name labels passing validation ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23246)) | ||||||
|  | @ -150,6 +160,7 @@ All notable changes to this project will be documented in this file. | ||||||
| - Fix crash when trying to fetch unobtainable avatar of user using external authentication ([lochiiconnectivity](https://github.com/mastodon/mastodon/pull/22462)) | - Fix crash when trying to fetch unobtainable avatar of user using external authentication ([lochiiconnectivity](https://github.com/mastodon/mastodon/pull/22462)) | ||||||
| - Fix potential duplicate statuses in Explore tab ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22121)) | - Fix potential duplicate statuses in Explore tab ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22121)) | ||||||
| - Fix deprecation warning in `tootctl accounts rotate` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22120)) | - Fix deprecation warning in `tootctl accounts rotate` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22120)) | ||||||
|  | - Fix styling of featured tags in light theme ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23252)) | ||||||
| - Fix missing style in warning and strike cards ([AtelierSnek](https://github.com/mastodon/mastodon/pull/22177), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/22302)) | - Fix missing style in warning and strike cards ([AtelierSnek](https://github.com/mastodon/mastodon/pull/22177), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/22302)) | ||||||
| - Fix wasteful request to `/api/v1/custom_emojis` when not logged in ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22326)) | - Fix wasteful request to `/api/v1/custom_emojis` when not logged in ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22326)) | ||||||
| - Fix replies sometimes being delivered to user-blocked domains ([tribela](https://github.com/mastodon/mastodon/pull/22117)) | - Fix replies sometimes being delivered to user-blocked domains ([tribela](https://github.com/mastodon/mastodon/pull/22117)) | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								Gemfile
									
									
									
									
									
								
							|  | @ -18,7 +18,7 @@ gem 'makara', '~> 0.5' | ||||||
| gem 'pghero' | gem 'pghero' | ||||||
| gem 'dotenv-rails', '~> 2.8' | gem 'dotenv-rails', '~> 2.8' | ||||||
| 
 | 
 | ||||||
| gem 'aws-sdk-s3', '~> 1.117', require: false | gem 'aws-sdk-s3', '~> 1.119', require: false | ||||||
| gem 'fog-core', '<= 2.4.0' | gem 'fog-core', '<= 2.4.0' | ||||||
| gem 'fog-openstack', '~> 0.3', require: false | gem 'fog-openstack', '~> 0.3', require: false | ||||||
| gem 'kt-paperclip', '~> 7.1' | gem 'kt-paperclip', '~> 7.1' | ||||||
|  | @ -40,7 +40,7 @@ end | ||||||
| gem 'net-ldap', '~> 0.17' | gem 'net-ldap', '~> 0.17' | ||||||
| gem 'omniauth-cas', '~> 2.0' | gem 'omniauth-cas', '~> 2.0' | ||||||
| gem 'omniauth-saml', '~> 1.10' | gem 'omniauth-saml', '~> 1.10' | ||||||
| gem 'gitlab-omniauth-openid-connect', '~>0.10.0', require: 'omniauth_openid_connect' | gem 'gitlab-omniauth-openid-connect', '~>0.10.1', require: 'omniauth_openid_connect' | ||||||
| gem 'omniauth', '~> 1.9' | gem 'omniauth', '~> 1.9' | ||||||
| gem 'omniauth-rails_csrf_protection', '~> 0.1' | gem 'omniauth-rails_csrf_protection', '~> 0.1' | ||||||
| 
 | 
 | ||||||
|  | @ -73,7 +73,7 @@ gem 'rack-attack', '~> 6.6' | ||||||
| gem 'rack-cors', '~> 1.1', require: 'rack/cors' | gem 'rack-cors', '~> 1.1', require: 'rack/cors' | ||||||
| gem 'rails-i18n', '~> 6.0' | gem 'rails-i18n', '~> 6.0' | ||||||
| gem 'rails-settings-cached', '~> 0.6' | gem 'rails-settings-cached', '~> 0.6' | ||||||
| gem 'redcarpet', '~> 3.5' | gem 'redcarpet', '~> 3.6' | ||||||
| gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis'] | gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis'] | ||||||
| gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' | gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' | ||||||
| gem 'rqrcode', '~> 2.1' | gem 'rqrcode', '~> 2.1' | ||||||
|  | @ -85,7 +85,7 @@ gem 'sidekiq-scheduler', '~> 4.0' | ||||||
| gem 'sidekiq-unique-jobs', '~> 7.1' | gem 'sidekiq-unique-jobs', '~> 7.1' | ||||||
| gem 'sidekiq-bulk', '~> 0.2.0' | gem 'sidekiq-bulk', '~> 0.2.0' | ||||||
| gem 'simple-navigation', '~> 4.4' | gem 'simple-navigation', '~> 4.4' | ||||||
| gem 'simple_form', '~> 5.1' | gem 'simple_form', '~> 5.2' | ||||||
| gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie' | gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie' | ||||||
| gem 'stoplight', '~> 3.0.1' | gem 'stoplight', '~> 3.0.1' | ||||||
| gem 'strong_migrations', '~> 0.7' | gem 'strong_migrations', '~> 0.7' | ||||||
|  |  | ||||||
							
								
								
									
										166
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										166
									
								
								Gemfile.lock
									
									
									
									
									
								
							|  | @ -10,40 +10,40 @@ GIT | ||||||
| GEM | GEM | ||||||
|   remote: https://rubygems.org/ |   remote: https://rubygems.org/ | ||||||
|   specs: |   specs: | ||||||
|     actioncable (6.1.7.1) |     actioncable (6.1.7.2) | ||||||
|       actionpack (= 6.1.7.1) |       actionpack (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       nio4r (~> 2.0) |       nio4r (~> 2.0) | ||||||
|       websocket-driver (>= 0.6.1) |       websocket-driver (>= 0.6.1) | ||||||
|     actionmailbox (6.1.7.1) |     actionmailbox (6.1.7.2) | ||||||
|       actionpack (= 6.1.7.1) |       actionpack (= 6.1.7.2) | ||||||
|       activejob (= 6.1.7.1) |       activejob (= 6.1.7.2) | ||||||
|       activerecord (= 6.1.7.1) |       activerecord (= 6.1.7.2) | ||||||
|       activestorage (= 6.1.7.1) |       activestorage (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       mail (>= 2.7.1) |       mail (>= 2.7.1) | ||||||
|     actionmailer (6.1.7.1) |     actionmailer (6.1.7.2) | ||||||
|       actionpack (= 6.1.7.1) |       actionpack (= 6.1.7.2) | ||||||
|       actionview (= 6.1.7.1) |       actionview (= 6.1.7.2) | ||||||
|       activejob (= 6.1.7.1) |       activejob (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       mail (~> 2.5, >= 2.5.4) |       mail (~> 2.5, >= 2.5.4) | ||||||
|       rails-dom-testing (~> 2.0) |       rails-dom-testing (~> 2.0) | ||||||
|     actionpack (6.1.7.1) |     actionpack (6.1.7.2) | ||||||
|       actionview (= 6.1.7.1) |       actionview (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       rack (~> 2.0, >= 2.0.9) |       rack (~> 2.0, >= 2.0.9) | ||||||
|       rack-test (>= 0.6.3) |       rack-test (>= 0.6.3) | ||||||
|       rails-dom-testing (~> 2.0) |       rails-dom-testing (~> 2.0) | ||||||
|       rails-html-sanitizer (~> 1.0, >= 1.2.0) |       rails-html-sanitizer (~> 1.0, >= 1.2.0) | ||||||
|     actiontext (6.1.7.1) |     actiontext (6.1.7.2) | ||||||
|       actionpack (= 6.1.7.1) |       actionpack (= 6.1.7.2) | ||||||
|       activerecord (= 6.1.7.1) |       activerecord (= 6.1.7.2) | ||||||
|       activestorage (= 6.1.7.1) |       activestorage (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       nokogiri (>= 1.8.5) |       nokogiri (>= 1.8.5) | ||||||
|     actionview (6.1.7.1) |     actionview (6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       builder (~> 3.1) |       builder (~> 3.1) | ||||||
|       erubi (~> 1.4) |       erubi (~> 1.4) | ||||||
|       rails-dom-testing (~> 2.0) |       rails-dom-testing (~> 2.0) | ||||||
|  | @ -54,22 +54,22 @@ GEM | ||||||
|       case_transform (>= 0.2) |       case_transform (>= 0.2) | ||||||
|       jsonapi-renderer (>= 0.1.1.beta1, < 0.3) |       jsonapi-renderer (>= 0.1.1.beta1, < 0.3) | ||||||
|     active_record_query_trace (1.8) |     active_record_query_trace (1.8) | ||||||
|     activejob (6.1.7.1) |     activejob (6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       globalid (>= 0.3.6) |       globalid (>= 0.3.6) | ||||||
|     activemodel (6.1.7.1) |     activemodel (6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|     activerecord (6.1.7.1) |     activerecord (6.1.7.2) | ||||||
|       activemodel (= 6.1.7.1) |       activemodel (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|     activestorage (6.1.7.1) |     activestorage (6.1.7.2) | ||||||
|       actionpack (= 6.1.7.1) |       actionpack (= 6.1.7.2) | ||||||
|       activejob (= 6.1.7.1) |       activejob (= 6.1.7.2) | ||||||
|       activerecord (= 6.1.7.1) |       activerecord (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       marcel (~> 1.0) |       marcel (~> 1.0) | ||||||
|       mini_mime (>= 1.1.0) |       mini_mime (>= 1.1.0) | ||||||
|     activesupport (6.1.7.1) |     activesupport (6.1.7.2) | ||||||
|       concurrent-ruby (~> 1.0, >= 1.0.2) |       concurrent-ruby (~> 1.0, >= 1.0.2) | ||||||
|       i18n (>= 1.6, < 2) |       i18n (>= 1.6, < 2) | ||||||
|       minitest (>= 5.1) |       minitest (>= 5.1) | ||||||
|  | @ -90,16 +90,16 @@ GEM | ||||||
|     attr_required (1.0.1) |     attr_required (1.0.1) | ||||||
|     awrence (1.2.1) |     awrence (1.2.1) | ||||||
|     aws-eventstream (1.2.0) |     aws-eventstream (1.2.0) | ||||||
|     aws-partitions (1.670.0) |     aws-partitions (1.701.0) | ||||||
|     aws-sdk-core (3.168.2) |     aws-sdk-core (3.170.0) | ||||||
|       aws-eventstream (~> 1, >= 1.0.2) |       aws-eventstream (~> 1, >= 1.0.2) | ||||||
|       aws-partitions (~> 1, >= 1.651.0) |       aws-partitions (~> 1, >= 1.651.0) | ||||||
|       aws-sigv4 (~> 1.5) |       aws-sigv4 (~> 1.5) | ||||||
|       jmespath (~> 1, >= 1.6.1) |       jmespath (~> 1, >= 1.6.1) | ||||||
|     aws-sdk-kms (1.60.0) |     aws-sdk-kms (1.62.0) | ||||||
|       aws-sdk-core (~> 3, >= 3.165.0) |       aws-sdk-core (~> 3, >= 3.165.0) | ||||||
|       aws-sigv4 (~> 1.1) |       aws-sigv4 (~> 1.1) | ||||||
|     aws-sdk-s3 (1.117.2) |     aws-sdk-s3 (1.119.0) | ||||||
|       aws-sdk-core (~> 3, >= 3.165.0) |       aws-sdk-core (~> 3, >= 3.165.0) | ||||||
|       aws-sdk-kms (~> 1) |       aws-sdk-kms (~> 1) | ||||||
|       aws-sigv4 (~> 1.4) |       aws-sigv4 (~> 1.4) | ||||||
|  | @ -117,7 +117,7 @@ GEM | ||||||
|       erubi (~> 1.4) |       erubi (~> 1.4) | ||||||
|       parser (>= 2.4) |       parser (>= 2.4) | ||||||
|       smart_properties |       smart_properties | ||||||
|     bindata (2.4.10) |     bindata (2.4.14) | ||||||
|     binding_of_caller (1.0.0) |     binding_of_caller (1.0.0) | ||||||
|       debug_inspector (>= 0.0.1) |       debug_inspector (>= 0.0.1) | ||||||
|     blurhash (0.1.6) |     blurhash (0.1.6) | ||||||
|  | @ -207,7 +207,7 @@ GEM | ||||||
|     docile (1.4.0) |     docile (1.4.0) | ||||||
|     domain_name (0.5.20190701) |     domain_name (0.5.20190701) | ||||||
|       unf (>= 0.0.5, < 1.0.0) |       unf (>= 0.0.5, < 1.0.0) | ||||||
|     doorkeeper (5.6.2) |     doorkeeper (5.6.3) | ||||||
|       railties (>= 5) |       railties (>= 5) | ||||||
|     dotenv (2.8.1) |     dotenv (2.8.1) | ||||||
|     dotenv-rails (2.8.1) |     dotenv-rails (2.8.1) | ||||||
|  | @ -279,11 +279,11 @@ 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) | ||||||
|     gitlab-omniauth-openid-connect (0.10.0) |     gitlab-omniauth-openid-connect (0.10.1) | ||||||
|       addressable (~> 2.7) |       addressable (~> 2.7) | ||||||
|       omniauth (>= 1.9, < 3) |       omniauth (>= 1.9, < 3) | ||||||
|       openid_connect (~> 1.2) |       openid_connect (~> 1.2) | ||||||
|     globalid (1.0.1) |     globalid (1.1.0) | ||||||
|       activesupport (>= 5.0) |       activesupport (>= 5.0) | ||||||
|     hamlit (2.13.0) |     hamlit (2.13.0) | ||||||
|       temple (>= 0.8.2) |       temple (>= 0.8.2) | ||||||
|  | @ -333,10 +333,11 @@ GEM | ||||||
|     jmespath (1.6.2) |     jmespath (1.6.2) | ||||||
|     json (2.6.3) |     json (2.6.3) | ||||||
|     json-canonicalization (0.3.0) |     json-canonicalization (0.3.0) | ||||||
|     json-jwt (1.14.0) |     json-jwt (1.15.3) | ||||||
|       activesupport (>= 4.2) |       activesupport (>= 4.2) | ||||||
|       aes_key_wrap |       aes_key_wrap | ||||||
|       bindata |       bindata | ||||||
|  |       httpclient | ||||||
|     json-ld (3.2.3) |     json-ld (3.2.3) | ||||||
|       htmlentities (~> 4.3) |       htmlentities (~> 4.3) | ||||||
|       json-canonicalization (~> 0.3) |       json-canonicalization (~> 0.3) | ||||||
|  | @ -418,7 +419,7 @@ GEM | ||||||
|     net-ldap (0.17.1) |     net-ldap (0.17.1) | ||||||
|     net-pop (0.1.2) |     net-pop (0.1.2) | ||||||
|       net-protocol |       net-protocol | ||||||
|     net-protocol (0.1.3) |     net-protocol (0.2.1) | ||||||
|       timeout |       timeout | ||||||
|     net-scp (4.0.0.rc1) |     net-scp (4.0.0.rc1) | ||||||
|       net-ssh (>= 2.6.5, < 8.0.0) |       net-ssh (>= 2.6.5, < 8.0.0) | ||||||
|  | @ -426,7 +427,7 @@ GEM | ||||||
|       net-protocol |       net-protocol | ||||||
|     net-ssh (7.0.1) |     net-ssh (7.0.1) | ||||||
|     nio4r (2.5.8) |     nio4r (2.5.8) | ||||||
|     nokogiri (1.14.0) |     nokogiri (1.14.1) | ||||||
|       mini_portile2 (~> 2.8.0) |       mini_portile2 (~> 2.8.0) | ||||||
|       racc (~> 1.4) |       racc (~> 1.4) | ||||||
|     nsa (0.2.8) |     nsa (0.2.8) | ||||||
|  | @ -448,21 +449,22 @@ GEM | ||||||
|     omniauth-saml (1.10.3) |     omniauth-saml (1.10.3) | ||||||
|       omniauth (~> 1.3, >= 1.3.2) |       omniauth (~> 1.3, >= 1.3.2) | ||||||
|       ruby-saml (~> 1.9) |       ruby-saml (~> 1.9) | ||||||
|     openid_connect (1.3.0) |     openid_connect (1.4.2) | ||||||
|       activemodel |       activemodel | ||||||
|       attr_required (>= 1.0.0) |       attr_required (>= 1.0.0) | ||||||
|       json-jwt (>= 1.5.0) |       json-jwt (>= 1.15.0) | ||||||
|       rack-oauth2 (>= 1.6.1) |       net-smtp | ||||||
|       swd (>= 1.0.0) |       rack-oauth2 (~> 1.21) | ||||||
|  |       swd (~> 1.3) | ||||||
|       tzinfo |       tzinfo | ||||||
|       validate_email |       validate_email | ||||||
|       validate_url |       validate_url | ||||||
|       webfinger (>= 1.0.1) |       webfinger (~> 1.2) | ||||||
|     openssl (3.0.0) |     openssl (3.0.0) | ||||||
|     openssl-signature_algorithm (1.2.1) |     openssl-signature_algorithm (1.2.1) | ||||||
|       openssl (> 2.0, < 3.1) |       openssl (> 2.0, < 3.1) | ||||||
|     orm_adapter (0.5.0) |     orm_adapter (0.5.0) | ||||||
|     ox (2.14.13) |     ox (2.14.14) | ||||||
|     parallel (1.22.1) |     parallel (1.22.1) | ||||||
|     parser (3.2.0.0) |     parser (3.2.0.0) | ||||||
|       ast (~> 2.4.1) |       ast (~> 2.4.1) | ||||||
|  | @ -503,7 +505,7 @@ GEM | ||||||
|       rack (>= 1.0, < 3) |       rack (>= 1.0, < 3) | ||||||
|     rack-cors (1.1.1) |     rack-cors (1.1.1) | ||||||
|       rack (>= 2.0.0) |       rack (>= 2.0.0) | ||||||
|     rack-oauth2 (1.19.0) |     rack-oauth2 (1.21.3) | ||||||
|       activesupport |       activesupport | ||||||
|       attr_required |       attr_required | ||||||
|       httpclient |       httpclient | ||||||
|  | @ -513,20 +515,20 @@ GEM | ||||||
|       rack |       rack | ||||||
|     rack-test (2.0.2) |     rack-test (2.0.2) | ||||||
|       rack (>= 1.3) |       rack (>= 1.3) | ||||||
|     rails (6.1.7.1) |     rails (6.1.7.2) | ||||||
|       actioncable (= 6.1.7.1) |       actioncable (= 6.1.7.2) | ||||||
|       actionmailbox (= 6.1.7.1) |       actionmailbox (= 6.1.7.2) | ||||||
|       actionmailer (= 6.1.7.1) |       actionmailer (= 6.1.7.2) | ||||||
|       actionpack (= 6.1.7.1) |       actionpack (= 6.1.7.2) | ||||||
|       actiontext (= 6.1.7.1) |       actiontext (= 6.1.7.2) | ||||||
|       actionview (= 6.1.7.1) |       actionview (= 6.1.7.2) | ||||||
|       activejob (= 6.1.7.1) |       activejob (= 6.1.7.2) | ||||||
|       activemodel (= 6.1.7.1) |       activemodel (= 6.1.7.2) | ||||||
|       activerecord (= 6.1.7.1) |       activerecord (= 6.1.7.2) | ||||||
|       activestorage (= 6.1.7.1) |       activestorage (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       bundler (>= 1.15.0) |       bundler (>= 1.15.0) | ||||||
|       railties (= 6.1.7.1) |       railties (= 6.1.7.2) | ||||||
|       sprockets-rails (>= 2.0.0) |       sprockets-rails (>= 2.0.0) | ||||||
|     rails-controller-testing (1.0.5) |     rails-controller-testing (1.0.5) | ||||||
|       actionpack (>= 5.0.1.rc1) |       actionpack (>= 5.0.1.rc1) | ||||||
|  | @ -535,16 +537,16 @@ GEM | ||||||
|     rails-dom-testing (2.0.3) |     rails-dom-testing (2.0.3) | ||||||
|       activesupport (>= 4.2.0) |       activesupport (>= 4.2.0) | ||||||
|       nokogiri (>= 1.6) |       nokogiri (>= 1.6) | ||||||
|     rails-html-sanitizer (1.4.4) |     rails-html-sanitizer (1.5.0) | ||||||
|       loofah (~> 2.19, >= 2.19.1) |       loofah (~> 2.19, >= 2.19.1) | ||||||
|     rails-i18n (6.0.0) |     rails-i18n (6.0.0) | ||||||
|       i18n (>= 0.7, < 2) |       i18n (>= 0.7, < 2) | ||||||
|       railties (>= 6.0.0, < 7) |       railties (>= 6.0.0, < 7) | ||||||
|     rails-settings-cached (0.6.6) |     rails-settings-cached (0.6.6) | ||||||
|       rails (>= 4.2.0) |       rails (>= 4.2.0) | ||||||
|     railties (6.1.7.1) |     railties (6.1.7.2) | ||||||
|       actionpack (= 6.1.7.1) |       actionpack (= 6.1.7.2) | ||||||
|       activesupport (= 6.1.7.1) |       activesupport (= 6.1.7.2) | ||||||
|       method_source |       method_source | ||||||
|       rake (>= 12.2) |       rake (>= 12.2) | ||||||
|       thor (~> 1.0) |       thor (~> 1.0) | ||||||
|  | @ -554,7 +556,7 @@ GEM | ||||||
|       link_header (~> 0.0, >= 0.0.8) |       link_header (~> 0.0, >= 0.0.8) | ||||||
|     rdf-normalize (0.5.1) |     rdf-normalize (0.5.1) | ||||||
|       rdf (~> 3.2) |       rdf (~> 3.2) | ||||||
|     redcarpet (3.5.1) |     redcarpet (3.6.0) | ||||||
|     redis (4.5.1) |     redis (4.5.1) | ||||||
|     redis-namespace (1.10.0) |     redis-namespace (1.10.0) | ||||||
|       redis (>= 4) |       redis (>= 4) | ||||||
|  | @ -595,7 +597,7 @@ GEM | ||||||
|     rspec-support (3.11.1) |     rspec-support (3.11.1) | ||||||
|     rspec_junit_formatter (0.6.0) |     rspec_junit_formatter (0.6.0) | ||||||
|       rspec-core (>= 2, < 4, != 2.12.0) |       rspec-core (>= 2, < 4, != 2.12.0) | ||||||
|     rubocop (1.44.0) |     rubocop (1.44.1) | ||||||
|       json (~> 2.3) |       json (~> 2.3) | ||||||
|       parallel (~> 1.10) |       parallel (~> 1.10) | ||||||
|       parser (>= 3.2.0.0) |       parser (>= 3.2.0.0) | ||||||
|  | @ -628,7 +630,7 @@ GEM | ||||||
|       fugit (~> 1.1, >= 1.1.6) |       fugit (~> 1.1, >= 1.1.6) | ||||||
|     safety_net_attestation (0.4.0) |     safety_net_attestation (0.4.0) | ||||||
|       jwt (~> 2.0) |       jwt (~> 2.0) | ||||||
|     sanitize (6.0.0) |     sanitize (6.0.1) | ||||||
|       crass (~> 1.0.2) |       crass (~> 1.0.2) | ||||||
|       nokogiri (>= 1.12.0) |       nokogiri (>= 1.12.0) | ||||||
|     scenic (1.7.0) |     scenic (1.7.0) | ||||||
|  | @ -654,7 +656,7 @@ GEM | ||||||
|       thor (>= 0.20, < 3.0) |       thor (>= 0.20, < 3.0) | ||||||
|     simple-navigation (4.4.0) |     simple-navigation (4.4.0) | ||||||
|       activesupport (>= 2.3.2) |       activesupport (>= 2.3.2) | ||||||
|     simple_form (5.1.0) |     simple_form (5.2.0) | ||||||
|       actionpack (>= 5.2) |       actionpack (>= 5.2) | ||||||
|       activemodel (>= 5.2) |       activemodel (>= 5.2) | ||||||
|     simplecov (0.22.0) |     simplecov (0.22.0) | ||||||
|  | @ -691,7 +693,7 @@ GEM | ||||||
|       climate_control (>= 0.0.3, < 1.0) |       climate_control (>= 0.0.3, < 1.0) | ||||||
|     thor (1.2.1) |     thor (1.2.1) | ||||||
|     tilt (2.0.11) |     tilt (2.0.11) | ||||||
|     timeout (0.3.0) |     timeout (0.3.1) | ||||||
|     tpm-key_attestation (0.11.0) |     tpm-key_attestation (0.11.0) | ||||||
|       bindata (~> 2.4) |       bindata (~> 2.4) | ||||||
|       openssl (> 2.0, < 3.1) |       openssl (> 2.0, < 3.1) | ||||||
|  | @ -709,7 +711,7 @@ GEM | ||||||
|     twitter-text (3.1.0) |     twitter-text (3.1.0) | ||||||
|       idn-ruby |       idn-ruby | ||||||
|       unf (~> 0.1.0) |       unf (~> 0.1.0) | ||||||
|     tzinfo (2.0.5) |     tzinfo (2.0.6) | ||||||
|       concurrent-ruby (~> 1.0) |       concurrent-ruby (~> 1.0) | ||||||
|     tzinfo-data (1.2022.7) |     tzinfo-data (1.2022.7) | ||||||
|       tzinfo (>= 1.0.0) |       tzinfo (>= 1.0.0) | ||||||
|  | @ -764,7 +766,7 @@ DEPENDENCIES | ||||||
|   active_record_query_trace (~> 1.8) |   active_record_query_trace (~> 1.8) | ||||||
|   addressable (~> 2.8) |   addressable (~> 2.8) | ||||||
|   annotate (~> 3.2) |   annotate (~> 3.2) | ||||||
|   aws-sdk-s3 (~> 1.117) |   aws-sdk-s3 (~> 1.119) | ||||||
|   better_errors (~> 2.9) |   better_errors (~> 2.9) | ||||||
|   binding_of_caller (~> 1.0) |   binding_of_caller (~> 1.0) | ||||||
|   blurhash (~> 0.1) |   blurhash (~> 0.1) | ||||||
|  | @ -799,7 +801,7 @@ DEPENDENCIES | ||||||
|   fog-core (<= 2.4.0) |   fog-core (<= 2.4.0) | ||||||
|   fog-openstack (~> 0.3) |   fog-openstack (~> 0.3) | ||||||
|   fuubar (~> 2.5) |   fuubar (~> 2.5) | ||||||
|   gitlab-omniauth-openid-connect (~> 0.10.0) |   gitlab-omniauth-openid-connect (~> 0.10.1) | ||||||
|   hamlit-rails (~> 0.2) |   hamlit-rails (~> 0.2) | ||||||
|   hcaptcha (~> 7.1) |   hcaptcha (~> 7.1) | ||||||
|   hiredis (~> 0.6) |   hiredis (~> 0.6) | ||||||
|  | @ -852,7 +854,7 @@ DEPENDENCIES | ||||||
|   rails-i18n (~> 6.0) |   rails-i18n (~> 6.0) | ||||||
|   rails-settings-cached (~> 0.6) |   rails-settings-cached (~> 0.6) | ||||||
|   rdf-normalize (~> 0.5) |   rdf-normalize (~> 0.5) | ||||||
|   redcarpet (~> 3.5) |   redcarpet (~> 3.6) | ||||||
|   redis (~> 4.5) |   redis (~> 4.5) | ||||||
|   redis-namespace (~> 1.10) |   redis-namespace (~> 1.10) | ||||||
|   rexml (~> 3.2) |   rexml (~> 3.2) | ||||||
|  | @ -872,7 +874,7 @@ DEPENDENCIES | ||||||
|   sidekiq-scheduler (~> 4.0) |   sidekiq-scheduler (~> 4.0) | ||||||
|   sidekiq-unique-jobs (~> 7.1) |   sidekiq-unique-jobs (~> 7.1) | ||||||
|   simple-navigation (~> 4.4) |   simple-navigation (~> 4.4) | ||||||
|   simple_form (~> 5.1) |   simple_form (~> 5.2) | ||||||
|   simplecov (~> 0.22) |   simplecov (~> 0.22) | ||||||
|   sprockets (~> 3.7.2) |   sprockets (~> 3.7.2) | ||||||
|   sprockets-rails (~> 3.4) |   sprockets-rails (~> 3.4) | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ class Api::V1::NotificationsController < Api::BaseController | ||||||
|   before_action :require_user! |   before_action :require_user! | ||||||
|   after_action :insert_pagination_headers, only: :index |   after_action :insert_pagination_headers, only: :index | ||||||
| 
 | 
 | ||||||
|   DEFAULT_NOTIFICATIONS_LIMIT = 15 |   DEFAULT_NOTIFICATIONS_LIMIT = 40 | ||||||
| 
 | 
 | ||||||
|   def index |   def index | ||||||
|     @notifications = load_notifications |     @notifications = load_notifications | ||||||
|  |  | ||||||
|  | @ -29,7 +29,13 @@ class Settings::ApplicationsController < Settings::BaseController | ||||||
| 
 | 
 | ||||||
|   def update |   def update | ||||||
|     if @application.update(application_params) |     if @application.update(application_params) | ||||||
|       redirect_to settings_applications_path, notice: I18n.t('generic.changes_saved_msg') |       if @application.scopes_previously_changed? | ||||||
|  |         @access_token = current_user.token_for_app(@application) | ||||||
|  |         @access_token.destroy | ||||||
|  |         redirect_to settings_application_path(@application), notice: I18n.t('applications.token_regenerated') | ||||||
|  |       else | ||||||
|  |         redirect_to settings_application_path(@application), notice: I18n.t('generic.changes_saved_msg') | ||||||
|  |       end | ||||||
|     else |     else | ||||||
|       render :show |       render :show | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  | @ -199,6 +199,8 @@ module LanguagesHelper | ||||||
|     sco: ['Scots', 'Scots'].freeze, |     sco: ['Scots', 'Scots'].freeze, | ||||||
|     sma: ['Southern Sami', 'Åarjelsaemien Gïele'].freeze, |     sma: ['Southern Sami', 'Åarjelsaemien Gïele'].freeze, | ||||||
|     smj: ['Lule Sami', 'Julevsámegiella'].freeze, |     smj: ['Lule Sami', 'Julevsámegiella'].freeze, | ||||||
|  |     szl: ['Silesian', 'ślůnsko godka'].freeze, | ||||||
|  |     tai: ['Tai', 'ภาษาไท or ภาษาไต'].freeze, | ||||||
|     tok: ['Toki Pona', 'toki pona'].freeze, |     tok: ['Toki Pona', 'toki pona'].freeze, | ||||||
|     zba: ['Balaibalan', 'باليبلن'].freeze, |     zba: ['Balaibalan', 'باليبلن'].freeze, | ||||||
|     zgh: ['Standard Moroccan Tamazight', 'ⵜⴰⵎⴰⵣⵉⵖⵜ'].freeze, |     zgh: ['Standard Moroccan Tamazight', 'ⵜⴰⵎⴰⵣⵉⵖⵜ'].freeze, | ||||||
|  | @ -210,8 +212,10 @@ module LanguagesHelper | ||||||
|   # names, but for some translations, we need the names of the |   # names, but for some translations, we need the names of the | ||||||
|   # regional variants specifically |   # regional variants specifically | ||||||
|   REGIONAL_LOCALE_NAMES = { |   REGIONAL_LOCALE_NAMES = { | ||||||
|  |     'en-GB': 'English (British)', | ||||||
|     'es-AR': 'Español (Argentina)', |     'es-AR': 'Español (Argentina)', | ||||||
|     'es-MX': 'Español (México)', |     'es-MX': 'Español (México)', | ||||||
|  |     'fr-QC': 'Français (Canadien)', | ||||||
|     'pt-BR': 'Português (Brasil)', |     'pt-BR': 'Português (Brasil)', | ||||||
|     'pt-PT': 'Português (Portugal)', |     'pt-PT': 'Português (Portugal)', | ||||||
|     'sr-Latn': 'Srpski (latinica)', |     'sr-Latn': 'Srpski (latinica)', | ||||||
|  |  | ||||||
|  | @ -60,7 +60,7 @@ export function fetchFollowedHashtagsRequest() { | ||||||
|   return { |   return { | ||||||
|     type: FOLLOWED_HASHTAGS_FETCH_REQUEST, |     type: FOLLOWED_HASHTAGS_FETCH_REQUEST, | ||||||
|   }; |   }; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| export function fetchFollowedHashtagsSuccess(followed_tags, next) { | export function fetchFollowedHashtagsSuccess(followed_tags, next) { | ||||||
|   return { |   return { | ||||||
|  | @ -68,14 +68,14 @@ export function fetchFollowedHashtagsSuccess(followed_tags, next) { | ||||||
|     followed_tags, |     followed_tags, | ||||||
|     next, |     next, | ||||||
|   }; |   }; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| export function fetchFollowedHashtagsFail(error) { | export function fetchFollowedHashtagsFail(error) { | ||||||
|   return { |   return { | ||||||
|     type: FOLLOWED_HASHTAGS_FETCH_FAIL, |     type: FOLLOWED_HASHTAGS_FETCH_FAIL, | ||||||
|     error, |     error, | ||||||
|   }; |   }; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| export function expandFollowedHashtags() { | export function expandFollowedHashtags() { | ||||||
|   return (dispatch, getState) => { |   return (dispatch, getState) => { | ||||||
|  | @ -94,13 +94,13 @@ export function expandFollowedHashtags() { | ||||||
|       dispatch(expandFollowedHashtagsFail(error)); |       dispatch(expandFollowedHashtagsFail(error)); | ||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| export function expandFollowedHashtagsRequest() { | export function expandFollowedHashtagsRequest() { | ||||||
|   return { |   return { | ||||||
|     type: FOLLOWED_HASHTAGS_EXPAND_REQUEST, |     type: FOLLOWED_HASHTAGS_EXPAND_REQUEST, | ||||||
|   }; |   }; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| export function expandFollowedHashtagsSuccess(followed_tags, next) { | export function expandFollowedHashtagsSuccess(followed_tags, next) { | ||||||
|   return { |   return { | ||||||
|  | @ -108,14 +108,14 @@ export function expandFollowedHashtagsSuccess(followed_tags, next) { | ||||||
|     followed_tags, |     followed_tags, | ||||||
|     next, |     next, | ||||||
|   }; |   }; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| export function expandFollowedHashtagsFail(error) { | export function expandFollowedHashtagsFail(error) { | ||||||
|   return { |   return { | ||||||
|     type: FOLLOWED_HASHTAGS_EXPAND_FAIL, |     type: FOLLOWED_HASHTAGS_EXPAND_FAIL, | ||||||
|     error, |     error, | ||||||
|   }; |   }; | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| export const followHashtag = name => (dispatch, getState) => { | export const followHashtag = name => (dispatch, getState) => { | ||||||
|   dispatch(followHashtagRequest(name)); |   dispatch(followHashtagRequest(name)); | ||||||
|  |  | ||||||
|  | @ -47,27 +47,27 @@ class Account extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleFollow = () => { |   handleFollow = () => { | ||||||
|     this.props.onFollow(this.props.account); |     this.props.onFollow(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBlock = () => { |   handleBlock = () => { | ||||||
|     this.props.onBlock(this.props.account); |     this.props.onBlock(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMute = () => { |   handleMute = () => { | ||||||
|     this.props.onMute(this.props.account); |     this.props.onMute(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMuteNotifications = () => { |   handleMuteNotifications = () => { | ||||||
|     this.props.onMuteNotifications(this.props.account, true); |     this.props.onMuteNotifications(this.props.account, true); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleUnmuteNotifications = () => { |   handleUnmuteNotifications = () => { | ||||||
|     this.props.onMuteNotifications(this.props.account, false); |     this.props.onMuteNotifications(this.props.account, false); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleAction = () => { |   handleAction = () => { | ||||||
|     this.props.onActionClick(this.props.account); |     this.props.onActionClick(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { account, intl, hidden, onActionClick, actionIcon, actionTitle, defaultAction, size } = this.props; |     const { account, intl, hidden, onActionClick, actionIcon, actionTitle, defaultAction, size } = this.props; | ||||||
|  |  | ||||||
|  | @ -38,13 +38,13 @@ export default class AnimatedNumber extends React.PureComponent { | ||||||
|     const { direction } = this.state; |     const { direction } = this.state; | ||||||
| 
 | 
 | ||||||
|     return { y: -1 * direction }; |     return { y: -1 * direction }; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   willLeave = () => { |   willLeave = () => { | ||||||
|     const { direction } = this.state; |     const { direction } = this.state; | ||||||
| 
 | 
 | ||||||
|     return { y: spring(1 * direction, { damping: 35, stiffness: 400 }) }; |     return { y: spring(1 * direction, { damping: 35, stiffness: 400 }) }; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, obfuscate } = this.props; |     const { value, obfuscate } = this.props; | ||||||
|  |  | ||||||
|  | @ -78,7 +78,7 @@ export default class AutosuggestInput extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.props.onChange(e); |     this.props.onChange(e); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onKeyDown = (e) => { |   onKeyDown = (e) => { | ||||||
|     const { suggestions, disabled } = this.props; |     const { suggestions, disabled } = this.props; | ||||||
|  | @ -136,22 +136,22 @@ export default class AutosuggestInput extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.props.onKeyDown(e); |     this.props.onKeyDown(e); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onBlur = () => { |   onBlur = () => { | ||||||
|     this.setState({ suggestionsHidden: true, focused: false }); |     this.setState({ suggestionsHidden: true, focused: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onFocus = () => { |   onFocus = () => { | ||||||
|     this.setState({ focused: true }); |     this.setState({ focused: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSuggestionClick = (e) => { |   onSuggestionClick = (e) => { | ||||||
|     const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index')); |     const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index')); | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); |     this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); | ||||||
|     this.input.focus(); |     this.input.focus(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillReceiveProps (nextProps) { |   componentWillReceiveProps (nextProps) { | ||||||
|     if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden && this.state.focused) { |     if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden && this.state.focused) { | ||||||
|  | @ -161,7 +161,7 @@ export default class AutosuggestInput extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   setInput = (c) => { |   setInput = (c) => { | ||||||
|     this.input = c; |     this.input = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderSuggestion = (suggestion, i) => { |   renderSuggestion = (suggestion, i) => { | ||||||
|     const { selectedSuggestion } = this.state; |     const { selectedSuggestion } = this.state; | ||||||
|  | @ -183,7 +183,7 @@ export default class AutosuggestInput extends ImmutablePureComponent { | ||||||
|         {inner} |         {inner} | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, className, id, maxLength, lang } = this.props; |     const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, className, id, maxLength, lang } = this.props; | ||||||
|  |  | ||||||
|  | @ -75,7 +75,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.props.onChange(e); |     this.props.onChange(e); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onKeyDown = (e) => { |   onKeyDown = (e) => { | ||||||
|     const { suggestions, disabled } = this.props; |     const { suggestions, disabled } = this.props; | ||||||
|  | @ -133,25 +133,25 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.props.onKeyDown(e); |     this.props.onKeyDown(e); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onBlur = () => { |   onBlur = () => { | ||||||
|     this.setState({ suggestionsHidden: true, focused: false }); |     this.setState({ suggestionsHidden: true, focused: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onFocus = (e) => { |   onFocus = (e) => { | ||||||
|     this.setState({ focused: true }); |     this.setState({ focused: true }); | ||||||
|     if (this.props.onFocus) { |     if (this.props.onFocus) { | ||||||
|       this.props.onFocus(e); |       this.props.onFocus(e); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSuggestionClick = (e) => { |   onSuggestionClick = (e) => { | ||||||
|     const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index')); |     const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index')); | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); |     this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); | ||||||
|     this.textarea.focus(); |     this.textarea.focus(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillReceiveProps (nextProps) { |   componentWillReceiveProps (nextProps) { | ||||||
|     if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden && this.state.focused) { |     if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden && this.state.focused) { | ||||||
|  | @ -161,14 +161,14 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   setTextarea = (c) => { |   setTextarea = (c) => { | ||||||
|     this.textarea = c; |     this.textarea = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onPaste = (e) => { |   onPaste = (e) => { | ||||||
|     if (e.clipboardData && e.clipboardData.files.length === 1) { |     if (e.clipboardData && e.clipboardData.files.length === 1) { | ||||||
|       this.props.onPaste(e.clipboardData.files); |       this.props.onPaste(e.clipboardData.files); | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderSuggestion = (suggestion, i) => { |   renderSuggestion = (suggestion, i) => { | ||||||
|     const { selectedSuggestion } = this.state; |     const { selectedSuggestion } = this.state; | ||||||
|  | @ -190,7 +190,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { | ||||||
|         {inner} |         {inner} | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, lang, children } = this.props; |     const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, lang, children } = this.props; | ||||||
|  |  | ||||||
|  | @ -27,12 +27,12 @@ export default class Avatar extends React.PureComponent { | ||||||
|   handleMouseEnter = () => { |   handleMouseEnter = () => { | ||||||
|     if (this.props.animate) return; |     if (this.props.animate) return; | ||||||
|     this.setState({ hovering: true }); |     this.setState({ hovering: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = () => { |   handleMouseLeave = () => { | ||||||
|     if (this.props.animate) return; |     if (this.props.animate) return; | ||||||
|     this.setState({ hovering: false }); |     this.setState({ hovering: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { account, size, animate, inline } = this.props; |     const { account, size, animate, inline } = this.props; | ||||||
|  |  | ||||||
|  | @ -29,12 +29,12 @@ export default class AvatarOverlay extends React.PureComponent { | ||||||
|   handleMouseEnter = () => { |   handleMouseEnter = () => { | ||||||
|     if (this.props.animate) return; |     if (this.props.animate) return; | ||||||
|     this.setState({ hovering: true }); |     this.setState({ hovering: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = () => { |   handleMouseLeave = () => { | ||||||
|     if (this.props.animate) return; |     if (this.props.animate) return; | ||||||
|     this.setState({ hovering: false }); |     this.setState({ hovering: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { account, friend, animate, size, baseSize, overlaySize } = this.props; |     const { account, friend, animate, size, baseSize, overlaySize } = this.props; | ||||||
|  |  | ||||||
|  | @ -24,11 +24,11 @@ export default class Button extends React.PureComponent { | ||||||
|     if (!this.props.disabled && this.props.onClick) { |     if (!this.props.disabled && this.props.onClick) { | ||||||
|       this.props.onClick(e); |       this.props.onClick(e); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = (c) => { |   setRef = (c) => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   focus() { |   focus() { | ||||||
|     this.node.focus(); |     this.node.focus(); | ||||||
|  |  | ||||||
|  | @ -27,11 +27,11 @@ export default class Column extends React.PureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this._interruptScrollAnimation(); |     this._interruptScrollAnimation(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     if (this.props.bindToDocument) { |     if (this.props.bindToDocument) { | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ export default class ColumnBackButton extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.context.router.history.goBack(); |       this.context.router.history.goBack(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { multiColumn } = this.props; |     const { multiColumn } = this.props; | ||||||
|  |  | ||||||
|  | @ -49,32 +49,32 @@ class ColumnHeader extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.context.router.history.goBack(); |       this.context.router.history.goBack(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleToggleClick = (e) => { |   handleToggleClick = (e) => { | ||||||
|     e.stopPropagation(); |     e.stopPropagation(); | ||||||
|     this.setState({ collapsed: !this.state.collapsed, animating: true }); |     this.setState({ collapsed: !this.state.collapsed, animating: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleTitleClick = () => { |   handleTitleClick = () => { | ||||||
|     this.props.onClick?.(); |     this.props.onClick?.(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMoveLeft = () => { |   handleMoveLeft = () => { | ||||||
|     this.props.onMove(-1); |     this.props.onMove(-1); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMoveRight = () => { |   handleMoveRight = () => { | ||||||
|     this.props.onMove(1); |     this.props.onMove(1); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBackClick = () => { |   handleBackClick = () => { | ||||||
|     this.historyBack(); |     this.historyBack(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleTransitionEnd = () => { |   handleTransitionEnd = () => { | ||||||
|     this.setState({ animating: false }); |     this.setState({ animating: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handlePin = () => { |   handlePin = () => { | ||||||
|     if (!this.props.pinned) { |     if (!this.props.pinned) { | ||||||
|  | @ -82,7 +82,7 @@ class ColumnHeader extends React.PureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.props.onPin(); |     this.props.onPin(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props; |     const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props; | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ class DismissableBanner extends React.PureComponent { | ||||||
|   handleDismiss = () => { |   handleDismiss = () => { | ||||||
|     const { id } = this.props; |     const { id } = this.props; | ||||||
|     this.setState({ visible: false }, () => bannerSettings.set(id, true)); |     this.setState({ visible: false }, () => bannerSettings.set(id, true)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { visible } = this.state; |     const { visible } = this.state; | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ export default class DisplayName extends React.PureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-original'); |       emoji.src = emoji.getAttribute('data-original'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = ({ currentTarget }) => { |   handleMouseLeave = ({ currentTarget }) => { | ||||||
|     if (autoPlayGif) { |     if (autoPlayGif) { | ||||||
|  | @ -36,7 +36,7 @@ export default class DisplayName extends React.PureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-static'); |       emoji.src = emoji.getAttribute('data-static'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { others, localDomain } = this.props; |     const { others, localDomain } = this.props; | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ class Account extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleDomainUnblock = () => { |   handleDomainUnblock = () => { | ||||||
|     this.props.onUnblockDomain(this.props.domain); |     this.props.onUnblockDomain(this.props.domain); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { domain, intl } = this.props; |     const { domain, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ class DropdownMenu extends React.PureComponent { | ||||||
|     if (this.node && !this.node.contains(e.target)) { |     if (this.node && !this.node.contains(e.target)) { | ||||||
|       this.props.onClose(); |       this.props.onClose(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     document.addEventListener('click', this.handleDocumentClick, false); |     document.addEventListener('click', this.handleDocumentClick, false); | ||||||
|  | @ -56,11 +56,11 @@ class DropdownMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setFocusRef = c => { |   setFocusRef = c => { | ||||||
|     this.focusedItem = c; |     this.focusedItem = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = e => { |   handleKeyDown = e => { | ||||||
|     const items = Array.from(this.node.querySelectorAll('a, button')); |     const items = Array.from(this.node.querySelectorAll('a, button')); | ||||||
|  | @ -97,18 +97,18 @@ class DropdownMenu extends React.PureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       e.stopPropagation(); |       e.stopPropagation(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleItemKeyPress = e => { |   handleItemKeyPress = e => { | ||||||
|     if (e.key === 'Enter' || e.key === ' ') { |     if (e.key === 'Enter' || e.key === ' ') { | ||||||
|       this.handleClick(e); |       this.handleClick(e); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = e => { |   handleClick = e => { | ||||||
|     const { onItemClick } = this.props; |     const { onItemClick } = this.props; | ||||||
|     onItemClick(e); |     onItemClick(e); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderItem = (option, i) => { |   renderItem = (option, i) => { | ||||||
|     if (option === null) { |     if (option === null) { | ||||||
|  | @ -124,7 +124,7 @@ class DropdownMenu extends React.PureComponent { | ||||||
|         </a> |         </a> | ||||||
|       </li> |       </li> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { items, scrollable, renderHeader, loading } = this.props; |     const { items, scrollable, renderHeader, loading } = this.props; | ||||||
|  | @ -194,7 +194,7 @@ export default class Dropdown extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.props.onOpen(this.state.id, this.handleItemClick, type !== 'click'); |       this.props.onOpen(this.state.id, this.handleItemClick, type !== 'click'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClose = () => { |   handleClose = () => { | ||||||
|     if (this.activeElement) { |     if (this.activeElement) { | ||||||
|  | @ -202,13 +202,13 @@ export default class Dropdown extends React.PureComponent { | ||||||
|       this.activeElement = null; |       this.activeElement = null; | ||||||
|     } |     } | ||||||
|     this.props.onClose(this.state.id); |     this.props.onClose(this.state.id); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseDown = () => { |   handleMouseDown = () => { | ||||||
|     if (!this.state.open) { |     if (!this.state.open) { | ||||||
|       this.activeElement = document.activeElement; |       this.activeElement = document.activeElement; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleButtonKeyDown = (e) => { |   handleButtonKeyDown = (e) => { | ||||||
|     switch(e.key) { |     switch(e.key) { | ||||||
|  | @ -217,7 +217,7 @@ export default class Dropdown extends React.PureComponent { | ||||||
|       this.handleMouseDown(); |       this.handleMouseDown(); | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyPress = (e) => { |   handleKeyPress = (e) => { | ||||||
|     switch(e.key) { |     switch(e.key) { | ||||||
|  | @ -228,7 +228,7 @@ export default class Dropdown extends React.PureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleItemClick = e => { |   handleItemClick = e => { | ||||||
|     const { onItemClick } = this.props; |     const { onItemClick } = this.props; | ||||||
|  | @ -247,25 +247,25 @@ export default class Dropdown extends React.PureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       this.context.router.history.push(item.to); |       this.context.router.history.push(item.to); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setTargetRef = c => { |   setTargetRef = c => { | ||||||
|     this.target = c; |     this.target = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   findTarget = () => { |   findTarget = () => { | ||||||
|     return this.target; |     return this.target; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillUnmount = () => { |   componentWillUnmount = () => { | ||||||
|     if (this.state.id === this.props.openDropdownId) { |     if (this.state.id === this.props.openDropdownId) { | ||||||
|       this.handleClose(); |       this.handleClose(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   close = () => { |   close = () => { | ||||||
|     this.handleClose(); |     this.handleClose(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { |     const { | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ class EditedTimestamp extends React.PureComponent { | ||||||
|     return ( |     return ( | ||||||
|       <FormattedMessage id='status.edited_x_times' defaultMessage='Edited {count, plural, one {{count} time} other {{count} times}}' values={{ count: items.size - 1 }} /> |       <FormattedMessage id='status.edited_x_times' defaultMessage='Edited {count, plural, one {{count} time} other {{count} times}}' values={{ count: items.size - 1 }} /> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderItem = (item, index, { onClick, onKeyPress }) => { |   renderItem = (item, index, { onClick, onKeyPress }) => { | ||||||
|     const formattedDate = <RelativeTimestamp timestamp={item.get('created_at')} short={false} />; |     const formattedDate = <RelativeTimestamp timestamp={item.get('created_at')} short={false} />; | ||||||
|  | @ -53,7 +53,7 @@ class EditedTimestamp extends React.PureComponent { | ||||||
|         <button data-index={index} onClick={onClick} onKeyPress={onKeyPress}>{label}</button> |         <button data-index={index} onClick={onClick} onKeyPress={onKeyPress}>{label}</button> | ||||||
|       </li> |       </li> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { timestamp, intl, statusId } = this.props; |     const { timestamp, intl, statusId } = this.props; | ||||||
|  |  | ||||||
|  | @ -64,7 +64,7 @@ export default class ErrorBoundary extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     this.setState({ copied: true }); |     this.setState({ copied: true }); | ||||||
|     setTimeout(() => this.setState({ copied: false }), 700); |     setTimeout(() => this.setState({ copied: false }), 700); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { hasError, copied, errorMessage } = this.state; |     const { hasError, copied, errorMessage } = this.state; | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ export default class GIFV extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleLoadedData = () => { |   handleLoadedData = () => { | ||||||
|     this.setState({ loading: false }); |     this.setState({ loading: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillReceiveProps (nextProps) { |   componentWillReceiveProps (nextProps) { | ||||||
|     if (nextProps.src !== this.props.src) { |     if (nextProps.src !== this.props.src) { | ||||||
|  | @ -32,7 +32,7 @@ export default class GIFV extends React.PureComponent { | ||||||
|       e.stopPropagation(); |       e.stopPropagation(); | ||||||
|       onClick(); |       onClick(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { src, width, height, alt } = this.props; |     const { src, width, height, alt } = this.props; | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ export default class IconButton extends React.PureComponent { | ||||||
|   state = { |   state = { | ||||||
|     activate: false, |     activate: false, | ||||||
|     deactivate: false, |     deactivate: false, | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillReceiveProps (nextProps) { |   componentWillReceiveProps (nextProps) { | ||||||
|     if (!nextProps.animate) return; |     if (!nextProps.animate) return; | ||||||
|  | @ -61,25 +61,25 @@ export default class IconButton extends React.PureComponent { | ||||||
|     if (!this.props.disabled) { |     if (!this.props.disabled) { | ||||||
|       this.props.onClick(e); |       this.props.onClick(e); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyPress = (e) => { |   handleKeyPress = (e) => { | ||||||
|     if (this.props.onKeyPress && !this.props.disabled) { |     if (this.props.onKeyPress && !this.props.disabled) { | ||||||
|       this.props.onKeyPress(e); |       this.props.onKeyPress(e); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseDown = (e) => { |   handleMouseDown = (e) => { | ||||||
|     if (!this.props.disabled && this.props.onMouseDown) { |     if (!this.props.disabled && this.props.onMouseDown) { | ||||||
|       this.props.onMouseDown(e); |       this.props.onMouseDown(e); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = (e) => { |   handleKeyDown = (e) => { | ||||||
|     if (!this.props.disabled && this.props.onKeyDown) { |     if (!this.props.disabled && this.props.onKeyDown) { | ||||||
|       this.props.onKeyDown(e); |       this.props.onKeyDown(e); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const style = { |     const style = { | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ export default class IntersectionObserverArticle extends React.Component { | ||||||
| 
 | 
 | ||||||
|   state = { |   state = { | ||||||
|     isHidden: false, // set to true in requestIdleCallback to trigger un-render
 |     isHidden: false, // set to true in requestIdleCallback to trigger un-render
 | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   shouldComponentUpdate (nextProps, nextState) { |   shouldComponentUpdate (nextProps, nextState) { | ||||||
|     const isUnrendered = !this.state.isIntersecting && (this.state.isHidden || this.props.cachedHeight); |     const isUnrendered = !this.state.isIntersecting && (this.state.isHidden || this.props.cachedHeight); | ||||||
|  | @ -62,7 +62,7 @@ export default class IntersectionObserverArticle extends React.Component { | ||||||
| 
 | 
 | ||||||
|     scheduleIdleTask(this.calculateHeight); |     scheduleIdleTask(this.calculateHeight); | ||||||
|     this.setState(this.updateStateAfterIntersection); |     this.setState(this.updateStateAfterIntersection); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   updateStateAfterIntersection = (prevState) => { |   updateStateAfterIntersection = (prevState) => { | ||||||
|     if (prevState.isIntersecting !== false && !this.entry.isIntersecting) { |     if (prevState.isIntersecting !== false && !this.entry.isIntersecting) { | ||||||
|  | @ -72,7 +72,7 @@ export default class IntersectionObserverArticle extends React.Component { | ||||||
|       isIntersecting: this.entry.isIntersecting, |       isIntersecting: this.entry.isIntersecting, | ||||||
|       isHidden: false, |       isHidden: false, | ||||||
|     }; |     }; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   calculateHeight = () => { |   calculateHeight = () => { | ||||||
|     const { onHeightChange, saveHeightKey, id } = this.props; |     const { onHeightChange, saveHeightKey, id } = this.props; | ||||||
|  | @ -83,7 +83,7 @@ export default class IntersectionObserverArticle extends React.Component { | ||||||
|     if (onHeightChange && saveHeightKey) { |     if (onHeightChange && saveHeightKey) { | ||||||
|       onHeightChange(saveHeightKey, id, this.height); |       onHeightChange(saveHeightKey, id, this.height); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   hideIfNotIntersecting = () => { |   hideIfNotIntersecting = () => { | ||||||
|     if (!this.componentMounted) { |     if (!this.componentMounted) { | ||||||
|  | @ -95,11 +95,11 @@ export default class IntersectionObserverArticle extends React.Component { | ||||||
|     // this is to save DOM nodes and avoid using up too much memory.
 |     // this is to save DOM nodes and avoid using up too much memory.
 | ||||||
|     // See: https://github.com/mastodon/mastodon/issues/2900
 |     // See: https://github.com/mastodon/mastodon/issues/2900
 | ||||||
|     this.setState((prevState) => ({ isHidden: !prevState.isIntersecting })); |     this.setState((prevState) => ({ isHidden: !prevState.isIntersecting })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleRef = (node) => { |   handleRef = (node) => { | ||||||
|     this.node = node; |     this.node = node; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { children, id, index, listLength, cachedHeight } = this.props; |     const { children, id, index, listLength, cachedHeight } = this.props; | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ class LoadGap extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     this.props.onClick(this.props.maxId); |     this.props.onClick(this.props.maxId); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { disabled, intl } = this.props; |     const { disabled, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -8,11 +8,11 @@ export default class LoadMore extends React.PureComponent { | ||||||
|     onClick: PropTypes.func, |     onClick: PropTypes.func, | ||||||
|     disabled: PropTypes.bool, |     disabled: PropTypes.bool, | ||||||
|     visible: PropTypes.bool, |     visible: PropTypes.bool, | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   static defaultProps = { |   static defaultProps = { | ||||||
|     visible: true, |     visible: true, | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { disabled, visible } = this.props; |     const { disabled, visible } = this.props; | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ export default class LoadPending extends React.PureComponent { | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|     onClick: PropTypes.func, |     onClick: PropTypes.func, | ||||||
|     count: PropTypes.number, |     count: PropTypes.number, | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { count } = this.props; |     const { count } = this.props; | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ export default class MediaAttachments extends ImmutablePureComponent { | ||||||
|     return ( |     return ( | ||||||
|       <div className='media-gallery' style={{ height, width }} /> |       <div className='media-gallery' style={{ height, width }} /> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderLoadingVideoPlayer = () => { |   renderLoadingVideoPlayer = () => { | ||||||
|     const { height, width } = this.props; |     const { height, width } = this.props; | ||||||
|  | @ -37,7 +37,7 @@ export default class MediaAttachments extends ImmutablePureComponent { | ||||||
|     return ( |     return ( | ||||||
|       <div className='video-player' style={{ height, width }} /> |       <div className='video-player' style={{ height, width }} /> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderLoadingAudioPlayer = () => { |   renderLoadingAudioPlayer = () => { | ||||||
|     const { height, width } = this.props; |     const { height, width } = this.props; | ||||||
|  | @ -45,7 +45,7 @@ export default class MediaAttachments extends ImmutablePureComponent { | ||||||
|     return ( |     return ( | ||||||
|       <div className='audio-player' style={{ height, width }} /> |       <div className='audio-player' style={{ height, width }} /> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { status, width, height } = this.props; |     const { status, width, height } = this.props; | ||||||
|  |  | ||||||
|  | @ -40,14 +40,14 @@ class Item extends React.PureComponent { | ||||||
|     if (this.hoverToPlay()) { |     if (this.hoverToPlay()) { | ||||||
|       e.target.play(); |       e.target.play(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = (e) => { |   handleMouseLeave = (e) => { | ||||||
|     if (this.hoverToPlay()) { |     if (this.hoverToPlay()) { | ||||||
|       e.target.pause(); |       e.target.pause(); | ||||||
|       e.target.currentTime = 0; |       e.target.currentTime = 0; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getAutoPlay() { |   getAutoPlay() { | ||||||
|     return this.props.autoplay || autoPlayGif; |     return this.props.autoplay || autoPlayGif; | ||||||
|  | @ -71,11 +71,11 @@ class Item extends React.PureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     e.stopPropagation(); |     e.stopPropagation(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleImageLoad = () => { |   handleImageLoad = () => { | ||||||
|     this.setState({ loaded: true }); |     this.setState({ loaded: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { attachment, index, size, standalone, displayWidth, visible } = this.props; |     const { attachment, index, size, standalone, displayWidth, visible } = this.props; | ||||||
|  | @ -277,11 +277,11 @@ class MediaGallery extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.setState({ visible: !this.state.visible }); |       this.setState({ visible: !this.state.visible }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = (index) => { |   handleClick = (index) => { | ||||||
|     this.props.onOpenMedia(this.props.media, index); |     this.props.onOpenMedia(this.props.media, index); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleRef = c => { |   handleRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|  | @ -289,7 +289,7 @@ class MediaGallery extends React.PureComponent { | ||||||
|     if (this.node) { |     if (this.node) { | ||||||
|       this._setDimensions(); |       this._setDimensions(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _setDimensions () { |   _setDimensions () { | ||||||
|     const width = this.node.offsetWidth; |     const width = this.node.offsetWidth; | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ export default class ModalRoot extends React.PureComponent { | ||||||
|          && !!this.props.children) { |          && !!this.props.children) { | ||||||
|       this.props.onClose(); |       this.props.onClose(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = (e) => { |   handleKeyDown = (e) => { | ||||||
|     if (e.key === 'Tab') { |     if (e.key === 'Tab') { | ||||||
|  | @ -49,7 +49,7 @@ export default class ModalRoot extends React.PureComponent { | ||||||
|         e.preventDefault(); |         e.preventDefault(); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     window.addEventListener('keyup', this.handleKeyUp, false); |     window.addEventListener('keyup', this.handleKeyUp, false); | ||||||
|  | @ -122,11 +122,11 @@ export default class ModalRoot extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   getSiblings = () => { |   getSiblings = () => { | ||||||
|     return Array(...this.node.parentElement.childNodes).filter(node => node !== this.node); |     return Array(...this.node.parentElement.childNodes).filter(node => node !== this.node); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = ref => { |   setRef = ref => { | ||||||
|     this.node = ref; |     this.node = ref; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { children, onClose } = this.props; |     const { children, onClose } = this.props; | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ class PictureInPicturePlaceholder extends React.PureComponent { | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|     dispatch(removePictureInPicture()); |     dispatch(removePictureInPicture()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|  | @ -30,7 +30,7 @@ class PictureInPicturePlaceholder extends React.PureComponent { | ||||||
|     if (this.node) { |     if (this.node) { | ||||||
|       this._setDimensions(); |       this._setDimensions(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _setDimensions () { |   _setDimensions () { | ||||||
|     const width  = this.node.offsetWidth; |     const width  = this.node.offsetWidth; | ||||||
|  |  | ||||||
|  | @ -95,7 +95,7 @@ class Poll extends ImmutablePureComponent { | ||||||
|       tmp[value] = true; |       tmp[value] = true; | ||||||
|       this.setState({ selected: tmp }); |       this.setState({ selected: tmp }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOptionChange = ({ target: { value } }) => { |   handleOptionChange = ({ target: { value } }) => { | ||||||
|     this._toggleOption(value); |     this._toggleOption(value); | ||||||
|  | @ -107,7 +107,7 @@ class Poll extends ImmutablePureComponent { | ||||||
|       e.stopPropagation(); |       e.stopPropagation(); | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleVote = () => { |   handleVote = () => { | ||||||
|     if (this.props.disabled) { |     if (this.props.disabled) { | ||||||
|  |  | ||||||
|  | @ -97,7 +97,7 @@ class ScrollableList extends PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       return this.node; |       return this.node; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setScrollTop = newScrollTop => { |   setScrollTop = newScrollTop => { | ||||||
|     if (this.getScrollTop() !== newScrollTop) { |     if (this.getScrollTop() !== newScrollTop) { | ||||||
|  | @ -143,7 +143,7 @@ class ScrollableList extends PureComponent { | ||||||
| 
 | 
 | ||||||
|     this.mouseMovedRecently = false; |     this.mouseMovedRecently = false; | ||||||
|     this.scrollToTopOnMouseIdle = false; |     this.scrollToTopOnMouseIdle = false; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     this.attachScrollListener(); |     this.attachScrollListener(); | ||||||
|  | @ -161,25 +161,25 @@ class ScrollableList extends PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       return null; |       return null; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getScrollTop = () => { |   getScrollTop = () => { | ||||||
|     return this._getScrollingElement().scrollTop; |     return this._getScrollingElement().scrollTop; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getScrollHeight = () => { |   getScrollHeight = () => { | ||||||
|     return this._getScrollingElement().scrollHeight; |     return this._getScrollingElement().scrollHeight; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getClientHeight = () => { |   getClientHeight = () => { | ||||||
|     return this._getScrollingElement().clientHeight; |     return this._getScrollingElement().clientHeight; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   updateScrollBottom = (snapshot) => { |   updateScrollBottom = (snapshot) => { | ||||||
|     const newScrollTop = this.getScrollHeight() - snapshot; |     const newScrollTop = this.getScrollHeight() - snapshot; | ||||||
| 
 | 
 | ||||||
|     this.setScrollTop(newScrollTop); |     this.setScrollTop(newScrollTop); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getSnapshotBeforeUpdate (prevProps) { |   getSnapshotBeforeUpdate (prevProps) { | ||||||
|     const someItemInserted = React.Children.count(prevProps.children) > 0 && |     const someItemInserted = React.Children.count(prevProps.children) > 0 && | ||||||
|  | @ -206,7 +206,7 @@ class ScrollableList extends PureComponent { | ||||||
|     if (width && this.state.cachedMediaWidth !== width) { |     if (width && this.state.cachedMediaWidth !== width) { | ||||||
|       this.setState({ cachedMediaWidth: width }); |       this.setState({ cachedMediaWidth: width }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillUnmount () { |   componentWillUnmount () { | ||||||
|     this.clearMouseIdleTimer(); |     this.clearMouseIdleTimer(); | ||||||
|  | @ -218,7 +218,7 @@ class ScrollableList extends PureComponent { | ||||||
| 
 | 
 | ||||||
|   onFullScreenChange = () => { |   onFullScreenChange = () => { | ||||||
|     this.setState({ fullscreen: isFullscreen() }); |     this.setState({ fullscreen: isFullscreen() }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   attachIntersectionObserver () { |   attachIntersectionObserver () { | ||||||
|     let nodeOptions = { |     let nodeOptions = { | ||||||
|  | @ -269,12 +269,12 @@ class ScrollableList extends PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = (c) => { |   setRef = (c) => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = e => { |   handleLoadMore = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     this.props.onLoadMore(); |     this.props.onLoadMore(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadPending = e => { |   handleLoadPending = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|  | @ -286,7 +286,7 @@ class ScrollableList extends PureComponent { | ||||||
|     this.clearMouseIdleTimer(); |     this.clearMouseIdleTimer(); | ||||||
|     this.mouseIdleTimer = setTimeout(this.handleMouseIdle, MOUSE_IDLE_DELAY); |     this.mouseIdleTimer = setTimeout(this.handleMouseIdle, MOUSE_IDLE_DELAY); | ||||||
|     this.mouseMovedRecently = true; |     this.mouseMovedRecently = true; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { children, scrollKey, trackScroll, showLoading, isLoading, hasMore, numPending, prepend, alwaysPrepend, append, emptyMessage, onLoadMore } = this.props; |     const { children, scrollKey, trackScroll, showLoading, isLoading, hasMore, numPending, prepend, alwaysPrepend, append, emptyMessage, onLoadMore } = this.props; | ||||||
|  |  | ||||||
|  | @ -135,7 +135,7 @@ class Status extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleToggleMediaVisibility = () => { |   handleToggleMediaVisibility = () => { | ||||||
|     this.setState({ showMedia: !this.state.showMedia }); |     this.setState({ showMedia: !this.state.showMedia }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = e => { |   handleClick = e => { | ||||||
|     if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) { |     if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) { | ||||||
|  | @ -147,11 +147,11 @@ class Status extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.handleHotkeyOpen(); |     this.handleHotkeyOpen(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handlePrependAccountClick = e => { |   handlePrependAccountClick = e => { | ||||||
|     this.handleAccountClick(e, false); |     this.handleAccountClick(e, false); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleAccountClick = (e, proper = true) => { |   handleAccountClick = (e, proper = true) => { | ||||||
|     if (e && (e.button !== 0 || e.ctrlKey || e.metaKey))  { |     if (e && (e.button !== 0 || e.ctrlKey || e.metaKey))  { | ||||||
|  | @ -163,19 +163,19 @@ class Status extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this._openProfile(proper); |     this._openProfile(proper); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleExpandedToggle = () => { |   handleExpandedToggle = () => { | ||||||
|     this.props.onToggleHidden(this._properStatus()); |     this.props.onToggleHidden(this._properStatus()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleCollapsedToggle = isCollapsed => { |   handleCollapsedToggle = isCollapsed => { | ||||||
|     this.props.onToggleCollapsed(this._properStatus(), isCollapsed); |     this.props.onToggleCollapsed(this._properStatus(), isCollapsed); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleTranslate = () => { |   handleTranslate = () => { | ||||||
|     this.props.onTranslate(this._properStatus()); |     this.props.onTranslate(this._properStatus()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderLoadingMediaGallery () { |   renderLoadingMediaGallery () { | ||||||
|     return <div className='media-gallery' style={{ height: '110px' }} />; |     return <div className='media-gallery' style={{ height: '110px' }} />; | ||||||
|  | @ -192,11 +192,11 @@ class Status extends ImmutablePureComponent { | ||||||
|   handleOpenVideo = (options) => { |   handleOpenVideo = (options) => { | ||||||
|     const status = this._properStatus(); |     const status = this._properStatus(); | ||||||
|     this.props.onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), options); |     this.props.onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), options); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOpenMedia = (media, index) => { |   handleOpenMedia = (media, index) => { | ||||||
|     this.props.onOpenMedia(this._properStatus().get('id'), media, index); |     this.props.onOpenMedia(this._properStatus().get('id'), media, index); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyOpenMedia = e => { |   handleHotkeyOpenMedia = e => { | ||||||
|     const { onOpenMedia, onOpenVideo } = this.props; |     const { onOpenMedia, onOpenVideo } = this.props; | ||||||
|  | @ -211,32 +211,32 @@ class Status extends ImmutablePureComponent { | ||||||
|         onOpenMedia(status.get('id'), status.get('media_attachments'), 0); |         onOpenMedia(status.get('id'), status.get('media_attachments'), 0); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleDeployPictureInPicture = (type, mediaProps) => { |   handleDeployPictureInPicture = (type, mediaProps) => { | ||||||
|     const { deployPictureInPicture } = this.props; |     const { deployPictureInPicture } = this.props; | ||||||
|     const status = this._properStatus(); |     const status = this._properStatus(); | ||||||
| 
 | 
 | ||||||
|     deployPictureInPicture(status, type, mediaProps); |     deployPictureInPicture(status, type, mediaProps); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyReply = e => { |   handleHotkeyReply = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     this.props.onReply(this._properStatus(), this.context.router.history); |     this.props.onReply(this._properStatus(), this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyFavourite = () => { |   handleHotkeyFavourite = () => { | ||||||
|     this.props.onFavourite(this._properStatus()); |     this.props.onFavourite(this._properStatus()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyBoost = e => { |   handleHotkeyBoost = e => { | ||||||
|     this.props.onReblog(this._properStatus(), e); |     this.props.onReblog(this._properStatus(), e); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyMention = e => { |   handleHotkeyMention = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     this.props.onMention(this._properStatus().get('account'), this.context.router.history); |     this.props.onMention(this._properStatus().get('account'), this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyOpen = () => { |   handleHotkeyOpen = () => { | ||||||
|     if (this.props.onClick) { |     if (this.props.onClick) { | ||||||
|  | @ -252,11 +252,11 @@ class Status extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); |     router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyOpenProfile = () => { |   handleHotkeyOpenProfile = () => { | ||||||
|     this._openProfile(); |     this._openProfile(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _openProfile = (proper = true) => { |   _openProfile = (proper = true) => { | ||||||
|     const { router } = this.context; |     const { router } = this.context; | ||||||
|  | @ -267,32 +267,32 @@ class Status extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     router.history.push(`/@${status.getIn(['account', 'acct'])}`); |     router.history.push(`/@${status.getIn(['account', 'acct'])}`); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyMoveUp = e => { |   handleHotkeyMoveUp = e => { | ||||||
|     this.props.onMoveUp(this.props.status.get('id'), e.target.getAttribute('data-featured')); |     this.props.onMoveUp(this.props.status.get('id'), e.target.getAttribute('data-featured')); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyMoveDown = e => { |   handleHotkeyMoveDown = e => { | ||||||
|     this.props.onMoveDown(this.props.status.get('id'), e.target.getAttribute('data-featured')); |     this.props.onMoveDown(this.props.status.get('id'), e.target.getAttribute('data-featured')); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyToggleHidden = () => { |   handleHotkeyToggleHidden = () => { | ||||||
|     this.props.onToggleHidden(this._properStatus()); |     this.props.onToggleHidden(this._properStatus()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyToggleSensitive = () => { |   handleHotkeyToggleSensitive = () => { | ||||||
|     this.handleToggleMediaVisibility(); |     this.handleToggleMediaVisibility(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleUnfilterClick = e => { |   handleUnfilterClick = e => { | ||||||
|     this.setState({ forceFilter: false }); |     this.setState({ forceFilter: false }); | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleFilterClick = () => { |   handleFilterClick = () => { | ||||||
|     this.setState({ forceFilter: true }); |     this.setState({ forceFilter: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _properStatus () { |   _properStatus () { | ||||||
|     const { status } = this.props; |     const { status } = this.props; | ||||||
|  | @ -306,7 +306,7 @@ class Status extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleRef = c => { |   handleRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     let media = null; |     let media = null; | ||||||
|  |  | ||||||
|  | @ -97,7 +97,7 @@ class StatusActionBar extends ImmutablePureComponent { | ||||||
|     'status', |     'status', | ||||||
|     'relationship', |     'relationship', | ||||||
|     'withDismiss', |     'withDismiss', | ||||||
|   ] |   ]; | ||||||
| 
 | 
 | ||||||
|   handleReplyClick = () => { |   handleReplyClick = () => { | ||||||
|     const { signedIn } = this.context.identity; |     const { signedIn } = this.context.identity; | ||||||
|  | @ -107,7 +107,7 @@ class StatusActionBar extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.props.onInteractionModal('reply', this.props.status); |       this.props.onInteractionModal('reply', this.props.status); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleShareClick = () => { |   handleShareClick = () => { | ||||||
|     navigator.share({ |     navigator.share({ | ||||||
|  | @ -116,7 +116,7 @@ class StatusActionBar extends ImmutablePureComponent { | ||||||
|     }).catch((e) => { |     }).catch((e) => { | ||||||
|       if (e.name !== 'AbortError') console.error(e); |       if (e.name !== 'AbortError') console.error(e); | ||||||
|     }); |     }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleFavouriteClick = () => { |   handleFavouriteClick = () => { | ||||||
|     const { signedIn } = this.context.identity; |     const { signedIn } = this.context.identity; | ||||||
|  | @ -126,7 +126,7 @@ class StatusActionBar extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.props.onInteractionModal('favourite', this.props.status); |       this.props.onInteractionModal('favourite', this.props.status); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleReblogClick = e => { |   handleReblogClick = e => { | ||||||
|     const { signedIn } = this.context.identity; |     const { signedIn } = this.context.identity; | ||||||
|  | @ -136,35 +136,35 @@ class StatusActionBar extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.props.onInteractionModal('reblog', this.props.status); |       this.props.onInteractionModal('reblog', this.props.status); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBookmarkClick = () => { |   handleBookmarkClick = () => { | ||||||
|     this.props.onBookmark(this.props.status); |     this.props.onBookmark(this.props.status); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleDeleteClick = () => { |   handleDeleteClick = () => { | ||||||
|     this.props.onDelete(this.props.status, this.context.router.history); |     this.props.onDelete(this.props.status, this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleRedraftClick = () => { |   handleRedraftClick = () => { | ||||||
|     this.props.onDelete(this.props.status, this.context.router.history, true); |     this.props.onDelete(this.props.status, this.context.router.history, true); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleEditClick = () => { |   handleEditClick = () => { | ||||||
|     this.props.onEdit(this.props.status, this.context.router.history); |     this.props.onEdit(this.props.status, this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handlePinClick = () => { |   handlePinClick = () => { | ||||||
|     this.props.onPin(this.props.status); |     this.props.onPin(this.props.status); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMentionClick = () => { |   handleMentionClick = () => { | ||||||
|     this.props.onMention(this.props.status.get('account'), this.context.router.history); |     this.props.onMention(this.props.status.get('account'), this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleDirectClick = () => { |   handleDirectClick = () => { | ||||||
|     this.props.onDirect(this.props.status.get('account'), this.context.router.history); |     this.props.onDirect(this.props.status.get('account'), this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMuteClick = () => { |   handleMuteClick = () => { | ||||||
|     const { status, relationship, onMute, onUnmute } = this.props; |     const { status, relationship, onMute, onUnmute } = this.props; | ||||||
|  | @ -175,7 +175,7 @@ class StatusActionBar extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       onMute(account); |       onMute(account); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBlockClick = () => { |   handleBlockClick = () => { | ||||||
|     const { status, relationship, onBlock, onUnblock } = this.props; |     const { status, relationship, onBlock, onUnblock } = this.props; | ||||||
|  | @ -186,50 +186,50 @@ class StatusActionBar extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       onBlock(status); |       onBlock(status); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBlockDomain = () => { |   handleBlockDomain = () => { | ||||||
|     const { status, onBlockDomain } = this.props; |     const { status, onBlockDomain } = this.props; | ||||||
|     const account = status.get('account'); |     const account = status.get('account'); | ||||||
| 
 | 
 | ||||||
|     onBlockDomain(account.get('acct').split('@')[1]); |     onBlockDomain(account.get('acct').split('@')[1]); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleUnblockDomain = () => { |   handleUnblockDomain = () => { | ||||||
|     const { status, onUnblockDomain } = this.props; |     const { status, onUnblockDomain } = this.props; | ||||||
|     const account = status.get('account'); |     const account = status.get('account'); | ||||||
| 
 | 
 | ||||||
|     onUnblockDomain(account.get('acct').split('@')[1]); |     onUnblockDomain(account.get('acct').split('@')[1]); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOpen = () => { |   handleOpen = () => { | ||||||
|     this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`); |     this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleEmbed = () => { |   handleEmbed = () => { | ||||||
|     this.props.onEmbed(this.props.status); |     this.props.onEmbed(this.props.status); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleReport = () => { |   handleReport = () => { | ||||||
|     this.props.onReport(this.props.status); |     this.props.onReport(this.props.status); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleConversationMuteClick = () => { |   handleConversationMuteClick = () => { | ||||||
|     this.props.onMuteConversation(this.props.status); |     this.props.onMuteConversation(this.props.status); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleFilterClick = () => { |   handleFilterClick = () => { | ||||||
|     this.props.onAddFilter(this.props.status); |     this.props.onAddFilter(this.props.status); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleCopy = () => { |   handleCopy = () => { | ||||||
|     const url = this.props.status.get('url'); |     const url = this.props.status.get('url'); | ||||||
|     navigator.clipboard.writeText(url); |     navigator.clipboard.writeText(url); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHideClick = () => { |   handleHideClick = () => { | ||||||
|     this.props.onFilter(); |     this.props.onFilter(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { status, relationship, intl, withDismiss, withCounters, scrollKey } = this.props; |     const { status, relationship, intl, withDismiss, withCounters, scrollKey } = this.props; | ||||||
|  |  | ||||||
|  | @ -130,7 +130,7 @@ class StatusContent extends React.PureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-original'); |       emoji.src = emoji.getAttribute('data-original'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = ({ currentTarget }) => { |   handleMouseLeave = ({ currentTarget }) => { | ||||||
|     if (autoPlayGif) { |     if (autoPlayGif) { | ||||||
|  | @ -143,7 +143,7 @@ class StatusContent extends React.PureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-static'); |       emoji.src = emoji.getAttribute('data-static'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     this._updateStatusLinks(); |     this._updateStatusLinks(); | ||||||
|  | @ -158,7 +158,7 @@ class StatusContent extends React.PureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       this.context.router.history.push(`/@${mention.get('acct')}`); |       this.context.router.history.push(`/@${mention.get('acct')}`); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onHashtagClick = (hashtag, e) => { |   onHashtagClick = (hashtag, e) => { | ||||||
|     hashtag = hashtag.replace(/^#/, ''); |     hashtag = hashtag.replace(/^#/, ''); | ||||||
|  | @ -167,11 +167,11 @@ class StatusContent extends React.PureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       this.context.router.history.push(`/tags/${hashtag}`); |       this.context.router.history.push(`/tags/${hashtag}`); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseDown = (e) => { |   handleMouseDown = (e) => { | ||||||
|     this.startXY = [e.clientX, e.clientY]; |     this.startXY = [e.clientX, e.clientY]; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseUp = (e) => { |   handleMouseUp = (e) => { | ||||||
|     if (!this.startXY) { |     if (!this.startXY) { | ||||||
|  | @ -194,7 +194,7 @@ class StatusContent extends React.PureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.startXY = null; |     this.startXY = null; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleSpoilerClick = (e) => { |   handleSpoilerClick = (e) => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|  | @ -205,15 +205,15 @@ class StatusContent extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.setState({ hidden: !this.state.hidden }); |       this.setState({ hidden: !this.state.hidden }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleTranslate = () => { |   handleTranslate = () => { | ||||||
|     this.props.onTranslate(); |     this.props.onTranslate(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = (c) => { |   setRef = (c) => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { status, intl } = this.props; |     const { status, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ export default class StatusList extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   getFeaturedStatusCount = () => { |   getFeaturedStatusCount = () => { | ||||||
|     return this.props.featuredStatusIds ? this.props.featuredStatusIds.size : 0; |     return this.props.featuredStatusIds ? this.props.featuredStatusIds.size : 0; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getCurrentStatusIndex = (id, featured) => { |   getCurrentStatusIndex = (id, featured) => { | ||||||
|     if (featured) { |     if (featured) { | ||||||
|  | @ -42,21 +42,21 @@ export default class StatusList extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       return this.props.statusIds.indexOf(id) + this.getFeaturedStatusCount(); |       return this.props.statusIds.indexOf(id) + this.getFeaturedStatusCount(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMoveUp = (id, featured) => { |   handleMoveUp = (id, featured) => { | ||||||
|     const elementIndex = this.getCurrentStatusIndex(id, featured) - 1; |     const elementIndex = this.getCurrentStatusIndex(id, featured) - 1; | ||||||
|     this._selectChild(elementIndex, true); |     this._selectChild(elementIndex, true); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMoveDown = (id, featured) => { |   handleMoveDown = (id, featured) => { | ||||||
|     const elementIndex = this.getCurrentStatusIndex(id, featured) + 1; |     const elementIndex = this.getCurrentStatusIndex(id, featured) + 1; | ||||||
|     this._selectChild(elementIndex, false); |     this._selectChild(elementIndex, false); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadOlder = debounce(() => { |   handleLoadOlder = debounce(() => { | ||||||
|     this.props.onLoadMore(this.props.statusIds.size > 0 ? this.props.statusIds.last() : undefined); |     this.props.onLoadMore(this.props.statusIds.size > 0 ? this.props.statusIds.last() : undefined); | ||||||
|   }, 300, { leading: true }) |   }, 300, { leading: true }); | ||||||
| 
 | 
 | ||||||
|   _selectChild (index, align_top) { |   _selectChild (index, align_top) { | ||||||
|     const container = this.node.node; |     const container = this.node.node; | ||||||
|  | @ -74,7 +74,7 @@ export default class StatusList extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { statusIds, featuredStatusIds, onLoadMore, timelineId, ...other }  = this.props; |     const { statusIds, featuredStatusIds, onLoadMore, timelineId, ...other }  = this.props; | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ export default class MediaContainer extends PureComponent { | ||||||
|     document.documentElement.style.marginRight = `${getScrollbarWidth()}px`; |     document.documentElement.style.marginRight = `${getScrollbarWidth()}px`; | ||||||
| 
 | 
 | ||||||
|     this.setState({ media, index }); |     this.setState({ media, index }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOpenVideo = (options) => { |   handleOpenVideo = (options) => { | ||||||
|     const { components } = this.props; |     const { components } = this.props; | ||||||
|  | @ -50,7 +50,7 @@ export default class MediaContainer extends PureComponent { | ||||||
|     document.documentElement.style.marginRight = `${getScrollbarWidth()}px`; |     document.documentElement.style.marginRight = `${getScrollbarWidth()}px`; | ||||||
| 
 | 
 | ||||||
|     this.setState({ media: mediaList, options }); |     this.setState({ media: mediaList, options }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleCloseMedia = () => { |   handleCloseMedia = () => { | ||||||
|     document.body.classList.remove('with-modals--active'); |     document.body.classList.remove('with-modals--active'); | ||||||
|  | @ -63,11 +63,11 @@ export default class MediaContainer extends PureComponent { | ||||||
|       backgroundColor: null, |       backgroundColor: null, | ||||||
|       options: null, |       options: null, | ||||||
|     }); |     }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setBackgroundColor = color => { |   setBackgroundColor = color => { | ||||||
|     this.setState({ backgroundColor: color }); |     this.setState({ backgroundColor: color }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { locale, components } = this.props; |     const { locale, components } = this.props; | ||||||
|  |  | ||||||
|  | @ -1,3 +1,2 @@ | ||||||
| import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'; | import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'; | ||||||
| import 'intersection-observer'; |  | ||||||
| import 'requestidlecallback'; | import 'requestidlecallback'; | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ class Section extends React.PureComponent { | ||||||
|     const { collapsed } = this.state; |     const { collapsed } = this.state; | ||||||
| 
 | 
 | ||||||
|     this.setState({ collapsed: !collapsed }, () => onOpen && onOpen()); |     this.setState({ collapsed: !collapsed }, () => onOpen && onOpen()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { title, children } = this.props; |     const { title, children } = this.props; | ||||||
|  | @ -106,7 +106,7 @@ class About extends React.PureComponent { | ||||||
|   handleDomainBlocksOpen = () => { |   handleDomainBlocksOpen = () => { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|     dispatch(fetchDomainBlocks()); |     dispatch(fetchDomainBlocks()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { multiColumn, intl, server, extendedDescription, domainBlocks } = this.props; |     const { multiColumn, intl, server, extendedDescription, domainBlocks } = this.props; | ||||||
|  |  | ||||||
|  | @ -90,7 +90,7 @@ class AccountNote extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   setTextareaRef = c => { |   setTextareaRef = c => { | ||||||
|     this.textarea = c; |     this.textarea = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleChange = e => { |   handleChange = e => { | ||||||
|     this.setState({ value: e.target.value, saving: false }); |     this.setState({ value: e.target.value, saving: false }); | ||||||
|  | @ -114,13 +114,13 @@ class AccountNote extends ImmutablePureComponent { | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBlur = () => { |   handleBlur = () => { | ||||||
|     if (this._isDirty()) { |     if (this._isDirty()) { | ||||||
|       this._save(); |       this._save(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _save (showMessage = true) { |   _save (showMessage = true) { | ||||||
|     this.setState({ saving: true }, () => this.props.onSave(this.state.value)); |     this.setState({ saving: true }, () => this.props.onSave(this.state.value)); | ||||||
|  |  | ||||||
|  | @ -109,7 +109,7 @@ class Header extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   openEditProfile = () => { |   openEditProfile = () => { | ||||||
|     window.open('/settings/profile', '_blank'); |     window.open('/settings/profile', '_blank'); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   isStatusesPageActive = (match, location) => { |   isStatusesPageActive = (match, location) => { | ||||||
|     if (!match) { |     if (!match) { | ||||||
|  | @ -117,7 +117,7 @@ class Header extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return !location.pathname.match(/\/(followers|following)\/?$/); |     return !location.pathname.match(/\/(followers|following)\/?$/); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseEnter = ({ currentTarget }) => { |   handleMouseEnter = ({ currentTarget }) => { | ||||||
|     if (autoPlayGif) { |     if (autoPlayGif) { | ||||||
|  | @ -130,7 +130,7 @@ class Header extends ImmutablePureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-original'); |       emoji.src = emoji.getAttribute('data-original'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = ({ currentTarget }) => { |   handleMouseLeave = ({ currentTarget }) => { | ||||||
|     if (autoPlayGif) { |     if (autoPlayGif) { | ||||||
|  | @ -143,14 +143,14 @@ class Header extends ImmutablePureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-static'); |       emoji.src = emoji.getAttribute('data-static'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleAvatarClick = e => { |   handleAvatarClick = e => { | ||||||
|     if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { |     if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       this.props.onOpenAvatar(); |       this.props.onOpenAvatar(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleShare = () => { |   handleShare = () => { | ||||||
|     const { account } = this.props; |     const { account } = this.props; | ||||||
|  | @ -161,7 +161,7 @@ class Header extends ImmutablePureComponent { | ||||||
|     }).catch((e) => { |     }).catch((e) => { | ||||||
|       if (e.name !== 'AbortError') console.error(e); |       if (e.name !== 'AbortError') console.error(e); | ||||||
|     }); |     }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { account, hidden, intl, domain } = this.props; |     const { account, hidden, intl, domain } = this.props; | ||||||
|  |  | ||||||
|  | @ -22,20 +22,20 @@ export default class MediaItem extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleImageLoad = () => { |   handleImageLoad = () => { | ||||||
|     this.setState({ loaded: true }); |     this.setState({ loaded: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseEnter = e => { |   handleMouseEnter = e => { | ||||||
|     if (this.hoverToPlay()) { |     if (this.hoverToPlay()) { | ||||||
|       e.target.play(); |       e.target.play(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = e => { |   handleMouseLeave = e => { | ||||||
|     if (this.hoverToPlay()) { |     if (this.hoverToPlay()) { | ||||||
|       e.target.pause(); |       e.target.pause(); | ||||||
|       e.target.currentTime = 0; |       e.target.currentTime = 0; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   hoverToPlay () { |   hoverToPlay () { | ||||||
|     return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1; |     return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1; | ||||||
|  | @ -51,7 +51,7 @@ export default class MediaItem extends ImmutablePureComponent { | ||||||
|         this.setState({ visible: true }); |         this.setState({ visible: true }); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { attachment, displayWidth } = this.props; |     const { attachment, displayWidth } = this.props; | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ class LoadMoreMedia extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = () => { |   handleLoadMore = () => { | ||||||
|     this.props.onLoadMore(this.props.maxId); |     this.props.onLoadMore(this.props.maxId); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     return ( |     return ( | ||||||
|  | @ -114,7 +114,7 @@ class AccountGallery extends ImmutablePureComponent { | ||||||
|     if (this.props.hasMore) { |     if (this.props.hasMore) { | ||||||
|       this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined); |       this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleScroll = e => { |   handleScroll = e => { | ||||||
|     const { scrollTop, scrollHeight, clientHeight } = e.target; |     const { scrollTop, scrollHeight, clientHeight } = e.target; | ||||||
|  | @ -123,7 +123,7 @@ class AccountGallery extends ImmutablePureComponent { | ||||||
|     if (150 > offset && !this.props.isLoading) { |     if (150 > offset && !this.props.isLoading) { | ||||||
|       this.handleScrollToBottom(); |       this.handleScrollToBottom(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = maxId => { |   handleLoadMore = maxId => { | ||||||
|     this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, { maxId })); |     this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, { maxId })); | ||||||
|  | @ -132,7 +132,7 @@ class AccountGallery extends ImmutablePureComponent { | ||||||
|   handleLoadOlder = e => { |   handleLoadOlder = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     this.handleScrollToBottom(); |     this.handleScrollToBottom(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOpenMedia = attachment => { |   handleOpenMedia = attachment => { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|  | @ -148,13 +148,13 @@ class AccountGallery extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|       dispatch(openModal('MEDIA', { media, index, statusId })); |       dispatch(openModal('MEDIA', { media, index, statusId })); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleRef = c => { |   handleRef = c => { | ||||||
|     if (c) { |     if (c) { | ||||||
|       this.setState({ width: c.offsetWidth }); |       this.setState({ width: c.offsetWidth }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { attachments, isLoading, hasMore, isAccount, multiColumn, blockedBy, suspended } = this.props; |     const { attachments, isLoading, hasMore, isAccount, multiColumn, blockedBy, suspended } = this.props; | ||||||
|  |  | ||||||
|  | @ -36,35 +36,35 @@ export default class Header extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleFollow = () => { |   handleFollow = () => { | ||||||
|     this.props.onFollow(this.props.account); |     this.props.onFollow(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBlock = () => { |   handleBlock = () => { | ||||||
|     this.props.onBlock(this.props.account); |     this.props.onBlock(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMention = () => { |   handleMention = () => { | ||||||
|     this.props.onMention(this.props.account, this.context.router.history); |     this.props.onMention(this.props.account, this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleDirect = () => { |   handleDirect = () => { | ||||||
|     this.props.onDirect(this.props.account, this.context.router.history); |     this.props.onDirect(this.props.account, this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleReport = () => { |   handleReport = () => { | ||||||
|     this.props.onReport(this.props.account); |     this.props.onReport(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleReblogToggle = () => { |   handleReblogToggle = () => { | ||||||
|     this.props.onReblogToggle(this.props.account); |     this.props.onReblogToggle(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleNotifyToggle = () => { |   handleNotifyToggle = () => { | ||||||
|     this.props.onNotifyToggle(this.props.account); |     this.props.onNotifyToggle(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMute = () => { |   handleMute = () => { | ||||||
|     this.props.onMute(this.props.account); |     this.props.onMute(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBlockDomain = () => { |   handleBlockDomain = () => { | ||||||
|     const domain = this.props.account.get('acct').split('@')[1]; |     const domain = this.props.account.get('acct').split('@')[1]; | ||||||
|  | @ -72,7 +72,7 @@ export default class Header extends ImmutablePureComponent { | ||||||
|     if (!domain) return; |     if (!domain) return; | ||||||
| 
 | 
 | ||||||
|     this.props.onBlockDomain(domain); |     this.props.onBlockDomain(domain); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleUnblockDomain = () => { |   handleUnblockDomain = () => { | ||||||
|     const domain = this.props.account.get('acct').split('@')[1]; |     const domain = this.props.account.get('acct').split('@')[1]; | ||||||
|  | @ -80,31 +80,31 @@ export default class Header extends ImmutablePureComponent { | ||||||
|     if (!domain) return; |     if (!domain) return; | ||||||
| 
 | 
 | ||||||
|     this.props.onUnblockDomain(domain); |     this.props.onUnblockDomain(domain); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleEndorseToggle = () => { |   handleEndorseToggle = () => { | ||||||
|     this.props.onEndorseToggle(this.props.account); |     this.props.onEndorseToggle(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleAddToList = () => { |   handleAddToList = () => { | ||||||
|     this.props.onAddToList(this.props.account); |     this.props.onAddToList(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleEditAccountNote = () => { |   handleEditAccountNote = () => { | ||||||
|     this.props.onEditAccountNote(this.props.account); |     this.props.onEditAccountNote(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleChangeLanguages = () => { |   handleChangeLanguages = () => { | ||||||
|     this.props.onChangeLanguages(this.props.account); |     this.props.onChangeLanguages(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleInteractionModal = () => { |   handleInteractionModal = () => { | ||||||
|     this.props.onInteractionModal(this.props.account); |     this.props.onInteractionModal(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOpenAvatar = () => { |   handleOpenAvatar = () => { | ||||||
|     this.props.onOpenAvatar(this.props.account); |     this.props.onOpenAvatar(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { account, hidden, hideTabs } = this.props; |     const { account, hidden, hideTabs } = this.props; | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ class LimitedAccountHint extends React.PureComponent { | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|     accountId: PropTypes.string.isRequired, |     accountId: PropTypes.string.isRequired, | ||||||
|     reveal: PropTypes.func, |     reveal: PropTypes.func, | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { reveal } = this.props; |     const { reveal } = this.props; | ||||||
|  |  | ||||||
|  | @ -145,7 +145,7 @@ class AccountTimeline extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = maxId => { |   handleLoadMore = maxId => { | ||||||
|     this.props.dispatch(expandAccountTimeline(this.props.accountId, { maxId, withReplies: this.props.withReplies, tagged: this.props.params.tagged })); |     this.props.dispatch(expandAccountTimeline(this.props.accountId, { maxId, withReplies: this.props.withReplies, tagged: this.props.params.tagged })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props; |     const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props; | ||||||
|  |  | ||||||
|  | @ -75,7 +75,7 @@ class Audio extends React.PureComponent { | ||||||
|     if (this.player) { |     if (this.player) { | ||||||
|       this._setDimensions(); |       this._setDimensions(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _pack() { |   _pack() { | ||||||
|     return { |     return { | ||||||
|  | @ -105,11 +105,11 @@ class Audio extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setSeekRef = c => { |   setSeekRef = c => { | ||||||
|     this.seek = c; |     this.seek = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setVolumeRef = c => { |   setVolumeRef = c => { | ||||||
|     this.volume = c; |     this.volume = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setAudioRef = c => { |   setAudioRef = c => { | ||||||
|     this.audio = c; |     this.audio = c; | ||||||
|  | @ -118,13 +118,13 @@ class Audio extends React.PureComponent { | ||||||
|       this.audio.volume = 1; |       this.audio.volume = 1; | ||||||
|       this.audio.muted = false; |       this.audio.muted = false; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setCanvasRef = c => { |   setCanvasRef = c => { | ||||||
|     this.canvas = c; |     this.canvas = c; | ||||||
| 
 | 
 | ||||||
|     this.visualizer.setCanvas(c); |     this.visualizer.setCanvas(c); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     window.addEventListener('scroll', this.handleScroll); |     window.addEventListener('scroll', this.handleScroll); | ||||||
|  | @ -163,7 +163,7 @@ class Audio extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.setState({ paused: true }, () => this.audio.pause()); |       this.setState({ paused: true }, () => this.audio.pause()); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleResize = debounce(() => { |   handleResize = debounce(() => { | ||||||
|     if (this.player) { |     if (this.player) { | ||||||
|  | @ -181,7 +181,7 @@ class Audio extends React.PureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this._renderCanvas(); |     this._renderCanvas(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handlePause = () => { |   handlePause = () => { | ||||||
|     this.setState({ paused: true }); |     this.setState({ paused: true }); | ||||||
|  | @ -189,7 +189,7 @@ class Audio extends React.PureComponent { | ||||||
|     if (this.audioContext) { |     if (this.audioContext) { | ||||||
|       this.audioContext.suspend(); |       this.audioContext.suspend(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleProgress = () => { |   handleProgress = () => { | ||||||
|     const lastTimeRange = this.audio.buffered.length - 1; |     const lastTimeRange = this.audio.buffered.length - 1; | ||||||
|  | @ -197,7 +197,7 @@ class Audio extends React.PureComponent { | ||||||
|     if (lastTimeRange > -1) { |     if (lastTimeRange > -1) { | ||||||
|       this.setState({ buffer: Math.ceil(this.audio.buffered.end(lastTimeRange) / this.audio.duration * 100) }); |       this.setState({ buffer: Math.ceil(this.audio.buffered.end(lastTimeRange) / this.audio.duration * 100) }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   toggleMute = () => { |   toggleMute = () => { | ||||||
|     const muted = !this.state.muted; |     const muted = !this.state.muted; | ||||||
|  | @ -207,7 +207,7 @@ class Audio extends React.PureComponent { | ||||||
|         this.gainNode.gain.value = muted ? 0 : this.state.volume; |         this.gainNode.gain.value = muted ? 0 : this.state.volume; | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   toggleReveal = () => { |   toggleReveal = () => { | ||||||
|     if (this.props.onToggleVisibility) { |     if (this.props.onToggleVisibility) { | ||||||
|  | @ -215,7 +215,7 @@ class Audio extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.setState({ revealed: !this.state.revealed }); |       this.setState({ revealed: !this.state.revealed }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleVolumeMouseDown = e => { |   handleVolumeMouseDown = e => { | ||||||
|     document.addEventListener('mousemove', this.handleMouseVolSlide, true); |     document.addEventListener('mousemove', this.handleMouseVolSlide, true); | ||||||
|  | @ -227,14 +227,14 @@ class Audio extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     e.stopPropagation(); |     e.stopPropagation(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleVolumeMouseUp = () => { |   handleVolumeMouseUp = () => { | ||||||
|     document.removeEventListener('mousemove', this.handleMouseVolSlide, true); |     document.removeEventListener('mousemove', this.handleMouseVolSlide, true); | ||||||
|     document.removeEventListener('mouseup', this.handleVolumeMouseUp, true); |     document.removeEventListener('mouseup', this.handleVolumeMouseUp, true); | ||||||
|     document.removeEventListener('touchmove', this.handleMouseVolSlide, true); |     document.removeEventListener('touchmove', this.handleMouseVolSlide, true); | ||||||
|     document.removeEventListener('touchend', this.handleVolumeMouseUp, true); |     document.removeEventListener('touchend', this.handleVolumeMouseUp, true); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseDown = e => { |   handleMouseDown = e => { | ||||||
|     document.addEventListener('mousemove', this.handleMouseMove, true); |     document.addEventListener('mousemove', this.handleMouseMove, true); | ||||||
|  | @ -248,7 +248,7 @@ class Audio extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     e.stopPropagation(); |     e.stopPropagation(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseUp = () => { |   handleMouseUp = () => { | ||||||
|     document.removeEventListener('mousemove', this.handleMouseMove, true); |     document.removeEventListener('mousemove', this.handleMouseMove, true); | ||||||
|  | @ -258,7 +258,7 @@ class Audio extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     this.setState({ dragging: false }); |     this.setState({ dragging: false }); | ||||||
|     this.audio.play(); |     this.audio.play(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseMove = throttle(e => { |   handleMouseMove = throttle(e => { | ||||||
|     const { x } = getPointerPosition(this.seek, e); |     const { x } = getPointerPosition(this.seek, e); | ||||||
|  | @ -276,7 +276,7 @@ class Audio extends React.PureComponent { | ||||||
|       currentTime: this.audio.currentTime, |       currentTime: this.audio.currentTime, | ||||||
|       duration: this.audio.duration, |       duration: this.audio.duration, | ||||||
|     }); |     }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseVolSlide = throttle(e => { |   handleMouseVolSlide = throttle(e => { | ||||||
|     const { x } = getPointerPosition(this.volume, e); |     const { x } = getPointerPosition(this.volume, e); | ||||||
|  | @ -311,11 +311,11 @@ class Audio extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleMouseEnter = () => { |   handleMouseEnter = () => { | ||||||
|     this.setState({ hovered: true }); |     this.setState({ hovered: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = () => { |   handleMouseLeave = () => { | ||||||
|     this.setState({ hovered: false }); |     this.setState({ hovered: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadedData = () => { |   handleLoadedData = () => { | ||||||
|     const { autoPlay, currentTime } = this.props; |     const { autoPlay, currentTime } = this.props; | ||||||
|  | @ -327,7 +327,7 @@ class Audio extends React.PureComponent { | ||||||
|     if (autoPlay) { |     if (autoPlay) { | ||||||
|       this.togglePlay(); |       this.togglePlay(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _initAudioContext () { |   _initAudioContext () { | ||||||
|     const AudioContext = window.AudioContext || window.webkitAudioContext; |     const AudioContext = window.AudioContext || window.webkitAudioContext; | ||||||
|  | @ -361,7 +361,7 @@ class Audio extends React.PureComponent { | ||||||
|     }).catch(err => { |     }).catch(err => { | ||||||
|       console.error(err); |       console.error(err); | ||||||
|     }); |     }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _renderCanvas () { |   _renderCanvas () { | ||||||
|     requestAnimationFrame(() => { |     requestAnimationFrame(() => { | ||||||
|  | @ -432,7 +432,7 @@ class Audio extends React.PureComponent { | ||||||
|       e.stopPropagation(); |       e.stopPropagation(); | ||||||
|       this.togglePlay(); |       this.togglePlay(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = e => { |   handleKeyDown = e => { | ||||||
|     switch(e.key) { |     switch(e.key) { | ||||||
|  | @ -457,7 +457,7 @@ class Audio extends React.PureComponent { | ||||||
|       this.seekBy(10); |       this.seekBy(10); | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { src, intl, alt, editable, autoPlay, sensitive, blurhash } = this.props; |     const { src, intl, alt, editable, autoPlay, sensitive, blurhash } = this.props; | ||||||
|  |  | ||||||
|  | @ -48,24 +48,24 @@ class Bookmarks extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(addColumn('BOOKMARKS', {})); |       dispatch(addColumn('BOOKMARKS', {})); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMove = (dir) => { |   handleMove = (dir) => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = debounce(() => { |   handleLoadMore = debounce(() => { | ||||||
|     this.props.dispatch(expandBookmarkedStatuses()); |     this.props.dispatch(expandBookmarkedStatuses()); | ||||||
|   }, 300, { leading: true }) |   }, 300, { leading: true }); | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props; |     const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props; | ||||||
|  |  | ||||||
|  | @ -60,16 +60,16 @@ class CommunityTimeline extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(addColumn('COMMUNITY', { other: { onlyMedia } })); |       dispatch(addColumn('COMMUNITY', { other: { onlyMedia } })); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMove = (dir) => { |   handleMove = (dir) => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     const { dispatch, onlyMedia } = this.props; |     const { dispatch, onlyMedia } = this.props; | ||||||
|  | @ -109,13 +109,13 @@ class CommunityTimeline extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = maxId => { |   handleLoadMore = maxId => { | ||||||
|     const { dispatch, onlyMedia } = this.props; |     const { dispatch, onlyMedia } = this.props; | ||||||
| 
 | 
 | ||||||
|     dispatch(expandCommunityTimeline({ maxId, onlyMedia })); |     dispatch(expandCommunityTimeline({ maxId, onlyMedia })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, hasUnread, columnId, multiColumn, onlyMedia } = this.props; |     const { intl, hasUnread, columnId, multiColumn, onlyMedia } = this.props; | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ class ActionBar extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleLogout = () => { |   handleLogout = () => { | ||||||
|     this.props.onLogout(); |     this.props.onLogout(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl } = this.props; |     const { intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -74,17 +74,17 @@ class ComposeForm extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleChange = (e) => { |   handleChange = (e) => { | ||||||
|     this.props.onChange(e.target.value); |     this.props.onChange(e.target.value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = (e) => { |   handleKeyDown = (e) => { | ||||||
|     if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { |     if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { | ||||||
|       this.handleSubmit(); |       this.handleSubmit(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getFulltextForCharacterCounting = () => { |   getFulltextForCharacterCounting = () => { | ||||||
|     return [this.props.spoiler? this.props.spoilerText: '', countableText(this.props.text)].join(''); |     return [this.props.spoiler? this.props.spoilerText: '', countableText(this.props.text)].join(''); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   canSubmit = () => { |   canSubmit = () => { | ||||||
|     const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props; |     const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props; | ||||||
|  | @ -92,7 +92,7 @@ class ComposeForm extends ImmutablePureComponent { | ||||||
|     const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0; |     const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0; | ||||||
| 
 | 
 | ||||||
|     return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxChars || (isOnlyWhitespace && !anyMedia)); |     return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxChars || (isOnlyWhitespace && !anyMedia)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleSubmit = (e) => { |   handleSubmit = (e) => { | ||||||
|     if (this.props.text !== this.autosuggestTextarea.textarea.value) { |     if (this.props.text !== this.autosuggestTextarea.textarea.value) { | ||||||
|  | @ -110,27 +110,27 @@ class ComposeForm extends ImmutablePureComponent { | ||||||
|     if (e) { |     if (e) { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSuggestionsClearRequested = () => { |   onSuggestionsClearRequested = () => { | ||||||
|     this.props.onClearSuggestions(); |     this.props.onClearSuggestions(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSuggestionsFetchRequested = (token) => { |   onSuggestionsFetchRequested = (token) => { | ||||||
|     this.props.onFetchSuggestions(token); |     this.props.onFetchSuggestions(token); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSuggestionSelected = (tokenStart, token, value) => { |   onSuggestionSelected = (tokenStart, token, value) => { | ||||||
|     this.props.onSuggestionSelected(tokenStart, token, value, ['text']); |     this.props.onSuggestionSelected(tokenStart, token, value, ['text']); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSpoilerSuggestionSelected = (tokenStart, token, value) => { |   onSpoilerSuggestionSelected = (tokenStart, token, value) => { | ||||||
|     this.props.onSuggestionSelected(tokenStart, token, value, ['spoiler_text']); |     this.props.onSuggestionSelected(tokenStart, token, value, ['spoiler_text']); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleChangeSpoilerText = (e) => { |   handleChangeSpoilerText = (e) => { | ||||||
|     this.props.onChangeSpoilerText(e.target.value); |     this.props.onChangeSpoilerText(e.target.value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleFocus = () => { |   handleFocus = () => { | ||||||
|     if (this.composeForm && !this.props.singleColumn) { |     if (this.composeForm && !this.props.singleColumn) { | ||||||
|  | @ -139,7 +139,7 @@ class ComposeForm extends ImmutablePureComponent { | ||||||
|         this.composeForm.scrollIntoView(); |         this.composeForm.scrollIntoView(); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     this._updateFocusAndSelection({ }); |     this._updateFocusAndSelection({ }); | ||||||
|  | @ -185,15 +185,15 @@ class ComposeForm extends ImmutablePureComponent { | ||||||
|         this.autosuggestTextarea.textarea.focus(); |         this.autosuggestTextarea.textarea.focus(); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setAutosuggestTextarea = (c) => { |   setAutosuggestTextarea = (c) => { | ||||||
|     this.autosuggestTextarea = c; |     this.autosuggestTextarea = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setSpoilerText = (c) => { |   setSpoilerText = (c) => { | ||||||
|     this.spoilerText = c; |     this.spoilerText = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.composeForm = c; |     this.composeForm = c; | ||||||
|  | @ -205,7 +205,7 @@ class ComposeForm extends ImmutablePureComponent { | ||||||
|     const needsSpace   = data.custom && position > 0 && !allowedAroundShortCode.includes(text[position - 1]); |     const needsSpace   = data.custom && position > 0 && !allowedAroundShortCode.includes(text[position - 1]); | ||||||
| 
 | 
 | ||||||
|     this.props.onPickEmoji(position, data, needsSpace); |     this.props.onPickEmoji(position, data, needsSpace); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, onPaste, autoFocus } = this.props; |     const { intl, onPaste, autoFocus } = this.props; | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ class ModifierPickerMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleClick = e => { |   handleClick = e => { | ||||||
|     this.props.onSelect(e.currentTarget.getAttribute('data-index') * 1); |     this.props.onSelect(e.currentTarget.getAttribute('data-index') * 1); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillReceiveProps (nextProps) { |   componentWillReceiveProps (nextProps) { | ||||||
|     if (nextProps.active) { |     if (nextProps.active) { | ||||||
|  | @ -75,7 +75,7 @@ class ModifierPickerMenu extends React.PureComponent { | ||||||
|     if (this.node && !this.node.contains(e.target)) { |     if (this.node && !this.node.contains(e.target)) { | ||||||
|       this.props.onClose(); |       this.props.onClose(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   attachListeners () { |   attachListeners () { | ||||||
|     document.addEventListener('click', this.handleDocumentClick, false); |     document.addEventListener('click', this.handleDocumentClick, false); | ||||||
|  | @ -89,7 +89,7 @@ class ModifierPickerMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { active } = this.props; |     const { active } = this.props; | ||||||
|  | @ -124,12 +124,12 @@ class ModifierPicker extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.props.onOpen(); |       this.props.onOpen(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleSelect = modifier => { |   handleSelect = modifier => { | ||||||
|     this.props.onChange(modifier); |     this.props.onChange(modifier); | ||||||
|     this.props.onClose(); |     this.props.onClose(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { active, modifier } = this.props; |     const { active, modifier } = this.props; | ||||||
|  | @ -174,7 +174,7 @@ class EmojiPickerMenu extends React.PureComponent { | ||||||
|     if (this.node && !this.node.contains(e.target)) { |     if (this.node && !this.node.contains(e.target)) { | ||||||
|       this.props.onClose(); |       this.props.onClose(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     document.addEventListener('click', this.handleDocumentClick, false); |     document.addEventListener('click', this.handleDocumentClick, false); | ||||||
|  | @ -198,7 +198,7 @@ class EmojiPickerMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getI18n = () => { |   getI18n = () => { | ||||||
|     const { intl } = this.props; |     const { intl } = this.props; | ||||||
|  | @ -219,7 +219,7 @@ class EmojiPickerMenu extends React.PureComponent { | ||||||
|         custom: intl.formatMessage(messages.custom), |         custom: intl.formatMessage(messages.custom), | ||||||
|       }, |       }, | ||||||
|     }; |     }; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = (emoji, event) => { |   handleClick = (emoji, event) => { | ||||||
|     if (!emoji.native) { |     if (!emoji.native) { | ||||||
|  | @ -229,19 +229,19 @@ class EmojiPickerMenu extends React.PureComponent { | ||||||
|       this.props.onClose(); |       this.props.onClose(); | ||||||
|     } |     } | ||||||
|     this.props.onPick(emoji); |     this.props.onPick(emoji); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleModifierOpen = () => { |   handleModifierOpen = () => { | ||||||
|     this.setState({ modifierOpen: true }); |     this.setState({ modifierOpen: true }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleModifierClose = () => { |   handleModifierClose = () => { | ||||||
|     this.setState({ modifierOpen: false }); |     this.setState({ modifierOpen: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleModifierChange = modifier => { |   handleModifierChange = modifier => { | ||||||
|     this.props.onSkinTone(modifier); |     this.props.onSkinTone(modifier); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { loading, style, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props; |     const { loading, style, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props; | ||||||
|  | @ -325,7 +325,7 @@ class EmojiPickerDropdown extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = (c) => { |   setRef = (c) => { | ||||||
|     this.dropdown = c; |     this.dropdown = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onShowDropdown = () => { |   onShowDropdown = () => { | ||||||
|     this.setState({ active: true }); |     this.setState({ active: true }); | ||||||
|  | @ -342,11 +342,11 @@ class EmojiPickerDropdown extends React.PureComponent { | ||||||
|         this.setState({ loading: false, active: false }); |         this.setState({ loading: false, active: false }); | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onHideDropdown = () => { |   onHideDropdown = () => { | ||||||
|     this.setState({ active: false }); |     this.setState({ active: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onToggle = (e) => { |   onToggle = (e) => { | ||||||
|     if (!this.state.loading && (!e.key || e.key === 'Enter')) { |     if (!this.state.loading && (!e.key || e.key === 'Enter')) { | ||||||
|  | @ -356,21 +356,21 @@ class EmojiPickerDropdown extends React.PureComponent { | ||||||
|         this.onShowDropdown(e); |         this.onShowDropdown(e); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = e => { |   handleKeyDown = e => { | ||||||
|     if (e.key === 'Escape') { |     if (e.key === 'Escape') { | ||||||
|       this.onHideDropdown(); |       this.onHideDropdown(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setTargetRef = c => { |   setTargetRef = c => { | ||||||
|     this.target = c; |     this.target = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   findTarget = () => { |   findTarget = () => { | ||||||
|     return this.target; |     return this.target; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis, button } = this.props; |     const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis, button } = this.props; | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ class LanguageDropdownMenu extends React.PureComponent { | ||||||
|     if (this.node && !this.node.contains(e.target)) { |     if (this.node && !this.node.contains(e.target)) { | ||||||
|       this.props.onClose(); |       this.props.onClose(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     document.addEventListener('click', this.handleDocumentClick, false); |     document.addEventListener('click', this.handleDocumentClick, false); | ||||||
|  | @ -63,15 +63,15 @@ class LanguageDropdownMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setListRef = c => { |   setListRef = c => { | ||||||
|     this.listNode = c; |     this.listNode = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleSearchChange = ({ target }) => { |   handleSearchChange = ({ target }) => { | ||||||
|     this.setState({ searchValue: target.value }); |     this.setState({ searchValue: target.value }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   search () { |   search () { | ||||||
|     const { languages, value, frequentlyUsedLanguages } = this.props; |     const { languages, value, frequentlyUsedLanguages } = this.props; | ||||||
|  | @ -122,7 +122,7 @@ class LanguageDropdownMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     this.props.onClose(); |     this.props.onClose(); | ||||||
|     this.props.onChange(value); |     this.props.onChange(value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = e => { |   handleKeyDown = e => { | ||||||
|     const { onClose } = this.props; |     const { onClose } = this.props; | ||||||
|  | @ -163,7 +163,7 @@ class LanguageDropdownMenu extends React.PureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       e.stopPropagation(); |       e.stopPropagation(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleSearchKeyDown = e => { |   handleSearchKeyDown = e => { | ||||||
|     const { onChange, onClose } = this.props; |     const { onChange, onClose } = this.props; | ||||||
|  | @ -199,11 +199,11 @@ class LanguageDropdownMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClear = () => { |   handleClear = () => { | ||||||
|     this.setState({ searchValue: '' }); |     this.setState({ searchValue: '' }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderItem = lang => { |   renderItem = lang => { | ||||||
|     const { value } = this.props; |     const { value } = this.props; | ||||||
|  | @ -213,7 +213,7 @@ class LanguageDropdownMenu extends React.PureComponent { | ||||||
|         <span className='language-dropdown__dropdown__results__item__native-name'>{lang[2]}</span> <span className='language-dropdown__dropdown__results__item__common-name'>({lang[1]})</span> |         <span className='language-dropdown__dropdown__results__item__native-name'>{lang[2]}</span> <span className='language-dropdown__dropdown__results__item__common-name'>({lang[1]})</span> | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl } = this.props; |     const { intl } = this.props; | ||||||
|  | @ -259,7 +259,7 @@ class LanguageDropdown extends React.PureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.setState({ open: !this.state.open }); |     this.setState({ open: !this.state.open }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClose = () => { |   handleClose = () => { | ||||||
|     const { value, onClose } = this.props; |     const { value, onClose } = this.props; | ||||||
|  | @ -270,24 +270,24 @@ class LanguageDropdown extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     this.setState({ open: false }); |     this.setState({ open: false }); | ||||||
|     onClose(value); |     onClose(value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleChange = value => { |   handleChange = value => { | ||||||
|     const { onChange } = this.props; |     const { onChange } = this.props; | ||||||
|     onChange(value); |     onChange(value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setTargetRef = c => { |   setTargetRef = c => { | ||||||
|     this.target = c; |     this.target = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   findTarget = () => { |   findTarget = () => { | ||||||
|     return this.target; |     return this.target; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOverlayEnter = (state) => { |   handleOverlayEnter = (state) => { | ||||||
|     this.setState({ placement: state.placement }); |     this.setState({ placement: state.placement }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, intl, frequentlyUsedLanguages } = this.props; |     const { value, intl, frequentlyUsedLanguages } = this.props; | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ class PollButton extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     this.props.onClick(); |     this.props.onClick(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, active, unavailable, disabled } = this.props; |     const { intl, active, unavailable, disabled } = this.props; | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ class Option extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|     title: PropTypes.string.isRequired, |     title: PropTypes.string.isRequired, | ||||||
|  |     lang: PropTypes.string, | ||||||
|     index: PropTypes.number.isRequired, |     index: PropTypes.number.isRequired, | ||||||
|     isPollMultiple: PropTypes.bool, |     isPollMultiple: PropTypes.bool, | ||||||
|     autoFocus: PropTypes.bool, |     autoFocus: PropTypes.bool, | ||||||
|  | @ -57,22 +58,22 @@ class Option extends React.PureComponent { | ||||||
|     if (e.key === 'Enter' || e.key === ' ') { |     if (e.key === 'Enter' || e.key === ' ') { | ||||||
|       this.handleToggleMultiple(e); |       this.handleToggleMultiple(e); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSuggestionsClearRequested = () => { |   onSuggestionsClearRequested = () => { | ||||||
|     this.props.onClearSuggestions(); |     this.props.onClearSuggestions(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSuggestionsFetchRequested = (token) => { |   onSuggestionsFetchRequested = (token) => { | ||||||
|     this.props.onFetchSuggestions(token); |     this.props.onFetchSuggestions(token); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onSuggestionSelected = (tokenStart, token, value) => { |   onSuggestionSelected = (tokenStart, token, value) => { | ||||||
|     this.props.onSuggestionSelected(tokenStart, token, value, ['poll', 'options', this.props.index]); |     this.props.onSuggestionSelected(tokenStart, token, value, ['poll', 'options', this.props.index]); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { isPollMultiple, title, index, autoFocus, intl } = this.props; |     const { isPollMultiple, title, lang, index, autoFocus, intl } = this.props; | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <li> |       <li> | ||||||
|  | @ -91,6 +92,7 @@ class Option extends React.PureComponent { | ||||||
|             placeholder={intl.formatMessage(messages.option_placeholder, { number: index + 1 })} |             placeholder={intl.formatMessage(messages.option_placeholder, { number: index + 1 })} | ||||||
|             maxLength={100} |             maxLength={100} | ||||||
|             value={title} |             value={title} | ||||||
|  |             lang={lang} | ||||||
|             onChange={this.handleOptionTitleChange} |             onChange={this.handleOptionTitleChange} | ||||||
|             suggestions={this.props.suggestions} |             suggestions={this.props.suggestions} | ||||||
|             onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} |             onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} | ||||||
|  | @ -116,6 +118,7 @@ class PollForm extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|     options: ImmutablePropTypes.list, |     options: ImmutablePropTypes.list, | ||||||
|  |     lang: PropTypes.string, | ||||||
|     expiresIn: PropTypes.number, |     expiresIn: PropTypes.number, | ||||||
|     isMultiple: PropTypes.bool, |     isMultiple: PropTypes.bool, | ||||||
|     onChangeOption: PropTypes.func.isRequired, |     onChangeOption: PropTypes.func.isRequired, | ||||||
|  | @ -142,7 +145,7 @@ class PollForm extends ImmutablePureComponent { | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { options, expiresIn, isMultiple, onChangeOption, onRemoveOption, intl, ...other } = this.props; |     const { options, lang, expiresIn, isMultiple, onChangeOption, onRemoveOption, intl, ...other } = this.props; | ||||||
| 
 | 
 | ||||||
|     if (!options) { |     if (!options) { | ||||||
|       return null; |       return null; | ||||||
|  | @ -153,7 +156,7 @@ class PollForm extends ImmutablePureComponent { | ||||||
|     return ( |     return ( | ||||||
|       <div className='compose-form__poll-wrapper'> |       <div className='compose-form__poll-wrapper'> | ||||||
|         <ul> |         <ul> | ||||||
|           {options.map((title, i) => <Option title={title} key={i} index={i} onChange={onChangeOption} onRemove={onRemoveOption} isPollMultiple={isMultiple} onToggleMultiple={this.handleToggleMultiple} autoFocus={i === autoFocusIndex} {...other} />)} |           {options.map((title, i) => <Option title={title} lang={lang} key={i} index={i} onChange={onChangeOption} onRemove={onRemoveOption} isPollMultiple={isMultiple} onToggleMultiple={this.handleToggleMultiple} autoFocus={i === autoFocusIndex} {...other} />)} | ||||||
|         </ul> |         </ul> | ||||||
| 
 | 
 | ||||||
|         <div className='poll__footer'> |         <div className='poll__footer'> | ||||||
|  |  | ||||||
|  | @ -35,7 +35,7 @@ class PrivacyDropdownMenu extends React.PureComponent { | ||||||
|     if (this.node && !this.node.contains(e.target)) { |     if (this.node && !this.node.contains(e.target)) { | ||||||
|       this.props.onClose(); |       this.props.onClose(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = e => { |   handleKeyDown = e => { | ||||||
|     const { items } = this.props; |     const { items } = this.props; | ||||||
|  | @ -79,7 +79,7 @@ class PrivacyDropdownMenu extends React.PureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       e.stopPropagation(); |       e.stopPropagation(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = e => { |   handleClick = e => { | ||||||
|     const value = e.currentTarget.getAttribute('data-index'); |     const value = e.currentTarget.getAttribute('data-index'); | ||||||
|  | @ -88,7 +88,7 @@ class PrivacyDropdownMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     this.props.onClose(); |     this.props.onClose(); | ||||||
|     this.props.onChange(value); |     this.props.onChange(value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     document.addEventListener('click', this.handleDocumentClick, false); |     document.addEventListener('click', this.handleDocumentClick, false); | ||||||
|  | @ -103,11 +103,11 @@ class PrivacyDropdownMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setFocusRef = c => { |   setFocusRef = c => { | ||||||
|     this.focusedItem = c; |     this.focusedItem = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { style, items, value } = this.props; |     const { style, items, value } = this.props; | ||||||
|  | @ -168,7 +168,7 @@ class PrivacyDropdown extends React.PureComponent { | ||||||
|       } |       } | ||||||
|       this.setState({ open: !this.state.open }); |       this.setState({ open: !this.state.open }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleModalActionClick = (e) => { |   handleModalActionClick = (e) => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|  | @ -177,7 +177,7 @@ class PrivacyDropdown extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     this.props.onModalClose(); |     this.props.onModalClose(); | ||||||
|     this.props.onChange(value); |     this.props.onChange(value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = e => { |   handleKeyDown = e => { | ||||||
|     switch(e.key) { |     switch(e.key) { | ||||||
|  | @ -185,13 +185,13 @@ class PrivacyDropdown extends React.PureComponent { | ||||||
|       this.handleClose(); |       this.handleClose(); | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseDown = () => { |   handleMouseDown = () => { | ||||||
|     if (!this.state.open) { |     if (!this.state.open) { | ||||||
|       this.activeElement = document.activeElement; |       this.activeElement = document.activeElement; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleButtonKeyDown = (e) => { |   handleButtonKeyDown = (e) => { | ||||||
|     switch(e.key) { |     switch(e.key) { | ||||||
|  | @ -200,18 +200,18 @@ class PrivacyDropdown extends React.PureComponent { | ||||||
|       this.handleMouseDown(); |       this.handleMouseDown(); | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClose = () => { |   handleClose = () => { | ||||||
|     if (this.state.open && this.activeElement) { |     if (this.state.open && this.activeElement) { | ||||||
|       this.activeElement.focus({ preventScroll: true }); |       this.activeElement.focus({ preventScroll: true }); | ||||||
|     } |     } | ||||||
|     this.setState({ open: false }); |     this.setState({ open: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleChange = value => { |   handleChange = value => { | ||||||
|     this.props.onChange(value); |     this.props.onChange(value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillMount () { |   componentWillMount () { | ||||||
|     const { intl: { formatMessage } } = this.props; |     const { intl: { formatMessage } } = this.props; | ||||||
|  | @ -231,15 +231,15 @@ class PrivacyDropdown extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setTargetRef = c => { |   setTargetRef = c => { | ||||||
|     this.target = c; |     this.target = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   findTarget = () => { |   findTarget = () => { | ||||||
|     return this.target; |     return this.target; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOverlayEnter = (state) => { |   handleOverlayEnter = (state) => { | ||||||
|     this.setState({ placement: state.placement }); |     this.setState({ placement: state.placement }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, container, disabled, intl } = this.props; |     const { value, container, disabled, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -27,14 +27,14 @@ class ReplyIndicator extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     this.props.onCancel(); |     this.props.onCancel(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleAccountClick = (e) => { |   handleAccountClick = (e) => { | ||||||
|     if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { |     if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`); |       this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { status, intl } = this.props; |     const { status, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -58,11 +58,11 @@ class Search extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.searchForm = c; |     this.searchForm = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleChange = (e) => { |   handleChange = (e) => { | ||||||
|     this.props.onChange(e.target.value); |     this.props.onChange(e.target.value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClear = (e) => { |   handleClear = (e) => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|  | @ -70,7 +70,7 @@ class Search extends React.PureComponent { | ||||||
|     if (this.props.value.length > 0 || this.props.submitted) { |     if (this.props.value.length > 0 || this.props.submitted) { | ||||||
|       this.props.onClear(); |       this.props.onClear(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyUp = (e) => { |   handleKeyUp = (e) => { | ||||||
|     if (e.key === 'Enter') { |     if (e.key === 'Enter') { | ||||||
|  | @ -84,7 +84,7 @@ class Search extends React.PureComponent { | ||||||
|     } else if (e.key === 'Escape') { |     } else if (e.key === 'Escape') { | ||||||
|       document.querySelector('.ui').parentElement.focus(); |       document.querySelector('.ui').parentElement.focus(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleFocus = () => { |   handleFocus = () => { | ||||||
|     this.setState({ expanded: true }); |     this.setState({ expanded: true }); | ||||||
|  | @ -96,15 +96,15 @@ class Search extends React.PureComponent { | ||||||
|         this.searchForm.scrollIntoView(); |         this.searchForm.scrollIntoView(); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleBlur = () => { |   handleBlur = () => { | ||||||
|     this.setState({ expanded: false }); |     this.setState({ expanded: false }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   findTarget = () => { |   findTarget = () => { | ||||||
|     return this.searchForm; |     return this.searchForm; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, value, submitted } = this.props; |     const { intl, value, submitted } = this.props; | ||||||
|  |  | ||||||
|  | @ -22,12 +22,12 @@ export default class Upload extends ImmutablePureComponent { | ||||||
|   handleUndoClick = e => { |   handleUndoClick = e => { | ||||||
|     e.stopPropagation(); |     e.stopPropagation(); | ||||||
|     this.props.onUndo(this.props.media.get('id')); |     this.props.onUndo(this.props.media.get('id')); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleFocalPointClick = e => { |   handleFocalPointClick = e => { | ||||||
|     e.stopPropagation(); |     e.stopPropagation(); | ||||||
|     this.props.onOpenFocalPoint(this.props.media.get('id')); |     this.props.onOpenFocalPoint(this.props.media.get('id')); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { media } = this.props; |     const { media } = this.props; | ||||||
|  |  | ||||||
|  | @ -41,15 +41,15 @@ class UploadButton extends ImmutablePureComponent { | ||||||
|     if (e.target.files.length > 0) { |     if (e.target.files.length > 0) { | ||||||
|       this.props.onSelectFile(e.target.files); |       this.props.onSelectFile(e.target.files); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     this.fileElement.click(); |     this.fileElement.click(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = (c) => { |   setRef = (c) => { | ||||||
|     this.fileElement = c; |     this.fileElement = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, resetFileKey, unavailable, disabled, acceptContentTypes } = this.props; |     const { intl, resetFileKey, unavailable, disabled, acceptContentTypes } = this.props; | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import { | ||||||
| const mapStateToProps = state => ({ | const mapStateToProps = state => ({ | ||||||
|   suggestions: state.getIn(['compose', 'suggestions']), |   suggestions: state.getIn(['compose', 'suggestions']), | ||||||
|   options: state.getIn(['compose', 'poll', 'options']), |   options: state.getIn(['compose', 'poll', 'options']), | ||||||
|  |   lang: state.getIn(['compose', 'language']), | ||||||
|   expiresIn: state.getIn(['compose', 'poll', 'expires_in']), |   expiresIn: state.getIn(['compose', 'poll', 'expires_in']), | ||||||
|   isMultiple: state.getIn(['compose', 'poll', 'multiple']), |   isMultiple: state.getIn(['compose', 'poll', 'multiple']), | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -74,15 +74,15 @@ class Compose extends React.PureComponent { | ||||||
|     })); |     })); | ||||||
| 
 | 
 | ||||||
|     return false; |     return false; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onFocus = () => { |   onFocus = () => { | ||||||
|     this.props.dispatch(changeComposing(true)); |     this.props.dispatch(changeComposing(true)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onBlur = () => { |   onBlur = () => { | ||||||
|     this.props.dispatch(changeComposing(false)); |     this.props.dispatch(changeComposing(false)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { multiColumn, showSearch, intl } = this.props; |     const { multiColumn, showSearch, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -55,7 +55,7 @@ class Conversation extends ImmutablePureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-original'); |       emoji.src = emoji.getAttribute('data-original'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = ({ currentTarget }) => { |   handleMouseLeave = ({ currentTarget }) => { | ||||||
|     if (autoPlayGif) { |     if (autoPlayGif) { | ||||||
|  | @ -68,7 +68,7 @@ class Conversation extends ImmutablePureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-static'); |       emoji.src = emoji.getAttribute('data-static'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     if (!this.context.router) { |     if (!this.context.router) { | ||||||
|  | @ -82,35 +82,35 @@ class Conversation extends ImmutablePureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.context.router.history.push(`/@${lastStatus.getIn(['account', 'acct'])}/${lastStatus.get('id')}`); |     this.context.router.history.push(`/@${lastStatus.getIn(['account', 'acct'])}/${lastStatus.get('id')}`); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMarkAsRead = () => { |   handleMarkAsRead = () => { | ||||||
|     this.props.markRead(); |     this.props.markRead(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleReply = () => { |   handleReply = () => { | ||||||
|     this.props.reply(this.props.lastStatus, this.context.router.history); |     this.props.reply(this.props.lastStatus, this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleDelete = () => { |   handleDelete = () => { | ||||||
|     this.props.delete(); |     this.props.delete(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyMoveUp = () => { |   handleHotkeyMoveUp = () => { | ||||||
|     this.props.onMoveUp(this.props.conversationId); |     this.props.onMoveUp(this.props.conversationId); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyMoveDown = () => { |   handleHotkeyMoveDown = () => { | ||||||
|     this.props.onMoveDown(this.props.conversationId); |     this.props.onMoveDown(this.props.conversationId); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleConversationMute = () => { |   handleConversationMute = () => { | ||||||
|     this.props.onMute(this.props.lastStatus); |     this.props.onMute(this.props.lastStatus); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleShowMore = () => { |   handleShowMore = () => { | ||||||
|     this.props.onToggleHidden(this.props.lastStatus); |     this.props.onToggleHidden(this.props.lastStatus); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { accounts, lastStatus, unread, scrollKey, intl } = this.props; |     const { accounts, lastStatus, unread, scrollKey, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -16,17 +16,17 @@ export default class ConversationsList extends ImmutablePureComponent { | ||||||
|     onLoadMore: PropTypes.func, |     onLoadMore: PropTypes.func, | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   getCurrentIndex = id => this.props.conversations.findIndex(x => x.get('id') === id) |   getCurrentIndex = id => this.props.conversations.findIndex(x => x.get('id') === id); | ||||||
| 
 | 
 | ||||||
|   handleMoveUp = id => { |   handleMoveUp = id => { | ||||||
|     const elementIndex = this.getCurrentIndex(id) - 1; |     const elementIndex = this.getCurrentIndex(id) - 1; | ||||||
|     this._selectChild(elementIndex, true); |     this._selectChild(elementIndex, true); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMoveDown = id => { |   handleMoveDown = id => { | ||||||
|     const elementIndex = this.getCurrentIndex(id) + 1; |     const elementIndex = this.getCurrentIndex(id) + 1; | ||||||
|     this._selectChild(elementIndex, false); |     this._selectChild(elementIndex, false); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _selectChild (index, align_top) { |   _selectChild (index, align_top) { | ||||||
|     const container = this.node.node; |     const container = this.node.node; | ||||||
|  | @ -44,7 +44,7 @@ export default class ConversationsList extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadOlder = debounce(() => { |   handleLoadOlder = debounce(() => { | ||||||
|     const last = this.props.conversations.last(); |     const last = this.props.conversations.last(); | ||||||
|  | @ -52,7 +52,7 @@ export default class ConversationsList extends ImmutablePureComponent { | ||||||
|     if (last && last.get('last_status')) { |     if (last && last.get('last_status')) { | ||||||
|       this.props.onLoadMore(last.get('last_status')); |       this.props.onLoadMore(last.get('last_status')); | ||||||
|     } |     } | ||||||
|   }, 300, { leading: true }) |   }, 300, { leading: true }); | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { conversations, onLoadMore, ...other } = this.props; |     const { conversations, onLoadMore, ...other } = this.props; | ||||||
|  |  | ||||||
|  | @ -34,16 +34,16 @@ class DirectTimeline extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(addColumn('DIRECT', {})); |       dispatch(addColumn('DIRECT', {})); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMove = (dir) => { |   handleMove = (dir) => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|  | @ -64,11 +64,11 @@ class DirectTimeline extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = maxId => { |   handleLoadMore = maxId => { | ||||||
|     this.props.dispatch(expandConversations({ maxId })); |     this.props.dispatch(expandConversations({ maxId })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, hasUnread, columnId, multiColumn } = this.props; |     const { intl, hasUnread, columnId, multiColumn } = this.props; | ||||||
|  |  | ||||||
|  | @ -115,7 +115,7 @@ class AccountCard extends ImmutablePureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-original'); |       emoji.src = emoji.getAttribute('data-original'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = ({ currentTarget }) => { |   handleMouseLeave = ({ currentTarget }) => { | ||||||
|     if (autoPlayGif) { |     if (autoPlayGif) { | ||||||
|  | @ -128,7 +128,7 @@ class AccountCard extends ImmutablePureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-static'); |       emoji.src = emoji.getAttribute('data-static'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleFollow = () => { |   handleFollow = () => { | ||||||
|     this.props.onFollow(this.props.account); |     this.props.onFollow(this.props.account); | ||||||
|  | @ -140,11 +140,11 @@ class AccountCard extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleMute = () => { |   handleMute = () => { | ||||||
|     this.props.onMute(this.props.account); |     this.props.onMute(this.props.account); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleEditProfile = () => { |   handleEditProfile = () => { | ||||||
|     window.open('/settings/profile', '_blank'); |     window.open('/settings/profile', '_blank'); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { account, intl } = this.props; |     const { account, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -64,7 +64,7 @@ class Directory extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(addColumn('DIRECTORY', this.getParams(this.props, this.state))); |       dispatch(addColumn('DIRECTORY', this.getParams(this.props, this.state))); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getParams = (props, state) => ({ |   getParams = (props, state) => ({ | ||||||
|     order: state.order === null ? (props.params.order || 'active') : state.order, |     order: state.order === null ? (props.params.order || 'active') : state.order, | ||||||
|  | @ -74,11 +74,11 @@ class Directory extends React.PureComponent { | ||||||
|   handleMove = dir => { |   handleMove = dir => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|  | @ -97,7 +97,7 @@ class Directory extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleChangeOrder = e => { |   handleChangeOrder = e => { | ||||||
|     const { dispatch, columnId } = this.props; |     const { dispatch, columnId } = this.props; | ||||||
|  | @ -107,7 +107,7 @@ class Directory extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.setState({ order: e.target.value }); |       this.setState({ order: e.target.value }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleChangeLocal = e => { |   handleChangeLocal = e => { | ||||||
|     const { dispatch, columnId } = this.props; |     const { dispatch, columnId } = this.props; | ||||||
|  | @ -117,12 +117,12 @@ class Directory extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.setState({ local: e.target.value === '1' }); |       this.setState({ local: e.target.value === '1' }); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = () => { |   handleLoadMore = () => { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|     dispatch(expandDirectory(this.getParams(this.props, this.state))); |     dispatch(expandDirectory(this.getParams(this.props, this.state))); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { isLoading, accountIds, intl, columnId, multiColumn, domain } = this.props; |     const { isLoading, accountIds, intl, columnId, multiColumn, domain } = this.props; | ||||||
|  |  | ||||||
|  | @ -135,19 +135,19 @@ function getData(emoji, skin, set) { | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (data.short_names.hasOwnProperty(emoji)) { |     if (Object.prototype.hasOwnProperty.call(data.short_names, emoji)) { | ||||||
|       emoji = data.short_names[emoji]; |       emoji = data.short_names[emoji]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (data.emojis.hasOwnProperty(emoji)) { |     if (Object.prototype.hasOwnProperty.call(data.emojis, emoji)) { | ||||||
|       emojiData = data.emojis[emoji]; |       emojiData = data.emojis[emoji]; | ||||||
|     } |     } | ||||||
|   } else if (emoji.id) { |   } else if (emoji.id) { | ||||||
|     if (data.short_names.hasOwnProperty(emoji.id)) { |     if (Object.prototype.hasOwnProperty.call(data.short_names, emoji.id)) { | ||||||
|       emoji.id = data.short_names[emoji.id]; |       emoji.id = data.short_names[emoji.id]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (data.emojis.hasOwnProperty(emoji.id)) { |     if (Object.prototype.hasOwnProperty.call(data.emojis, emoji.id)) { | ||||||
|       emojiData = data.emojis[emoji.id]; |       emojiData = data.emojis[emoji.id]; | ||||||
|       skin = skin || emoji.skin; |       skin = skin || emoji.skin; | ||||||
|     } |     } | ||||||
|  | @ -216,7 +216,7 @@ function deepMerge(a, b) { | ||||||
|     let originalValue = a[key], |     let originalValue = a[key], | ||||||
|       value = originalValue; |       value = originalValue; | ||||||
| 
 | 
 | ||||||
|     if (b.hasOwnProperty(key)) { |     if (Object.prototype.hasOwnProperty.call(b, key)) { | ||||||
|       value = b[key]; |       value = b[key]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,11 +41,11 @@ class Explore extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { intl, multiColumn, isSearching } = this.props; |     const { intl, multiColumn, isSearching } = this.props; | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ class Statuses extends React.PureComponent { | ||||||
|   handleLoadMore = debounce(() => { |   handleLoadMore = debounce(() => { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|     dispatch(expandTrendingStatuses()); |     dispatch(expandTrendingStatuses()); | ||||||
|   }, 300, { leading: true }) |   }, 300, { leading: true }); | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { isLoading, hasMore, statusIds, multiColumn } = this.props; |     const { isLoading, hasMore, statusIds, multiColumn } = this.props; | ||||||
|  |  | ||||||
|  | @ -48,24 +48,24 @@ class Favourites extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(addColumn('FAVOURITES', {})); |       dispatch(addColumn('FAVOURITES', {})); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMove = (dir) => { |   handleMove = (dir) => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = debounce(() => { |   handleLoadMore = debounce(() => { | ||||||
|     this.props.dispatch(expandFavouritedStatuses()); |     this.props.dispatch(expandFavouritedStatuses()); | ||||||
|   }, 300, { leading: true }) |   }, 300, { leading: true }); | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props; |     const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props; | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ class Favourites extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleRefresh = () => { |   handleRefresh = () => { | ||||||
|     this.props.dispatch(fetchFavourites(this.props.params.statusId)); |     this.props.dispatch(fetchFavourites(this.props.params.statusId)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, accountIds, multiColumn } = this.props; |     const { intl, accountIds, multiColumn } = this.props; | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ class SelectFilter extends React.PureComponent { | ||||||
|         <span className='language-dropdown__dropdown__results__item__native-name'>{filter[1]}</span> {warning} |         <span className='language-dropdown__dropdown__results__item__native-name'>{filter[1]}</span> {warning} | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   renderCreateNew (name) { |   renderCreateNew (name) { | ||||||
|     return ( |     return ( | ||||||
|  | @ -83,11 +83,11 @@ class SelectFilter extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleSearchChange = ({ target }) => { |   handleSearchChange = ({ target }) => { | ||||||
|     this.setState({ searchValue: target.value }); |     this.setState({ searchValue: target.value }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setListRef = c => { |   setListRef = c => { | ||||||
|     this.listNode = c; |     this.listNode = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyDown = e => { |   handleKeyDown = e => { | ||||||
|     const index = Array.from(this.listNode.childNodes).findIndex(node => node === e.currentTarget); |     const index = Array.from(this.listNode.childNodes).findIndex(node => node === e.currentTarget); | ||||||
|  | @ -125,7 +125,7 @@ class SelectFilter extends React.PureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       e.stopPropagation(); |       e.stopPropagation(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleSearchKeyDown = e => { |   handleSearchKeyDown = e => { | ||||||
|     let element = null; |     let element = null; | ||||||
|  | @ -143,11 +143,11 @@ class SelectFilter extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClear = () => { |   handleClear = () => { | ||||||
|     this.setState({ searchValue: '' }); |     this.setState({ searchValue: '' }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleItemClick = e => { |   handleItemClick = e => { | ||||||
|     const value = e.currentTarget.getAttribute('data-index'); |     const value = e.currentTarget.getAttribute('data-index'); | ||||||
|  | @ -155,7 +155,7 @@ class SelectFilter extends React.PureComponent { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
| 
 | 
 | ||||||
|     this.props.onSelectFilter(value); |     this.props.onSelectFilter(value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleNewFilterClick = e => { |   handleNewFilterClick = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ class Account extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(followAccount(account.get('id'))); |       dispatch(followAccount(account.get('id'))); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { account, intl } = this.props; |     const { account, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ class FollowRecommendations extends ImmutablePureComponent { | ||||||
|     })); |     })); | ||||||
| 
 | 
 | ||||||
|     router.history.push('/home'); |     router.history.push('/home'); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { suggestions, isLoading } = this.props; |     const { suggestions, isLoading } = this.props; | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ class FollowedTags extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   componentDidMount() { |   componentDidMount() { | ||||||
|     this.props.dispatch(fetchFollowedHashtags()); |     this.props.dispatch(fetchFollowedHashtags()); | ||||||
|   }; |   } | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = debounce(() => { |   handleLoadMore = debounce(() => { | ||||||
|     this.props.dispatch(expandFollowedHashtags()); |     this.props.dispatch(expandFollowedHashtags()); | ||||||
|  |  | ||||||
|  | @ -35,7 +35,7 @@ class Content extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     this._updateLinks(); |     this._updateLinks(); | ||||||
|  | @ -89,7 +89,7 @@ class Content extends ImmutablePureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       this.context.router.history.push(`/@${mention.get('acct')}`); |       this.context.router.history.push(`/@${mention.get('acct')}`); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onHashtagClick = (hashtag, e) => { |   onHashtagClick = (hashtag, e) => { | ||||||
|     hashtag = hashtag.replace(/^#/, ''); |     hashtag = hashtag.replace(/^#/, ''); | ||||||
|  | @ -98,14 +98,14 @@ class Content extends ImmutablePureComponent { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       this.context.router.history.push(`/tags/${hashtag}`); |       this.context.router.history.push(`/tags/${hashtag}`); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onStatusClick = (status, e) => { |   onStatusClick = (status, e) => { | ||||||
|     if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { |     if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { | ||||||
|       e.preventDefault(); |       e.preventDefault(); | ||||||
|       this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); |       this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseEnter = ({ currentTarget }) => { |   handleMouseEnter = ({ currentTarget }) => { | ||||||
|     if (autoPlayGif) { |     if (autoPlayGif) { | ||||||
|  | @ -118,7 +118,7 @@ class Content extends ImmutablePureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-original'); |       emoji.src = emoji.getAttribute('data-original'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = ({ currentTarget }) => { |   handleMouseLeave = ({ currentTarget }) => { | ||||||
|     if (autoPlayGif) { |     if (autoPlayGif) { | ||||||
|  | @ -131,7 +131,7 @@ class Content extends ImmutablePureComponent { | ||||||
|       let emoji = emojis[i]; |       let emoji = emojis[i]; | ||||||
|       emoji.src = emoji.getAttribute('data-static'); |       emoji.src = emoji.getAttribute('data-static'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { announcement } = this.props; |     const { announcement } = this.props; | ||||||
|  | @ -216,11 +216,11 @@ class Reaction extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       addReaction(announcementId, reaction.get('name')); |       addReaction(announcementId, reaction.get('name')); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMouseEnter = () => this.setState({ hovered: true }) |   handleMouseEnter = () => this.setState({ hovered: true }); | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave = () => this.setState({ hovered: false }) |   handleMouseLeave = () => this.setState({ hovered: false }); | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { reaction } = this.props; |     const { reaction } = this.props; | ||||||
|  | @ -254,7 +254,7 @@ class ReactionsBar extends ImmutablePureComponent { | ||||||
|   handleEmojiPick = data => { |   handleEmojiPick = data => { | ||||||
|     const { addReaction, announcementId } = this.props; |     const { addReaction, announcementId } = this.props; | ||||||
|     addReaction(announcementId, data.native.replace(/:/g, '')); |     addReaction(announcementId, data.native.replace(/:/g, '')); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   willEnter () { |   willEnter () { | ||||||
|     return { scale: reduceMotion ? 1 : 0 }; |     return { scale: reduceMotion ? 1 : 0 }; | ||||||
|  | @ -397,15 +397,15 @@ class Announcements extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   handleChangeIndex = index => { |   handleChangeIndex = index => { | ||||||
|     this.setState({ index: index % this.props.announcements.size }); |     this.setState({ index: index % this.props.announcements.size }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleNextClick = () => { |   handleNextClick = () => { | ||||||
|     this.setState({ index: (this.state.index + 1) % this.props.announcements.size }); |     this.setState({ index: (this.state.index + 1) % this.props.announcements.size }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handlePrevClick = () => { |   handlePrevClick = () => { | ||||||
|     this.setState({ index: (this.props.announcements.size + this.state.index - 1) % this.props.announcements.size }); |     this.setState({ index: (this.props.announcements.size + this.state.index - 1) % this.props.announcements.size }); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { announcements, intl } = this.props; |     const { announcements, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ class HashtagTimeline extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(addColumn('HASHTAG', { id: this.props.params.id })); |       dispatch(addColumn('HASHTAG', { id: this.props.params.id })); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   title = () => { |   title = () => { | ||||||
|     const { id } = this.props.params; |     const { id } = this.props.params; | ||||||
|  | @ -73,7 +73,7 @@ class HashtagTimeline extends React.PureComponent { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return title; |     return title; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   additionalFor = (mode) => { |   additionalFor = (mode) => { | ||||||
|     const { tags } = this.props.params; |     const { tags } = this.props.params; | ||||||
|  | @ -83,16 +83,16 @@ class HashtagTimeline extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       return ''; |       return ''; | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMove = (dir) => { |   handleMove = (dir) => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _subscribe (dispatch, id, tags = {}, local) { |   _subscribe (dispatch, id, tags = {}, local) { | ||||||
|     const { signedIn } = this.context.identity; |     const { signedIn } = this.context.identity; | ||||||
|  | @ -157,14 +157,14 @@ class HashtagTimeline extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = maxId => { |   handleLoadMore = maxId => { | ||||||
|     const { dispatch, params } = this.props; |     const { dispatch, params } = this.props; | ||||||
|     const { id, tags, local }  = params; |     const { id, tags, local }  = params; | ||||||
| 
 | 
 | ||||||
|     dispatch(expandHashtagTimeline(id, { maxId, tags, local })); |     dispatch(expandHashtagTimeline(id, { maxId, tags, local })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleFollow = () => { |   handleFollow = () => { | ||||||
|     const { dispatch, params, tag } = this.props; |     const { dispatch, params, tag } = this.props; | ||||||
|  | @ -180,7 +180,7 @@ class HashtagTimeline extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(followHashtag(id)); |       dispatch(followHashtag(id)); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { hasUnread, columnId, multiColumn, tag, intl } = this.props; |     const { hasUnread, columnId, multiColumn, tag, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -58,24 +58,24 @@ class HomeTimeline extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(addColumn('HOME', {})); |       dispatch(addColumn('HOME', {})); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMove = (dir) => { |   handleMove = (dir) => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = maxId => { |   handleLoadMore = maxId => { | ||||||
|     this.props.dispatch(expandHomeTimeline({ maxId })); |     this.props.dispatch(expandHomeTimeline({ maxId })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     setTimeout(() => this.props.dispatch(fetchAnnouncements()), 700); |     setTimeout(() => this.props.dispatch(fetchAnnouncements()), 700); | ||||||
|  | @ -114,7 +114,7 @@ class HomeTimeline extends React.PureComponent { | ||||||
|   handleToggleAnnouncementsClick = (e) => { |   handleToggleAnnouncementsClick = (e) => { | ||||||
|     e.stopPropagation(); |     e.stopPropagation(); | ||||||
|     this.props.dispatch(toggleShowAnnouncements()); |     this.props.dispatch(toggleShowAnnouncements()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl, hasUnread, columnId, multiColumn, hasAnnouncements, unreadAnnouncements, showAnnouncements } = this.props; |     const { intl, hasUnread, columnId, multiColumn, hasAnnouncements, unreadAnnouncements, showAnnouncements } = this.props; | ||||||
|  |  | ||||||
|  | @ -30,14 +30,14 @@ class Copypaste extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.input = c; |     this.input = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleInputClick = () => { |   handleInputClick = () => { | ||||||
|     this.setState({ copied: false }); |     this.setState({ copied: false }); | ||||||
|     this.input.focus(); |     this.input.focus(); | ||||||
|     this.input.select(); |     this.input.select(); | ||||||
|     this.input.setSelectionRange(0, this.input.value.length); |     this.input.setSelectionRange(0, this.input.value.length); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleButtonClick = () => { |   handleButtonClick = () => { | ||||||
|     const { value } = this.props; |     const { value } = this.props; | ||||||
|  | @ -45,7 +45,7 @@ class Copypaste extends React.PureComponent { | ||||||
|     this.input.blur(); |     this.input.blur(); | ||||||
|     this.setState({ copied: true }); |     this.setState({ copied: true }); | ||||||
|     this.timeout = setTimeout(() => this.setState({ copied: false }), 700); |     this.timeout = setTimeout(() => this.setState({ copied: false }), 700); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillUnmount () { |   componentWillUnmount () { | ||||||
|     if (this.timeout) clearTimeout(this.timeout); |     if (this.timeout) clearTimeout(this.timeout); | ||||||
|  | @ -86,7 +86,7 @@ class InteractionModal extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleSignupClick = () => { |   handleSignupClick = () => { | ||||||
|     this.props.onSignupClick(); |     this.props.onSignupClick(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { url, type, displayNameHtml } = this.props; |     const { url, type, displayNameHtml } = this.props; | ||||||
|  |  | ||||||
|  | @ -33,16 +33,16 @@ class ListForm extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleChange = e => { |   handleChange = e => { | ||||||
|     this.props.onChange(e.target.value); |     this.props.onChange(e.target.value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleSubmit = e => { |   handleSubmit = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     this.props.onSubmit(); |     this.props.onSubmit(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     this.props.onSubmit(); |     this.props.onSubmit(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, disabled, intl } = this.props; |     const { value, disabled, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -34,17 +34,17 @@ class Search extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleChange = e => { |   handleChange = e => { | ||||||
|     this.props.onChange(e.target.value); |     this.props.onChange(e.target.value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleKeyUp = e => { |   handleKeyUp = e => { | ||||||
|     if (e.keyCode === 13) { |     if (e.keyCode === 13) { | ||||||
|       this.props.onSubmit(this.props.value); |       this.props.onSubmit(this.props.value); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClear = () => { |   handleClear = () => { | ||||||
|     this.props.onClear(); |     this.props.onClear(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, intl } = this.props; |     const { value, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -58,16 +58,16 @@ class ListTimeline extends React.PureComponent { | ||||||
|       dispatch(addColumn('LIST', { id: this.props.params.id })); |       dispatch(addColumn('LIST', { id: this.props.params.id })); | ||||||
|       this.context.router.history.push('/'); |       this.context.router.history.push('/'); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMove = (dir) => { |   handleMove = (dir) => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|  | @ -105,16 +105,16 @@ class ListTimeline extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleLoadMore = maxId => { |   handleLoadMore = maxId => { | ||||||
|     const { id } = this.props.params; |     const { id } = this.props.params; | ||||||
|     this.props.dispatch(expandListTimeline(id, { maxId })); |     this.props.dispatch(expandListTimeline(id, { maxId })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleEditClick = () => { |   handleEditClick = () => { | ||||||
|     this.props.dispatch(openModal('LIST_EDITOR', { listId: this.props.params.id })); |     this.props.dispatch(openModal('LIST_EDITOR', { listId: this.props.params.id })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleDeleteClick = () => { |   handleDeleteClick = () => { | ||||||
|     const { dispatch, columnId, intl } = this.props; |     const { dispatch, columnId, intl } = this.props; | ||||||
|  | @ -133,13 +133,13 @@ class ListTimeline extends React.PureComponent { | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|     })); |     })); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleRepliesPolicyChange = ({ target }) => { |   handleRepliesPolicyChange = ({ target }) => { | ||||||
|     const { dispatch } = this.props; |     const { dispatch } = this.props; | ||||||
|     const { id } = this.props.params; |     const { id } = this.props.params; | ||||||
|     dispatch(updateList(id, undefined, false, target.value)); |     dispatch(updateList(id, undefined, false, target.value)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { hasUnread, columnId, multiColumn, list, intl } = this.props; |     const { hasUnread, columnId, multiColumn, list, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -34,16 +34,16 @@ class NewListForm extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleChange = e => { |   handleChange = e => { | ||||||
|     this.props.onChange(e.target.value); |     this.props.onChange(e.target.value); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleSubmit = e => { |   handleSubmit = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|     this.props.onSubmit(); |     this.props.onSubmit(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     this.props.onSubmit(); |     this.props.onSubmit(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, disabled, intl } = this.props; |     const { value, disabled, intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ export default class ColumnSettings extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   onPushChange = (path, checked) => { |   onPushChange = (path, checked) => { | ||||||
|     this.props.onChange(['push', ...path], checked); |     this.props.onChange(['push', ...path], checked); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission } = this.props; |     const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission } = this.props; | ||||||
|  |  | ||||||
|  | @ -61,12 +61,12 @@ class Notification extends ImmutablePureComponent { | ||||||
|   handleMoveUp = () => { |   handleMoveUp = () => { | ||||||
|     const { notification, onMoveUp } = this.props; |     const { notification, onMoveUp } = this.props; | ||||||
|     onMoveUp(notification.get('id')); |     onMoveUp(notification.get('id')); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMoveDown = () => { |   handleMoveDown = () => { | ||||||
|     const { notification, onMoveDown } = this.props; |     const { notification, onMoveDown } = this.props; | ||||||
|     onMoveDown(notification.get('id')); |     onMoveDown(notification.get('id')); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOpen = () => { |   handleOpen = () => { | ||||||
|     const { notification } = this.props; |     const { notification } = this.props; | ||||||
|  | @ -76,34 +76,34 @@ class Notification extends ImmutablePureComponent { | ||||||
|     } else { |     } else { | ||||||
|       this.handleOpenProfile(); |       this.handleOpenProfile(); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleOpenProfile = () => { |   handleOpenProfile = () => { | ||||||
|     const { notification } = this.props; |     const { notification } = this.props; | ||||||
|     this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`); |     this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMention = e => { |   handleMention = e => { | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
| 
 | 
 | ||||||
|     const { notification, onMention } = this.props; |     const { notification, onMention } = this.props; | ||||||
|     onMention(notification.get('account'), this.context.router.history); |     onMention(notification.get('account'), this.context.router.history); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyFavourite = () => { |   handleHotkeyFavourite = () => { | ||||||
|     const { status } = this.props; |     const { status } = this.props; | ||||||
|     if (status) this.props.onFavourite(status); |     if (status) this.props.onFavourite(status); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyBoost = e => { |   handleHotkeyBoost = e => { | ||||||
|     const { status } = this.props; |     const { status } = this.props; | ||||||
|     if (status) this.props.onReblog(status, e); |     if (status) this.props.onReblog(status, e); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHotkeyToggleHidden = () => { |   handleHotkeyToggleHidden = () => { | ||||||
|     const { status } = this.props; |     const { status } = this.props; | ||||||
|     if (status) this.props.onToggleHidden(status); |     if (status) this.props.onToggleHidden(status); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   getHandlers () { |   getHandlers () { | ||||||
|     return { |     return { | ||||||
|  |  | ||||||
|  | @ -23,11 +23,11 @@ class NotificationsPermissionBanner extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   handleClick = () => { |   handleClick = () => { | ||||||
|     this.props.dispatch(requestBrowserPermission()); |     this.props.dispatch(requestBrowserPermission()); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleClose = () => { |   handleClose = () => { | ||||||
|     this.props.dispatch(changeSetting(['notifications', 'dismissPermissionBanner'], true)); |     this.props.dispatch(changeSetting(['notifications', 'dismissPermissionBanner'], true)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { intl } = this.props; |     const { intl } = this.props; | ||||||
|  |  | ||||||
|  | @ -13,11 +13,11 @@ export default class SettingToggle extends React.PureComponent { | ||||||
|     onChange: PropTypes.func.isRequired, |     onChange: PropTypes.func.isRequired, | ||||||
|     defaultValue: PropTypes.bool, |     defaultValue: PropTypes.bool, | ||||||
|     disabled: PropTypes.bool, |     disabled: PropTypes.bool, | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   onChange = ({ target }) => { |   onChange = ({ target }) => { | ||||||
|     this.props.onChange(this.props.settingPath, target.checked); |     this.props.onChange(this.props.settingPath, target.checked); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { prefix, settings, settingPath, label, defaultValue, disabled } = this.props; |     const { prefix, settings, settingPath, label, defaultValue, disabled } = this.props; | ||||||
|  |  | ||||||
|  | @ -136,30 +136,30 @@ class Notifications extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       dispatch(addColumn('NOTIFICATIONS', {})); |       dispatch(addColumn('NOTIFICATIONS', {})); | ||||||
|     } |     } | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMove = (dir) => { |   handleMove = (dir) => { | ||||||
|     const { columnId, dispatch } = this.props; |     const { columnId, dispatch } = this.props; | ||||||
|     dispatch(moveColumn(columnId, dir)); |     dispatch(moveColumn(columnId, dir)); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleHeaderClick = () => { |   handleHeaderClick = () => { | ||||||
|     this.column.scrollTop(); |     this.column.scrollTop(); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   setColumnRef = c => { |   setColumnRef = c => { | ||||||
|     this.column = c; |     this.column = c; | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMoveUp = id => { |   handleMoveUp = id => { | ||||||
|     const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) - 1; |     const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) - 1; | ||||||
|     this._selectChild(elementIndex, true); |     this._selectChild(elementIndex, true); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   handleMoveDown = id => { |   handleMoveDown = id => { | ||||||
|     const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) + 1; |     const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) + 1; | ||||||
|     this._selectChild(elementIndex, false); |     this._selectChild(elementIndex, false); | ||||||
|   } |   }; | ||||||
| 
 | 
 | ||||||
|   _selectChild (index, align_top) { |   _selectChild (index, align_top) { | ||||||
|     const container = this.column.node; |     const container = this.column.node; | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue