Compare commits

..

1 commit

Author SHA1 Message Date
Effy Elden
aeed3a9a1b
Add publish_button_text site setting 2022-11-16 21:54:41 +11:00
659 changed files with 13013 additions and 37127 deletions

View file

@ -1,8 +1,8 @@
version: 2.1 version: 2.1
orbs: orbs:
ruby: circleci/ruby@2.0.0 ruby: circleci/ruby@1.4.1
node: circleci/node@5.0.3 node: circleci/node@5.0.1
executors: executors:
default: default:
@ -19,11 +19,11 @@ executors:
DB_USER: root DB_USER: root
DISABLE_SIMPLECOV: true DISABLE_SIMPLECOV: true
RAILS_ENV: test RAILS_ENV: test
- image: cimg/postgres:14.5 - image: cimg/postgres:14.0
environment: environment:
POSTGRES_USER: root POSTGRES_USER: root
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
- image: cimg/redis:7.0 - image: cimg/redis:6.2
commands: commands:
install-system-dependencies: install-system-dependencies:
@ -45,7 +45,7 @@ commands:
bundle config without 'development production' bundle config without 'development production'
name: Set bundler settings name: Set bundler settings
- ruby/install-deps: - ruby/install-deps:
bundler-version: '2.3.26' bundler-version: '2.3.8'
key: ruby<< parameters.ruby-version >>-gems-v1 key: ruby<< parameters.ruby-version >>-gems-v1
wait-db: wait-db:
steps: steps:
@ -68,9 +68,7 @@ jobs:
cache-version: v1 cache-version: v1
pkg-manager: yarn pkg-manager: yarn
- run: - run:
command: | command: ./bin/rails assets:precompile
export NODE_OPTIONS=--openssl-legacy-provider
./bin/rails assets:precompile
name: Precompile assets name: Precompile assets
- persist_to_workspace: - persist_to_workspace:
paths: paths:
@ -221,5 +219,5 @@ workflows:
pkg-manager: yarn pkg-manager: yarn
requires: requires:
- build - build
version: '16.18' version: lts
yarn-run: test:jest yarn-run: test:jest

View file

@ -9,7 +9,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/ruby:${VARIANT}
# The value is a comma-separated list of allowed domains # The value is a comma-separated list of allowed domains
ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev" ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev"
# [Choice] Node.js version: lts/*, 18, 16, 14 # [Choice] Node.js version: lts/*, 16, 14, 12, 10
ARG NODE_VERSION="lts/*" ARG NODE_VERSION="lts/*"
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1" RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"

View file

@ -2,7 +2,7 @@
"name": "Mastodon", "name": "Mastodon",
"dockerComposeFile": "docker-compose.yml", "dockerComposeFile": "docker-compose.yml",
"service": "app", "service": "app",
"workspaceFolder": "/mastodon", "workspaceFolder": "/workspaces/mastodon",
// Set *default* container specific settings.json values on container create. // Set *default* container specific settings.json values on container create.
"settings": {}, "settings": {},
@ -20,7 +20,7 @@
"forwardPorts": [3000, 4000], "forwardPorts": [3000, 4000],
// Use 'postCreateCommand' to run commands after the container is created. // Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": ".devcontainer/post-create.sh", "postCreateCommand": "bundle install --path vendor/bundle && yarn install && git checkout -- Gemfile.lock && ./bin/rails db:setup",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode" "remoteUser": "vscode"

View file

@ -11,9 +11,9 @@ services:
# Use -bullseye variants on local arm64/Apple Silicon. # Use -bullseye variants on local arm64/Apple Silicon.
VARIANT: '3.0-bullseye' VARIANT: '3.0-bullseye'
# Optional Node.js version to install # Optional Node.js version to install
NODE_VERSION: '16' NODE_VERSION: '14'
volumes: volumes:
- ..:/mastodon:cached - ..:/workspaces/mastodon:cached
environment: environment:
RAILS_ENV: development RAILS_ENV: development
NODE_ENV: development NODE_ENV: development

View file

@ -1,21 +0,0 @@
#!/bin/bash
set -e # Fail the whole script on first error
# Fetch Ruby gem dependencies
bundle install --path vendor/bundle --with='development test'
# Fetch Javascript dependencies
yarn install
# Make Gemfile.lock pristine again
git checkout -- Gemfile.lock
# [re]create, migrate, and seed the test database
RAILS_ENV=test ./bin/rails db:setup
# Precompile assets for development
RAILS_ENV=development ./bin/rails assets:precompile
# Precompile assets for test
RAILS_ENV=test NODE_ENV=tests ./bin/rails assets:precompile

View file

@ -54,7 +54,7 @@ VAPID_PUBLIC_KEY=
# Sending mail # Sending mail
# ------------ # ------------
SMTP_SERVER= SMTP_SERVER=smtp.mailgun.org
SMTP_PORT=587 SMTP_PORT=587
SMTP_LOGIN= SMTP_LOGIN=
SMTP_PASSWORD= SMTP_PASSWORD=

View file

@ -1,10 +1,6 @@
module.exports = { module.exports = {
root: true, root: true,
extends: [
'eslint:recommended',
],
env: { env: {
browser: true, browser: true,
node: true, node: true,
@ -68,8 +64,8 @@ module.exports = {
eqeqeq: 'error', eqeqeq: 'error',
indent: ['warn', 2], indent: ['warn', 2],
'jsx-quotes': ['error', 'prefer-single'], 'jsx-quotes': ['error', 'prefer-single'],
'no-case-declarations': 'off',
'no-catch-shadow': 'error', 'no-catch-shadow': 'error',
'no-cond-assign': 'error',
'no-console': [ 'no-console': [
'warn', 'warn',
{ {
@ -79,16 +75,18 @@ module.exports = {
], ],
}, },
], ],
'no-empty': 'off', 'no-fallthrough': 'error',
'no-irregular-whitespace': 'error',
'no-mixed-spaces-and-tabs': 'warn',
'no-nested-ternary': 'warn', '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.' },
{ property: 'substr', message: 'Use .slice instead of .substr.' }, { property: 'substr', message: 'Use .slice instead of .substr.' },
], ],
'no-self-assign': 'off',
'no-trailing-spaces': 'warn', 'no-trailing-spaces': 'warn',
'no-undef': 'error',
'no-unreachable': 'error',
'no-unused-expressions': 'error', 'no-unused-expressions': 'error',
'no-unused-vars': [ 'no-unused-vars': [
'error', 'error',
@ -98,7 +96,6 @@ module.exports = {
ignoreRestSiblings: true, ignoreRestSiblings: true,
}, },
], ],
'no-useless-escape': 'off',
'object-curly-spacing': ['error', 'always'], 'object-curly-spacing': ['error', 'always'],
'padded-blocks': [ 'padded-blocks': [
'error', 'error',
@ -108,6 +105,7 @@ module.exports = {
], ],
quotes: ['error', 'single'], quotes: ['error', 'single'],
semi: 'error', semi: 'error',
strict: 'off',
'valid-typeof': 'error', 'valid-typeof': 'error',
'react/jsx-boolean-value': 'error', 'react/jsx-boolean-value': 'error',

View file

@ -1,6 +1,6 @@
name: Bug Report name: Bug Report
description: If something isn't working as expected description: If something isn't working as expected
labels: [bug] labels: bug
body: body:
- type: markdown - type: markdown
attributes: attributes:

View file

@ -1,6 +1,6 @@
name: Feature Request name: Feature Request
description: I have a suggestion description: I have a suggestion
labels: [suggestion] labels: suggestion
body: body:
- type: markdown - type: markdown
attributes: attributes:

View file

@ -18,7 +18,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: hadolint/hadolint-action@v3.0.0
- uses: docker/setup-qemu-action@v2 - uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2 - uses: docker/setup-buildx-action@v2
- uses: docker/login-action@v2 - uses: docker/login-action@v2
@ -41,8 +40,7 @@ jobs:
with: with:
context: . context: .
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
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 }}
cache-from: type=gha cache-from: type=registry,ref=tootsuite/mastodon:edge
cache-to: type=gha,mode=max cache-to: type=inline

View file

@ -25,7 +25,7 @@ jobs:
- name: Set up Ruby - name: Set up Ruby
uses: ruby/setup-ruby@v1 uses: ruby/setup-ruby@v1
with: with:
ruby-version: .ruby-version ruby-version: '3.0'
bundler-cache: true bundler-cache: true
- name: Check locale file normalization - name: Check locale file normalization
run: bundle exec i18n-tasks check-normalized run: bundle exec i18n-tasks check-normalized

View file

@ -1,62 +0,0 @@
name: 'CodeQL'
on:
push:
branches: ['main']
pull_request:
# The branches below must be a subset of the branches above
branches: ['main']
schedule:
- cron: '22 6 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript', 'ruby']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: '/language:${{matrix.language}}'

View file

@ -53,12 +53,10 @@ jobs:
- name: Set-up Node.js - name: Set-up Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version-file: .nvmrc node-version: 16.x
cache: yarn cache: yarn
- name: Install dependencies - name: Install dependencies
run: yarn install --frozen-lockfile run: yarn install --frozen-lockfile
- name: Check prettier formatting
run: yarn format-check
- name: Set-up RuboCop Problem Mathcher - name: Set-up RuboCop Problem Mathcher
uses: r7kamura/rubocop-problem-matchers-action@v1 uses: r7kamura/rubocop-problem-matchers-action@v1
- name: Set-up Stylelint Problem Matcher - name: Set-up Stylelint Problem Matcher

View file

@ -1,17 +0,0 @@
name: PR Needs Rebase
on:
push:
pull_request_target:
types: [synchronize]
jobs:
label-rebase-needed:
runs-on: ubuntu-latest
steps:
- name: Check for merge conflicts
uses: eps1lon/actions-label-merge-conflict@releases/2.x
with:
dirtyLabel: 'rebase needed :construction:'
repoToken: '${{ secrets.GITHUB_TOKEN }}'
commentOnDirty: This pull request has merge conflicts that must be resolved before it can be merged.

138
.github/workflows/test-chart.yml vendored Normal file
View file

@ -0,0 +1,138 @@
# This is a GitHub workflow defining a set of jobs with a set of steps.
# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
#
name: Test chart
on:
pull_request:
paths:
- "chart/**"
- "!**.md"
- ".github/workflows/test-chart.yml"
push:
paths:
- "chart/**"
- "!**.md"
- ".github/workflows/test-chart.yml"
branches-ignore:
- "dependabot/**"
workflow_dispatch:
permissions:
contents: read
defaults:
run:
working-directory: chart
jobs:
lint-templates:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Install dependencies (yamllint)
run: pip install yamllint
- run: helm dependency update
- name: helm lint
run: |
helm lint . \
--values dev-values.yaml
- name: helm template
run: |
helm template . \
--values dev-values.yaml \
--output-dir rendered-templates
- name: yamllint (only on templates we manage)
run: |
rm -rf rendered-templates/mastodon/charts
yamllint rendered-templates \
--config-data "{rules: {indentation: {spaces: 2}, line-length: disable}}"
# This job helps us validate that rendered templates are valid k8s resources
# against a k8s api-server, via "helm template --validate", but also that a
# basic configuration can be used to successfully startup mastodon.
#
test-install:
runs-on: ubuntu-22.04
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
# k3s-channel reference: https://update.k3s.io/v1-release/channels
- k3s-channel: latest
- k3s-channel: stable
# This represents the oldest configuration we test against.
#
# The k8s version chosen is based on the oldest still supported k8s
# version among two managed k8s services, GKE, EKS.
# - GKE: https://endoflife.date/google-kubernetes-engine
# - EKS: https://endoflife.date/amazon-eks
#
# The helm client's version can influence what helper functions is
# available for use in the templates, currently we need v3.6.0 or
# higher.
#
- k3s-channel: v1.21
helm-version: v3.6.0
steps:
- uses: actions/checkout@v3
# This action starts a k8s cluster with NetworkPolicy enforcement and
# installs both kubectl and helm.
#
# ref: https://github.com/jupyterhub/action-k3s-helm#readme
#
- uses: jupyterhub/action-k3s-helm@v3
with:
k3s-channel: ${{ matrix.k3s-channel }}
helm-version: ${{ matrix.helm-version }}
metrics-enabled: false
traefik-enabled: false
docker-enabled: false
- run: helm dependency update
# Validate rendered helm templates against the k8s api-server
- name: helm template --validate
run: |
helm template --validate mastodon . \
--values dev-values.yaml
- name: helm install
run: |
helm install mastodon . \
--values dev-values.yaml \
--timeout 10m
# This actions provides a report about the state of the k8s cluster,
# providing logs etc on anything that has failed and workloads marked as
# important.
#
# ref: https://github.com/jupyterhub/action-k8s-namespace-report#readme
#
- name: Kubernetes namespace report
uses: jupyterhub/action-k8s-namespace-report@v1
if: always()
with:
important-workloads: >-
deploy/mastodon-sidekiq
deploy/mastodon-streaming
deploy/mastodon-web
job/mastodon-assets-precompile
job/mastodon-chewy-upgrade
job/mastodon-create-admin
job/mastodon-db-migrate

6
.gitignore vendored
View file

@ -44,6 +44,12 @@
/redis /redis
/elasticsearch /elasticsearch
# ignore Helm charts
/chart/*.tgz
# ignore Helm dependency charts
/chart/charts/*.tgz
# Ignore Apple files # Ignore Apple files
.DS_Store .DS_Store

2
.nvmrc
View file

@ -1 +1 @@
16 14

View file

@ -44,6 +44,9 @@
/redis /redis
/elasticsearch /elasticsearch
# ignore Helm dependency charts
/chart/charts/*.tgz
# Ignore Apple files # Ignore Apple files
.DS_Store .DS_Store
@ -64,6 +67,9 @@ yarn-debug.log
# Ignore Docker option files # Ignore Docker option files
docker-compose.override.yml docker-compose.override.yml
# Ignore Helm files
/chart
# Ignore emoji map file # Ignore emoji map file
/app/javascript/mastodon/features/emoji/emoji_map.json /app/javascript/mastodon/features/emoji/emoji_map.json

View file

@ -1,18 +1,12 @@
require: require:
- rubocop-rails - rubocop-rails
- rubocop-rspec
- rubocop-performance
AllCops: AllCops:
TargetRubyVersion: 2.7 TargetRubyVersion: 2.5
DisplayCopNames: true NewCops: disable
DisplayStyleGuide: true
ExtraDetails: true
UseCache: true
CacheRootDirectory: tmp
NewCops: enable
Exclude: Exclude:
- db/schema.rb - 'spec/**/*'
- 'db/**/*'
- 'app/views/**/*' - 'app/views/**/*'
- 'config/**/*' - 'config/**/*'
- 'bin/*' - 'bin/*'
@ -73,57 +67,15 @@ Lint/UselessAccessModifier:
- class_methods - class_methods
Metrics/AbcSize: Metrics/AbcSize:
Max: 34 # RuboCop default 17 Max: 115
Exclude: Exclude:
- 'lib/**/*cli*.rb' - 'lib/mastodon/*_cli.rb'
- db/*migrate/**/*
- lib/paperclip/color_extractor.rb
- app/workers/scheduler/follow_recommendations_scheduler.rb
- app/services/activitypub/fetch*_service.rb
- lib/paperclip/**/*
CountRepeatedAttributes: false
AllowedMethods:
- update_media_attachments!
- account_link_to
- attempt_oembed
- build_crutches
- calculate_scores
- cc
- dump_actor!
- filter_from_home?
- hydrate
- import_bookmarks!
- import_relationships!
- initialize
- link_to_mention
- log_target
- matches_time_window?
- parse_metadata
- perform_statuses_search!
- privatize_media_attachments!
- process_update
- publish_media_attachments!
- remotable_attachment
- render_initial_state
- render_with_cache
- searchable_by
- self.cached_filters_for
- set_fetchable_attributes!
- signed_request_actor
- statuses_to_delete
- update_poll!
Metrics/BlockLength: Metrics/BlockLength:
Max: 55 Max: 55
Exclude: Exclude:
- 'lib/tasks/**/*'
- 'lib/mastodon/*_cli.rb' - 'lib/mastodon/*_cli.rb'
CountComments: false
CountAsOne: [array, heredoc]
AllowedMethods:
- task
- namespace
- class_methods
- included
Metrics/BlockNesting: Metrics/BlockNesting:
Max: 3 Max: 3
@ -133,144 +85,34 @@ Metrics/BlockNesting:
Metrics/ClassLength: Metrics/ClassLength:
CountComments: false CountComments: false
Max: 500 Max: 500
CountAsOne: [array, heredoc]
Exclude: Exclude:
- 'lib/mastodon/*_cli.rb' - 'lib/mastodon/*_cli.rb'
Metrics/CyclomaticComplexity: Metrics/CyclomaticComplexity:
Max: 12 Max: 25
Exclude: Exclude:
- lib/mastodon/*cli*.rb - 'lib/mastodon/*_cli.rb'
- db/*migrate/**/*
AllowedMethods:
- attempt_oembed
- blocked?
- build_crutches
- calculate_scores
- cc
- discover_endpoint!
- filter_from_home?
- hydrate
- klass
- link_to_mention
- log_target
- matches_time_window?
- patch_for_forwarding!
- preprocess_attributes!
- process_update
- remotable_attachment
- scan_text!
- self.cached_filters_for
- set_fetchable_attributes!
- setup_redis_env_url
- update_media_attachments!
Layout/LineLength: Layout/LineLength:
Max: 140 # RuboCop default 120
AllowHeredoc: true
AllowURI: true AllowURI: true
IgnoreCopDirectives: true Enabled: false
AllowedPatterns:
# Allow comments to be long lines
- !ruby/regexp / \# .*$/
- !ruby/regexp /^\# .*$/
Exclude:
- lib/**/*cli*.rb
- db/*migrate/**/*
- db/seeds/**/*
Metrics/MethodLength: Metrics/MethodLength:
CountComments: false CountComments: false
CountAsOne: [array, heredoc] Max: 65
Max: 25 # RuboCop default 10
Exclude: Exclude:
- 'lib/mastodon/*_cli.rb' - 'lib/mastodon/*_cli.rb'
AllowedMethods:
- account_link_to
- attempt_oembed
- body_with_limit
- build_crutches
- cached_filters_for
- calculate_scores
- check_webfinger!
- clean_feeds!
- collection_items
- collection_presenter
- copy_account_notes!
- deduplicate_accounts!
- deduplicate_conversations!
- deduplicate_local_accounts!
- deduplicate_statuses!
- deduplicate_tags!
- deduplicate_users!
- discover_endpoint!
- extract_extra_uris_with_indices
- extract_hashtags_with_indices
- extract_mentions_or_lists_with_indices
- filter_from_home?
- from_elasticsearch
- handle_explicit_update!
- handle_mark_as_sensitive!
- hsl_to_rgb
- import_bookmarks!
- import_domain_blocks!
- import_relationships!
- ldap_options
- matches_time_window?
- outbox_presenter
- pam_get_user
- parallelize_with_progress
- parse_and_transform
- patch_for_forwarding!
- populate_home
- post_process_style
- preload_cache_collection_target_statuses
- privatize_media_attachments!
- provides_callback_for
- publish_media_attachments!
- relevant_account_timestamp
- remotable_attachment
- rgb_to_hsl
- rss_status_content_format
- set_fetchable_attributes!
- setup_redis_env_url
- signed_request_actor
- to_preview_card_attributes
- upgrade_storage_filesystem
- upgrade_storage_s3
- user_settings_params
- hydrate
- cc
- self_destruct
Metrics/ModuleLength: Metrics/ModuleLength:
CountComments: false CountComments: false
Max: 200 Max: 200
CountAsOne: [array, heredoc]
Metrics/ParameterLists: Metrics/ParameterLists:
Max: 5 # RuboCop default 5 Max: 5
CountKeywordArgs: true # RuboCop default true CountKeywordArgs: true
MaxOptionalParameters: 3 # RuboCop default 3
Exclude:
- app/models/concerns/account_interactions.rb
- app/services/activitypub/fetch_remote_account_service.rb
- app/services/activitypub/fetch_remote_actor_service.rb
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 16 # RuboCop default 8 Max: 25
AllowedMethods:
- attempt_oembed
- build_crutches
- calculate_scores
- deduplicate_users!
- discover_endpoint!
- filter_from_home?
- hydrate
- patch_for_forwarding!
- process_update
- remove_orphans
- update_media_attachments!
Naming/MemoizedInstanceVariableName: Naming/MemoizedInstanceVariableName:
Enabled: false Enabled: false
@ -401,10 +243,6 @@ Style/HashTransformKeys:
Style/HashTransformValues: Style/HashTransformValues:
Enabled: false Enabled: false
Style/HashSyntax:
Enabled: true
EnforcedStyle: ruby19_no_mixed_keys
Style/IfUnlessModifier: Style/IfUnlessModifier:
Enabled: false Enabled: false
@ -425,6 +263,9 @@ Style/PercentLiteralDelimiters:
Style/PerlBackrefs: Style/PerlBackrefs:
AutoCorrect: false AutoCorrect: false
Style/RedundantAssignment:
Enabled: false
Style/RedundantFetchBlock: Style/RedundantFetchBlock:
Enabled: true Enabled: true
@ -447,7 +288,7 @@ Style/RegexpLiteral:
Enabled: false Enabled: false
Style/RescueStandardError: Style/RescueStandardError:
Enabled: true Enabled: false
Style/SignalException: Style/SignalException:
Enabled: false Enabled: false
@ -466,14 +307,3 @@ Style/TrailingCommaInHashLiteral:
Style/UnpackFirst: Style/UnpackFirst:
Enabled: false Enabled: false
RSpec/ScatteredSetup:
Enabled: false
RSpec/ImplicitExpect:
Enabled: false
RSpec/NamedSubject:
Enabled: false
RSpec/DescribeClass:
Enabled: false
RSpec/LetSetup:
Enabled: false

22
Aptfile
View file

@ -1,4 +1,26 @@
ffmpeg ffmpeg
libicu[0-9][0-9]
libicu-dev
libidn12
libidn-dev
libpq-dev libpq-dev
libxdamage1 libxdamage1
libxfixes3 libxfixes3
zlib1g-dev
libcairo2
libcroco3
libdatrie1
libgdk-pixbuf2.0-0
libgraphite2-3
libharfbuzz0b
libpango-1.0-0
libpangocairo-1.0-0
libpangoft2-1.0-0
libpixman-1-0
librsvg2-2
libthai-data
libthai0
libvpx[5-9]
libxcb-render0
libxcb-shm0
libxrender1

View file

@ -40,7 +40,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version] This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org [homepage]: http://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/ [version]: http://contributor-covenant.org/version/1/4/

View file

@ -1,99 +1,121 @@
# syntax=docker/dockerfile:1.4 FROM ubuntu:20.04 as build-dep
# This needs to be bullseye-slim because the Ruby image is built on bullseye-slim
ARG NODE_VERSION="16.18.1-bullseye-slim"
FROM ghcr.io/moritzheiber/ruby-jemalloc:3.0.4-slim as ruby # Use bash for the shell
FROM node:${NODE_VERSION} as build SHELL ["/bin/bash", "-c"]
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
COPY --link --from=ruby /opt/ruby /opt/ruby # Install Node v16 (LTS)
ENV NODE_VER="16.17.1"
RUN ARCH= && \
dpkgArch="$(dpkg --print-architecture)" && \
case "${dpkgArch##*-}" in \
amd64) ARCH='x64';; \
ppc64el) ARCH='ppc64le';; \
s390x) ARCH='s390x';; \
arm64) ARCH='arm64';; \
armhf) ARCH='armv7l';; \
i386) ARCH='x86';; \
*) echo "unsupported architecture"; exit 1 ;; \
esac && \
echo "Etc/UTC" > /etc/localtime && \
apt-get update && \
apt-get install -y --no-install-recommends ca-certificates wget python3 apt-utils && \
cd ~ && \
wget -q https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \
tar xf node-v$NODE_VER-linux-$ARCH.tar.gz && \
rm node-v$NODE_VER-linux-$ARCH.tar.gz && \
mv node-v$NODE_VER-linux-$ARCH /opt/node
ENV DEBIAN_FRONTEND="noninteractive" \ # Install Ruby 3.0
PATH="${PATH}:/opt/ruby/bin" ENV RUBY_VER="3.0.4"
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
WORKDIR /opt/mastodon
COPY Gemfile* package.json yarn.lock /opt/mastodon/
# hadolint ignore=DL3008
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential \ apt-get install -y --no-install-recommends build-essential \
ca-certificates \ bison libyaml-dev libgdbm-dev libreadline-dev libjemalloc-dev \
git \ libncurses5-dev libffi-dev zlib1g-dev libssl-dev && \
libicu-dev \ cd ~ && \
libidn11-dev \ wget https://cache.ruby-lang.org/pub/ruby/${RUBY_VER%.*}/ruby-$RUBY_VER.tar.gz && \
libpq-dev \ tar xf ruby-$RUBY_VER.tar.gz && \
libjemalloc-dev \ cd ruby-$RUBY_VER && \
zlib1g-dev \ ./configure --prefix=/opt/ruby \
libgdbm-dev \ --with-jemalloc \
libgmp-dev \ --with-shared \
libssl-dev \ --disable-install-doc && \
libyaml-0-2 \ make -j"$(nproc)" > /dev/null && \
ca-certificates \ make install && \
libreadline8 \ rm -rf ../ruby-$RUBY_VER.tar.gz ../ruby-$RUBY_VER
python3 \
shared-mime-info && \ ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin"
RUN npm install -g npm@latest && \
npm install -g yarn && \
gem install bundler && \
apt-get update && \
apt-get install -y --no-install-recommends git libicu-dev libidn11-dev \
libpq-dev shared-mime-info
COPY Gemfile* package.json yarn.lock /opt/mastodon/
RUN cd /opt/mastodon && \
bundle config set --local deployment 'true' && \ bundle config set --local deployment 'true' && \
bundle config set --local without 'development test' && \ bundle config set --local without 'development test' && \
bundle config set silence_root_warning true && \ bundle config set silence_root_warning true && \
bundle install -j"$(nproc)" && \ bundle install -j"$(nproc)" && \
yarn install --pure-lockfile --network-timeout 600000 yarn install --pure-lockfile
FROM node:${NODE_VERSION} FROM ubuntu:20.04
ARG UID="991" # Copy over all the langs needed for runtime
ARG GID="991" COPY --from=build-dep /opt/node /opt/node
COPY --from=build-dep /opt/ruby /opt/ruby
COPY --link --from=ruby /opt/ruby /opt/ruby # Add more PATHs to the PATH
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin"
# Create the mastodon user
ARG UID=991
ARG GID=991
SHELL ["/bin/bash", "-o", "pipefail", "-c"] SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV DEBIAN_FRONTEND="noninteractive" \
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin"
# Ignoreing these here since we don't want to pin any versions and the Debian image removes apt-get content after use
# hadolint ignore=DL3008,DL3009
RUN apt-get update && \ RUN apt-get update && \
echo "Etc/UTC" > /etc/localtime && \ echo "Etc/UTC" > /etc/localtime && \
groupadd -g "${GID}" mastodon && \ apt-get install -y --no-install-recommends whois wget && \
useradd -l -u "$UID" -g "${GID}" -m -d /opt/mastodon mastodon && \ addgroup --gid $GID mastodon && \
apt-get -y --no-install-recommends install whois \ useradd -m -u $UID -g $GID -d /opt/mastodon mastodon && \
wget \ echo "mastodon:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24 | mkpasswd -s -m sha-256)" | chpasswd && \
procps \ rm -rf /var/lib/apt/lists/*
libssl1.1 \
libpq5 \
imagemagick \
ffmpeg \
libjemalloc2 \
libicu67 \
libidn11 \
libyaml-0-2 \
file \
ca-certificates \
tzdata \
libreadline8 \
tini && \
ln -s /opt/mastodon /mastodon
# Note: no, cleaning here since Debian does this automatically # Install mastodon runtime deps
# See the file /etc/apt/apt.conf.d/docker-clean within the Docker image's filesystem RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update && \
apt-get -y --no-install-recommends install \
libssl1.1 libpq5 imagemagick ffmpeg libjemalloc2 \
libicu66 libidn11 libyaml-0-2 \
file ca-certificates tzdata libreadline8 gcc tini apt-utils && \
ln -s /opt/mastodon /mastodon && \
gem install bundler && \
rm -rf /var/cache && \
rm -rf /var/lib/apt/lists/*
# Copy over mastodon source, and dependencies from building, and set permissions
COPY --chown=mastodon:mastodon . /opt/mastodon COPY --chown=mastodon:mastodon . /opt/mastodon
COPY --chown=mastodon:mastodon --from=build /opt/mastodon /opt/mastodon COPY --from=build-dep --chown=mastodon:mastodon /opt/mastodon /opt/mastodon
ENV RAILS_ENV="production" \ # Run mastodon services in prod mode
NODE_ENV="production" \ ENV RAILS_ENV="production"
RAILS_SERVE_STATIC_FILES="true" \ ENV NODE_ENV="production"
BIND="0.0.0.0"
# Tell rails to serve static files
ENV RAILS_SERVE_STATIC_FILES="true"
ENV BIND="0.0.0.0"
# Set the run user # Set the run user
USER mastodon USER mastodon
WORKDIR /opt/mastodon
# Precompile assets # Precompile assets
RUN OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile && \ RUN cd ~ && \
OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile && \
yarn cache clean yarn cache clean
# Set the work dir and the container entry point # Set the work dir and the container entry point
WORKDIR /opt/mastodon
ENTRYPOINT ["/usr/bin/tini", "--"] ENTRYPOINT ["/usr/bin/tini", "--"]
EXPOSE 3000 4000 EXPOSE 3000 4000

36
Gemfile
View file

@ -1,9 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '>= 2.7.0', '< 3.1.0' ruby '>= 2.6.0', '< 3.1.0'
gem 'pkg-config', '~> 1.5' gem 'pkg-config', '~> 1.4'
gem 'rexml', '~> 3.2' gem 'rexml', '~> 3.2'
gem 'puma', '~> 5.6' gem 'puma', '~> 5.6'
@ -18,15 +18,15 @@ gem 'makara', '~> 0.5'
gem 'pghero', '~> 2.8' gem 'pghero', '~> 2.8'
gem 'dotenv-rails', '~> 2.8' gem 'dotenv-rails', '~> 2.8'
gem 'aws-sdk-s3', '~> 1.117', require: false gem 'aws-sdk-s3', '~> 1.114', require: false
gem 'fog-core', '<= 2.4.0' gem 'fog-core', '<= 2.1.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'
gem 'blurhash', '~> 0.1' gem 'blurhash', '~> 0.1'
gem 'active_model_serializers', '~> 0.10' gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.8' gem 'addressable', '~> 2.8'
gem 'bootsnap', '~> 1.15.0', require: false gem 'bootsnap', '~> 1.13.0', require: false
gem 'browser' gem 'browser'
gem 'charlock_holmes', '~> 0.7.7' gem 'charlock_holmes', '~> 0.7.7'
gem 'chewy', '~> 7.2' gem 'chewy', '~> 7.2'
@ -55,7 +55,7 @@ gem 'redis-namespace', '~> 1.9'
gem 'htmlentities', '~> 4.3' gem 'htmlentities', '~> 4.3'
gem 'http', '~> 5.1' gem 'http', '~> 5.1'
gem 'http_accept_language', '~> 2.1' gem 'http_accept_language', '~> 2.1'
gem 'httplog', '~> 1.6.2' gem 'httplog', '~> 1.6.0'
gem 'idn-ruby', require: 'idn' gem 'idn-ruby', require: 'idn'
gem 'kaminari', '~> 1.2' gem 'kaminari', '~> 1.2'
gem 'link_header', '~> 0.0' gem 'link_header', '~> 0.0'
@ -66,8 +66,7 @@ gem 'oj', '~> 3.13'
gem 'ox', '~> 2.14' gem 'ox', '~> 2.14'
gem 'parslet' gem 'parslet'
gem 'posix-spawn' gem 'posix-spawn'
gem 'public_suffix', '~> 5.0' gem 'pundit', '~> 2.2'
gem 'pundit', '~> 2.3'
gem 'premailer-rails' gem 'premailer-rails'
gem 'rack-attack', '~> 6.6' gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 1.1', require: 'rack/cors' gem 'rack-cors', '~> 1.1', require: 'rack/cors'
@ -79,7 +78,7 @@ gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'rqrcode', '~> 2.1' gem 'rqrcode', '~> 2.1'
gem 'ruby-progressbar', '~> 1.11' gem 'ruby-progressbar', '~> 1.11'
gem 'sanitize', '~> 6.0' gem 'sanitize', '~> 6.0'
gem 'scenic', '~> 1.7' gem 'scenic', '~> 1.6'
gem 'sidekiq', '~> 6.5' gem 'sidekiq', '~> 6.5'
gem 'sidekiq-scheduler', '~> 4.0' gem 'sidekiq-scheduler', '~> 4.0'
gem 'sidekiq-unique-jobs', '~> 7.1' gem 'sidekiq-unique-jobs', '~> 7.1'
@ -87,7 +86,7 @@ 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.1'
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.0'
gem 'strong_migrations', '~> 0.7' gem 'strong_migrations', '~> 0.7'
gem 'tty-prompt', '~> 0.23', require: false gem 'tty-prompt', '~> 0.23', require: false
gem 'twitter-text', '~> 3.1.0' gem 'twitter-text', '~> 3.1.0'
@ -107,10 +106,6 @@ group :development, :test do
gem 'pry-byebug', '~> 3.10' gem 'pry-byebug', '~> 3.10'
gem 'pry-rails', '~> 0.3' gem 'pry-rails', '~> 0.3'
gem 'rspec-rails', '~> 5.1' gem 'rspec-rails', '~> 5.1'
gem 'rubocop-performance', require: false
gem 'rubocop-rails', require: false
gem 'rubocop-rspec', require: false
gem 'rubocop', require: false
end end
group :production, :test do group :production, :test do
@ -118,17 +113,16 @@ group :production, :test do
end end
group :test do group :test do
gem 'capybara', '~> 3.38' gem 'capybara', '~> 3.37'
gem 'climate_control', '~> 0.2' gem 'climate_control', '~> 0.2'
gem 'faker', '~> 3.0' gem 'faker', '~> 2.23'
gem 'json-schema', '~> 3.0'
gem 'microformats', '~> 4.4' gem 'microformats', '~> 4.4'
gem 'rack-test', '~> 2.0'
gem 'rails-controller-testing', '~> 1.0' gem 'rails-controller-testing', '~> 1.0'
gem 'rspec_junit_formatter', '~> 0.6'
gem 'rspec-sidekiq', '~> 3.1' gem 'rspec-sidekiq', '~> 3.1'
gem 'simplecov', '~> 0.21', require: false gem 'simplecov', '~> 0.21', require: false
gem 'webmock', '~> 3.18' gem 'webmock', '~> 3.18'
gem 'rspec_junit_formatter', '~> 0.6'
gem 'rack-test', '~> 2.0'
end end
group :development do group :development do
@ -140,7 +134,9 @@ group :development do
gem 'letter_opener', '~> 1.8' gem 'letter_opener', '~> 1.8'
gem 'letter_opener_web', '~> 2.0' gem 'letter_opener_web', '~> 2.0'
gem 'memory_profiler' gem 'memory_profiler'
gem 'brakeman', '~> 5.4', require: false gem 'rubocop', '~> 1.30', require: false
gem 'rubocop-rails', '~> 2.15', require: false
gem 'brakeman', '~> 5.3', require: false
gem 'bundler-audit', '~> 0.9', require: false gem 'bundler-audit', '~> 0.9', require: false
gem 'capistrano', '~> 3.17' gem 'capistrano', '~> 3.17'

View file

@ -90,20 +90,20 @@ 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.587.0)
aws-sdk-core (3.168.2) aws-sdk-core (3.130.2)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0) aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.60.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.117.2) jmespath (~> 1.0)
aws-sdk-core (~> 3, >= 3.165.0) aws-sdk-kms (1.56.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.114.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4) aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.2) aws-sigv4 (1.5.0)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
bcrypt (3.1.17) bcrypt (3.1.17)
better_errors (2.9.1) better_errors (2.9.1)
@ -122,15 +122,15 @@ GEM
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
blurhash (0.1.6) blurhash (0.1.6)
ffi (~> 1.14) ffi (~> 1.14)
bootsnap (1.15.0) bootsnap (1.13.0)
msgpack (~> 1.2) msgpack (~> 1.2)
brakeman (5.4.0) brakeman (5.3.1)
browser (4.2.0) browser (4.2.0)
brpoplpush-redis_script (0.1.3) brpoplpush-redis_script (0.1.2)
concurrent-ruby (~> 1.0, >= 1.0.5) concurrent-ruby (~> 1.0, >= 1.0.5)
redis (>= 1.0, < 6) redis (>= 1.0, <= 5.0)
builder (3.2.4) builder (3.2.4)
bullet (7.0.4) bullet (7.0.3)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.11) uniform_notifier (~> 1.11)
bundler-audit (0.9.1) bundler-audit (0.9.1)
@ -152,7 +152,7 @@ GEM
sshkit (~> 1.3) sshkit (~> 1.3)
capistrano-yarn (2.0.2) capistrano-yarn (2.0.2)
capistrano (~> 3.0) capistrano (~> 3.0)
capybara (3.38.0) capybara (3.37.1)
addressable addressable
matrix matrix
mini_mime (>= 0.1.3) mini_mime (>= 0.1.3)
@ -182,7 +182,7 @@ GEM
crack (0.4.5) crack (0.4.5)
rexml rexml
crass (1.0.6) crass (1.0.6)
css_parser (1.12.0) css_parser (1.7.1)
addressable addressable
debug_inspector (1.0.0) debug_inspector (1.0.0)
devise (4.8.1) devise (4.8.1)
@ -206,7 +206,7 @@ GEM
docile (1.3.4) docile (1.3.4)
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.0)
railties (>= 5) railties (>= 5)
dotenv (2.8.1) dotenv (2.8.1)
dotenv-rails (2.8.1) dotenv-rails (2.8.1)
@ -226,9 +226,9 @@ GEM
erubi (1.11.0) erubi (1.11.0)
et-orbi (1.2.7) et-orbi (1.2.7)
tzinfo tzinfo
excon (0.95.0) excon (0.76.0)
fabrication (2.30.0) fabrication (2.30.0)
faker (3.0.0) faker (2.23.0)
i18n (>= 1.8.11, < 2) i18n (>= 1.8.11, < 2)
faraday (1.9.3) faraday (1.9.3)
faraday-em_http (~> 1.0) faraday-em_http (~> 1.0)
@ -271,7 +271,7 @@ GEM
fog-core (>= 1.45, <= 2.1.0) fog-core (>= 1.45, <= 2.1.0)
fog-json (>= 1.0) fog-json (>= 1.0)
ipaddress (>= 0.8) ipaddress (>= 0.8)
formatador (0.3.0) formatador (0.2.5)
fugit (1.7.1) fugit (1.7.1)
et-orbi (~> 1, >= 1.2.7) et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4) raabro (~> 1.4)
@ -299,7 +299,7 @@ GEM
hiredis (0.6.3) hiredis (0.6.3)
hkdf (0.3.0) hkdf (0.3.0)
htmlentities (4.3.4) htmlentities (4.3.4)
http (5.1.1) http (5.1.0)
addressable (~> 2.8) addressable (~> 2.8)
http-cookie (~> 1.0) http-cookie (~> 1.0)
http-form_data (~> 2.2) http-form_data (~> 2.2)
@ -309,7 +309,7 @@ GEM
http-form_data (2.3.0) http-form_data (2.3.0)
http_accept_language (2.1.1) http_accept_language (2.1.1)
httpclient (2.8.3) httpclient (2.8.3)
httplog (1.6.2) httplog (1.6.0)
rack (>= 2.0) rack (>= 2.0)
rainbow (>= 2.0.0) rainbow (>= 2.0.0)
i18n (1.12.0) i18n (1.12.0)
@ -325,9 +325,9 @@ GEM
rails-i18n rails-i18n
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
terminal-table (>= 1.5.1) terminal-table (>= 1.5.1)
idn-ruby (0.1.5) idn-ruby (0.1.4)
ipaddress (0.8.3) ipaddress (0.8.3)
jmespath (1.6.2) jmespath (1.6.1)
json (2.6.2) json (2.6.2)
json-canonicalization (0.3.0) json-canonicalization (0.3.0)
json-jwt (1.13.0) json-jwt (1.13.0)
@ -341,11 +341,9 @@ GEM
multi_json (~> 1.15) multi_json (~> 1.15)
rack (~> 2.2) rack (~> 2.2)
rdf (~> 3.2, >= 3.2.9) rdf (~> 3.2, >= 3.2.9)
json-ld-preloaded (3.2.2) json-ld-preloaded (3.2.0)
json-ld (~> 3.2) json-ld (~> 3.2)
rdf (~> 3.2) rdf (~> 3.2)
json-schema (3.0.0)
addressable (>= 2.8)
jsonapi-renderer (0.2.2) jsonapi-renderer (0.2.2)
jwt (2.4.1) jwt (2.4.1)
kaminari (1.2.2) kaminari (1.2.2)
@ -384,7 +382,7 @@ GEM
activesupport (>= 4) activesupport (>= 4)
railties (>= 4) railties (>= 4)
request_store (~> 1.0) request_store (~> 1.0)
loofah (2.19.1) loofah (2.19.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.7.1) mail (2.7.1)
@ -395,7 +393,7 @@ GEM
mario-redis-lock (1.2.1) mario-redis-lock (1.2.1)
redis (>= 3.0.5) redis (>= 3.0.5)
matrix (0.4.2) matrix (0.4.2)
memory_profiler (1.0.1) memory_profiler (1.0.0)
method_source (1.0.0) method_source (1.0.0)
microformats (4.4.1) microformats (4.4.1)
json (~> 2.2) json (~> 2.2)
@ -406,19 +404,15 @@ GEM
mini_mime (1.1.2) mini_mime (1.1.2)
mini_portile2 (2.8.0) mini_portile2 (2.8.0)
minitest (5.16.3) minitest (5.16.3)
msgpack (1.6.0) msgpack (1.5.4)
multi_json (1.15.0) multi_json (1.15.0)
multipart-post (2.1.1) multipart-post (2.1.1)
net-ldap (0.17.1) net-ldap (0.17.1)
net-protocol (0.1.3)
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)
net-smtp (0.3.3)
net-protocol
net-ssh (7.0.1) net-ssh (7.0.1)
nio4r (2.5.8) nio4r (2.5.8)
nokogiri (1.13.10) nokogiri (1.13.9)
mini_portile2 (~> 2.8.0) mini_portile2 (~> 2.8.0)
racc (~> 1.4) racc (~> 1.4)
nsa (0.2.8) nsa (0.2.8)
@ -426,7 +420,7 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5) sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0) statsd-ruby (~> 1.4, >= 1.4.0)
oj (3.13.23) oj (3.13.21)
omniauth (1.9.2) omniauth (1.9.2)
hashie (>= 3.4.6) hashie (>= 3.4.6)
rack (>= 1.6.2, < 3) rack (>= 1.6.2, < 3)
@ -461,18 +455,17 @@ GEM
parslet (2.0.0) parslet (2.0.0)
pastel (0.8.0) pastel (0.8.0)
tty-color (~> 0.5) tty-color (~> 0.5)
pg (1.4.5) pg (1.4.3)
pghero (2.8.3) pghero (2.8.3)
activerecord (>= 5) activerecord (>= 5)
pkg-config (1.5.1) pkg-config (1.4.9)
posix-spawn (0.3.15) posix-spawn (0.3.15)
premailer (1.18.0) premailer (1.14.2)
addressable addressable
css_parser (>= 1.12.0) css_parser (>= 1.6.0)
htmlentities (>= 4.0.0) htmlentities (>= 4.0.0)
premailer-rails (1.12.0) premailer-rails (1.11.1)
actionmailer (>= 3) actionmailer (>= 3)
net-smtp
premailer (~> 1.7, >= 1.7.9) premailer (~> 1.7, >= 1.7.9)
private_address_check (0.5.0) private_address_check (0.5.0)
pry (0.14.1) pry (0.14.1)
@ -483,13 +476,13 @@ GEM
pry (>= 0.13, < 0.15) pry (>= 0.13, < 0.15)
pry-rails (0.3.9) pry-rails (0.3.9)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (5.0.1) public_suffix (5.0.0)
puma (5.6.5) puma (5.6.5)
nio4r (~> 2.0) nio4r (~> 2.0)
pundit (2.3.0) pundit (2.2.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.4.0) raabro (1.4.0)
racc (1.6.1) racc (1.6.0)
rack (2.2.4) rack (2.2.4)
rack-attack (6.6.1) rack-attack (6.6.1)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
@ -527,8 +520,8 @@ 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.4.3)
loofah (~> 2.19, >= 2.19.1) loofah (~> 2.3)
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)
@ -544,15 +537,13 @@ GEM
rake (13.0.6) rake (13.0.6)
rdf (3.2.9) rdf (3.2.9)
link_header (~> 0.0, >= 0.0.8) link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.5.1) rdf-normalize (0.5.0)
rdf (~> 3.2) rdf (~> 3.2)
redcarpet (3.5.1) redcarpet (3.5.1)
redis (4.5.1) redis (4.5.1)
redis-namespace (1.9.0) redis-namespace (1.9.0)
redis (>= 4) redis (>= 4)
redlock (1.3.2) regexp_parser (2.5.0)
redis (>= 3.0.0, < 6.0)
regexp_parser (2.6.0)
request_store (1.5.1) request_store (1.5.1)
rack (>= 1.4) rack (>= 1.4)
responders (3.0.1) responders (3.0.1)
@ -587,27 +578,21 @@ 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.39.0) rubocop (1.30.1)
json (~> 2.3)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.1.2.1) parser (>= 3.1.0.0)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0) regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0) rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.23.0, < 2.0) rubocop-ast (>= 1.18.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0) unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.23.0) rubocop-ast (1.18.0)
parser (>= 3.1.1.0) parser (>= 3.1.1.0)
rubocop-performance (1.15.1) rubocop-rails (2.15.0)
rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.17.2)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0) rubocop (>= 1.7.0, < 2.0)
rubocop-rspec (2.15.0)
rubocop (~> 1.33)
ruby-progressbar (1.11.0) ruby-progressbar (1.11.0)
ruby-saml (1.13.0) ruby-saml (1.13.0)
nokogiri (>= 1.10.5) nokogiri (>= 1.10.5)
@ -620,12 +605,12 @@ GEM
sanitize (6.0.0) sanitize (6.0.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.12.0) nokogiri (>= 1.12.0)
scenic (1.7.0) scenic (1.6.0)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
railties (>= 4.0.0) railties (>= 4.0.0)
semantic_range (3.0.0) semantic_range (3.0.0)
sidekiq (6.5.8) sidekiq (6.5.7)
connection_pool (>= 2.2.5, < 3) connection_pool (>= 2.2.5)
rack (~> 2.0) rack (~> 2.0)
redis (>= 4.5.0, < 5) redis (>= 4.5.0, < 5)
sidekiq-bulk (0.2.0) sidekiq-bulk (0.2.0)
@ -635,11 +620,10 @@ GEM
rufus-scheduler (~> 3.2) rufus-scheduler (~> 3.2)
sidekiq (>= 4, < 7) sidekiq (>= 4, < 7)
tilt (>= 1.4.0) tilt (>= 1.4.0)
sidekiq-unique-jobs (7.1.29) sidekiq-unique-jobs (7.1.27)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0) brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
concurrent-ruby (~> 1.0, >= 1.0.5) concurrent-ruby (~> 1.0, >= 1.0.5)
redis (< 5.0) sidekiq (>= 5.0, < 8.0)
sidekiq (>= 5.0, < 7.0)
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)
@ -663,10 +647,9 @@ GEM
sshkit (1.21.2) sshkit (1.21.2)
net-scp (>= 1.1.2) net-scp (>= 1.1.2)
net-ssh (>= 2.8.0) net-ssh (>= 2.8.0)
stackprof (0.2.23) stackprof (0.2.22)
statsd-ruby (1.5.0) statsd-ruby (1.5.0)
stoplight (3.0.1) stoplight (3.0.0)
redlock (~> 1.0)
strong_migrations (0.7.9) strong_migrations (0.7.9)
activerecord (>= 5) activerecord (>= 5)
swd (1.3.0) swd (1.3.0)
@ -680,7 +663,6 @@ 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)
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)
@ -700,7 +682,7 @@ GEM
unf (~> 0.1.0) unf (~> 0.1.0)
tzinfo (2.0.5) tzinfo (2.0.5)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
tzinfo-data (1.2022.7) tzinfo-data (1.2022.4)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
@ -743,7 +725,7 @@ GEM
xorcist (1.1.3) xorcist (1.1.3)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.6.6) zeitwerk (2.6.0)
PLATFORMS PLATFORMS
ruby ruby
@ -753,12 +735,12 @@ 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.114)
better_errors (~> 2.9) better_errors (~> 2.9)
binding_of_caller (~> 1.0) binding_of_caller (~> 1.0)
blurhash (~> 0.1) blurhash (~> 0.1)
bootsnap (~> 1.15.0) bootsnap (~> 1.13.0)
brakeman (~> 5.4) brakeman (~> 5.3)
browser browser
bullet (~> 7.0) bullet (~> 7.0)
bundler-audit (~> 0.9) bundler-audit (~> 0.9)
@ -766,7 +748,7 @@ DEPENDENCIES
capistrano-rails (~> 1.6) capistrano-rails (~> 1.6)
capistrano-rbenv (~> 2.2) capistrano-rbenv (~> 2.2)
capistrano-yarn (~> 2.0) capistrano-yarn (~> 2.0)
capybara (~> 3.38) capybara (~> 3.37)
charlock_holmes (~> 0.7.7) charlock_holmes (~> 0.7.7)
chewy (~> 7.2) chewy (~> 7.2)
climate_control (~> 0.2) climate_control (~> 0.2)
@ -782,10 +764,10 @@ DEPENDENCIES
dotenv-rails (~> 2.8) dotenv-rails (~> 2.8)
ed25519 (~> 1.3) ed25519 (~> 1.3)
fabrication (~> 2.30) fabrication (~> 2.30)
faker (~> 3.0) faker (~> 2.23)
fast_blank (~> 1.0) fast_blank (~> 1.0)
fastimage fastimage
fog-core (<= 2.4.0) fog-core (<= 2.1.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.0)
@ -794,12 +776,11 @@ DEPENDENCIES
htmlentities (~> 4.3) htmlentities (~> 4.3)
http (~> 5.1) http (~> 5.1)
http_accept_language (~> 2.1) http_accept_language (~> 2.1)
httplog (~> 1.6.2) httplog (~> 1.6.0)
i18n-tasks (~> 1.0) i18n-tasks (~> 1.0)
idn-ruby idn-ruby
json-ld json-ld
json-ld-preloaded (~> 3.2) json-ld-preloaded (~> 3.2)
json-schema (~> 3.0)
kaminari (~> 1.2) kaminari (~> 1.2)
kt-paperclip (~> 7.1) kt-paperclip (~> 7.1)
letter_opener (~> 1.8) letter_opener (~> 1.8)
@ -823,15 +804,14 @@ DEPENDENCIES
parslet parslet
pg (~> 1.4) pg (~> 1.4)
pghero (~> 2.8) pghero (~> 2.8)
pkg-config (~> 1.5) pkg-config (~> 1.4)
posix-spawn posix-spawn
premailer-rails premailer-rails
private_address_check (~> 0.5) private_address_check (~> 0.5)
pry-byebug (~> 3.10) pry-byebug (~> 3.10)
pry-rails (~> 0.3) pry-rails (~> 0.3)
public_suffix (~> 5.0)
puma (~> 5.6) puma (~> 5.6)
pundit (~> 2.3) pundit (~> 2.2)
rack (~> 2.2.4) rack (~> 2.2.4)
rack-attack (~> 6.6) rack-attack (~> 6.6)
rack-cors (~> 1.1) rack-cors (~> 1.1)
@ -849,13 +829,11 @@ DEPENDENCIES
rspec-rails (~> 5.1) rspec-rails (~> 5.1)
rspec-sidekiq (~> 3.1) rspec-sidekiq (~> 3.1)
rspec_junit_formatter (~> 0.6) rspec_junit_formatter (~> 0.6)
rubocop rubocop (~> 1.30)
rubocop-performance rubocop-rails (~> 2.15)
rubocop-rails
rubocop-rspec
ruby-progressbar (~> 1.11) ruby-progressbar (~> 1.11)
sanitize (~> 6.0) sanitize (~> 6.0)
scenic (~> 1.7) scenic (~> 1.6)
sidekiq (~> 6.5) sidekiq (~> 6.5)
sidekiq-bulk (~> 0.2.0) sidekiq-bulk (~> 0.2.0)
sidekiq-scheduler (~> 4.0) sidekiq-scheduler (~> 4.0)
@ -866,7 +844,7 @@ DEPENDENCIES
sprockets (~> 3.7.2) sprockets (~> 3.7.2)
sprockets-rails (~> 3.4) sprockets-rails (~> 3.4)
stackprof stackprof
stoplight (~> 3.0.1) stoplight (~> 3.0.0)
strong_migrations (~> 0.7) strong_migrations (~> 0.7)
thor (~> 1.2) thor (~> 1.2)
tty-prompt (~> 0.23) tty-prompt (~> 0.23)
@ -877,9 +855,3 @@ DEPENDENCIES
webpacker (~> 5.4) webpacker (~> 5.4)
webpush! webpush!
xorcist (~> 1.1) xorcist (~> 1.1)
RUBY VERSION
ruby 3.0.4p208
BUNDLED WITH
2.2.33

View file

@ -72,8 +72,8 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre
- **PostgreSQL** 9.5+ - **PostgreSQL** 9.5+
- **Redis** 4+ - **Redis** 4+
- **Ruby** 2.7+ - **Ruby** 2.6+
- **Node.js** 16+ - **Node.js** 14+
The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation.

71
Vagrantfile vendored
View file

@ -3,14 +3,16 @@
ENV["PORT"] ||= "3000" ENV["PORT"] ||= "3000"
$provisionA = <<SCRIPT $provision = <<SCRIPT
cd /vagrant # This is where the host folder/repo is mounted
# Add the yarn repo + yarn repo keys # Add the yarn repo + yarn repo keys
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main' sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
# Add repo for NodeJS # Add repo for NodeJS
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash - curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -
# Add firewall rule to redirect 80 to PORT and save # Add firewall rule to redirect 80 to PORT and save
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]} sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
@ -31,56 +33,32 @@ sudo apt-get install \
redis-tools \ redis-tools \
postgresql \ postgresql \
postgresql-contrib \ postgresql-contrib \
yarn \
libicu-dev \ libicu-dev \
libidn11-dev \ libidn11-dev \
libreadline6-dev \ libreadline-dev \
autoconf \ libpam0g-dev \
bison \
build-essential \
ffmpeg \
file \
gcc \
libffi-dev \
libgdbm-dev \
libjemalloc-dev \
libncurses5-dev \
libprotobuf-dev \
libssl-dev \
libyaml-dev \
pkg-config \
protobuf-compiler \
zlib1g-dev \
-y -y
# Install rvm # Install rvm
sudo apt-add-repository -y ppa:rael-gc/rvm read RUBY_VERSION < .ruby-version
sudo apt-get install rvm -y
sudo usermod -a -G rvm $USER curl -sSL https://rvm.io/mpapis.asc | gpg --import
curl -sSL https://rvm.io/pkuczynski.asc | gpg --import
SCRIPT curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION
source /home/vagrant/.rvm/scripts/rvm
$provisionB = <<SCRIPT
source "/etc/profile.d/rvm.sh"
# Install Ruby # Install Ruby
read RUBY_VERSION < /vagrant/.ruby-version rvm reinstall ruby-$RUBY_VERSION --disable-binary
rvm install ruby-$RUBY_VERSION --disable-binary
# Configure database # Configure database
sudo -u postgres createuser -U postgres vagrant -s sudo -u postgres createuser -U postgres vagrant -s
sudo -u postgres createdb -U postgres mastodon_development sudo -u postgres createdb -U postgres mastodon_development
cd /vagrant # This is where the host folder/repo is mounted # Install gems and node modules
# Install gems
gem install bundler foreman gem install bundler foreman
bundle install bundle install
# Install node modules
sudo corepack enable
yarn set version classic
yarn install yarn install
# Build Mastodon # Build Mastodon
@ -94,11 +72,18 @@ echo 'export $(cat "/vagrant/.env.vagrant" | xargs)' >> ~/.bash_profile
SCRIPT SCRIPT
$start = <<SCRIPT
echo 'To start server'
echo ' $ vagrant ssh -c "cd /vagrant && foreman start"'
SCRIPT
VAGRANTFILE_API_VERSION = "2" VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "ubuntu/focal64" config.vm.box = "ubuntu/bionic64"
config.vm.provider :virtualbox do |vb| config.vm.provider :virtualbox do |vb|
vb.name = "mastodon" vb.name = "mastodon"
@ -115,6 +100,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Use "virtio" network interfaces for better performance. # Use "virtio" network interfaces for better performance.
vb.customize ["modifyvm", :id, "--nictype1", "virtio"] vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
vb.customize ["modifyvm", :id, "--nictype2", "virtio"] vb.customize ["modifyvm", :id, "--nictype2", "virtio"]
end end
# This uses the vagrant-hostsupdater plugin, and lets you # This uses the vagrant-hostsupdater plugin, and lets you
@ -132,7 +118,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
end end
if config.vm.networks.any? { |type, options| type == :private_network } if config.vm.networks.any? { |type, options| type == :private_network }
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'actimeo=1'] config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'vers=3', 'tcp', 'actimeo=1']
else else
config.vm.synced_folder ".", "/vagrant" config.vm.synced_folder ".", "/vagrant"
end end
@ -143,12 +129,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.network :forwarded_port, guest: 8080, host: 8080 config.vm.network :forwarded_port, guest: 8080, host: 8080
# Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision' # Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision'
config.vm.provision :shell, inline: $provisionA, privileged: false, reset: true config.vm.provision :shell, inline: $provision, privileged: false
config.vm.provision :shell, inline: $provisionB, privileged: false
config.vm.post_up_message = <<MESSAGE # Start up script, runs on every 'vagrant up'
To start server config.vm.provision :shell, inline: $start, run: 'always', privileged: false
$ vagrant ssh -c "cd /vagrant && foreman start"
MESSAGE
end end

View file

@ -17,8 +17,6 @@ class AccountsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
expires_in 0, public: true unless user_signed_in? expires_in 0, public: true unless user_signed_in?
@rss_url = rss_url
end end
format.rss do format.rss do

View file

@ -55,14 +55,12 @@ module Admin
def approve def approve
authorize @account.user, :approve? authorize @account.user, :approve?
@account.user.approve! @account.user.approve!
log_action :approve, @account.user
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.approved_msg', username: @account.acct) redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.approved_msg', username: @account.acct)
end end
def reject def reject
authorize @account.user, :reject? authorize @account.user, :reject?
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false) DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
log_action :reject, @account.user
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct) redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
end end

View file

@ -4,18 +4,6 @@ module Admin
class DomainBlocksController < BaseController class DomainBlocksController < BaseController
before_action :set_domain_block, only: [:show, :destroy, :edit, :update] before_action :set_domain_block, only: [:show, :destroy, :edit, :update]
def batch
authorize :domain_block, :create?
@form = Form::DomainBlockBatch.new(form_domain_block_batch_params.merge(current_account: current_account, action: action_from_button))
@form.save
rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.domain_blocks.no_domain_block_selected')
rescue Mastodon::NotPermittedError
flash[:alert] = I18n.t('admin.domain_blocks.not_permitted')
else
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
end
def new def new
authorize :domain_block, :create? authorize :domain_block, :create?
@domain_block = DomainBlock.new(domain: params[:_domain]) @domain_block = DomainBlock.new(domain: params[:_domain])
@ -55,8 +43,12 @@ module Admin
def update def update
authorize :domain_block, :update? authorize :domain_block, :update?
if @domain_block.update(update_params) @domain_block.update(update_params)
DomainBlockWorker.perform_async(@domain_block.id, @domain_block.severity_previously_changed?)
severity_changed = @domain_block.severity_changed?
if @domain_block.save
DomainBlockWorker.perform_async(@domain_block.id, severity_changed)
log_action :update, @domain_block log_action :update, @domain_block
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg') redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
else else
@ -84,15 +76,5 @@ module Admin
def resource_params def resource_params
params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate) params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate)
end end
def form_domain_block_batch_params
params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate])
end
def action_from_button
if params[:save]
'save'
end
end
end end
end end

View file

@ -19,7 +19,7 @@ module Admin
rescue ActionController::ParameterMissing rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.email_domain_blocks.no_email_domain_block_selected') flash[:alert] = I18n.t('admin.email_domain_blocks.no_email_domain_block_selected')
rescue Mastodon::NotPermittedError rescue Mastodon::NotPermittedError
flash[:alert] = I18n.t('admin.email_domain_blocks.not_permitted') flash[:alert] = I18n.t('admin.custom_emojis.not_permitted')
ensure ensure
redirect_to admin_email_domain_blocks_path redirect_to admin_email_domain_blocks_path
end end

View file

@ -1,60 +0,0 @@
# frozen_string_literal: true
require 'csv'
module Admin
class ExportDomainAllowsController < BaseController
include AdminExportControllerConcern
before_action :set_dummy_import!, only: [:new]
def new
authorize :domain_allow, :create?
end
def export
authorize :instance, :index?
send_export_file
end
def import
authorize :domain_allow, :create?
begin
@import = Admin::Import.new(import_params)
return render :new unless @import.validate
parse_import_data!(export_headers)
@data.take(Admin::Import::ROWS_PROCESSING_LIMIT).each do |row|
domain = row['#domain'].strip
next if DomainAllow.allowed?(domain)
domain_allow = DomainAllow.new(domain: domain)
log_action :create, domain_allow if domain_allow.save
end
flash[:notice] = I18n.t('admin.domain_allows.created_msg')
rescue ActionController::ParameterMissing
flash[:error] = I18n.t('admin.export_domain_allows.no_file')
end
redirect_to admin_instances_path
end
private
def export_filename
'domain_allows.csv'
end
def export_headers
%w(#domain)
end
def export_data
CSV.generate(headers: export_headers, write_headers: true) do |content|
DomainAllow.allowed_domains.each do |instance|
content << [instance.domain]
end
end
end
end
end

View file

@ -1,71 +0,0 @@
# frozen_string_literal: true
require 'csv'
module Admin
class ExportDomainBlocksController < BaseController
include AdminExportControllerConcern
before_action :set_dummy_import!, only: [:new]
def new
authorize :domain_block, :create?
end
def export
authorize :instance, :index?
send_export_file
end
def import
authorize :domain_block, :create?
@import = Admin::Import.new(import_params)
return render :new unless @import.validate
parse_import_data!(export_headers)
@global_private_comment = I18n.t('admin.export_domain_blocks.import.private_comment_template', source: @import.data_file_name, date: I18n.l(Time.now.utc))
@form = Form::DomainBlockBatch.new
@domain_blocks = @data.take(Admin::Import::ROWS_PROCESSING_LIMIT).filter_map do |row|
domain = row['#domain'].strip
next if DomainBlock.rule_for(domain).present?
domain_block = DomainBlock.new(domain: domain,
severity: row['#severity'].strip,
reject_media: row['#reject_media'].strip,
reject_reports: row['#reject_reports'].strip,
private_comment: @global_private_comment,
public_comment: row['#public_comment']&.strip,
obfuscate: row['#obfuscate'].strip)
domain_block if domain_block.valid?
end
@warning_domains = Instance.where(domain: @domain_blocks.map(&:domain)).where('EXISTS (SELECT 1 FROM follows JOIN accounts ON follows.account_id = accounts.id OR follows.target_account_id = accounts.id WHERE accounts.domain = instances.domain)').pluck(:domain)
rescue ActionController::ParameterMissing
flash.now[:alert] = I18n.t('admin.export_domain_blocks.no_file')
set_dummy_import!
render :new
end
private
def export_filename
'domain_blocks.csv'
end
def export_headers
%w(#domain #severity #reject_media #reject_reports #public_comment #obfuscate)
end
def export_data
CSV.generate(headers: export_headers, write_headers: true) do |content|
DomainBlock.with_limitations.each do |instance|
content << [instance.domain, instance.severity, instance.reject_media, instance.reject_reports, instance.public_comment, instance.obfuscate]
end
end
end
end
end

View file

@ -57,7 +57,7 @@ module Admin
end end
def preload_delivery_failures! def preload_delivery_failures!
warning_domains_map = DeliveryFailureTracker.warning_domains_map(@instances.map(&:domain)) warning_domains_map = DeliveryFailureTracker.warning_domains_map
@instances.each do |instance| @instances.each do |instance|
instance.failure_days = warning_domains_map[instance.domain] instance.failure_days = warning_domains_map[instance.domain]

View file

@ -3,7 +3,7 @@
module Admin module Admin
class RelaysController < BaseController class RelaysController < BaseController
before_action :set_relay, except: [:index, :new, :create] before_action :set_relay, except: [:index, :new, :create]
before_action :warn_signatures_not_enabled!, only: [:new, :create, :enable] before_action :require_signatures_enabled!, only: [:new, :create, :enable]
def index def index
authorize :relay, :update? authorize :relay, :update?
@ -56,8 +56,8 @@ module Admin
params.require(:relay).permit(:inbox_url) params.require(:relay).permit(:inbox_url)
end end
def warn_signatures_not_enabled! def require_signatures_enabled!
flash.now[:error] = I18n.t('admin.relays.signatures_not_enabled') if authorized_fetch_mode? redirect_to admin_relays_path, alert: I18n.t('admin.relays.signatures_not_enabled') if authorized_fetch_mode?
end end
end end
end end

View file

@ -16,26 +16,6 @@ class Api::BaseController < ApplicationController
protect_from_forgery with: :null_session protect_from_forgery with: :null_session
content_security_policy do |p|
# Set every directive that does not have a fallback
p.default_src :none
p.frame_ancestors :none
p.form_action :none
# Disable every directive with a fallback to cut on response size
p.base_uri false
p.font_src false
p.img_src false
p.style_src false
p.media_src false
p.frame_src false
p.manifest_src false
p.connect_src false
p.script_src false
p.child_src false
p.worker_src false
end
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e| rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
render json: { error: e.to_s }, status: 422 render json: { error: e.to_s }, status: 422
end end
@ -149,7 +129,7 @@ class Api::BaseController < ApplicationController
end end
def set_cache_headers def set_cache_headers
response.headers['Cache-Control'] = 'private, no-store' response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
end end
def disallow_unauthenticated_api_access? def disallow_unauthenticated_api_access?

View file

@ -54,14 +54,12 @@ class Api::V1::Admin::AccountsController < Api::BaseController
def approve def approve
authorize @account.user, :approve? authorize @account.user, :approve?
@account.user.approve! @account.user.approve!
log_action :approve, @account.user
render json: @account, serializer: REST::Admin::AccountSerializer render json: @account, serializer: REST::Admin::AccountSerializer
end end
def reject def reject
authorize @account.user, :reject? authorize @account.user, :reject?
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false) DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
log_action :reject, @account.user
render_empty render_empty
end end

View file

@ -40,8 +40,10 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
def update def update
authorize @domain_block, :update? authorize @domain_block, :update?
@domain_block.update!(domain_block_params) @domain_block.update(domain_block_params)
DomainBlockWorker.perform_async(@domain_block.id, @domain_block.severity_previously_changed?) severity_changed = @domain_block.severity_changed?
@domain_block.save!
DomainBlockWorker.perform_async(@domain_block.id, severity_changed)
log_action :update, @domain_block log_action :update, @domain_block
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer
end end

View file

@ -13,7 +13,7 @@ class Api::V1::FiltersController < Api::BaseController
def create def create
ApplicationRecord.transaction do ApplicationRecord.transaction do
filter_category = current_account.custom_filters.create!(filter_params) filter_category = current_account.custom_filters.create!(resource_params)
@filter = filter_category.keywords.create!(keyword_params) @filter = filter_category.keywords.create!(keyword_params)
end end
@ -52,11 +52,11 @@ class Api::V1::FiltersController < Api::BaseController
end end
def resource_params def resource_params
params.permit(:phrase, :expires_in, :irreversible, :whole_word, context: []) params.permit(:phrase, :expires_in, :irreversible, context: [])
end end
def filter_params def filter_params
resource_params.slice(:phrase, :expires_in, :irreversible, :context) resource_params.slice(:expires_in, :irreversible, :context)
end end
def keyword_params def keyword_params

View file

@ -3,11 +3,11 @@
class Api::V1::FollowedTagsController < Api::BaseController class Api::V1::FollowedTagsController < Api::BaseController
TAGS_LIMIT = 100 TAGS_LIMIT = 100
before_action -> { doorkeeper_authorize! :follow, :read, :'read:follows' } before_action -> { doorkeeper_authorize! :follow, :read, :'read:follows' }, except: :show
before_action :require_user! before_action :require_user!
before_action :set_results before_action :set_results
after_action :insert_pagination_headers after_action :insert_pagination_headers, only: :show
def index def index
render json: @results.map(&:tag), each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@results.map(&:tag), current_user&.account_id) render json: @results.map(&:tag), each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@results.map(&:tag), current_user&.account_id)
@ -43,7 +43,7 @@ class Api::V1::FollowedTagsController < Api::BaseController
end end
def records_continue? def records_continue?
@results.size == limit_param(TAGS_LIMIT) @results.size == limit_param(TAG_LIMIT)
end end
def pagination_params(core_params) def pagination_params(core_params)

View file

@ -31,7 +31,7 @@ class Api::V1::NotificationsController < Api::BaseController
private private
def load_notifications def load_notifications
notifications = browserable_account_notifications.includes(from_account: [:account_stat, :user]).to_a_paginated_by_id( notifications = browserable_account_notifications.includes(from_account: :account_stat).to_a_paginated_by_id(
limit_param(DEFAULT_NOTIFICATIONS_LIMIT), limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
params_slice(:max_id, :since_id, :min_id) params_slice(:max_id, :since_id, :min_id)
) )

View file

@ -12,7 +12,7 @@ class Api::V1::TagsController < Api::BaseController
end end
def follow def follow
TagFollow.create_with(rate_limit: true).find_or_create_by!(tag: @tag, account: current_account) TagFollow.create!(tag: @tag, account: current_account, rate_limit: true)
render json: @tag, serializer: REST::TagSerializer render json: @tag, serializer: REST::TagSerializer
end end

View file

@ -10,8 +10,6 @@ class Auth::PasswordsController < Devise::PasswordsController
super do |resource| super do |resource|
if resource.errors.empty? if resource.errors.empty?
resource.session_activations.destroy_all resource.session_activations.destroy_all
resource.revoke_access!
end end
end end
end end

View file

@ -56,8 +56,8 @@ class Auth::RegistrationsController < Devise::RegistrationsController
end end
def configure_sign_up_params def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up) do |user_params| devise_parameter_sanitizer.permit(:sign_up) do |u|
user_params.permit({ account_attributes: [:username, :display_name], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password) u.permit({ account_attributes: [:username, :display_name], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
end end
end end
@ -154,6 +154,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
end end
def set_cache_headers def set_cache_headers
response.headers['Cache-Control'] = 'private, no-store' response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
end end
end end

View file

@ -14,10 +14,6 @@ class Auth::SessionsController < Devise::SessionsController
before_action :set_instance_presenter, only: [:new] before_action :set_instance_presenter, only: [:new]
before_action :set_body_classes before_action :set_body_classes
content_security_policy only: :new do |p|
p.form_action(false)
end
def check_suspicious! def check_suspicious!
user = find_user user = find_user
@login_is_suspicious = suspicious_sign_in?(user) unless user.nil? @login_is_suspicious = suspicious_sign_in?(user) unless user.nil?

View file

@ -1,39 +0,0 @@
# frozen_string_literal: true
module AdminExportControllerConcern
extend ActiveSupport::Concern
private
def send_export_file
respond_to do |format|
format.csv { send_data export_data, filename: export_filename }
end
end
def export_data
raise 'Override in controller'
end
def export_filename
raise 'Override in controller'
end
def set_dummy_import!
@import = Admin::Import.new
end
def import_params
params.require(:admin_import).permit(:data)
end
def import_data_path
params[:admin_import][:data].path
end
def parse_import_data!(default_headers)
data = CSV.read(import_data_path, headers: true, encoding: 'UTF-8')
data = CSV.read(import_data_path, headers: default_headers, encoding: 'UTF-8') unless data.headers&.first&.strip&.include?(default_headers[0])
@data = data.reject(&:blank?)
end
end

View file

@ -58,7 +58,7 @@ module RateLimitHeaders
end end
def api_throttle_data def api_throttle_data
most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_key, value| value[:limit] - value[:count] } most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] - v[:count] }
request.env['rack.attack.throttle_data'][most_limited_type] request.env['rack.attack.throttle_data'][most_limited_type]
end end

View file

@ -28,8 +28,8 @@ module SignatureVerification
end end
class SignatureParamsTransformer < Parslet::Transform class SignatureParamsTransformer < Parslet::Transform
rule(params: subtree(:param)) do rule(params: subtree(:p)) do
(param.is_a?(Array) ? param : [param]).each_with_object({}) { |(key, value), hash| hash[key] = value } (p.is_a?(Array) ? p : [p]).each_with_object({}) { |(key, val), h| h[key] = val }
end end
rule(param: { key: simple(:key), value: simple(:val) }) do rule(param: { key: simple(:key), value: simple(:val) }) do

View file

@ -63,7 +63,7 @@ class FollowerAccountsController < ApplicationController
id: account_followers_url(@account, page: params.fetch(:page, 1)), id: account_followers_url(@account, page: params.fetch(:page, 1)),
type: :ordered, type: :ordered,
size: @account.followers_count, size: @account.followers_count,
items: follows.map { |follow| ActivityPub::TagManager.instance.uri_for(follow.account) }, items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.account) },
part_of: account_followers_url(@account), part_of: account_followers_url(@account),
next: next_page_url, next: next_page_url,
prev: prev_page_url prev: prev_page_url

View file

@ -66,7 +66,7 @@ class FollowingAccountsController < ApplicationController
id: account_following_index_url(@account, page: params.fetch(:page, 1)), id: account_following_index_url(@account, page: params.fetch(:page, 1)),
type: :ordered, type: :ordered,
size: @account.following_count, size: @account.following_count,
items: follows.map { |follow| ActivityPub::TagManager.instance.uri_for(follow.target_account) }, items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.target_account) },
part_of: account_following_index_url(@account), part_of: account_following_index_url(@account),
next: next_page_url, next: next_page_url,
prev: prev_page_url prev: prev_page_url

View file

@ -12,8 +12,8 @@ class MediaController < ApplicationController
before_action :check_playable, only: :player before_action :check_playable, only: :player
before_action :allow_iframing, only: :player before_action :allow_iframing, only: :player
content_security_policy only: :player do |policy| content_security_policy only: :player do |p|
policy.frame_ancestors(false) p.frame_ancestors(false)
end end
def show def show

View file

@ -7,10 +7,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
before_action :authenticate_resource_owner! before_action :authenticate_resource_owner!
before_action :set_cache_headers before_action :set_cache_headers
content_security_policy do |p|
p.form_action(false)
end
include Localized include Localized
private private
@ -34,6 +30,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
end end
def set_cache_headers def set_cache_headers
response.headers['Cache-Control'] = 'private, no-store' response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
end end
end end

View file

@ -14,7 +14,7 @@ class Settings::BaseController < ApplicationController
end end
def set_cache_headers def set_cache_headers
response.headers['Cache-Control'] = 'private, no-store' response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
end end
def require_not_suspended! def require_not_suspended!

View file

@ -19,10 +19,6 @@ class StatusesCleanupController < ApplicationController
# Do nothing # Do nothing
end end
def require_functional!
redirect_to edit_user_registration_path unless current_user.functional_or_moved?
end
private private
def set_policy def set_policy

View file

@ -17,8 +17,8 @@ class StatusesController < ApplicationController
skip_around_action :set_locale, if: -> { request.format == :json } skip_around_action :set_locale, if: -> { request.format == :json }
skip_before_action :require_functional!, only: [:show, :embed], unless: :whitelist_mode? skip_before_action :require_functional!, only: [:show, :embed], unless: :whitelist_mode?
content_security_policy only: :embed do |policy| content_security_policy only: :embed do |p|
policy.frame_ancestors(false) p.frame_ancestors(false)
end end
def show def show

View file

@ -65,7 +65,7 @@ class TagsController < ApplicationController
id: tag_url(@tag), id: tag_url(@tag),
type: :ordered, type: :ordered,
size: @tag.statuses.count, size: @tag.statuses.count,
items: @statuses.map { |status| ActivityPub::TagManager.instance.uri_for(status) } items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) }
) )
end end
end end

View file

@ -23,28 +23,19 @@ module FormattingHelper
before_html = begin before_html = begin
if status.spoiler_text? if status.spoiler_text?
tag.p do "<p><strong>#{I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale)}</strong> #{h(status.spoiler_text)}</p><hr />"
tag.strong do else
I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale) ''
end
status.spoiler_text
end + tag.hr
end
end end
end.html_safe # rubocop:disable Rails/OutputSafety
after_html = begin after_html = begin
if status.preloadable_poll if status.preloadable_poll
tag.p do "<p>#{status.preloadable_poll.options.map { |o| "<input type=#{status.preloadable_poll.multiple? ? 'checkbox' : 'radio'} disabled /> #{h(o)}" }.join('<br />')}</p>"
safe_join( else
status.preloadable_poll.options.map do |o| ''
tag.send(status.preloadable_poll.multiple? ? 'checkbox' : 'radio', o, disabled: true)
end,
tag.br
)
end
end
end end
end.html_safe # rubocop:disable Rails/OutputSafety
prerender_custom_emojis( prerender_custom_emojis(
safe_join([before_html, html, after_html]), safe_join([before_html, html, after_html]),

View file

@ -190,15 +190,12 @@ module LanguagesHelper
ISO_639_3 = { ISO_639_3 = {
ast: ['Asturian', 'Asturianu'].freeze, ast: ['Asturian', 'Asturianu'].freeze,
ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze, ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze,
cnr: ['Montenegrin', 'crnogorski'].freeze,
jbo: ['Lojban', 'la .lojban.'].freeze, jbo: ['Lojban', 'la .lojban.'].freeze,
kab: ['Kabyle', 'Taqbaylit'].freeze, kab: ['Kabyle', 'Taqbaylit'].freeze,
kmr: ['Kurmanji (Kurdish)', 'Kurmancî'].freeze, kmr: ['Kurmanji (Kurdish)', 'Kurmancî'].freeze,
ldn: ['Láadan', 'Láadan'].freeze, ldn: ['Láadan', 'Láadan'].freeze,
lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze, lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze,
sco: ['Scots', 'Scots'].freeze, sco: ['Scots', 'Scots'].freeze,
sma: ['Southern Sami', 'Åarjelsaemien Gïele'].freeze,
smj: ['Lule Sami', 'Julevsámegiella'].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,

View file

@ -21,7 +21,7 @@ module StatusesHelper
def media_summary(status) def media_summary(status)
attachments = { image: 0, video: 0, audio: 0 } attachments = { image: 0, video: 0, audio: 0 }
status.ordered_media_attachments.each do |media| status.media_attachments.each do |media|
if media.video? if media.video?
attachments[:video] += 1 attachments[:video] += 1
elsif media.audio? elsif media.audio?

View file

@ -1,2 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="79" height="79" viewBox="0 0 79 75"><symbol id="logo-symbol-icon"><path d="M74.7135 16.6043C73.6199 8.54587 66.5351 2.19527 58.1366 0.964691C56.7196 0.756754 51.351 0 38.9148 0H38.822C26.3824 0 23.7135 0.756754 22.2966 0.964691C14.1319 2.16118 6.67571 7.86752 4.86669 16.0214C3.99657 20.0369 3.90371 24.4888 4.06535 28.5726C4.29578 34.4289 4.34049 40.275 4.877 46.1075C5.24791 49.9817 5.89495 53.8251 6.81328 57.6088C8.53288 64.5968 15.4938 70.4122 22.3138 72.7848C29.6155 75.259 37.468 75.6697 44.9919 73.971C45.8196 73.7801 46.6381 73.5586 47.4475 73.3063C49.2737 72.7302 51.4164 72.086 52.9915 70.9542C53.0131 70.9384 53.0308 70.9178 53.0433 70.8942C53.0558 70.8706 53.0628 70.8445 53.0637 70.8179V65.1661C53.0634 65.1412 53.0574 65.1167 53.0462 65.0944C53.035 65.0721 53.0189 65.0525 52.9992 65.0371C52.9794 65.0218 52.9564 65.011 52.9318 65.0056C52.9073 65.0002 52.8819 65.0003 52.8574 65.0059C48.0369 66.1472 43.0971 66.7193 38.141 66.7103C29.6118 66.7103 27.3178 62.6981 26.6609 61.0278C26.1329 59.5842 25.7976 58.0784 25.6636 56.5486C25.6622 56.5229 25.667 56.4973 25.6775 56.4738C25.688 56.4502 25.7039 56.4295 25.724 56.4132C25.7441 56.397 25.7678 56.3856 25.7931 56.3801C25.8185 56.3746 25.8448 56.3751 25.8699 56.3816C30.6101 57.5151 35.4693 58.0873 40.3455 58.086C41.5183 58.086 42.6876 58.086 43.8604 58.0553C48.7647 57.919 53.9339 57.6701 58.7591 56.7361C58.8794 56.7123 58.9998 56.6918 59.103 56.6611C66.7139 55.2124 73.9569 50.665 74.6929 39.1501C74.7204 38.6967 74.7892 34.4016 74.7892 33.9312C74.7926 32.3325 75.3085 22.5901 74.7135 16.6043ZM62.9996 45.3371H54.9966V25.9069C54.9966 21.8163 53.277 19.7302 49.7793 19.7302C45.9343 19.7302 44.0083 22.1981 44.0083 27.0727V37.7082H36.0534V27.0727C36.0534 22.1981 34.124 19.7302 30.279 19.7302C26.8019 19.7302 25.0651 21.8163 25.0617 25.9069V45.3371H17.0656V25.3172C17.0656 21.2266 18.1191 17.9769 20.2262 15.568C22.3998 13.1648 25.2509 11.9308 28.7898 11.9308C32.8859 11.9308 35.9812 13.492 38.0447 16.6111L40.036 19.9245L42.0308 16.6111C44.0943 13.492 47.1896 11.9308 51.2788 11.9308C54.8143 11.9308 57.6654 13.1648 59.8459 15.568C61.9529 17.9746 63.0065 21.2243 63.0065 25.3172L62.9996 45.3371Z" fill="currentColor"/></symbol><use xlink:href="#logo-symbol-icon"/></svg> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="79" height="79" viewBox="0 0 79 75"><symbol id="logo-symbol-icon"><path d="M74.7135 16.6043C73.6199 8.54587 66.5351 2.19527 58.1366 0.964691C56.7196 0.756754 51.351 0 38.9148 0H38.822C26.3824 0 23.7135 0.756754 22.2966 0.964691C14.1319 2.16118 6.67571 7.86752 4.86669 16.0214C3.99657 20.0369 3.90371 24.4888 4.06535 28.5726C4.29578 34.4289 4.34049 40.275 4.877 46.1075C5.24791 49.9817 5.89495 53.8251 6.81328 57.6088C8.53288 64.5968 15.4938 70.4122 22.3138 72.7848C29.6155 75.259 37.468 75.6697 44.9919 73.971C45.8196 73.7801 46.6381 73.5586 47.4475 73.3063C49.2737 72.7302 51.4164 72.086 52.9915 70.9542C53.0131 70.9384 53.0308 70.9178 53.0433 70.8942C53.0558 70.8706 53.0628 70.8445 53.0637 70.8179V65.1661C53.0634 65.1412 53.0574 65.1167 53.0462 65.0944C53.035 65.0721 53.0189 65.0525 52.9992 65.0371C52.9794 65.0218 52.9564 65.011 52.9318 65.0056C52.9073 65.0002 52.8819 65.0003 52.8574 65.0059C48.0369 66.1472 43.0971 66.7193 38.141 66.7103C29.6118 66.7103 27.3178 62.6981 26.6609 61.0278C26.1329 59.5842 25.7976 58.0784 25.6636 56.5486C25.6622 56.5229 25.667 56.4973 25.6775 56.4738C25.688 56.4502 25.7039 56.4295 25.724 56.4132C25.7441 56.397 25.7678 56.3856 25.7931 56.3801C25.8185 56.3746 25.8448 56.3751 25.8699 56.3816C30.6101 57.5151 35.4693 58.0873 40.3455 58.086C41.5183 58.086 42.6876 58.086 43.8604 58.0553C48.7647 57.919 53.9339 57.6701 58.7591 56.7361C58.8794 56.7123 58.9998 56.6918 59.103 56.6611C66.7139 55.2124 73.9569 50.665 74.6929 39.1501C74.7204 38.6967 74.7892 34.4016 74.7892 33.9312C74.7926 32.3325 75.3085 22.5901 74.7135 16.6043ZM62.9996 45.3371H54.9966V25.9069C54.9966 21.8163 53.277 19.7302 49.7793 19.7302C45.9343 19.7302 44.0083 22.1981 44.0083 27.0727V37.7082H36.0534V27.0727C36.0534 22.1981 34.124 19.7302 30.279 19.7302C26.8019 19.7302 25.0651 21.8163 25.0617 25.9069V45.3371H17.0656V25.3172C17.0656 21.2266 18.1191 17.9769 20.2262 15.568C22.3998 13.1648 25.2509 11.9308 28.7898 11.9308C32.8859 11.9308 35.9812 13.492 38.0447 16.6111L40.036 19.9245L42.0308 16.6111C44.0943 13.492 47.1896 11.9308 51.2788 11.9308C54.8143 11.9308 57.6654 13.1648 59.8459 15.568C61.9529 17.9746 63.0065 21.2243 63.0065 25.3172L62.9996 45.3371Z" fill="currentColor"/></symbol><use xlink:href="#logo-symbol-icon" style="color:#fff" /></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -7,5 +7,5 @@
<stop stop-color="#6364FF"/> <stop stop-color="#6364FF"/>
<stop offset="1" stop-color="#563ACC"/> <stop offset="1" stop-color="#563ACC"/>
</linearGradient> </linearGradient>
</defs></symbol><use xlink:href="#logo-symbol-wordmark"/> </defs></symbol><use xlink:href="#logo-symbol-wordmark" style="color:#fff"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

@ -14,24 +14,24 @@ export function submitAccountNote(id, value) {
dispatch(submitAccountNoteSuccess(response.data)); dispatch(submitAccountNoteSuccess(response.data));
}).catch(error => dispatch(submitAccountNoteFail(error))); }).catch(error => dispatch(submitAccountNoteFail(error)));
}; };
} };
export function submitAccountNoteRequest() { export function submitAccountNoteRequest() {
return { return {
type: ACCOUNT_NOTE_SUBMIT_REQUEST, type: ACCOUNT_NOTE_SUBMIT_REQUEST,
}; };
} };
export function submitAccountNoteSuccess(relationship) { export function submitAccountNoteSuccess(relationship) {
return { return {
type: ACCOUNT_NOTE_SUBMIT_SUCCESS, type: ACCOUNT_NOTE_SUBMIT_SUCCESS,
relationship, relationship,
}; };
} };
export function submitAccountNoteFail(error) { export function submitAccountNoteFail(error) {
return { return {
type: ACCOUNT_NOTE_SUBMIT_FAIL, type: ACCOUNT_NOTE_SUBMIT_FAIL,
error, error,
}; };
} };

View file

@ -91,7 +91,7 @@ export function fetchAccount(id) {
dispatch(fetchAccountFail(id, error)); dispatch(fetchAccountFail(id, error));
}); });
}; };
} };
export const lookupAccount = acct => (dispatch, getState) => { export const lookupAccount = acct => (dispatch, getState) => {
dispatch(lookupAccountRequest(acct)); dispatch(lookupAccountRequest(acct));
@ -126,13 +126,13 @@ export function fetchAccountRequest(id) {
type: ACCOUNT_FETCH_REQUEST, type: ACCOUNT_FETCH_REQUEST,
id, id,
}; };
} };
export function fetchAccountSuccess() { export function fetchAccountSuccess() {
return { return {
type: ACCOUNT_FETCH_SUCCESS, type: ACCOUNT_FETCH_SUCCESS,
}; };
} };
export function fetchAccountFail(id, error) { export function fetchAccountFail(id, error) {
return { return {
@ -141,7 +141,7 @@ export function fetchAccountFail(id, error) {
error, error,
skipAlert: true, skipAlert: true,
}; };
} };
export function followAccount(id, options = { reblogs: true }) { export function followAccount(id, options = { reblogs: true }) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -156,7 +156,7 @@ export function followAccount(id, options = { reblogs: true }) {
dispatch(followAccountFail(error, locked)); dispatch(followAccountFail(error, locked));
}); });
}; };
} };
export function unfollowAccount(id) { export function unfollowAccount(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -168,7 +168,7 @@ export function unfollowAccount(id) {
dispatch(unfollowAccountFail(error)); dispatch(unfollowAccountFail(error));
}); });
}; };
} };
export function followAccountRequest(id, locked) { export function followAccountRequest(id, locked) {
return { return {
@ -177,7 +177,7 @@ export function followAccountRequest(id, locked) {
locked, locked,
skipLoading: true, skipLoading: true,
}; };
} };
export function followAccountSuccess(relationship, alreadyFollowing) { export function followAccountSuccess(relationship, alreadyFollowing) {
return { return {
@ -186,7 +186,7 @@ export function followAccountSuccess(relationship, alreadyFollowing) {
alreadyFollowing, alreadyFollowing,
skipLoading: true, skipLoading: true,
}; };
} };
export function followAccountFail(error, locked) { export function followAccountFail(error, locked) {
return { return {
@ -195,7 +195,7 @@ export function followAccountFail(error, locked) {
locked, locked,
skipLoading: true, skipLoading: true,
}; };
} };
export function unfollowAccountRequest(id) { export function unfollowAccountRequest(id) {
return { return {
@ -203,7 +203,7 @@ export function unfollowAccountRequest(id) {
id, id,
skipLoading: true, skipLoading: true,
}; };
} };
export function unfollowAccountSuccess(relationship, statuses) { export function unfollowAccountSuccess(relationship, statuses) {
return { return {
@ -212,7 +212,7 @@ export function unfollowAccountSuccess(relationship, statuses) {
statuses, statuses,
skipLoading: true, skipLoading: true,
}; };
} };
export function unfollowAccountFail(error) { export function unfollowAccountFail(error) {
return { return {
@ -220,7 +220,7 @@ export function unfollowAccountFail(error) {
error, error,
skipLoading: true, skipLoading: true,
}; };
} };
export function blockAccount(id) { export function blockAccount(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -233,7 +233,7 @@ export function blockAccount(id) {
dispatch(blockAccountFail(id, error)); dispatch(blockAccountFail(id, error));
}); });
}; };
} };
export function unblockAccount(id) { export function unblockAccount(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -245,14 +245,14 @@ export function unblockAccount(id) {
dispatch(unblockAccountFail(id, error)); dispatch(unblockAccountFail(id, error));
}); });
}; };
} };
export function blockAccountRequest(id) { export function blockAccountRequest(id) {
return { return {
type: ACCOUNT_BLOCK_REQUEST, type: ACCOUNT_BLOCK_REQUEST,
id, id,
}; };
} };
export function blockAccountSuccess(relationship, statuses) { export function blockAccountSuccess(relationship, statuses) {
return { return {
@ -260,35 +260,35 @@ export function blockAccountSuccess(relationship, statuses) {
relationship, relationship,
statuses, statuses,
}; };
} };
export function blockAccountFail(error) { export function blockAccountFail(error) {
return { return {
type: ACCOUNT_BLOCK_FAIL, type: ACCOUNT_BLOCK_FAIL,
error, error,
}; };
} };
export function unblockAccountRequest(id) { export function unblockAccountRequest(id) {
return { return {
type: ACCOUNT_UNBLOCK_REQUEST, type: ACCOUNT_UNBLOCK_REQUEST,
id, id,
}; };
} };
export function unblockAccountSuccess(relationship) { export function unblockAccountSuccess(relationship) {
return { return {
type: ACCOUNT_UNBLOCK_SUCCESS, type: ACCOUNT_UNBLOCK_SUCCESS,
relationship, relationship,
}; };
} };
export function unblockAccountFail(error) { export function unblockAccountFail(error) {
return { return {
type: ACCOUNT_UNBLOCK_FAIL, type: ACCOUNT_UNBLOCK_FAIL,
error, error,
}; };
} };
export function muteAccount(id, notifications, duration=0) { export function muteAccount(id, notifications, duration=0) {
@ -302,7 +302,7 @@ export function muteAccount(id, notifications, duration=0) {
dispatch(muteAccountFail(id, error)); dispatch(muteAccountFail(id, error));
}); });
}; };
} };
export function unmuteAccount(id) { export function unmuteAccount(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -314,14 +314,14 @@ export function unmuteAccount(id) {
dispatch(unmuteAccountFail(id, error)); dispatch(unmuteAccountFail(id, error));
}); });
}; };
} };
export function muteAccountRequest(id) { export function muteAccountRequest(id) {
return { return {
type: ACCOUNT_MUTE_REQUEST, type: ACCOUNT_MUTE_REQUEST,
id, id,
}; };
} };
export function muteAccountSuccess(relationship, statuses) { export function muteAccountSuccess(relationship, statuses) {
return { return {
@ -329,35 +329,35 @@ export function muteAccountSuccess(relationship, statuses) {
relationship, relationship,
statuses, statuses,
}; };
} };
export function muteAccountFail(error) { export function muteAccountFail(error) {
return { return {
type: ACCOUNT_MUTE_FAIL, type: ACCOUNT_MUTE_FAIL,
error, error,
}; };
} };
export function unmuteAccountRequest(id) { export function unmuteAccountRequest(id) {
return { return {
type: ACCOUNT_UNMUTE_REQUEST, type: ACCOUNT_UNMUTE_REQUEST,
id, id,
}; };
} };
export function unmuteAccountSuccess(relationship) { export function unmuteAccountSuccess(relationship) {
return { return {
type: ACCOUNT_UNMUTE_SUCCESS, type: ACCOUNT_UNMUTE_SUCCESS,
relationship, relationship,
}; };
} };
export function unmuteAccountFail(error) { export function unmuteAccountFail(error) {
return { return {
type: ACCOUNT_UNMUTE_FAIL, type: ACCOUNT_UNMUTE_FAIL,
error, error,
}; };
} };
export function fetchFollowers(id) { export function fetchFollowers(id) {
@ -374,14 +374,14 @@ export function fetchFollowers(id) {
dispatch(fetchFollowersFail(id, error)); dispatch(fetchFollowersFail(id, error));
}); });
}; };
} };
export function fetchFollowersRequest(id) { export function fetchFollowersRequest(id) {
return { return {
type: FOLLOWERS_FETCH_REQUEST, type: FOLLOWERS_FETCH_REQUEST,
id, id,
}; };
} };
export function fetchFollowersSuccess(id, accounts, next) { export function fetchFollowersSuccess(id, accounts, next) {
return { return {
@ -390,7 +390,7 @@ export function fetchFollowersSuccess(id, accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function fetchFollowersFail(id, error) { export function fetchFollowersFail(id, error) {
return { return {
@ -399,7 +399,7 @@ export function fetchFollowersFail(id, error) {
error, error,
skipNotFound: true, skipNotFound: true,
}; };
} };
export function expandFollowers(id) { export function expandFollowers(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -421,14 +421,14 @@ export function expandFollowers(id) {
dispatch(expandFollowersFail(id, error)); dispatch(expandFollowersFail(id, error));
}); });
}; };
} };
export function expandFollowersRequest(id) { export function expandFollowersRequest(id) {
return { return {
type: FOLLOWERS_EXPAND_REQUEST, type: FOLLOWERS_EXPAND_REQUEST,
id, id,
}; };
} };
export function expandFollowersSuccess(id, accounts, next) { export function expandFollowersSuccess(id, accounts, next) {
return { return {
@ -437,7 +437,7 @@ export function expandFollowersSuccess(id, accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function expandFollowersFail(id, error) { export function expandFollowersFail(id, error) {
return { return {
@ -445,7 +445,7 @@ export function expandFollowersFail(id, error) {
id, id,
error, error,
}; };
} };
export function fetchFollowing(id) { export function fetchFollowing(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -461,14 +461,14 @@ export function fetchFollowing(id) {
dispatch(fetchFollowingFail(id, error)); dispatch(fetchFollowingFail(id, error));
}); });
}; };
} };
export function fetchFollowingRequest(id) { export function fetchFollowingRequest(id) {
return { return {
type: FOLLOWING_FETCH_REQUEST, type: FOLLOWING_FETCH_REQUEST,
id, id,
}; };
} };
export function fetchFollowingSuccess(id, accounts, next) { export function fetchFollowingSuccess(id, accounts, next) {
return { return {
@ -477,7 +477,7 @@ export function fetchFollowingSuccess(id, accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function fetchFollowingFail(id, error) { export function fetchFollowingFail(id, error) {
return { return {
@ -486,7 +486,7 @@ export function fetchFollowingFail(id, error) {
error, error,
skipNotFound: true, skipNotFound: true,
}; };
} };
export function expandFollowing(id) { export function expandFollowing(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -508,14 +508,14 @@ export function expandFollowing(id) {
dispatch(expandFollowingFail(id, error)); dispatch(expandFollowingFail(id, error));
}); });
}; };
} };
export function expandFollowingRequest(id) { export function expandFollowingRequest(id) {
return { return {
type: FOLLOWING_EXPAND_REQUEST, type: FOLLOWING_EXPAND_REQUEST,
id, id,
}; };
} };
export function expandFollowingSuccess(id, accounts, next) { export function expandFollowingSuccess(id, accounts, next) {
return { return {
@ -524,7 +524,7 @@ export function expandFollowingSuccess(id, accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function expandFollowingFail(id, error) { export function expandFollowingFail(id, error) {
return { return {
@ -532,7 +532,7 @@ export function expandFollowingFail(id, error) {
id, id,
error, error,
}; };
} };
export function fetchRelationships(accountIds) { export function fetchRelationships(accountIds) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -553,7 +553,7 @@ export function fetchRelationships(accountIds) {
dispatch(fetchRelationshipsFail(error)); dispatch(fetchRelationshipsFail(error));
}); });
}; };
} };
export function fetchRelationshipsRequest(ids) { export function fetchRelationshipsRequest(ids) {
return { return {
@ -561,7 +561,7 @@ export function fetchRelationshipsRequest(ids) {
ids, ids,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchRelationshipsSuccess(relationships) { export function fetchRelationshipsSuccess(relationships) {
return { return {
@ -569,7 +569,7 @@ export function fetchRelationshipsSuccess(relationships) {
relationships, relationships,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchRelationshipsFail(error) { export function fetchRelationshipsFail(error) {
return { return {
@ -578,7 +578,7 @@ export function fetchRelationshipsFail(error) {
skipLoading: true, skipLoading: true,
skipNotFound: true, skipNotFound: true,
}; };
} };
export function fetchFollowRequests() { export function fetchFollowRequests() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -590,13 +590,13 @@ export function fetchFollowRequests() {
dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null)); dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null));
}).catch(error => dispatch(fetchFollowRequestsFail(error))); }).catch(error => dispatch(fetchFollowRequestsFail(error)));
}; };
} };
export function fetchFollowRequestsRequest() { export function fetchFollowRequestsRequest() {
return { return {
type: FOLLOW_REQUESTS_FETCH_REQUEST, type: FOLLOW_REQUESTS_FETCH_REQUEST,
}; };
} };
export function fetchFollowRequestsSuccess(accounts, next) { export function fetchFollowRequestsSuccess(accounts, next) {
return { return {
@ -604,14 +604,14 @@ export function fetchFollowRequestsSuccess(accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function fetchFollowRequestsFail(error) { export function fetchFollowRequestsFail(error) {
return { return {
type: FOLLOW_REQUESTS_FETCH_FAIL, type: FOLLOW_REQUESTS_FETCH_FAIL,
error, error,
}; };
} };
export function expandFollowRequests() { export function expandFollowRequests() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -629,13 +629,13 @@ export function expandFollowRequests() {
dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null)); dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null));
}).catch(error => dispatch(expandFollowRequestsFail(error))); }).catch(error => dispatch(expandFollowRequestsFail(error)));
}; };
} };
export function expandFollowRequestsRequest() { export function expandFollowRequestsRequest() {
return { return {
type: FOLLOW_REQUESTS_EXPAND_REQUEST, type: FOLLOW_REQUESTS_EXPAND_REQUEST,
}; };
} };
export function expandFollowRequestsSuccess(accounts, next) { export function expandFollowRequestsSuccess(accounts, next) {
return { return {
@ -643,14 +643,14 @@ export function expandFollowRequestsSuccess(accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function expandFollowRequestsFail(error) { export function expandFollowRequestsFail(error) {
return { return {
type: FOLLOW_REQUESTS_EXPAND_FAIL, type: FOLLOW_REQUESTS_EXPAND_FAIL,
error, error,
}; };
} };
export function authorizeFollowRequest(id) { export function authorizeFollowRequest(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -661,21 +661,21 @@ export function authorizeFollowRequest(id) {
.then(() => dispatch(authorizeFollowRequestSuccess(id))) .then(() => dispatch(authorizeFollowRequestSuccess(id)))
.catch(error => dispatch(authorizeFollowRequestFail(id, error))); .catch(error => dispatch(authorizeFollowRequestFail(id, error)));
}; };
} };
export function authorizeFollowRequestRequest(id) { export function authorizeFollowRequestRequest(id) {
return { return {
type: FOLLOW_REQUEST_AUTHORIZE_REQUEST, type: FOLLOW_REQUEST_AUTHORIZE_REQUEST,
id, id,
}; };
} };
export function authorizeFollowRequestSuccess(id) { export function authorizeFollowRequestSuccess(id) {
return { return {
type: FOLLOW_REQUEST_AUTHORIZE_SUCCESS, type: FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
id, id,
}; };
} };
export function authorizeFollowRequestFail(id, error) { export function authorizeFollowRequestFail(id, error) {
return { return {
@ -683,7 +683,7 @@ export function authorizeFollowRequestFail(id, error) {
id, id,
error, error,
}; };
} };
export function rejectFollowRequest(id) { export function rejectFollowRequest(id) {
@ -695,21 +695,21 @@ export function rejectFollowRequest(id) {
.then(() => dispatch(rejectFollowRequestSuccess(id))) .then(() => dispatch(rejectFollowRequestSuccess(id)))
.catch(error => dispatch(rejectFollowRequestFail(id, error))); .catch(error => dispatch(rejectFollowRequestFail(id, error)));
}; };
} };
export function rejectFollowRequestRequest(id) { export function rejectFollowRequestRequest(id) {
return { return {
type: FOLLOW_REQUEST_REJECT_REQUEST, type: FOLLOW_REQUEST_REJECT_REQUEST,
id, id,
}; };
} };
export function rejectFollowRequestSuccess(id) { export function rejectFollowRequestSuccess(id) {
return { return {
type: FOLLOW_REQUEST_REJECT_SUCCESS, type: FOLLOW_REQUEST_REJECT_SUCCESS,
id, id,
}; };
} };
export function rejectFollowRequestFail(id, error) { export function rejectFollowRequestFail(id, error) {
return { return {
@ -717,7 +717,7 @@ export function rejectFollowRequestFail(id, error) {
id, id,
error, error,
}; };
} };
export function pinAccount(id) { export function pinAccount(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -729,7 +729,7 @@ export function pinAccount(id) {
dispatch(pinAccountFail(error)); dispatch(pinAccountFail(error));
}); });
}; };
} };
export function unpinAccount(id) { export function unpinAccount(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -741,49 +741,49 @@ export function unpinAccount(id) {
dispatch(unpinAccountFail(error)); dispatch(unpinAccountFail(error));
}); });
}; };
} };
export function pinAccountRequest(id) { export function pinAccountRequest(id) {
return { return {
type: ACCOUNT_PIN_REQUEST, type: ACCOUNT_PIN_REQUEST,
id, id,
}; };
} };
export function pinAccountSuccess(relationship) { export function pinAccountSuccess(relationship) {
return { return {
type: ACCOUNT_PIN_SUCCESS, type: ACCOUNT_PIN_SUCCESS,
relationship, relationship,
}; };
} };
export function pinAccountFail(error) { export function pinAccountFail(error) {
return { return {
type: ACCOUNT_PIN_FAIL, type: ACCOUNT_PIN_FAIL,
error, error,
}; };
} };
export function unpinAccountRequest(id) { export function unpinAccountRequest(id) {
return { return {
type: ACCOUNT_UNPIN_REQUEST, type: ACCOUNT_UNPIN_REQUEST,
id, id,
}; };
} };
export function unpinAccountSuccess(relationship) { export function unpinAccountSuccess(relationship) {
return { return {
type: ACCOUNT_UNPIN_SUCCESS, type: ACCOUNT_UNPIN_SUCCESS,
relationship, relationship,
}; };
} };
export function unpinAccountFail(error) { export function unpinAccountFail(error) {
return { return {
type: ACCOUNT_UNPIN_FAIL, type: ACCOUNT_UNPIN_FAIL,
error, error,
}; };
} };
export const revealAccount = id => ({ export const revealAccount = id => ({
type: ACCOUNT_REVEAL, type: ACCOUNT_REVEAL,

View file

@ -17,13 +17,13 @@ export function dismissAlert(alert) {
type: ALERT_DISMISS, type: ALERT_DISMISS,
alert, alert,
}; };
} };
export function clearAlert() { export function clearAlert() {
return { return {
type: ALERT_CLEAR, type: ALERT_CLEAR,
}; };
} };
export function showAlert(title = messages.unexpectedTitle, message = messages.unexpectedMessage, message_values = undefined) { export function showAlert(title = messages.unexpectedTitle, message = messages.unexpectedMessage, message_values = undefined) {
return { return {
@ -32,7 +32,7 @@ export function showAlert(title = messages.unexpectedTitle, message = messages.u
message, message,
message_values, message_values,
}; };
} };
export function showAlertForError(error, skipNotFound = false) { export function showAlertForError(error, skipNotFound = false) {
if (error.response) { if (error.response) {

View file

@ -102,7 +102,7 @@ export const addReaction = (announcementId, name) => (dispatch, getState) => {
dispatch(addReactionRequest(announcementId, name, alreadyAdded)); dispatch(addReactionRequest(announcementId, name, alreadyAdded));
} }
api(getState).put(`/api/v1/announcements/${announcementId}/reactions/${encodeURIComponent(name)}`).then(() => { api(getState).put(`/api/v1/announcements/${announcementId}/reactions/${name}`).then(() => {
dispatch(addReactionSuccess(announcementId, name, alreadyAdded)); dispatch(addReactionSuccess(announcementId, name, alreadyAdded));
}).catch(err => { }).catch(err => {
if (!alreadyAdded) { if (!alreadyAdded) {
@ -136,7 +136,7 @@ export const addReactionFail = (announcementId, name, error) => ({
export const removeReaction = (announcementId, name) => (dispatch, getState) => { export const removeReaction = (announcementId, name) => (dispatch, getState) => {
dispatch(removeReactionRequest(announcementId, name)); dispatch(removeReactionRequest(announcementId, name));
api(getState).delete(`/api/v1/announcements/${announcementId}/reactions/${encodeURIComponent(name)}`).then(() => { api(getState).delete(`/api/v1/announcements/${announcementId}/reactions/${name}`).then(() => {
dispatch(removeReactionSuccess(announcementId, name)); dispatch(removeReactionSuccess(announcementId, name));
}).catch(err => { }).catch(err => {
dispatch(removeReactionFail(announcementId, name, err)); dispatch(removeReactionFail(announcementId, name, err));

View file

@ -24,13 +24,13 @@ export function fetchBlocks() {
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
}).catch(error => dispatch(fetchBlocksFail(error))); }).catch(error => dispatch(fetchBlocksFail(error)));
}; };
} };
export function fetchBlocksRequest() { export function fetchBlocksRequest() {
return { return {
type: BLOCKS_FETCH_REQUEST, type: BLOCKS_FETCH_REQUEST,
}; };
} };
export function fetchBlocksSuccess(accounts, next) { export function fetchBlocksSuccess(accounts, next) {
return { return {
@ -38,14 +38,14 @@ export function fetchBlocksSuccess(accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function fetchBlocksFail(error) { export function fetchBlocksFail(error) {
return { return {
type: BLOCKS_FETCH_FAIL, type: BLOCKS_FETCH_FAIL,
error, error,
}; };
} };
export function expandBlocks() { export function expandBlocks() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -64,13 +64,13 @@ export function expandBlocks() {
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
}).catch(error => dispatch(expandBlocksFail(error))); }).catch(error => dispatch(expandBlocksFail(error)));
}; };
} };
export function expandBlocksRequest() { export function expandBlocksRequest() {
return { return {
type: BLOCKS_EXPAND_REQUEST, type: BLOCKS_EXPAND_REQUEST,
}; };
} };
export function expandBlocksSuccess(accounts, next) { export function expandBlocksSuccess(accounts, next) {
return { return {
@ -78,14 +78,14 @@ export function expandBlocksSuccess(accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function expandBlocksFail(error) { export function expandBlocksFail(error) {
return { return {
type: BLOCKS_EXPAND_FAIL, type: BLOCKS_EXPAND_FAIL,
error, error,
}; };
} };
export function initBlockModal(account) { export function initBlockModal(account) {
return dispatch => { return dispatch => {

View file

@ -25,13 +25,13 @@ export function fetchBookmarkedStatuses() {
dispatch(fetchBookmarkedStatusesFail(error)); dispatch(fetchBookmarkedStatusesFail(error));
}); });
}; };
} };
export function fetchBookmarkedStatusesRequest() { export function fetchBookmarkedStatusesRequest() {
return { return {
type: BOOKMARKED_STATUSES_FETCH_REQUEST, type: BOOKMARKED_STATUSES_FETCH_REQUEST,
}; };
} };
export function fetchBookmarkedStatusesSuccess(statuses, next) { export function fetchBookmarkedStatusesSuccess(statuses, next) {
return { return {
@ -39,14 +39,14 @@ export function fetchBookmarkedStatusesSuccess(statuses, next) {
statuses, statuses,
next, next,
}; };
} };
export function fetchBookmarkedStatusesFail(error) { export function fetchBookmarkedStatusesFail(error) {
return { return {
type: BOOKMARKED_STATUSES_FETCH_FAIL, type: BOOKMARKED_STATUSES_FETCH_FAIL,
error, error,
}; };
} };
export function expandBookmarkedStatuses() { export function expandBookmarkedStatuses() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -66,13 +66,13 @@ export function expandBookmarkedStatuses() {
dispatch(expandBookmarkedStatusesFail(error)); dispatch(expandBookmarkedStatusesFail(error));
}); });
}; };
} };
export function expandBookmarkedStatusesRequest() { export function expandBookmarkedStatusesRequest() {
return { return {
type: BOOKMARKED_STATUSES_EXPAND_REQUEST, type: BOOKMARKED_STATUSES_EXPAND_REQUEST,
}; };
} };
export function expandBookmarkedStatusesSuccess(statuses, next) { export function expandBookmarkedStatusesSuccess(statuses, next) {
return { return {
@ -80,11 +80,11 @@ export function expandBookmarkedStatusesSuccess(statuses, next) {
statuses, statuses,
next, next,
}; };
} };
export function expandBookmarkedStatusesFail(error) { export function expandBookmarkedStatusesFail(error) {
return { return {
type: BOOKMARKED_STATUSES_EXPAND_FAIL, type: BOOKMARKED_STATUSES_EXPAND_FAIL,
error, error,
}; };
} };

View file

@ -15,7 +15,7 @@ export function addColumn(id, params) {
dispatch(saveSettings()); dispatch(saveSettings());
}; };
} };
export function removeColumn(uuid) { export function removeColumn(uuid) {
return dispatch => { return dispatch => {
@ -26,7 +26,7 @@ export function removeColumn(uuid) {
dispatch(saveSettings()); dispatch(saveSettings());
}; };
} };
export function moveColumn(uuid, direction) { export function moveColumn(uuid, direction) {
return dispatch => { return dispatch => {
@ -38,7 +38,7 @@ export function moveColumn(uuid, direction) {
dispatch(saveSettings()); dispatch(saveSettings());
}; };
} };
export function changeColumnParams(uuid, path, value) { export function changeColumnParams(uuid, path, value) {
return dispatch => { return dispatch => {

View file

@ -94,14 +94,14 @@ export function setComposeToStatus(status, text, spoiler_text) {
text, text,
spoiler_text, spoiler_text,
}; };
} };
export function changeCompose(text) { export function changeCompose(text) {
return { return {
type: COMPOSE_CHANGE, type: COMPOSE_CHANGE,
text: text, text: text,
}; };
} };
export function replyCompose(status, routerHistory) { export function replyCompose(status, routerHistory) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -112,19 +112,19 @@ export function replyCompose(status, routerHistory) {
ensureComposeIsVisible(getState, routerHistory); ensureComposeIsVisible(getState, routerHistory);
}; };
} };
export function cancelReplyCompose() { export function cancelReplyCompose() {
return { return {
type: COMPOSE_REPLY_CANCEL, type: COMPOSE_REPLY_CANCEL,
}; };
} };
export function resetCompose() { export function resetCompose() {
return { return {
type: COMPOSE_RESET, type: COMPOSE_RESET,
}; };
} };
export function mentionCompose(account, routerHistory) { export function mentionCompose(account, routerHistory) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -135,7 +135,7 @@ export function mentionCompose(account, routerHistory) {
ensureComposeIsVisible(getState, routerHistory); ensureComposeIsVisible(getState, routerHistory);
}; };
} };
export function directCompose(account, routerHistory) { export function directCompose(account, routerHistory) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -146,7 +146,7 @@ export function directCompose(account, routerHistory) {
ensureComposeIsVisible(getState, routerHistory); ensureComposeIsVisible(getState, routerHistory);
}; };
} };
export function submitCompose(routerHistory) { export function submitCompose(routerHistory) {
return function (dispatch, getState) { return function (dispatch, getState) {
@ -211,27 +211,27 @@ export function submitCompose(routerHistory) {
dispatch(submitComposeFail(error)); dispatch(submitComposeFail(error));
}); });
}; };
} };
export function submitComposeRequest() { export function submitComposeRequest() {
return { return {
type: COMPOSE_SUBMIT_REQUEST, type: COMPOSE_SUBMIT_REQUEST,
}; };
} };
export function submitComposeSuccess(status) { export function submitComposeSuccess(status) {
return { return {
type: COMPOSE_SUBMIT_SUCCESS, type: COMPOSE_SUBMIT_SUCCESS,
status: status, status: status,
}; };
} };
export function submitComposeFail(error) { export function submitComposeFail(error) {
return { return {
type: COMPOSE_SUBMIT_FAIL, type: COMPOSE_SUBMIT_FAIL,
error: error, error: error,
}; };
} };
export function uploadCompose(files) { export function uploadCompose(files) {
return function (dispatch, getState) { return function (dispatch, getState) {
@ -294,9 +294,9 @@ export function uploadCompose(files) {
} }
}); });
}).catch(error => dispatch(uploadComposeFail(error))); }).catch(error => dispatch(uploadComposeFail(error)));
}
}; };
} };
};
export const uploadComposeProcessing = () => ({ export const uploadComposeProcessing = () => ({
type: COMPOSE_UPLOAD_PROCESSING, type: COMPOSE_UPLOAD_PROCESSING,
@ -354,14 +354,14 @@ export function initMediaEditModal(id) {
dispatch(openModal('FOCAL_POINT', { id })); dispatch(openModal('FOCAL_POINT', { id }));
}; };
} };
export function onChangeMediaDescription(description) { export function onChangeMediaDescription(description) {
return { return {
type: COMPOSE_CHANGE_MEDIA_DESCRIPTION, type: COMPOSE_CHANGE_MEDIA_DESCRIPTION,
description, description,
}; };
} };
export function onChangeMediaFocus(focusX, focusY) { export function onChangeMediaFocus(focusX, focusY) {
return { return {
@ -369,7 +369,7 @@ export function onChangeMediaFocus(focusX, focusY) {
focusX, focusX,
focusY, focusY,
}; };
} };
export function changeUploadCompose(id, params) { export function changeUploadCompose(id, params) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -381,14 +381,14 @@ export function changeUploadCompose(id, params) {
dispatch(changeUploadComposeFail(id, error)); dispatch(changeUploadComposeFail(id, error));
}); });
}; };
} };
export function changeUploadComposeRequest() { export function changeUploadComposeRequest() {
return { return {
type: COMPOSE_UPLOAD_CHANGE_REQUEST, type: COMPOSE_UPLOAD_CHANGE_REQUEST,
skipLoading: true, skipLoading: true,
}; };
} };
export function changeUploadComposeSuccess(media) { export function changeUploadComposeSuccess(media) {
return { return {
@ -396,7 +396,7 @@ export function changeUploadComposeSuccess(media) {
media: media, media: media,
skipLoading: true, skipLoading: true,
}; };
} };
export function changeUploadComposeFail(error) { export function changeUploadComposeFail(error) {
return { return {
@ -404,14 +404,14 @@ export function changeUploadComposeFail(error) {
error: error, error: error,
skipLoading: true, skipLoading: true,
}; };
} };
export function uploadComposeRequest() { export function uploadComposeRequest() {
return { return {
type: COMPOSE_UPLOAD_REQUEST, type: COMPOSE_UPLOAD_REQUEST,
skipLoading: true, skipLoading: true,
}; };
} };
export function uploadComposeProgress(loaded, total) { export function uploadComposeProgress(loaded, total) {
return { return {
@ -419,7 +419,7 @@ export function uploadComposeProgress(loaded, total) {
loaded: loaded, loaded: loaded,
total: total, total: total,
}; };
} };
export function uploadComposeSuccess(media, file) { export function uploadComposeSuccess(media, file) {
return { return {
@ -428,7 +428,7 @@ export function uploadComposeSuccess(media, file) {
file: file, file: file,
skipLoading: true, skipLoading: true,
}; };
} };
export function uploadComposeFail(error) { export function uploadComposeFail(error) {
return { return {
@ -436,14 +436,14 @@ export function uploadComposeFail(error) {
error: error, error: error,
skipLoading: true, skipLoading: true,
}; };
} };
export function undoUploadCompose(media_id) { export function undoUploadCompose(media_id) {
return { return {
type: COMPOSE_UPLOAD_UNDO, type: COMPOSE_UPLOAD_UNDO,
media_id: media_id, media_id: media_id,
}; };
} };
export function clearComposeSuggestions() { export function clearComposeSuggestions() {
if (fetchComposeSuggestionsAccountsController) { if (fetchComposeSuggestionsAccountsController) {
@ -452,7 +452,7 @@ export function clearComposeSuggestions() {
return { return {
type: COMPOSE_SUGGESTIONS_CLEAR, type: COMPOSE_SUGGESTIONS_CLEAR,
}; };
} };
const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => { const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => {
if (fetchComposeSuggestionsAccountsController) { if (fetchComposeSuggestionsAccountsController) {
@ -530,7 +530,7 @@ export function fetchComposeSuggestions(token) {
break; break;
} }
}; };
} };
export function readyComposeSuggestionsEmojis(token, emojis) { export function readyComposeSuggestionsEmojis(token, emojis) {
return { return {
@ -538,7 +538,7 @@ export function readyComposeSuggestionsEmojis(token, emojis) {
token, token,
emojis, emojis,
}; };
} };
export function readyComposeSuggestionsAccounts(token, accounts) { export function readyComposeSuggestionsAccounts(token, accounts) {
return { return {
@ -546,7 +546,7 @@ export function readyComposeSuggestionsAccounts(token, accounts) {
token, token,
accounts, accounts,
}; };
} };
export const readyComposeSuggestionsTags = (token, tags) => ({ export const readyComposeSuggestionsTags = (token, tags) => ({
type: COMPOSE_SUGGESTIONS_READY, type: COMPOSE_SUGGESTIONS_READY,
@ -591,7 +591,7 @@ export function selectComposeSuggestion(position, token, suggestion, path) {
}); });
} }
}; };
} };
export function updateSuggestionTags(token) { export function updateSuggestionTags(token) {
return { return {
@ -652,19 +652,19 @@ export function mountCompose() {
return { return {
type: COMPOSE_MOUNT, type: COMPOSE_MOUNT,
}; };
} };
export function unmountCompose() { export function unmountCompose() {
return { return {
type: COMPOSE_UNMOUNT, type: COMPOSE_UNMOUNT,
}; };
} };
export function changeComposeSensitivity() { export function changeComposeSensitivity() {
return { return {
type: COMPOSE_SENSITIVITY_CHANGE, type: COMPOSE_SENSITIVITY_CHANGE,
}; };
} };
export const changeComposeLanguage = language => ({ export const changeComposeLanguage = language => ({
type: COMPOSE_LANGUAGE_CHANGE, type: COMPOSE_LANGUAGE_CHANGE,
@ -675,21 +675,21 @@ export function changeComposeSpoilerness() {
return { return {
type: COMPOSE_SPOILERNESS_CHANGE, type: COMPOSE_SPOILERNESS_CHANGE,
}; };
} };
export function changeComposeSpoilerText(text) { export function changeComposeSpoilerText(text) {
return { return {
type: COMPOSE_SPOILER_TEXT_CHANGE, type: COMPOSE_SPOILER_TEXT_CHANGE,
text, text,
}; };
} };
export function changeComposeVisibility(value) { export function changeComposeVisibility(value) {
return { return {
type: COMPOSE_VISIBILITY_CHANGE, type: COMPOSE_VISIBILITY_CHANGE,
value, value,
}; };
} };
export function insertEmojiCompose(position, emoji, needsSpace) { export function insertEmojiCompose(position, emoji, needsSpace) {
return { return {
@ -698,33 +698,33 @@ export function insertEmojiCompose(position, emoji, needsSpace) {
emoji, emoji,
needsSpace, needsSpace,
}; };
} };
export function changeComposing(value) { export function changeComposing(value) {
return { return {
type: COMPOSE_COMPOSING_CHANGE, type: COMPOSE_COMPOSING_CHANGE,
value, value,
}; };
} };
export function addPoll() { export function addPoll() {
return { return {
type: COMPOSE_POLL_ADD, type: COMPOSE_POLL_ADD,
}; };
} };
export function removePoll() { export function removePoll() {
return { return {
type: COMPOSE_POLL_REMOVE, type: COMPOSE_POLL_REMOVE,
}; };
} };
export function addPollOption(title) { export function addPollOption(title) {
return { return {
type: COMPOSE_POLL_OPTION_ADD, type: COMPOSE_POLL_OPTION_ADD,
title, title,
}; };
} };
export function changePollOption(index, title) { export function changePollOption(index, title) {
return { return {
@ -732,14 +732,14 @@ export function changePollOption(index, title) {
index, index,
title, title,
}; };
} };
export function removePollOption(index) { export function removePollOption(index) {
return { return {
type: COMPOSE_POLL_OPTION_REMOVE, type: COMPOSE_POLL_OPTION_REMOVE,
index, index,
}; };
} };
export function changePollSettings(expiresIn, isMultiple) { export function changePollSettings(expiresIn, isMultiple) {
return { return {
@ -747,4 +747,4 @@ export function changePollSettings(expiresIn, isMultiple) {
expiresIn, expiresIn,
isMultiple, isMultiple,
}; };
} };

View file

@ -14,14 +14,14 @@ export function fetchCustomEmojis() {
dispatch(fetchCustomEmojisFail(error)); dispatch(fetchCustomEmojisFail(error));
}); });
}; };
} };
export function fetchCustomEmojisRequest() { export function fetchCustomEmojisRequest() {
return { return {
type: CUSTOM_EMOJIS_FETCH_REQUEST, type: CUSTOM_EMOJIS_FETCH_REQUEST,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchCustomEmojisSuccess(custom_emojis) { export function fetchCustomEmojisSuccess(custom_emojis) {
return { return {
@ -29,7 +29,7 @@ export function fetchCustomEmojisSuccess(custom_emojis) {
custom_emojis, custom_emojis,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchCustomEmojisFail(error) { export function fetchCustomEmojisFail(error) {
return { return {
@ -37,4 +37,4 @@ export function fetchCustomEmojisFail(error) {
error, error,
skipLoading: true, skipLoading: true,
}; };
} };

View file

@ -29,14 +29,14 @@ export function blockDomain(domain) {
dispatch(blockDomainFail(domain, err)); dispatch(blockDomainFail(domain, err));
}); });
}; };
} };
export function blockDomainRequest(domain) { export function blockDomainRequest(domain) {
return { return {
type: DOMAIN_BLOCK_REQUEST, type: DOMAIN_BLOCK_REQUEST,
domain, domain,
}; };
} };
export function blockDomainSuccess(domain, accounts) { export function blockDomainSuccess(domain, accounts) {
return { return {
@ -44,7 +44,7 @@ export function blockDomainSuccess(domain, accounts) {
domain, domain,
accounts, accounts,
}; };
} };
export function blockDomainFail(domain, error) { export function blockDomainFail(domain, error) {
return { return {
@ -52,7 +52,7 @@ export function blockDomainFail(domain, error) {
domain, domain,
error, error,
}; };
} };
export function unblockDomain(domain) { export function unblockDomain(domain) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -66,14 +66,14 @@ export function unblockDomain(domain) {
dispatch(unblockDomainFail(domain, err)); dispatch(unblockDomainFail(domain, err));
}); });
}; };
} };
export function unblockDomainRequest(domain) { export function unblockDomainRequest(domain) {
return { return {
type: DOMAIN_UNBLOCK_REQUEST, type: DOMAIN_UNBLOCK_REQUEST,
domain, domain,
}; };
} };
export function unblockDomainSuccess(domain, accounts) { export function unblockDomainSuccess(domain, accounts) {
return { return {
@ -81,7 +81,7 @@ export function unblockDomainSuccess(domain, accounts) {
domain, domain,
accounts, accounts,
}; };
} };
export function unblockDomainFail(domain, error) { export function unblockDomainFail(domain, error) {
return { return {
@ -89,7 +89,7 @@ export function unblockDomainFail(domain, error) {
domain, domain,
error, error,
}; };
} };
export function fetchDomainBlocks() { export function fetchDomainBlocks() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -102,13 +102,13 @@ export function fetchDomainBlocks() {
dispatch(fetchDomainBlocksFail(err)); dispatch(fetchDomainBlocksFail(err));
}); });
}; };
} };
export function fetchDomainBlocksRequest() { export function fetchDomainBlocksRequest() {
return { return {
type: DOMAIN_BLOCKS_FETCH_REQUEST, type: DOMAIN_BLOCKS_FETCH_REQUEST,
}; };
} };
export function fetchDomainBlocksSuccess(domains, next) { export function fetchDomainBlocksSuccess(domains, next) {
return { return {
@ -116,14 +116,14 @@ export function fetchDomainBlocksSuccess(domains, next) {
domains, domains,
next, next,
}; };
} };
export function fetchDomainBlocksFail(error) { export function fetchDomainBlocksFail(error) {
return { return {
type: DOMAIN_BLOCKS_FETCH_FAIL, type: DOMAIN_BLOCKS_FETCH_FAIL,
error, error,
}; };
} };
export function expandDomainBlocks() { export function expandDomainBlocks() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -142,13 +142,13 @@ export function expandDomainBlocks() {
dispatch(expandDomainBlocksFail(err)); dispatch(expandDomainBlocksFail(err));
}); });
}; };
} };
export function expandDomainBlocksRequest() { export function expandDomainBlocksRequest() {
return { return {
type: DOMAIN_BLOCKS_EXPAND_REQUEST, type: DOMAIN_BLOCKS_EXPAND_REQUEST,
}; };
} };
export function expandDomainBlocksSuccess(domains, next) { export function expandDomainBlocksSuccess(domains, next) {
return { return {
@ -156,11 +156,11 @@ export function expandDomainBlocksSuccess(domains, next) {
domains, domains,
next, next,
}; };
} };
export function expandDomainBlocksFail(error) { export function expandDomainBlocksFail(error) {
return { return {
type: DOMAIN_BLOCKS_EXPAND_FAIL, type: DOMAIN_BLOCKS_EXPAND_FAIL,
error, error,
}; };
} };

View file

@ -11,4 +11,4 @@ export function useEmoji(emoji) {
dispatch(saveSettings()); dispatch(saveSettings());
}; };
} };

View file

@ -25,14 +25,14 @@ export function fetchFavouritedStatuses() {
dispatch(fetchFavouritedStatusesFail(error)); dispatch(fetchFavouritedStatusesFail(error));
}); });
}; };
} };
export function fetchFavouritedStatusesRequest() { export function fetchFavouritedStatusesRequest() {
return { return {
type: FAVOURITED_STATUSES_FETCH_REQUEST, type: FAVOURITED_STATUSES_FETCH_REQUEST,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchFavouritedStatusesSuccess(statuses, next) { export function fetchFavouritedStatusesSuccess(statuses, next) {
return { return {
@ -41,7 +41,7 @@ export function fetchFavouritedStatusesSuccess(statuses, next) {
next, next,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchFavouritedStatusesFail(error) { export function fetchFavouritedStatusesFail(error) {
return { return {
@ -49,7 +49,7 @@ export function fetchFavouritedStatusesFail(error) {
error, error,
skipLoading: true, skipLoading: true,
}; };
} };
export function expandFavouritedStatuses() { export function expandFavouritedStatuses() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -69,13 +69,13 @@ export function expandFavouritedStatuses() {
dispatch(expandFavouritedStatusesFail(error)); dispatch(expandFavouritedStatusesFail(error));
}); });
}; };
} };
export function expandFavouritedStatusesRequest() { export function expandFavouritedStatusesRequest() {
return { return {
type: FAVOURITED_STATUSES_EXPAND_REQUEST, type: FAVOURITED_STATUSES_EXPAND_REQUEST,
}; };
} };
export function expandFavouritedStatusesSuccess(statuses, next) { export function expandFavouritedStatusesSuccess(statuses, next) {
return { return {
@ -83,11 +83,11 @@ export function expandFavouritedStatusesSuccess(statuses, next) {
statuses, statuses,
next, next,
}; };
} };
export function expandFavouritedStatusesFail(error) { export function expandFavouritedStatusesFail(error) {
return { return {
type: FAVOURITED_STATUSES_EXPAND_FAIL, type: FAVOURITED_STATUSES_EXPAND_FAIL,
error, error,
}; };
} };

View file

@ -8,10 +8,10 @@ export function setHeight (key, id, height) {
id, id,
height, height,
}; };
} };
export function clearHeight () { export function clearHeight () {
return { return {
type: HEIGHT_CACHE_CLEAR, type: HEIGHT_CACHE_CLEAR,
}; };
} };

View file

@ -54,7 +54,7 @@ export function reblog(status, visibility) {
dispatch(reblogFail(status, error)); dispatch(reblogFail(status, error));
}); });
}; };
} };
export function unreblog(status) { export function unreblog(status) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -67,7 +67,7 @@ export function unreblog(status) {
dispatch(unreblogFail(status, error)); dispatch(unreblogFail(status, error));
}); });
}; };
} };
export function reblogRequest(status) { export function reblogRequest(status) {
return { return {
@ -75,7 +75,7 @@ export function reblogRequest(status) {
status: status, status: status,
skipLoading: true, skipLoading: true,
}; };
} };
export function reblogSuccess(status) { export function reblogSuccess(status) {
return { return {
@ -83,7 +83,7 @@ export function reblogSuccess(status) {
status: status, status: status,
skipLoading: true, skipLoading: true,
}; };
} };
export function reblogFail(status, error) { export function reblogFail(status, error) {
return { return {
@ -92,7 +92,7 @@ export function reblogFail(status, error) {
error: error, error: error,
skipLoading: true, skipLoading: true,
}; };
} };
export function unreblogRequest(status) { export function unreblogRequest(status) {
return { return {
@ -100,7 +100,7 @@ export function unreblogRequest(status) {
status: status, status: status,
skipLoading: true, skipLoading: true,
}; };
} };
export function unreblogSuccess(status) { export function unreblogSuccess(status) {
return { return {
@ -108,7 +108,7 @@ export function unreblogSuccess(status) {
status: status, status: status,
skipLoading: true, skipLoading: true,
}; };
} };
export function unreblogFail(status, error) { export function unreblogFail(status, error) {
return { return {
@ -117,7 +117,7 @@ export function unreblogFail(status, error) {
error: error, error: error,
skipLoading: true, skipLoading: true,
}; };
} };
export function favourite(status) { export function favourite(status) {
return function (dispatch, getState) { return function (dispatch, getState) {
@ -130,7 +130,7 @@ export function favourite(status) {
dispatch(favouriteFail(status, error)); dispatch(favouriteFail(status, error));
}); });
}; };
} };
export function unfavourite(status) { export function unfavourite(status) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -143,7 +143,7 @@ export function unfavourite(status) {
dispatch(unfavouriteFail(status, error)); dispatch(unfavouriteFail(status, error));
}); });
}; };
} };
export function favouriteRequest(status) { export function favouriteRequest(status) {
return { return {
@ -151,7 +151,7 @@ export function favouriteRequest(status) {
status: status, status: status,
skipLoading: true, skipLoading: true,
}; };
} };
export function favouriteSuccess(status) { export function favouriteSuccess(status) {
return { return {
@ -159,7 +159,7 @@ export function favouriteSuccess(status) {
status: status, status: status,
skipLoading: true, skipLoading: true,
}; };
} };
export function favouriteFail(status, error) { export function favouriteFail(status, error) {
return { return {
@ -168,7 +168,7 @@ export function favouriteFail(status, error) {
error: error, error: error,
skipLoading: true, skipLoading: true,
}; };
} };
export function unfavouriteRequest(status) { export function unfavouriteRequest(status) {
return { return {
@ -176,7 +176,7 @@ export function unfavouriteRequest(status) {
status: status, status: status,
skipLoading: true, skipLoading: true,
}; };
} };
export function unfavouriteSuccess(status) { export function unfavouriteSuccess(status) {
return { return {
@ -184,7 +184,7 @@ export function unfavouriteSuccess(status) {
status: status, status: status,
skipLoading: true, skipLoading: true,
}; };
} };
export function unfavouriteFail(status, error) { export function unfavouriteFail(status, error) {
return { return {
@ -193,7 +193,7 @@ export function unfavouriteFail(status, error) {
error: error, error: error,
skipLoading: true, skipLoading: true,
}; };
} };
export function bookmark(status) { export function bookmark(status) {
return function (dispatch, getState) { return function (dispatch, getState) {
@ -206,7 +206,7 @@ export function bookmark(status) {
dispatch(bookmarkFail(status, error)); dispatch(bookmarkFail(status, error));
}); });
}; };
} };
export function unbookmark(status) { export function unbookmark(status) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -219,14 +219,14 @@ export function unbookmark(status) {
dispatch(unbookmarkFail(status, error)); dispatch(unbookmarkFail(status, error));
}); });
}; };
} };
export function bookmarkRequest(status) { export function bookmarkRequest(status) {
return { return {
type: BOOKMARK_REQUEST, type: BOOKMARK_REQUEST,
status: status, status: status,
}; };
} };
export function bookmarkSuccess(status, response) { export function bookmarkSuccess(status, response) {
return { return {
@ -234,7 +234,7 @@ export function bookmarkSuccess(status, response) {
status: status, status: status,
response: response, response: response,
}; };
} };
export function bookmarkFail(status, error) { export function bookmarkFail(status, error) {
return { return {
@ -242,14 +242,14 @@ export function bookmarkFail(status, error) {
status: status, status: status,
error: error, error: error,
}; };
} };
export function unbookmarkRequest(status) { export function unbookmarkRequest(status) {
return { return {
type: UNBOOKMARK_REQUEST, type: UNBOOKMARK_REQUEST,
status: status, status: status,
}; };
} };
export function unbookmarkSuccess(status, response) { export function unbookmarkSuccess(status, response) {
return { return {
@ -257,7 +257,7 @@ export function unbookmarkSuccess(status, response) {
status: status, status: status,
response: response, response: response,
}; };
} };
export function unbookmarkFail(status, error) { export function unbookmarkFail(status, error) {
return { return {
@ -265,7 +265,7 @@ export function unbookmarkFail(status, error) {
status: status, status: status,
error: error, error: error,
}; };
} };
export function fetchReblogs(id) { export function fetchReblogs(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -278,14 +278,14 @@ export function fetchReblogs(id) {
dispatch(fetchReblogsFail(id, error)); dispatch(fetchReblogsFail(id, error));
}); });
}; };
} };
export function fetchReblogsRequest(id) { export function fetchReblogsRequest(id) {
return { return {
type: REBLOGS_FETCH_REQUEST, type: REBLOGS_FETCH_REQUEST,
id, id,
}; };
} };
export function fetchReblogsSuccess(id, accounts) { export function fetchReblogsSuccess(id, accounts) {
return { return {
@ -293,14 +293,14 @@ export function fetchReblogsSuccess(id, accounts) {
id, id,
accounts, accounts,
}; };
} };
export function fetchReblogsFail(id, error) { export function fetchReblogsFail(id, error) {
return { return {
type: REBLOGS_FETCH_FAIL, type: REBLOGS_FETCH_FAIL,
error, error,
}; };
} };
export function fetchFavourites(id) { export function fetchFavourites(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -313,14 +313,14 @@ export function fetchFavourites(id) {
dispatch(fetchFavouritesFail(id, error)); dispatch(fetchFavouritesFail(id, error));
}); });
}; };
} };
export function fetchFavouritesRequest(id) { export function fetchFavouritesRequest(id) {
return { return {
type: FAVOURITES_FETCH_REQUEST, type: FAVOURITES_FETCH_REQUEST,
id, id,
}; };
} };
export function fetchFavouritesSuccess(id, accounts) { export function fetchFavouritesSuccess(id, accounts) {
return { return {
@ -328,14 +328,14 @@ export function fetchFavouritesSuccess(id, accounts) {
id, id,
accounts, accounts,
}; };
} };
export function fetchFavouritesFail(id, error) { export function fetchFavouritesFail(id, error) {
return { return {
type: FAVOURITES_FETCH_FAIL, type: FAVOURITES_FETCH_FAIL,
error, error,
}; };
} };
export function pin(status) { export function pin(status) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -348,7 +348,7 @@ export function pin(status) {
dispatch(pinFail(status, error)); dispatch(pinFail(status, error));
}); });
}; };
} };
export function pinRequest(status) { export function pinRequest(status) {
return { return {
@ -356,7 +356,7 @@ export function pinRequest(status) {
status, status,
skipLoading: true, skipLoading: true,
}; };
} };
export function pinSuccess(status) { export function pinSuccess(status) {
return { return {
@ -364,7 +364,7 @@ export function pinSuccess(status) {
status, status,
skipLoading: true, skipLoading: true,
}; };
} };
export function pinFail(status, error) { export function pinFail(status, error) {
return { return {
@ -373,7 +373,7 @@ export function pinFail(status, error) {
error, error,
skipLoading: true, skipLoading: true,
}; };
} };
export function unpin (status) { export function unpin (status) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -386,7 +386,7 @@ export function unpin (status) {
dispatch(unpinFail(status, error)); dispatch(unpinFail(status, error));
}); });
}; };
} };
export function unpinRequest(status) { export function unpinRequest(status) {
return { return {
@ -394,7 +394,7 @@ export function unpinRequest(status) {
status, status,
skipLoading: true, skipLoading: true,
}; };
} };
export function unpinSuccess(status) { export function unpinSuccess(status) {
return { return {
@ -402,7 +402,7 @@ export function unpinSuccess(status) {
status, status,
skipLoading: true, skipLoading: true,
}; };
} };
export function unpinFail(status, error) { export function unpinFail(status, error) {
return { return {
@ -411,4 +411,4 @@ export function unpinFail(status, error) {
error, error,
skipLoading: true, skipLoading: true,
}; };
} };

View file

@ -101,7 +101,7 @@ export function submitMarkersSuccess({ home, notifications }) {
home: (home || {}).last_read_id, home: (home || {}).last_read_id,
notifications: (notifications || {}).last_read_id, notifications: (notifications || {}).last_read_id,
}; };
} };
export function submitMarkers(params = {}) { export function submitMarkers(params = {}) {
const result = (dispatch, getState) => debouncedSubmitMarkers(dispatch, getState); const result = (dispatch, getState) => debouncedSubmitMarkers(dispatch, getState);
@ -111,7 +111,7 @@ export function submitMarkers(params = {}) {
} }
return result; return result;
} };
export const fetchMarkers = () => (dispatch, getState) => { export const fetchMarkers = () => (dispatch, getState) => {
const params = { timeline: ['notifications'] }; const params = { timeline: ['notifications'] };
@ -130,7 +130,7 @@ export function fetchMarkersRequest() {
type: MARKERS_FETCH_REQUEST, type: MARKERS_FETCH_REQUEST,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchMarkersSuccess(markers) { export function fetchMarkersSuccess(markers) {
return { return {
@ -138,7 +138,7 @@ export function fetchMarkersSuccess(markers) {
markers, markers,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchMarkersFail(error) { export function fetchMarkersFail(error) {
return { return {
@ -147,4 +147,4 @@ export function fetchMarkersFail(error) {
skipLoading: true, skipLoading: true,
skipAlert: true, skipAlert: true,
}; };
} };

View file

@ -7,7 +7,7 @@ export function openModal(type, props) {
modalType: type, modalType: type,
modalProps: props, modalProps: props,
}; };
} };
export function closeModal(type, options = { ignoreFocus: false }) { export function closeModal(type, options = { ignoreFocus: false }) {
return { return {
@ -15,4 +15,4 @@ export function closeModal(type, options = { ignoreFocus: false }) {
modalType: type, modalType: type,
ignoreFocus: options.ignoreFocus, ignoreFocus: options.ignoreFocus,
}; };
} };

View file

@ -26,13 +26,13 @@ export function fetchMutes() {
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
}).catch(error => dispatch(fetchMutesFail(error))); }).catch(error => dispatch(fetchMutesFail(error)));
}; };
} };
export function fetchMutesRequest() { export function fetchMutesRequest() {
return { return {
type: MUTES_FETCH_REQUEST, type: MUTES_FETCH_REQUEST,
}; };
} };
export function fetchMutesSuccess(accounts, next) { export function fetchMutesSuccess(accounts, next) {
return { return {
@ -40,14 +40,14 @@ export function fetchMutesSuccess(accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function fetchMutesFail(error) { export function fetchMutesFail(error) {
return { return {
type: MUTES_FETCH_FAIL, type: MUTES_FETCH_FAIL,
error, error,
}; };
} };
export function expandMutes() { export function expandMutes() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -66,13 +66,13 @@ export function expandMutes() {
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
}).catch(error => dispatch(expandMutesFail(error))); }).catch(error => dispatch(expandMutesFail(error)));
}; };
} };
export function expandMutesRequest() { export function expandMutesRequest() {
return { return {
type: MUTES_EXPAND_REQUEST, type: MUTES_EXPAND_REQUEST,
}; };
} };
export function expandMutesSuccess(accounts, next) { export function expandMutesSuccess(accounts, next) {
return { return {
@ -80,14 +80,14 @@ export function expandMutesSuccess(accounts, next) {
accounts, accounts,
next, next,
}; };
} };
export function expandMutesFail(error) { export function expandMutesFail(error) {
return { return {
type: MUTES_EXPAND_FAIL, type: MUTES_EXPAND_FAIL,
error, error,
}; };
} };
export function initMuteModal(account) { export function initMuteModal(account) {
return dispatch => { return dispatch => {

View file

@ -118,7 +118,7 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
}); });
} }
}; };
} };
const excludeTypesFromSettings = state => state.getIn(['settings', 'notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS(); const excludeTypesFromSettings = state => state.getIn(['settings', 'notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS();
@ -197,14 +197,14 @@ export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
done(); done();
}); });
}; };
} };
export function expandNotificationsRequest(isLoadingMore) { export function expandNotificationsRequest(isLoadingMore) {
return { return {
type: NOTIFICATIONS_EXPAND_REQUEST, type: NOTIFICATIONS_EXPAND_REQUEST,
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
}; };
} };
export function expandNotificationsSuccess(notifications, next, isLoadingMore, isLoadingRecent, usePendingItems) { export function expandNotificationsSuccess(notifications, next, isLoadingMore, isLoadingRecent, usePendingItems) {
return { return {
@ -215,7 +215,7 @@ export function expandNotificationsSuccess(notifications, next, isLoadingMore, i
usePendingItems, usePendingItems,
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
}; };
} };
export function expandNotificationsFail(error, isLoadingMore) { export function expandNotificationsFail(error, isLoadingMore) {
return { return {
@ -224,7 +224,7 @@ export function expandNotificationsFail(error, isLoadingMore) {
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
skipAlert: !isLoadingMore || error.name === 'AbortError', skipAlert: !isLoadingMore || error.name === 'AbortError',
}; };
} };
export function clearNotifications() { export function clearNotifications() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -234,14 +234,14 @@ export function clearNotifications() {
api(getState).post('/api/v1/notifications/clear'); api(getState).post('/api/v1/notifications/clear');
}; };
} };
export function scrollTopNotifications(top) { export function scrollTopNotifications(top) {
return { return {
type: NOTIFICATIONS_SCROLL_TOP, type: NOTIFICATIONS_SCROLL_TOP,
top, top,
}; };
} };
export function setFilter (filterType) { export function setFilter (filterType) {
return dispatch => { return dispatch => {
@ -253,7 +253,7 @@ export function setFilter (filterType) {
dispatch(expandNotifications({ forceLoad: true })); dispatch(expandNotifications({ forceLoad: true }));
dispatch(saveSettings()); dispatch(saveSettings());
}; };
} };
export const mountNotifications = () => ({ export const mountNotifications = () => ({
type: NOTIFICATIONS_MOUNT, type: NOTIFICATIONS_MOUNT,
@ -291,7 +291,7 @@ export function requestBrowserPermission(callback = noOp) {
callback(permission); callback(permission);
}); });
}; };
} };
export function setBrowserSupport (value) { export function setBrowserSupport (value) {
return { return {

View file

@ -18,13 +18,13 @@ export function fetchPinnedStatuses() {
dispatch(fetchPinnedStatusesFail(error)); dispatch(fetchPinnedStatusesFail(error));
}); });
}; };
} };
export function fetchPinnedStatusesRequest() { export function fetchPinnedStatusesRequest() {
return { return {
type: PINNED_STATUSES_FETCH_REQUEST, type: PINNED_STATUSES_FETCH_REQUEST,
}; };
} };
export function fetchPinnedStatusesSuccess(statuses, next) { export function fetchPinnedStatusesSuccess(statuses, next) {
return { return {
@ -32,11 +32,11 @@ export function fetchPinnedStatusesSuccess(statuses, next) {
statuses, statuses,
next, next,
}; };
} };
export function fetchPinnedStatusesFail(error) { export function fetchPinnedStatusesFail(error) {
return { return {
type: PINNED_STATUSES_FETCH_FAIL, type: PINNED_STATUSES_FETCH_FAIL,
error, error,
}; };
} };

View file

@ -19,13 +19,13 @@ export function changeSearch(value) {
type: SEARCH_CHANGE, type: SEARCH_CHANGE,
value, value,
}; };
} };
export function clearSearch() { export function clearSearch() {
return { return {
type: SEARCH_CLEAR, type: SEARCH_CLEAR,
}; };
} };
export function submitSearch() { export function submitSearch() {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -60,13 +60,13 @@ export function submitSearch() {
dispatch(fetchSearchFail(error)); dispatch(fetchSearchFail(error));
}); });
}; };
} };
export function fetchSearchRequest() { export function fetchSearchRequest() {
return { return {
type: SEARCH_FETCH_REQUEST, type: SEARCH_FETCH_REQUEST,
}; };
} };
export function fetchSearchSuccess(results, searchTerm) { export function fetchSearchSuccess(results, searchTerm) {
return { return {
@ -74,14 +74,14 @@ export function fetchSearchSuccess(results, searchTerm) {
results, results,
searchTerm, searchTerm,
}; };
} };
export function fetchSearchFail(error) { export function fetchSearchFail(error) {
return { return {
type: SEARCH_FETCH_FAIL, type: SEARCH_FETCH_FAIL,
error, error,
}; };
} };
export const expandSearch = type => (dispatch, getState) => { export const expandSearch = type => (dispatch, getState) => {
const value = getState().getIn(['search', 'value']); const value = getState().getIn(['search', 'value']);

View file

@ -15,7 +15,7 @@ export function changeSetting(path, value) {
dispatch(saveSettings()); dispatch(saveSettings());
}; };
} };
const debouncedSave = debounce((dispatch, getState) => { const debouncedSave = debounce((dispatch, getState) => {
if (getState().getIn(['settings', 'saved'])) { if (getState().getIn(['settings', 'saved'])) {
@ -31,4 +31,4 @@ const debouncedSave = debounce((dispatch, getState) => {
export function saveSettings() { export function saveSettings() {
return (dispatch, getState) => debouncedSave(dispatch, getState); return (dispatch, getState) => debouncedSave(dispatch, getState);
} };

View file

@ -45,7 +45,7 @@ export function fetchStatusRequest(id, skipLoading) {
id, id,
skipLoading, skipLoading,
}; };
} };
export function fetchStatus(id, forceFetch = false) { export function fetchStatus(id, forceFetch = false) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -66,14 +66,14 @@ export function fetchStatus(id, forceFetch = false) {
dispatch(fetchStatusFail(id, error, skipLoading)); dispatch(fetchStatusFail(id, error, skipLoading));
}); });
}; };
} };
export function fetchStatusSuccess(skipLoading) { export function fetchStatusSuccess(skipLoading) {
return { return {
type: STATUS_FETCH_SUCCESS, type: STATUS_FETCH_SUCCESS,
skipLoading, skipLoading,
}; };
} };
export function fetchStatusFail(id, error, skipLoading) { export function fetchStatusFail(id, error, skipLoading) {
return { return {
@ -83,7 +83,7 @@ export function fetchStatusFail(id, error, skipLoading) {
skipLoading, skipLoading,
skipAlert: true, skipAlert: true,
}; };
} };
export function redraft(status, raw_text) { export function redraft(status, raw_text) {
return { return {
@ -91,7 +91,7 @@ export function redraft(status, raw_text) {
status, status,
raw_text, raw_text,
}; };
} };
export const editStatus = (id, routerHistory) => (dispatch, getState) => { export const editStatus = (id, routerHistory) => (dispatch, getState) => {
let status = getState().getIn(['statuses', id]); let status = getState().getIn(['statuses', id]);
@ -147,21 +147,21 @@ export function deleteStatus(id, routerHistory, withRedraft = false) {
dispatch(deleteStatusFail(id, error)); dispatch(deleteStatusFail(id, error));
}); });
}; };
} };
export function deleteStatusRequest(id) { export function deleteStatusRequest(id) {
return { return {
type: STATUS_DELETE_REQUEST, type: STATUS_DELETE_REQUEST,
id: id, id: id,
}; };
} };
export function deleteStatusSuccess(id) { export function deleteStatusSuccess(id) {
return { return {
type: STATUS_DELETE_SUCCESS, type: STATUS_DELETE_SUCCESS,
id: id, id: id,
}; };
} };
export function deleteStatusFail(id, error) { export function deleteStatusFail(id, error) {
return { return {
@ -169,7 +169,7 @@ export function deleteStatusFail(id, error) {
id: id, id: id,
error: error, error: error,
}; };
} };
export const updateStatus = status => dispatch => export const updateStatus = status => dispatch =>
dispatch(importFetchedStatus(status)); dispatch(importFetchedStatus(status));
@ -190,14 +190,14 @@ export function fetchContext(id) {
dispatch(fetchContextFail(id, error)); dispatch(fetchContextFail(id, error));
}); });
}; };
} };
export function fetchContextRequest(id) { export function fetchContextRequest(id) {
return { return {
type: CONTEXT_FETCH_REQUEST, type: CONTEXT_FETCH_REQUEST,
id, id,
}; };
} };
export function fetchContextSuccess(id, ancestors, descendants) { export function fetchContextSuccess(id, ancestors, descendants) {
return { return {
@ -207,7 +207,7 @@ export function fetchContextSuccess(id, ancestors, descendants) {
descendants, descendants,
statuses: ancestors.concat(descendants), statuses: ancestors.concat(descendants),
}; };
} };
export function fetchContextFail(id, error) { export function fetchContextFail(id, error) {
return { return {
@ -216,7 +216,7 @@ export function fetchContextFail(id, error) {
error, error,
skipAlert: true, skipAlert: true,
}; };
} };
export function muteStatus(id) { export function muteStatus(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -228,21 +228,21 @@ export function muteStatus(id) {
dispatch(muteStatusFail(id, error)); dispatch(muteStatusFail(id, error));
}); });
}; };
} };
export function muteStatusRequest(id) { export function muteStatusRequest(id) {
return { return {
type: STATUS_MUTE_REQUEST, type: STATUS_MUTE_REQUEST,
id, id,
}; };
} };
export function muteStatusSuccess(id) { export function muteStatusSuccess(id) {
return { return {
type: STATUS_MUTE_SUCCESS, type: STATUS_MUTE_SUCCESS,
id, id,
}; };
} };
export function muteStatusFail(id, error) { export function muteStatusFail(id, error) {
return { return {
@ -250,7 +250,7 @@ export function muteStatusFail(id, error) {
id, id,
error, error,
}; };
} };
export function unmuteStatus(id) { export function unmuteStatus(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -262,21 +262,21 @@ export function unmuteStatus(id) {
dispatch(unmuteStatusFail(id, error)); dispatch(unmuteStatusFail(id, error));
}); });
}; };
} };
export function unmuteStatusRequest(id) { export function unmuteStatusRequest(id) {
return { return {
type: STATUS_UNMUTE_REQUEST, type: STATUS_UNMUTE_REQUEST,
id, id,
}; };
} };
export function unmuteStatusSuccess(id) { export function unmuteStatusSuccess(id) {
return { return {
type: STATUS_UNMUTE_SUCCESS, type: STATUS_UNMUTE_SUCCESS,
id, id,
}; };
} };
export function unmuteStatusFail(id, error) { export function unmuteStatusFail(id, error) {
return { return {
@ -284,7 +284,7 @@ export function unmuteStatusFail(id, error) {
id, id,
error, error,
}; };
} };
export function hideStatus(ids) { export function hideStatus(ids) {
if (!Array.isArray(ids)) { if (!Array.isArray(ids)) {
@ -295,7 +295,7 @@ export function hideStatus(ids) {
type: STATUS_HIDE, type: STATUS_HIDE,
ids, ids,
}; };
} };
export function revealStatus(ids) { export function revealStatus(ids) {
if (!Array.isArray(ids)) { if (!Array.isArray(ids)) {
@ -306,7 +306,7 @@ export function revealStatus(ids) {
type: STATUS_REVEAL, type: STATUS_REVEAL,
ids, ids,
}; };
} };
export function toggleStatusCollapse(id, isCollapsed) { export function toggleStatusCollapse(id, isCollapsed) {
return { return {
@ -314,7 +314,7 @@ export function toggleStatusCollapse(id, isCollapsed) {
id, id,
isCollapsed, isCollapsed,
}; };
} };
export const translateStatus = id => (dispatch, getState) => { export const translateStatus = id => (dispatch, getState) => {
dispatch(translateStatusRequest(id)); dispatch(translateStatusRequest(id));

View file

@ -21,4 +21,4 @@ export function hydrateStore(rawState) {
dispatch(hydrateCompose()); dispatch(hydrateCompose());
dispatch(importFetchedAccounts(Object.values(rawState.accounts))); dispatch(importFetchedAccounts(Object.values(rawState.accounts)));
}; };
} };

View file

@ -21,14 +21,14 @@ export function fetchSuggestions(withRelationships = false) {
} }
}).catch(error => dispatch(fetchSuggestionsFail(error))); }).catch(error => dispatch(fetchSuggestionsFail(error)));
}; };
} };
export function fetchSuggestionsRequest() { export function fetchSuggestionsRequest() {
return { return {
type: SUGGESTIONS_FETCH_REQUEST, type: SUGGESTIONS_FETCH_REQUEST,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchSuggestionsSuccess(suggestions) { export function fetchSuggestionsSuccess(suggestions) {
return { return {
@ -36,7 +36,7 @@ export function fetchSuggestionsSuccess(suggestions) {
suggestions, suggestions,
skipLoading: true, skipLoading: true,
}; };
} };
export function fetchSuggestionsFail(error) { export function fetchSuggestionsFail(error) {
return { return {
@ -45,7 +45,7 @@ export function fetchSuggestionsFail(error) {
skipLoading: true, skipLoading: true,
skipAlert: true, skipAlert: true,
}; };
} };
export const dismissSuggestion = accountId => (dispatch, getState) => { export const dismissSuggestion = accountId => (dispatch, getState) => {
dispatch({ dispatch({

View file

@ -51,7 +51,7 @@ export function updateTimeline(timeline, status, accept) {
dispatch(submitMarkers()); dispatch(submitMarkers());
} }
}; };
} };
export function deleteFromTimelines(id) { export function deleteFromTimelines(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -67,13 +67,13 @@ export function deleteFromTimelines(id) {
reblogOf, reblogOf,
}); });
}; };
} };
export function clearTimeline(timeline) { export function clearTimeline(timeline) {
return (dispatch) => { return (dispatch) => {
dispatch({ type: TIMELINE_CLEAR, timeline }); dispatch({ type: TIMELINE_CLEAR, timeline });
}; };
} };
const noOp = () => {}; const noOp = () => {};
@ -122,7 +122,7 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
done(); done();
}); });
}; };
} };
export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) { export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -168,7 +168,7 @@ export function expandTimelineRequest(timeline, isLoadingMore) {
timeline, timeline,
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
}; };
} };
export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadingRecent, isLoadingMore, usePendingItems) { export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadingRecent, isLoadingMore, usePendingItems) {
return { return {
@ -181,7 +181,7 @@ export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadi
usePendingItems, usePendingItems,
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
}; };
} };
export function expandTimelineFail(timeline, error, isLoadingMore) { export function expandTimelineFail(timeline, error, isLoadingMore) {
return { return {
@ -191,7 +191,7 @@ export function expandTimelineFail(timeline, error, isLoadingMore) {
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
skipNotFound: timeline.startsWith('account:'), skipNotFound: timeline.startsWith('account:'),
}; };
} };
export function scrollTopTimeline(timeline, top) { export function scrollTopTimeline(timeline, top) {
return { return {
@ -199,7 +199,7 @@ export function scrollTopTimeline(timeline, top) {
timeline, timeline,
top, top,
}; };
} };
export function connectTimeline(timeline) { export function connectTimeline(timeline) {
return { return {
@ -207,7 +207,7 @@ export function connectTimeline(timeline) {
timeline, timeline,
usePendingItems: preferPendingItems, usePendingItems: preferPendingItems,
}; };
} };
export const disconnectTimeline = timeline => ({ export const disconnectTimeline = timeline => ({
type: TIMELINE_DISCONNECT, type: TIMELINE_DISCONNECT,

View file

@ -9,4 +9,4 @@ export function start() {
} catch (e) { } catch (e) {
// If called twice // If called twice
} }
} };

View file

@ -8,4 +8,4 @@ export default function compareId (id1, id2) {
} else { } else {
return id1.length > id2.length ? 1 : -1; return id1.length > id2.length ? 1 : -1;
} }
} };

View file

@ -137,7 +137,7 @@ export default class Retention extends React.PureComponent {
break; break;
default: default:
title = <FormattedMessage id='admin.dashboard.monthly_retention' defaultMessage='User retention rate by month after sign-up' />; title = <FormattedMessage id='admin.dashboard.monthly_retention' defaultMessage='User retention rate by month after sign-up' />;
} };
return ( return (
<div className='retention'> <div className='retention'>

View file

@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import { is } from 'immutable'; import { is } from 'immutable';
import IconButton from './icon_button'; import IconButton from './icon_button';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { isIOS } from '../is_mobile';
import classNames from 'classnames'; import classNames from 'classnames';
import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_state'; import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_state';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
@ -180,7 +181,7 @@ class Item extends React.PureComponent {
</a> </a>
); );
} else if (attachment.get('type') === 'gifv') { } else if (attachment.get('type') === 'gifv') {
const autoPlay = this.getAutoPlay(); const autoPlay = !isIOS() && this.getAutoPlay();
thumbnail = ( thumbnail = (
<div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}> <div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}>
@ -194,7 +195,6 @@ class Item extends React.PureComponent {
onMouseEnter={this.handleMouseEnter} onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave} onMouseLeave={this.handleMouseLeave}
autoPlay={autoPlay} autoPlay={autoPlay}
playsInline
loop loop
muted muted
/> />

View file

@ -246,13 +246,12 @@ class StatusActionBar extends ImmutablePureComponent {
menu.push({ text: intl.formatMessage(messages.open), action: this.handleOpen }); menu.push({ text: intl.formatMessage(messages.open), action: this.handleOpen });
if (publicStatus && isRemote) { if (publicStatus) {
if (isRemote) {
menu.push({ text: intl.formatMessage(messages.openOriginalPage), href: status.get('url') }); menu.push({ text: intl.formatMessage(messages.openOriginalPage), href: status.get('url') });
} }
menu.push({ text: intl.formatMessage(messages.copy), action: this.handleCopy }); menu.push({ text: intl.formatMessage(messages.copy), action: this.handleCopy });
if (publicStatus) {
menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed }); menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed });
} }

View file

@ -23,9 +23,7 @@ export const store = configureStore();
const hydrateAction = hydrateStore(initialState); const hydrateAction = hydrateStore(initialState);
store.dispatch(hydrateAction); store.dispatch(hydrateAction);
if (initialState.meta.me) { store.dispatch(fetchCustomEmojis());
store.dispatch(fetchCustomEmojis());
}
const createIdentityContext = state => ({ const createIdentityContext = state => ({
signedIn: !!state.meta.me, signedIn: !!state.meta.me,

View file

@ -1,37 +0,0 @@
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Icon from 'mastodon/components/icon';
export default class FollowRequestNote extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map.isRequired,
};
render () {
const { account, onAuthorize, onReject } = this.props;
return (
<div className='follow-request-banner'>
<div className='follow-request-banner__message'>
<FormattedMessage id='account.requested_follow' defaultMessage='{name} has requested to follow you' values={{ name: <bdi><strong dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /></bdi> }} />
</div>
<div className='follow-request-banner__action'>
<button type='button' className='button button-tertiary button--confirmation' onClick={onAuthorize}>
<Icon id='check' fixedWidth />
<FormattedMessage id='follow_request.authorize' defaultMessage='Authorize' />
</button>
<button type='button' className='button button-tertiary button--destructive' onClick={onReject}>
<Icon id='times' fixedWidth />
<FormattedMessage id='follow_request.reject' defaultMessage='Reject' />
</button>
</div>
</div>
);
}
}

View file

@ -14,7 +14,6 @@ import ShortNumber from 'mastodon/components/short_number';
import { NavLink } from 'react-router-dom'; import { NavLink } from 'react-router-dom';
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container'; import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
import AccountNoteContainer from '../containers/account_note_container'; import AccountNoteContainer from '../containers/account_note_container';
import FollowRequestNoteContainer from '../containers/follow_request_note_container';
import { PERMISSION_MANAGE_USERS } from 'mastodon/permissions'; import { PERMISSION_MANAGE_USERS } from 'mastodon/permissions';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
@ -150,17 +149,6 @@ class Header extends ImmutablePureComponent {
} }
} }
handleShare = () => {
const { account } = this.props;
navigator.share({
text: `${titleFromAccount(account)}\n${account.get('note_plain')}`,
url: account.get('url'),
}).catch((e) => {
if (e.name !== 'AbortError') console.error(e);
});
}
render () { render () {
const { account, hidden, intl, domain } = this.props; const { account, hidden, intl, domain } = this.props;
const { signedIn } = this.context.identity; const { signedIn } = this.context.identity;
@ -312,8 +300,6 @@ class Header extends ImmutablePureComponent {
return ( return (
<div className={classNames('account__header', { inactive: !!account.get('moved') })} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> <div className={classNames('account__header', { inactive: !!account.get('moved') })} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
{!(suspended || hidden || account.get('moved')) && account.getIn(['relationship', 'requested_by']) && <FollowRequestNoteContainer account={account} />}
<div className='account__header__image'> <div className='account__header__image'>
<div className='account__header__info'> <div className='account__header__info'>
{!suspended && info} {!suspended && info}
@ -345,9 +331,7 @@ class Header extends ImmutablePureComponent {
<div className='account__header__tabs__name'> <div className='account__header__tabs__name'>
<h1> <h1>
<span dangerouslySetInnerHTML={displayNameHtml} /> {badge} <span dangerouslySetInnerHTML={displayNameHtml} /> {badge}
<small> <small>@{acct} {lockedIcon}</small>
<span>@{acct}</span> {lockedIcon}
</small>
</h1> </h1>
</div> </div>

View file

@ -1,15 +0,0 @@
import { connect } from 'react-redux';
import FollowRequestNote from '../components/follow_request_note';
import { authorizeFollowRequest, rejectFollowRequest } from 'mastodon/actions/accounts';
const mapDispatchToProps = (dispatch, { account }) => ({
onAuthorize () {
dispatch(authorizeFollowRequest(account.get('id')));
},
onReject () {
dispatch(rejectFollowRequest(account.get('id')));
},
});
export default connect(null, mapDispatchToProps)(FollowRequestNote);

View file

@ -2,6 +2,7 @@ import Blurhash from 'mastodon/components/blurhash';
import classNames from 'classnames'; import classNames from 'classnames';
import Icon from 'mastodon/components/icon'; import Icon from 'mastodon/components/icon';
import { autoPlayGif, displayMedia, useBlurhash } from 'mastodon/initial_state'; import { autoPlayGif, displayMedia, useBlurhash } from 'mastodon/initial_state';
import { isIOS } from 'mastodon/is_mobile';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
@ -104,13 +105,11 @@ export default class MediaItem extends ImmutablePureComponent {
<video <video
className='media-gallery__item-gifv-thumbnail' className='media-gallery__item-gifv-thumbnail'
aria-label={attachment.get('description')} aria-label={attachment.get('description')}
title={attachment.get('description')}
role='application' role='application'
src={attachment.get('url')} src={attachment.get('url')}
onMouseEnter={this.handleMouseEnter} onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave} onMouseLeave={this.handleMouseLeave}
autoPlay={autoPlayGif} autoPlay={!isIOS() && autoPlayGif}
playsInline
loop loop
muted muted
/> />

View file

@ -26,13 +26,7 @@ const emptyList = ImmutableList();
const mapStateToProps = (state, { params: { acct, id, tagged }, withReplies = false }) => { const mapStateToProps = (state, { params: { acct, id, tagged }, withReplies = false }) => {
const accountId = id || state.getIn(['accounts_map', normalizeForLookup(acct)]); const accountId = id || state.getIn(['accounts_map', normalizeForLookup(acct)]);
if (accountId === null) { if (!accountId) {
return {
isLoading: false,
isAccount: false,
statusIds: emptyList,
};
} else if (!accountId) {
return { return {
isLoading: true, isLoading: true,
statusIds: emptyList, statusIds: emptyList,

View file

@ -72,4 +72,4 @@ class ClosedRegistrationsModal extends ImmutablePureComponent {
); );
} }
} };

View file

@ -16,10 +16,12 @@ import PollFormContainer from '../containers/poll_form_container';
import UploadFormContainer from '../containers/upload_form_container'; import UploadFormContainer from '../containers/upload_form_container';
import WarningContainer from '../containers/warning_container'; import WarningContainer from '../containers/warning_container';
import LanguageDropdown from '../containers/language_dropdown_container'; import LanguageDropdown from '../containers/language_dropdown_container';
import { isMobile } from '../../../is_mobile';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { length } from 'stringz'; import { length } from 'stringz';
import { countableText } from '../util/counter'; import { countableText } from '../util/counter';
import Icon from 'mastodon/components/icon'; import Icon from 'mastodon/components/icon';
import { publish_button_text } from 'mastodon/initial_state';
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d'; const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
@ -60,14 +62,14 @@ class ComposeForm extends ImmutablePureComponent {
onChangeSpoilerText: PropTypes.func.isRequired, onChangeSpoilerText: PropTypes.func.isRequired,
onPaste: PropTypes.func.isRequired, onPaste: PropTypes.func.isRequired,
onPickEmoji: PropTypes.func.isRequired, onPickEmoji: PropTypes.func.isRequired,
autoFocus: PropTypes.bool, showSearch: PropTypes.bool,
anyMedia: PropTypes.bool, anyMedia: PropTypes.bool,
isInReply: PropTypes.bool, isInReply: PropTypes.bool,
singleColumn: PropTypes.bool, singleColumn: PropTypes.bool,
}; };
static defaultProps = { static defaultProps = {
autoFocus: false, showSearch: false,
}; };
handleChange = (e) => { handleChange = (e) => {
@ -153,7 +155,7 @@ class ComposeForm extends ImmutablePureComponent {
// - Replying to zero or one users, places the cursor at the end of the textbox. // - Replying to zero or one users, places the cursor at the end of the textbox.
// - Replying to more than one user, selects any usernames past the first; // - Replying to more than one user, selects any usernames past the first;
// this provides a convenient shortcut to drop everyone else from the conversation. // this provides a convenient shortcut to drop everyone else from the conversation.
if (this.props.focusDate && this.props.focusDate !== prevProps.focusDate) { if (this.props.focusDate !== prevProps.focusDate) {
let selectionEnd, selectionStart; let selectionEnd, selectionStart;
if (this.props.preselectDate !== prevProps.preselectDate && this.props.isInReply) { if (this.props.preselectDate !== prevProps.preselectDate && this.props.isInReply) {
@ -179,7 +181,7 @@ class ComposeForm extends ImmutablePureComponent {
} else if (this.props.spoiler !== prevProps.spoiler) { } else if (this.props.spoiler !== prevProps.spoiler) {
if (this.props.spoiler) { if (this.props.spoiler) {
this.spoilerText.input.focus(); this.spoilerText.input.focus();
} else if (prevProps.spoiler) { } else {
this.autosuggestTextarea.textarea.focus(); this.autosuggestTextarea.textarea.focus();
} }
} }
@ -206,17 +208,18 @@ class ComposeForm extends ImmutablePureComponent {
} }
render () { render () {
const { intl, onPaste, autoFocus } = this.props; const { intl, onPaste, showSearch } = this.props;
const disabled = this.props.isSubmitting; const disabled = this.props.isSubmitting;
let publishText = ''; let publishText = '';
let publishButtonText = publish_button_text || intl.formatMessage(messages.publish);
if (this.props.isEditing) { if (this.props.isEditing) {
publishText = intl.formatMessage(messages.saveChanges); publishText = intl.formatMessage(messages.saveChanges);
} else if (this.props.privacy === 'private' || this.props.privacy === 'direct') { } else if (this.props.privacy === 'private' || this.props.privacy === 'direct') {
publishText = <span className='compose-form__publish-private'><Icon id='lock' /> {intl.formatMessage(messages.publish)}</span>; publishText = <span className='compose-form__publish-private'><Icon id='lock' /> {publishButtonText}</span>;
} else { } else {
publishText = this.props.privacy !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: intl.formatMessage(messages.publish) }) : intl.formatMessage(messages.publish); publishText = this.props.privacy !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: publishButtonText }) : publishButtonText;
} }
return ( return (
@ -256,7 +259,7 @@ class ComposeForm extends ImmutablePureComponent {
onSuggestionsClearRequested={this.onSuggestionsClearRequested} onSuggestionsClearRequested={this.onSuggestionsClearRequested}
onSuggestionSelected={this.onSuggestionSelected} onSuggestionSelected={this.onSuggestionSelected}
onPaste={onPaste} onPaste={onPaste}
autoFocus={autoFocus} autoFocus={!showSearch && !isMobile(window.innerWidth)}
> >
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} /> <EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} />

View file

@ -165,7 +165,6 @@ class PollForm extends ImmutablePureComponent {
<option value={1800}>{intl.formatMessage(messages.minutes, { number: 30 })}</option> <option value={1800}>{intl.formatMessage(messages.minutes, { number: 30 })}</option>
<option value={3600}>{intl.formatMessage(messages.hours, { number: 1 })}</option> <option value={3600}>{intl.formatMessage(messages.hours, { number: 1 })}</option>
<option value={21600}>{intl.formatMessage(messages.hours, { number: 6 })}</option> <option value={21600}>{intl.formatMessage(messages.hours, { number: 6 })}</option>
<option value={43200}>{intl.formatMessage(messages.hours, { number: 12 })}</option>
<option value={86400}>{intl.formatMessage(messages.days, { number: 1 })}</option> <option value={86400}>{intl.formatMessage(messages.days, { number: 1 })}</option>
<option value={259200}>{intl.formatMessage(messages.days, { number: 3 })}</option> <option value={259200}>{intl.formatMessage(messages.days, { number: 3 })}</option>
<option value={604800}>{intl.formatMessage(messages.days, { number: 7 })}</option> <option value={604800}>{intl.formatMessage(messages.days, { number: 7 })}</option>

View file

@ -123,24 +123,27 @@ class Search extends React.PureComponent {
return ( return (
<div className='search'> <div className='search'>
<label>
<span style={{ display: 'none' }}>{intl.formatMessage(messages.placeholder)}</span>
<input <input
ref={this.setRef} ref={this.setRef}
className='search__input' className='search__input'
type='text' type='text'
placeholder={intl.formatMessage(signedIn ? messages.placeholderSignedIn : messages.placeholder)} placeholder={intl.formatMessage(signedIn ? messages.placeholderSignedIn : messages.placeholder)}
aria-label={intl.formatMessage(signedIn ? messages.placeholderSignedIn : messages.placeholder)}
value={value} value={value}
onChange={this.handleChange} onChange={this.handleChange}
onKeyUp={this.handleKeyUp} onKeyUp={this.handleKeyUp}
onFocus={this.handleFocus} onFocus={this.handleFocus}
onBlur={this.handleBlur} onBlur={this.handleBlur}
/> />
</label>
<div role='button' tabIndex='0' className='search__icon' onClick={this.handleClear}> <div role='button' tabIndex='0' className='search__icon' onClick={this.handleClear}>
<Icon id='search' className={hasValue ? '' : 'active'} /> <Icon id='search' className={hasValue ? '' : 'active'} />
<Icon id='times-circle' className={hasValue ? 'active' : ''} aria-label={intl.formatMessage(messages.placeholder)} /> <Icon id='times-circle' className={hasValue ? 'active' : ''} aria-label={intl.formatMessage(messages.placeholder)} />
</div> </div>
<Overlay show={expanded && !hasValue} placement='bottom' target={this} container={this}>
<Overlay show={expanded && !hasValue} placement='bottom' target={this}>
<SearchPopout /> <SearchPopout />
</Overlay> </Overlay>
</div> </div>

Some files were not shown because too many files have changed in this diff Show more