Merge pull request #746 from kmycode/upstream-20240524
Upstream 20240524
This commit is contained in:
commit
d39b6d3317
350 changed files with 3931 additions and 1855 deletions
|
@ -6,7 +6,8 @@ LOCAL_HTTPS=true
|
|||
# Elasticsearch
|
||||
ES_PREFIX=test
|
||||
|
||||
# Required by ActiveRecord encryption feature
|
||||
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=fkSxKD2bF396kdQbrP1EJ7WbU7ZgNokR
|
||||
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=r0hvVmzBVsjxC7AMlwhOzmtc36ZCOS1E
|
||||
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=PhdFyyfy5xJ7WVd2lWBpcPScRQHzRTNr
|
||||
# Secret values required by ActiveRecord encryption feature
|
||||
# Use `bin/rails db:encryption:init` to generate fresh secrets
|
||||
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=test_determinist_key_DO_NOT_USE_IN_PRODUCTION
|
||||
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=test_salt_DO_NOT_USE_IN_PRODUCTION
|
||||
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=test_primary_key_DO_NOT_USE_IN_PRODUCTION
|
||||
|
|
7
.github/renovate.json5
vendored
7
.github/renovate.json5
vendored
|
@ -141,6 +141,13 @@
|
|||
matchUpdateTypes: ['patch', 'minor'],
|
||||
groupName: 'RSpec (non-major)',
|
||||
},
|
||||
{
|
||||
// Group all opentelemetry-ruby packages in the same PR
|
||||
matchManagers: ['bundler'],
|
||||
matchPackagePrefixes: ['opentelemetry-'],
|
||||
matchUpdateTypes: ['patch', 'minor'],
|
||||
groupName: 'opentelemetry-ruby (non-major)',
|
||||
},
|
||||
// Add labels depending on package manager
|
||||
{ matchManagers: ['npm', 'nvm'], addLabels: ['javascript'] },
|
||||
{ matchManagers: ['bundler', 'ruby-version'], addLabels: ['ruby'] },
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
# ======================== Elasticsearch Configuration =========================
|
||||
#
|
||||
# NOTE: Elasticsearch comes with reasonable defaults for most settings.
|
||||
# Before you set out to tweak and tune the configuration, make sure you
|
||||
# understand what are you trying to accomplish and the consequences.
|
||||
#
|
||||
# The primary way of configuring a node is via this file. This template lists
|
||||
# the most important settings you may want to configure for a production cluster.
|
||||
#
|
||||
# Please consult the documentation for further information on configuration options:
|
||||
# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
|
||||
#
|
||||
# ---------------------------------- Cluster -----------------------------------
|
||||
#
|
||||
# Use a descriptive name for your cluster:
|
||||
#
|
||||
#cluster.name: my-application
|
||||
#
|
||||
# ------------------------------------ Node ------------------------------------
|
||||
#
|
||||
# Use a descriptive name for the node:
|
||||
#
|
||||
#node.name: node-1
|
||||
#
|
||||
# Add custom attributes to the node:
|
||||
#
|
||||
#node.attr.rack: r1
|
||||
#
|
||||
# ----------------------------------- Paths ------------------------------------
|
||||
#
|
||||
# Path to directory where to store the data (separate multiple locations by comma):
|
||||
#
|
||||
path.data: /var/lib/elasticsearch
|
||||
#
|
||||
# Path to log files:
|
||||
#
|
||||
path.logs: /var/log/elasticsearch
|
||||
#
|
||||
# ----------------------------------- Memory -----------------------------------
|
||||
#
|
||||
# Lock the memory on startup:
|
||||
#
|
||||
#bootstrap.memory_lock: true
|
||||
#
|
||||
# Make sure that the heap size is set to about half the memory available
|
||||
# on the system and that the owner of the process is allowed to use this
|
||||
# limit.
|
||||
#
|
||||
# Elasticsearch performs poorly when the system is swapping the memory.
|
||||
#
|
||||
# ---------------------------------- Network -----------------------------------
|
||||
#
|
||||
# By default Elasticsearch is only accessible on localhost. Set a different
|
||||
# address here to expose this node on the network:
|
||||
#
|
||||
#network.host: 192.168.0.1
|
||||
#
|
||||
# By default Elasticsearch listens for HTTP traffic on the first free port it
|
||||
# finds starting at 9200. Set a specific HTTP port here:
|
||||
#
|
||||
#http.port: 9200
|
||||
#
|
||||
# For more information, consult the network module documentation.
|
||||
#
|
||||
# --------------------------------- Discovery ----------------------------------
|
||||
#
|
||||
# Pass an initial list of hosts to perform discovery when this node is started:
|
||||
# The default list of hosts is ["127.0.0.1", "[::1]"]
|
||||
#
|
||||
#discovery.seed_hosts: ["host1", "host2"]
|
||||
#
|
||||
# Bootstrap the cluster using an initial set of master-eligible nodes:
|
||||
#
|
||||
#cluster.initial_master_nodes: ["node-1", "node-2"]
|
||||
#
|
||||
# For more information, consult the discovery and cluster formation module documentation.
|
||||
#
|
||||
# ---------------------------------- Various -----------------------------------
|
||||
#
|
||||
# Require explicit names when deleting indices:
|
||||
#
|
||||
#action.destructive_requires_name: true
|
||||
#
|
||||
# ---------------------------------- Security ----------------------------------
|
||||
#
|
||||
# *** WARNING ***
|
||||
#
|
||||
# Elasticsearch security features are not enabled by default.
|
||||
# These features are free, but require configuration changes to enable them.
|
||||
# This means that users don’t have to provide credentials and can get full access
|
||||
# to the cluster. Network connections are also not encrypted.
|
||||
#
|
||||
# To protect your data, we strongly encourage you to enable the Elasticsearch security features.
|
||||
# Refer to the following documentation for instructions.
|
||||
#
|
||||
xpack.security.enabled: false
|
||||
discovery.type: single-node
|
||||
# https://www.elastic.co/guide/en/elasticsearch/reference/7.16/configuring-stack-security.html
|
65
.github/workflows/test-ruby.yml
vendored
65
.github/workflows/test-ruby.yml
vendored
|
@ -146,6 +146,8 @@ jobs:
|
|||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
files: coverage/lcov/mastodon.lcov
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
test-e2e:
|
||||
name: End to End testing
|
||||
|
@ -186,6 +188,8 @@ jobs:
|
|||
RAILS_ENV: test
|
||||
BUNDLE_WITH: test
|
||||
ES_ENABLED: false
|
||||
LOCAL_DOMAIN: localhost:3000
|
||||
LOCAL_HTTPS: false
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -215,7 +219,7 @@ jobs:
|
|||
- name: Load database schema
|
||||
run: './bin/rails db:create db:schema:load db:seed'
|
||||
|
||||
- run: bundle exec rake spec:system
|
||||
- run: bin/rspec spec/system --tag streaming --tag js
|
||||
|
||||
- name: Archive logs
|
||||
uses: actions/upload-artifact@v4
|
||||
|
@ -262,6 +266,33 @@ jobs:
|
|||
ports:
|
||||
- 6379:6379
|
||||
|
||||
elasticsearch:
|
||||
image: ${{ contains(matrix.search-image, 'elasticsearch') && matrix.search-image || '' }}
|
||||
env:
|
||||
discovery.type: single-node
|
||||
xpack.security.enabled: false
|
||||
options: >-
|
||||
--health-cmd "curl http://localhost:9200/_cluster/health"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 10
|
||||
ports:
|
||||
- 9200:9200
|
||||
|
||||
opensearch:
|
||||
image: ${{ contains(matrix.search-image, 'opensearch') && matrix.search-image || '' }}
|
||||
env:
|
||||
discovery.type: single-node
|
||||
DISABLE_INSTALL_DEMO_CONFIG: true
|
||||
DISABLE_SECURITY_PLUGIN: true
|
||||
options: >-
|
||||
--health-cmd "curl http://localhost:9200/_cluster/health"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 10
|
||||
ports:
|
||||
- 9200:9200
|
||||
|
||||
env:
|
||||
DB_HOST: localhost
|
||||
DB_USER: postgres
|
||||
|
@ -285,6 +316,8 @@ jobs:
|
|||
include:
|
||||
- ruby-version: '.ruby-version'
|
||||
search-image: docker.elastic.co/elasticsearch/elasticsearch:8.10.2
|
||||
- ruby-version: '.ruby-version'
|
||||
search-image: opensearchproject/opensearch:2
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
@ -303,36 +336,6 @@ jobs:
|
|||
- name: Set up Javascript environment
|
||||
uses: ./.github/actions/setup-javascript
|
||||
|
||||
- name: Configure sysctl limits
|
||||
run: |
|
||||
sudo swapoff -a
|
||||
sudo sysctl -w vm.swappiness=1
|
||||
sudo sysctl -w fs.file-max=262144
|
||||
sudo sysctl -w vm.max_map_count=262144
|
||||
|
||||
- name: Install Elasticsearch
|
||||
run: |
|
||||
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.10-amd64.deb
|
||||
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.10-amd64.deb.sha512
|
||||
shasum -a 512 -c elasticsearch-7.17.10-amd64.deb.sha512
|
||||
sudo dpkg -i elasticsearch-7.17.10-amd64.deb
|
||||
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install https://github.com/WorksApplications/elasticsearch-sudachi/releases/download/v3.1.0/elasticsearch-7.17.10-analysis-sudachi-3.1.0.zip
|
||||
|
||||
- name: Install dictionary
|
||||
run: |
|
||||
wget http://sudachi.s3-website-ap-northeast-1.amazonaws.com/sudachidict/sudachi-dictionary-latest-core.zip
|
||||
unzip sudachi-dictionary-latest-core.zip
|
||||
sudo mkdir /etc/elasticsearch/sudachi -p
|
||||
sudo cp sudachi-dictionary-*/system_core.dic /etc/elasticsearch/sudachi
|
||||
|
||||
- name: Set security settings
|
||||
run: |
|
||||
sudo cp .github/workflows/elasticsearch-settings/elasticsearch.yml /etc/elasticsearch
|
||||
|
||||
- name: Running Elasticsearch
|
||||
run: |
|
||||
sudo systemctl start elasticsearch
|
||||
|
||||
- name: Load database schema
|
||||
run: './bin/rails db:create db:schema:load db:seed'
|
||||
|
||||
|
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
|||
20.12
|
||||
20.13
|
||||
|
|
|
@ -223,6 +223,11 @@ Style/PercentLiteralDelimiters:
|
|||
Style/RedundantBegin:
|
||||
Enabled: false
|
||||
|
||||
# Reason: Prevailing style choice
|
||||
# https://docs.rubocop.org/rubocop/cops_style.html#styleredundantfetchblock
|
||||
Style/RedundantFetchBlock:
|
||||
Enabled: false
|
||||
|
||||
# Reason: Overridden to reduce implicit StandardError rescues
|
||||
# https://docs.rubocop.org/rubocop/cops_style.html#stylerescuestandarderror
|
||||
Style/RescueStandardError:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp`
|
||||
# using RuboCop version 1.62.1.
|
||||
# using RuboCop version 1.63.5.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
|
@ -58,10 +58,6 @@ Style/ClassEqualityComparison:
|
|||
- 'app/helpers/jsonld_helper.rb'
|
||||
- 'app/serializers/activitypub/outbox_serializer.rb'
|
||||
|
||||
Style/ClassVars:
|
||||
Exclude:
|
||||
- 'config/initializers/devise.rb'
|
||||
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: AllowedVars.
|
||||
Style/FetchEnvVar:
|
||||
|
@ -78,7 +74,7 @@ Style/FetchEnvVar:
|
|||
- 'config/initializers/vapid.rb'
|
||||
- 'lib/mastodon/redis_config.rb'
|
||||
- 'lib/tasks/repo.rake'
|
||||
- 'spec/features/profile_spec.rb'
|
||||
- 'spec/system/profile_spec.rb'
|
||||
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, AllowedMethods, AllowedPatterns.
|
||||
|
@ -130,13 +126,6 @@ Style/HashTransformValues:
|
|||
- 'app/serializers/rest/web_push_subscription_serializer.rb'
|
||||
- 'app/services/import_service.rb'
|
||||
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/IfUnlessModifier:
|
||||
Exclude:
|
||||
- 'config/environments/production.rb'
|
||||
- 'config/initializers/devise.rb'
|
||||
- 'config/initializers/ffmpeg.rb'
|
||||
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/MapToHash:
|
||||
Exclude:
|
||||
|
@ -184,16 +173,6 @@ Style/RedundantConstantBase:
|
|||
- 'config/environments/production.rb'
|
||||
- 'config/initializers/sidekiq.rb'
|
||||
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: SafeForConstants.
|
||||
Style/RedundantFetchBlock:
|
||||
Exclude:
|
||||
- 'config/initializers/1_hosts.rb'
|
||||
- 'config/initializers/chewy.rb'
|
||||
- 'config/initializers/devise.rb'
|
||||
- 'config/initializers/paperclip.rb'
|
||||
- 'config/puma.rb'
|
||||
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
|
||||
# AllowedMethods: present?, blank?, presence, try, try!
|
||||
|
|
22
.simplecov
22
.simplecov
|
@ -1,22 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
if ENV['CI']
|
||||
require 'simplecov-lcov'
|
||||
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
|
||||
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
|
||||
else
|
||||
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
|
||||
end
|
||||
|
||||
SimpleCov.start 'rails' do
|
||||
enable_coverage :branch
|
||||
|
||||
add_filter 'lib/linter'
|
||||
|
||||
add_group 'Libraries', 'lib'
|
||||
add_group 'Policies', 'app/policies'
|
||||
add_group 'Presenters', 'app/presenters'
|
||||
add_group 'Serializers', 'app/serializers'
|
||||
add_group 'Services', 'app/services'
|
||||
add_group 'Validators', 'app/validators'
|
||||
end
|
24
Gemfile
24
Gemfile
|
@ -57,7 +57,7 @@ gem 'htmlentities', '~> 4.3'
|
|||
gem 'http', '~> 5.2.0'
|
||||
gem 'http_accept_language', '~> 2.1'
|
||||
gem 'httplog', '~> 1.6.2'
|
||||
gem 'i18n', '1.14.1' # TODO: Remove version when resolved: https://github.com/glebm/i18n-tasks/issues/552 / https://github.com/ruby-i18n/i18n/pull/688
|
||||
gem 'i18n'
|
||||
gem 'idn-ruby', require: 'idn'
|
||||
gem 'inline_svg'
|
||||
gem 'kaminari', '~> 1.2'
|
||||
|
@ -103,6 +103,24 @@ gem 'rdf-normalize', '~> 0.5'
|
|||
|
||||
gem 'private_address_check', '~> 0.5'
|
||||
|
||||
group :opentelemetry do
|
||||
gem 'opentelemetry-exporter-otlp', '~> 0.26.3', require: false
|
||||
gem 'opentelemetry-instrumentation-active_job', '~> 0.7.1', require: false
|
||||
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.20.1', require: false
|
||||
gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.21.2', require: false
|
||||
gem 'opentelemetry-instrumentation-excon', '~> 0.22.0', require: false
|
||||
gem 'opentelemetry-instrumentation-faraday', '~> 0.24.1', require: false
|
||||
gem 'opentelemetry-instrumentation-http', '~> 0.23.2', require: false
|
||||
gem 'opentelemetry-instrumentation-http_client', '~> 0.22.3', require: false
|
||||
gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false
|
||||
gem 'opentelemetry-instrumentation-pg', '~> 0.27.1', require: false
|
||||
gem 'opentelemetry-instrumentation-rack', '~> 0.24.1', require: false
|
||||
gem 'opentelemetry-instrumentation-rails', '~> 0.30.0', require: false
|
||||
gem 'opentelemetry-instrumentation-redis', '~> 0.25.3', require: false
|
||||
gem 'opentelemetry-instrumentation-sidekiq', '~> 0.25.2', require: false
|
||||
gem 'opentelemetry-sdk', '~> 1.4', require: false
|
||||
end
|
||||
|
||||
group :test do
|
||||
# Adds RSpec Error/Warning annotations to GitHub PRs on the Files tab
|
||||
gem 'rspec-github', '~> 2.4', require: false
|
||||
|
@ -114,7 +132,7 @@ group :test do
|
|||
gem 'email_spec'
|
||||
|
||||
# Extra RSpec extension methods and helpers for sidekiq
|
||||
gem 'rspec-sidekiq', '~> 4.0'
|
||||
gem 'rspec-sidekiq', '~> 5.0'
|
||||
|
||||
# Browser integration testing
|
||||
gem 'capybara', '~> 3.39'
|
||||
|
@ -160,7 +178,7 @@ group :development do
|
|||
|
||||
# Preview mail in the browser
|
||||
gem 'letter_opener', '~> 1.8'
|
||||
gem 'letter_opener_web', '~> 2.0'
|
||||
gem 'letter_opener_web', '~> 3.0'
|
||||
|
||||
# Security analysis CLI tools
|
||||
gem 'brakeman', '~> 6.0', require: false
|
||||
|
|
287
Gemfile.lock
287
Gemfile.lock
|
@ -10,35 +10,35 @@ GIT
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
actioncable (7.1.3.3)
|
||||
actionpack (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
zeitwerk (~> 2.6)
|
||||
actionmailbox (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activejob (= 7.1.3.2)
|
||||
activerecord (= 7.1.3.2)
|
||||
activestorage (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
actionmailbox (7.1.3.3)
|
||||
actionpack (= 7.1.3.3)
|
||||
activejob (= 7.1.3.3)
|
||||
activerecord (= 7.1.3.3)
|
||||
activestorage (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
actionview (= 7.1.3.2)
|
||||
activejob (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
actionmailer (7.1.3.3)
|
||||
actionpack (= 7.1.3.3)
|
||||
actionview (= 7.1.3.3)
|
||||
activejob (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.2)
|
||||
actionpack (7.1.3.2)
|
||||
actionview (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
actionpack (7.1.3.3)
|
||||
actionview (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
nokogiri (>= 1.8.5)
|
||||
racc
|
||||
rack (>= 2.2.4)
|
||||
|
@ -46,15 +46,15 @@ GEM
|
|||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
actiontext (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activerecord (= 7.1.3.2)
|
||||
activestorage (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
actiontext (7.1.3.3)
|
||||
actionpack (= 7.1.3.3)
|
||||
activerecord (= 7.1.3.3)
|
||||
activestorage (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
actionview (7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.11)
|
||||
rails-dom-testing (~> 2.2)
|
||||
|
@ -64,22 +64,22 @@ GEM
|
|||
activemodel (>= 4.1)
|
||||
case_transform (>= 0.2)
|
||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||
activejob (7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
activejob (7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
activerecord (7.1.3.2)
|
||||
activemodel (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
activemodel (7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
activerecord (7.1.3.3)
|
||||
activemodel (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
timeout (>= 0.4.0)
|
||||
activestorage (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activejob (= 7.1.3.2)
|
||||
activerecord (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
activestorage (7.1.3.3)
|
||||
actionpack (= 7.1.3.3)
|
||||
activejob (= 7.1.3.3)
|
||||
activerecord (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
marcel (~> 1.0)
|
||||
activesupport (7.1.3.2)
|
||||
activesupport (7.1.3.3)
|
||||
base64
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
|
@ -100,16 +100,16 @@ GEM
|
|||
attr_required (1.0.2)
|
||||
awrence (1.2.1)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.922.0)
|
||||
aws-sdk-core (3.194.1)
|
||||
aws-partitions (1.929.0)
|
||||
aws-sdk-core (3.196.1)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.8)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.80.0)
|
||||
aws-sdk-kms (1.81.0)
|
||||
aws-sdk-core (~> 3, >= 3.193.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.149.1)
|
||||
aws-sdk-s3 (1.151.0)
|
||||
aws-sdk-core (~> 3, >= 3.194.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.8)
|
||||
|
@ -130,14 +130,7 @@ GEM
|
|||
erubi (>= 1.0.0)
|
||||
rack (>= 0.9.0)
|
||||
rouge (>= 1.0.0)
|
||||
better_html (2.1.1)
|
||||
actionview (>= 6.0)
|
||||
activesupport (>= 6.0)
|
||||
ast (~> 2.0)
|
||||
erubi (~> 1.4)
|
||||
parser (>= 2.4)
|
||||
smart_properties
|
||||
bigdecimal (3.1.7)
|
||||
bigdecimal (3.1.8)
|
||||
bindata (2.5.0)
|
||||
binding_of_caller (1.0.1)
|
||||
debug_inspector (>= 1.2.0)
|
||||
|
@ -279,7 +272,7 @@ GEM
|
|||
fog-json (1.2.0)
|
||||
fog-core
|
||||
multi_json (~> 1.10)
|
||||
fog-openstack (1.1.0)
|
||||
fog-openstack (1.1.1)
|
||||
fog-core (~> 2.1)
|
||||
fog-json (>= 1.0)
|
||||
formatador (1.1.0)
|
||||
|
@ -291,6 +284,9 @@ GEM
|
|||
ruby-progressbar (~> 1.4)
|
||||
globalid (1.2.1)
|
||||
activesupport (>= 6.1)
|
||||
google-protobuf (3.25.3)
|
||||
googleapis-common-protos-types (1.14.0)
|
||||
google-protobuf (~> 3.18)
|
||||
haml (6.3.0)
|
||||
temple (>= 0.8.2)
|
||||
thor
|
||||
|
@ -328,12 +324,11 @@ GEM
|
|||
httplog (1.6.3)
|
||||
rack (>= 2.0)
|
||||
rainbow (>= 2.0.0)
|
||||
i18n (1.14.1)
|
||||
i18n (1.14.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-tasks (1.0.13)
|
||||
i18n-tasks (1.0.14)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
better_html (>= 1.0, < 3.0)
|
||||
erubi
|
||||
highline (>= 2.0.0)
|
||||
i18n
|
||||
|
@ -394,10 +389,10 @@ GEM
|
|||
addressable (~> 2.8)
|
||||
letter_opener (1.10.0)
|
||||
launchy (>= 2.2, < 4)
|
||||
letter_opener_web (2.0.0)
|
||||
actionmailer (>= 5.2)
|
||||
letter_opener (~> 1.7)
|
||||
railties (>= 5.2)
|
||||
letter_opener_web (3.0.0)
|
||||
actionmailer (>= 6.1)
|
||||
letter_opener (~> 1.9)
|
||||
railties (>= 6.1)
|
||||
rexml
|
||||
link_header (0.0.8)
|
||||
llhttp-ffi (0.5.0)
|
||||
|
@ -427,10 +422,10 @@ GEM
|
|||
memory_profiler (1.0.1)
|
||||
mime-types (3.5.2)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2024.0305)
|
||||
mime-types-data (3.2024.0507)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.6)
|
||||
minitest (5.22.3)
|
||||
minitest (5.23.0)
|
||||
msgpack (1.7.2)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.0)
|
||||
|
@ -439,7 +434,7 @@ GEM
|
|||
uri
|
||||
net-http-persistent (4.0.2)
|
||||
connection_pool (~> 2.2)
|
||||
net-imap (0.4.10)
|
||||
net-imap (0.4.11)
|
||||
date
|
||||
net-protocol
|
||||
net-ldap (0.19.0)
|
||||
|
@ -449,8 +444,8 @@ GEM
|
|||
timeout
|
||||
net-smtp (0.5.0)
|
||||
net-protocol
|
||||
nio4r (2.7.1)
|
||||
nokogiri (1.16.4)
|
||||
nio4r (2.7.3)
|
||||
nokogiri (1.16.5)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nsa (0.3.0)
|
||||
|
@ -491,6 +486,96 @@ GEM
|
|||
openssl (3.2.0)
|
||||
openssl-signature_algorithm (1.3.0)
|
||||
openssl (> 2.0)
|
||||
opentelemetry-api (1.2.5)
|
||||
opentelemetry-common (0.20.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-exporter-otlp (0.26.3)
|
||||
google-protobuf (~> 3.14)
|
||||
googleapis-common-protos-types (~> 1.3)
|
||||
opentelemetry-api (~> 1.1)
|
||||
opentelemetry-common (~> 0.20)
|
||||
opentelemetry-sdk (~> 1.2)
|
||||
opentelemetry-semantic_conventions
|
||||
opentelemetry-helpers-sql-obfuscation (0.1.0)
|
||||
opentelemetry-common (~> 0.20)
|
||||
opentelemetry-instrumentation-action_pack (0.9.0)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-rack (~> 0.21)
|
||||
opentelemetry-instrumentation-action_view (0.7.0)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-active_support (~> 0.1)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-active_job (0.7.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-active_model_serializers (0.20.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-active_record (0.7.2)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-active_support (0.5.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-base (0.22.3)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-registry (~> 0.1)
|
||||
opentelemetry-instrumentation-concurrent_ruby (0.21.3)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-excon (0.22.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-common (~> 0.20.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-faraday (0.24.2)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-common (~> 0.20.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-http (0.23.3)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-http_client (0.22.4)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-common (~> 0.20.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-net_http (0.22.4)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-common (~> 0.20.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-pg (0.27.3)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-helpers-sql-obfuscation
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-rack (0.24.3)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-common (~> 0.20.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-rails (0.30.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-action_pack (~> 0.9.0)
|
||||
opentelemetry-instrumentation-action_view (~> 0.7.0)
|
||||
opentelemetry-instrumentation-active_job (~> 0.7.0)
|
||||
opentelemetry-instrumentation-active_record (~> 0.7.0)
|
||||
opentelemetry-instrumentation-active_support (~> 0.5.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-redis (0.25.4)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-common (~> 0.20.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-instrumentation-sidekiq (0.25.3)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-common (~> 0.20.0)
|
||||
opentelemetry-instrumentation-base (~> 0.22.1)
|
||||
opentelemetry-registry (0.3.1)
|
||||
opentelemetry-api (~> 1.1)
|
||||
opentelemetry-sdk (1.4.1)
|
||||
opentelemetry-api (~> 1.1)
|
||||
opentelemetry-common (~> 0.20)
|
||||
opentelemetry-registry (~> 0.2)
|
||||
opentelemetry-semantic_conventions
|
||||
opentelemetry-semantic_conventions (1.10.0)
|
||||
opentelemetry-api (~> 1.0)
|
||||
orm_adapter (0.5.0)
|
||||
ox (2.14.18)
|
||||
parallel (1.24.0)
|
||||
|
@ -522,10 +607,10 @@ GEM
|
|||
public_suffix (5.0.5)
|
||||
puma (6.4.2)
|
||||
nio4r (~> 2.0)
|
||||
pundit (2.3.1)
|
||||
pundit (2.3.2)
|
||||
activesupport (>= 3.0.0)
|
||||
raabro (1.4.0)
|
||||
racc (1.7.3)
|
||||
racc (1.8.0)
|
||||
rack (2.2.9)
|
||||
rack-attack (6.7.0)
|
||||
rack (>= 1.0, < 4)
|
||||
|
@ -549,20 +634,20 @@ GEM
|
|||
rackup (1.0.0)
|
||||
rack (< 3)
|
||||
webrick
|
||||
rails (7.1.3.2)
|
||||
actioncable (= 7.1.3.2)
|
||||
actionmailbox (= 7.1.3.2)
|
||||
actionmailer (= 7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
actiontext (= 7.1.3.2)
|
||||
actionview (= 7.1.3.2)
|
||||
activejob (= 7.1.3.2)
|
||||
activemodel (= 7.1.3.2)
|
||||
activerecord (= 7.1.3.2)
|
||||
activestorage (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
rails (7.1.3.3)
|
||||
actioncable (= 7.1.3.3)
|
||||
actionmailbox (= 7.1.3.3)
|
||||
actionmailer (= 7.1.3.3)
|
||||
actionpack (= 7.1.3.3)
|
||||
actiontext (= 7.1.3.3)
|
||||
actionview (= 7.1.3.3)
|
||||
activejob (= 7.1.3.3)
|
||||
activemodel (= 7.1.3.3)
|
||||
activerecord (= 7.1.3.3)
|
||||
activestorage (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.1.3.2)
|
||||
railties (= 7.1.3.3)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
actionview (>= 5.0.1.rc1)
|
||||
|
@ -577,9 +662,9 @@ GEM
|
|||
rails-i18n (7.0.9)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 8)
|
||||
railties (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
railties (7.1.3.3)
|
||||
actionpack (= 7.1.3.3)
|
||||
activesupport (= 7.1.3.3)
|
||||
irb
|
||||
rackup (>= 1.0.0)
|
||||
rake (>= 12.2)
|
||||
|
@ -600,15 +685,16 @@ GEM
|
|||
redis (>= 4)
|
||||
redlock (1.3.2)
|
||||
redis (>= 3.0.0, < 6.0)
|
||||
regexp_parser (2.9.0)
|
||||
reline (0.5.5)
|
||||
regexp_parser (2.9.2)
|
||||
reline (0.5.7)
|
||||
io-console (~> 0.5)
|
||||
request_store (1.6.0)
|
||||
rack (>= 1.4)
|
||||
responders (3.1.1)
|
||||
actionpack (>= 5.2)
|
||||
railties (>= 5.2)
|
||||
rexml (3.2.6)
|
||||
rexml (3.2.8)
|
||||
strscan (>= 3.0.9)
|
||||
rotp (6.3.0)
|
||||
rouge (4.2.1)
|
||||
rpam2 (4.0.2)
|
||||
|
@ -623,7 +709,7 @@ GEM
|
|||
rspec-support (~> 3.13.0)
|
||||
rspec-github (2.4.0)
|
||||
rspec-core (~> 3.0)
|
||||
rspec-mocks (3.13.0)
|
||||
rspec-mocks (3.13.1)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-rails (6.1.2)
|
||||
|
@ -634,13 +720,13 @@ GEM
|
|||
rspec-expectations (~> 3.13)
|
||||
rspec-mocks (~> 3.13)
|
||||
rspec-support (~> 3.13)
|
||||
rspec-sidekiq (4.2.0)
|
||||
rspec-sidekiq (5.0.0)
|
||||
rspec-core (~> 3.0)
|
||||
rspec-expectations (~> 3.0)
|
||||
rspec-mocks (~> 3.0)
|
||||
sidekiq (>= 5, < 8)
|
||||
rspec-support (3.13.1)
|
||||
rubocop (1.63.4)
|
||||
rubocop (1.63.5)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (>= 3.17.0)
|
||||
parallel (~> 1.10)
|
||||
|
@ -660,7 +746,7 @@ GEM
|
|||
rubocop-performance (1.21.0)
|
||||
rubocop (>= 1.48.1, < 2.0)
|
||||
rubocop-ast (>= 1.31.1, < 2.0)
|
||||
rubocop-rails (2.24.1)
|
||||
rubocop-rails (2.25.0)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.33.0, < 2.0)
|
||||
|
@ -689,7 +775,7 @@ GEM
|
|||
scenic (1.8.0)
|
||||
activerecord (>= 4.0.0)
|
||||
railties (>= 4.0.0)
|
||||
selenium-webdriver (4.20.1)
|
||||
selenium-webdriver (4.21.1)
|
||||
base64 (~> 0.2)
|
||||
rexml (~> 3.2, >= 3.2.5)
|
||||
rubyzip (>= 1.2.2, < 3.0)
|
||||
|
@ -723,7 +809,6 @@ GEM
|
|||
simplecov-html (0.12.3)
|
||||
simplecov-lcov (0.8.0)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
smart_properties (1.17.0)
|
||||
stackprof (0.2.26)
|
||||
statsd-ruby (1.5.0)
|
||||
stoplight (4.1.0)
|
||||
|
@ -731,6 +816,7 @@ GEM
|
|||
stringio (3.1.0)
|
||||
strong_migrations (1.8.0)
|
||||
activerecord (>= 5.2)
|
||||
strscan (3.1.0)
|
||||
swd (1.3.0)
|
||||
activesupport (>= 3)
|
||||
attr_required (>= 0.0.5)
|
||||
|
@ -809,7 +895,7 @@ GEM
|
|||
xorcist (1.1.3)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.13)
|
||||
zeitwerk (2.6.14)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
@ -860,7 +946,7 @@ DEPENDENCIES
|
|||
http (~> 5.2.0)
|
||||
http_accept_language (~> 2.1)
|
||||
httplog (~> 1.6.2)
|
||||
i18n (= 1.14.1)
|
||||
i18n
|
||||
i18n-tasks (~> 1.0)
|
||||
idn-ruby
|
||||
inline_svg
|
||||
|
@ -871,7 +957,7 @@ DEPENDENCIES
|
|||
kaminari (~> 1.2)
|
||||
kt-paperclip (~> 7.2)
|
||||
letter_opener (~> 1.8)
|
||||
letter_opener_web (~> 2.0)
|
||||
letter_opener_web (~> 3.0)
|
||||
link_header (~> 0.0)
|
||||
lograge (~> 0.12)
|
||||
mail (~> 2.8)
|
||||
|
@ -889,6 +975,21 @@ DEPENDENCIES
|
|||
omniauth-rails_csrf_protection (~> 1.0)
|
||||
omniauth-saml (~> 2.0)
|
||||
omniauth_openid_connect (~> 0.6.1)
|
||||
opentelemetry-exporter-otlp (~> 0.26.3)
|
||||
opentelemetry-instrumentation-active_job (~> 0.7.1)
|
||||
opentelemetry-instrumentation-active_model_serializers (~> 0.20.1)
|
||||
opentelemetry-instrumentation-concurrent_ruby (~> 0.21.2)
|
||||
opentelemetry-instrumentation-excon (~> 0.22.0)
|
||||
opentelemetry-instrumentation-faraday (~> 0.24.1)
|
||||
opentelemetry-instrumentation-http (~> 0.23.2)
|
||||
opentelemetry-instrumentation-http_client (~> 0.22.3)
|
||||
opentelemetry-instrumentation-net_http (~> 0.22.4)
|
||||
opentelemetry-instrumentation-pg (~> 0.27.1)
|
||||
opentelemetry-instrumentation-rack (~> 0.24.1)
|
||||
opentelemetry-instrumentation-rails (~> 0.30.0)
|
||||
opentelemetry-instrumentation-redis (~> 0.25.3)
|
||||
opentelemetry-instrumentation-sidekiq (~> 0.25.2)
|
||||
opentelemetry-sdk (~> 1.4)
|
||||
ox (~> 2.14)
|
||||
parslet
|
||||
pg (~> 1.5)
|
||||
|
@ -913,7 +1014,7 @@ DEPENDENCIES
|
|||
rqrcode (~> 2.2)
|
||||
rspec-github (~> 2.4)
|
||||
rspec-rails (~> 6.0)
|
||||
rspec-sidekiq (~> 4.0)
|
||||
rspec-sidekiq (~> 5.0)
|
||||
rubocop
|
||||
rubocop-capybara
|
||||
rubocop-performance
|
||||
|
|
|
@ -25,7 +25,7 @@ class AccountsController < ApplicationController
|
|||
|
||||
limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE
|
||||
@statuses = filtered_statuses.without_reblogs.limit(limit)
|
||||
@statuses = cache_collection(@statuses, Status)
|
||||
@statuses = preload_collection(@statuses, Status)
|
||||
end
|
||||
|
||||
format.json do
|
||||
|
|
|
@ -18,7 +18,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
|
|||
def set_items
|
||||
case params[:id]
|
||||
when 'featured'
|
||||
@items = for_signed_account { cache_collection(@account.pinned_statuses, Status) }
|
||||
@items = for_signed_account { preload_collection(@account.pinned_statuses, Status) }
|
||||
@items = @items.map { |item| item.distributable? ? item : ActivityPub::TagManager.instance.uri_for(item) }
|
||||
when 'tags'
|
||||
@items = for_signed_account { @account.featured_tags }
|
||||
|
|
|
@ -60,7 +60,7 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
|
|||
def set_statuses
|
||||
return unless page_requested?
|
||||
|
||||
@statuses = cache_collection_paginated_by_id(
|
||||
@statuses = preload_collection_paginated_by_id(
|
||||
AccountStatusesFilter.new(@account, signed_request_account).results,
|
||||
Status,
|
||||
LIMIT,
|
||||
|
|
|
@ -31,7 +31,7 @@ class ActivityPub::ReferencesController < ActivityPub::BaseController
|
|||
end
|
||||
|
||||
def cached_references
|
||||
cache_collection(Status.where(id: results).reorder(:id), Status)
|
||||
preload_collection(Status.where(id: results).reorder(:id), Status)
|
||||
end
|
||||
|
||||
def results
|
||||
|
|
|
@ -142,7 +142,7 @@ module Admin
|
|||
def unblock_email
|
||||
authorize @account, :unblock_email?
|
||||
|
||||
CanonicalEmailBlock.matching_account(@account).delete_all
|
||||
CanonicalEmailBlock.where(reference_account: @account).delete_all
|
||||
|
||||
log_action :unblock_email, @account
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
|||
end
|
||||
|
||||
def load_statuses
|
||||
@account.unavailable? ? [] : cached_account_statuses
|
||||
@account.unavailable? ? [] : preloaded_account_statuses
|
||||
end
|
||||
|
||||
def cached_account_statuses
|
||||
cache_collection_paginated_by_id(
|
||||
def preloaded_account_statuses
|
||||
preload_collection_paginated_by_id(
|
||||
AccountStatusesFilter.new(@account, current_account, params).results,
|
||||
Status,
|
||||
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||
|
|
|
@ -4,6 +4,6 @@ class Api::V1::Apps::CredentialsController < Api::BaseController
|
|||
def show
|
||||
return doorkeeper_render_error unless valid_doorkeeper_token?
|
||||
|
||||
render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key client_id scopes)
|
||||
render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ class Api::V1::AppsController < Api::BaseController
|
|||
|
||||
def create
|
||||
@app = Doorkeeper::Application.create!(application_options)
|
||||
render json: @app, serializer: REST::ApplicationSerializer
|
||||
render json: @app, serializer: REST::CredentialApplicationSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -24,6 +24,6 @@ class Api::V1::AppsController < Api::BaseController
|
|||
end
|
||||
|
||||
def app_params
|
||||
params.permit(:client_name, :redirect_uris, :scopes, :website)
|
||||
params.permit(:client_name, :scopes, :website, :redirect_uris, redirect_uris: [])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,11 +15,11 @@ class Api::V1::BookmarksController < Api::BaseController
|
|||
private
|
||||
|
||||
def load_statuses
|
||||
cached_bookmarks
|
||||
preloaded_bookmarks
|
||||
end
|
||||
|
||||
def cached_bookmarks
|
||||
cache_collection(results.map(&:status), Status)
|
||||
def preloaded_bookmarks
|
||||
preload_collection(results.map(&:status), Status)
|
||||
end
|
||||
|
||||
def results
|
||||
|
|
|
@ -19,7 +19,7 @@ class Api::V1::EmojiReactionsController < Api::BaseController
|
|||
end
|
||||
|
||||
def cached_emoji_reactions
|
||||
cache_collection(results.map(&:status), EmojiReaction)
|
||||
preload_collection(results.map(&:status), EmojiReaction)
|
||||
end
|
||||
|
||||
def results
|
||||
|
|
|
@ -15,11 +15,11 @@ class Api::V1::FavouritesController < Api::BaseController
|
|||
private
|
||||
|
||||
def load_statuses
|
||||
cached_favourites
|
||||
preloaded_favourites
|
||||
end
|
||||
|
||||
def cached_favourites
|
||||
cache_collection(results.map(&:status), Status)
|
||||
def preloaded_favourites
|
||||
preload_collection(results.map(&:status), Status)
|
||||
end
|
||||
|
||||
def results
|
||||
|
|
|
@ -41,7 +41,7 @@ class Api::V1::Notifications::RequestsController < Api::BaseController
|
|||
)
|
||||
|
||||
NotificationRequest.preload_cache_collection(requests) do |statuses|
|
||||
cache_collection(statuses, Status)
|
||||
preload_collection(statuses, Status)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class Api::V1::NotificationsController < Api::BaseController
|
|||
)
|
||||
|
||||
Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses|
|
||||
cache_collection(target_statuses, Status)
|
||||
preload_collection(target_statuses, Status)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class Api::V1::Statuses::ReferredByStatusesController < Api::BaseController
|
|||
domains = statuses.filter_map(&:account_domain).uniq
|
||||
relations = account&.relations_map(account_ids, domains) || {}
|
||||
|
||||
statuses = cache_collection_paginated_by_id(
|
||||
statuses = preload_collection_paginated_by_id(
|
||||
statuses,
|
||||
Status,
|
||||
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||
|
|
|
@ -26,13 +26,13 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
DESCENDANTS_DEPTH_LIMIT = 20
|
||||
|
||||
def index
|
||||
@statuses = cache_collection(@statuses, Status)
|
||||
@statuses = preload_collection(@statuses, Status)
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer
|
||||
end
|
||||
|
||||
def show
|
||||
cache_if_unauthenticated!
|
||||
@status = cache_collection([@status], Status).first
|
||||
@status = preload_collection([@status], Status).first
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
end
|
||||
|
||||
|
@ -52,9 +52,9 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(ancestors_limit, current_account)
|
||||
descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit)
|
||||
references_results = @status.readable_references(current_account)
|
||||
loaded_ancestors = cache_collection(ancestors_results, Status)
|
||||
loaded_descendants = cache_collection(descendants_results, Status)
|
||||
loaded_references = cache_collection(references_results, Status)
|
||||
loaded_ancestors = preload_collection(ancestors_results, Status)
|
||||
loaded_descendants = preload_collection(descendants_results, Status)
|
||||
loaded_references = preload_collection(references_results, Status)
|
||||
|
||||
if params[:with_reference]
|
||||
loaded_references.reject! { |status| loaded_ancestors.any? { |ancestor| ancestor.id == status.id } }
|
||||
|
|
|
@ -25,7 +25,7 @@ class Api::V1::Timelines::AntennaController < Api::V1::Timelines::BaseController
|
|||
end
|
||||
|
||||
def cached_list_statuses
|
||||
cache_collection list_statuses, Status
|
||||
preload_collection list_statuses, Status
|
||||
end
|
||||
|
||||
def list_statuses
|
||||
|
|
|
@ -23,11 +23,11 @@ class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController
|
|||
private
|
||||
|
||||
def load_statuses
|
||||
cached_home_statuses
|
||||
preloaded_home_statuses
|
||||
end
|
||||
|
||||
def cached_home_statuses
|
||||
cache_collection home_statuses, Status
|
||||
def preloaded_home_statuses
|
||||
preload_collection home_statuses, Status
|
||||
end
|
||||
|
||||
def home_statuses
|
||||
|
|
|
@ -21,11 +21,11 @@ class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController
|
|||
end
|
||||
|
||||
def set_statuses
|
||||
@statuses = cached_list_statuses
|
||||
@statuses = preloaded_list_statuses
|
||||
end
|
||||
|
||||
def cached_list_statuses
|
||||
cache_collection list_statuses, Status
|
||||
def preloaded_list_statuses
|
||||
preload_collection list_statuses, Status
|
||||
end
|
||||
|
||||
def list_statuses
|
||||
|
|
|
@ -20,11 +20,11 @@ class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController
|
|||
end
|
||||
|
||||
def load_statuses
|
||||
cached_public_statuses_page
|
||||
preloaded_public_statuses_page
|
||||
end
|
||||
|
||||
def cached_public_statuses_page
|
||||
cache_collection(public_statuses, Status)
|
||||
def preloaded_public_statuses_page
|
||||
preload_collection(public_statuses, Status)
|
||||
end
|
||||
|
||||
def public_statuses
|
||||
|
|
|
@ -25,11 +25,11 @@ class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController
|
|||
end
|
||||
|
||||
def load_statuses
|
||||
cached_tagged_statuses
|
||||
preloaded_tagged_statuses
|
||||
end
|
||||
|
||||
def cached_tagged_statuses
|
||||
@tag.nil? ? [] : cache_collection(tag_timeline_statuses, Status)
|
||||
def preloaded_tagged_statuses
|
||||
@tag.nil? ? [] : preload_collection(tag_timeline_statuses, Status)
|
||||
end
|
||||
|
||||
def tag_timeline_statuses
|
||||
|
|
|
@ -20,7 +20,7 @@ class Api::V1::Trends::StatusesController < Api::BaseController
|
|||
|
||||
def set_statuses
|
||||
@statuses = if enabled?
|
||||
cache_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status)
|
||||
preload_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status)
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
|
|
@ -9,6 +9,7 @@ class ApplicationController < ActionController::Base
|
|||
include UserTrackingConcern
|
||||
include SessionTrackingConcern
|
||||
include CacheConcern
|
||||
include PreloadingConcern
|
||||
include DomainControlHelper
|
||||
include DatabaseHelper
|
||||
include AuthorizedFetchHelper
|
||||
|
|
|
@ -55,20 +55,4 @@ module CacheConcern
|
|||
Rails.cache.write(key, response.body, expires_in: expires_in, raw: true)
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Rename this method, as it does not perform any caching anymore.
|
||||
def cache_collection(raw, klass)
|
||||
return raw unless klass.respond_to?(:preload_cacheable_associations)
|
||||
|
||||
records = raw.to_a
|
||||
|
||||
klass.preload_cacheable_associations(records)
|
||||
|
||||
records
|
||||
end
|
||||
|
||||
# TODO: Rename this method, as it does not perform any caching anymore.
|
||||
def cache_collection_paginated_by_id(raw, klass, limit, options)
|
||||
cache_collection raw.to_a_paginated_by_id(limit, options), klass
|
||||
end
|
||||
end
|
||||
|
|
17
app/controllers/concerns/preloading_concern.rb
Normal file
17
app/controllers/concerns/preloading_concern.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PreloadingConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def preload_collection(scope, klass)
|
||||
return scope unless klass.respond_to?(:preload_cacheable_associations)
|
||||
|
||||
scope.to_a.tap do |records|
|
||||
klass.preload_cacheable_associations(records)
|
||||
end
|
||||
end
|
||||
|
||||
def preload_collection_paginated_by_id(scope, klass, limit, options)
|
||||
preload_collection scope.to_a_paginated_by_id(limit, options), klass
|
||||
end
|
||||
end
|
|
@ -13,7 +13,7 @@ class Settings::ApplicationsController < Settings::BaseController
|
|||
def new
|
||||
@application = Doorkeeper::Application.new(
|
||||
redirect_uri: Doorkeeper.configuration.native_redirect_uri,
|
||||
scopes: 'read write follow'
|
||||
scopes: 'read:me'
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class TagsController < ApplicationController
|
|||
end
|
||||
|
||||
def set_statuses
|
||||
@statuses = cache_collection(TagFeed.new(@tag, nil, local: @local).get(limit_param), Status)
|
||||
@statuses = preload_collection(TagFeed.new(@tag, nil, local: @local).get(limit_param), Status)
|
||||
end
|
||||
|
||||
def limit_param
|
||||
|
|
|
@ -254,11 +254,20 @@ module ApplicationHelper
|
|||
prerender_custom_emojis(html, JSON.parse([custom_emojis_hash].to_json, object_class: OpenStruct)) # rubocop:disable Style/OpenStructUse
|
||||
end
|
||||
|
||||
def site_icon_path(type, size = '48')
|
||||
icon = SiteUpload.find_by(var: type)
|
||||
return nil unless icon
|
||||
def mascot_url
|
||||
full_asset_url(instance_presenter.mascot&.file&.url || frontend_asset_path('images/elephant_ui_plane.svg'))
|
||||
end
|
||||
|
||||
icon.file.url(size)
|
||||
def instance_presenter
|
||||
@instance_presenter ||= InstancePresenter.new
|
||||
end
|
||||
|
||||
def favicon_path(size = '48')
|
||||
instance_presenter.favicon&.file&.url(size)
|
||||
end
|
||||
|
||||
def app_icon_path(size = '48')
|
||||
instance_presenter.app_icon&.file&.url(size)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MascotHelper
|
||||
def mascot_url
|
||||
full_asset_url(instance_presenter.mascot&.file&.url || frontend_asset_path('images/elephant_ui_plane.svg'))
|
||||
end
|
||||
|
||||
def instance_presenter
|
||||
@instance_presenter ||= InstancePresenter.new
|
||||
end
|
||||
end
|
|
@ -26,7 +26,7 @@ module RegistrationLimitationHelper
|
|||
end
|
||||
|
||||
def today_increase_user_count_value
|
||||
User.confirmed.enabled.where('users.created_at >= ?', Time.now.utc.beginning_of_day).joins(:account).merge(Account.without_suspended).count
|
||||
User.confirmed.enabled.where(users: { created_at: Time.now.utc.beginning_of_day.. }).joins(:account).merge(Account.without_suspended).count
|
||||
end
|
||||
|
||||
def registrations_in_time?
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
|
||||
import { createAppAsyncThunk } from 'mastodon/store/typed_functions';
|
||||
import { apiSubmitAccountNote } from 'mastodon/api/accounts';
|
||||
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
|
||||
|
||||
import api from '../api';
|
||||
|
||||
export const submitAccountNote = createAppAsyncThunk(
|
||||
export const submitAccountNote = createDataLoadingThunk(
|
||||
'account_note/submit',
|
||||
async (args: { id: string; value: string }, { getState }) => {
|
||||
const response = await api(getState).post<ApiRelationshipJSON>(
|
||||
`/api/v1/accounts/${args.id}/note`,
|
||||
{
|
||||
comment: args.value,
|
||||
},
|
||||
);
|
||||
|
||||
return { relationship: response.data };
|
||||
},
|
||||
({ accountId, note }: { accountId: string; note: string }) =>
|
||||
apiSubmitAccountNote(accountId, note),
|
||||
(relationship) => ({ relationship }),
|
||||
{ skipLoading: true },
|
||||
);
|
||||
|
|
|
@ -76,11 +76,11 @@ export const ACCOUNT_REVEAL = 'ACCOUNT_REVEAL';
|
|||
export * from './accounts_typed';
|
||||
|
||||
export function fetchAccount(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchRelationships([id]));
|
||||
dispatch(fetchAccountRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${id}`).then(response => {
|
||||
api().get(`/api/v1/accounts/${id}`).then(response => {
|
||||
dispatch(importFetchedAccount(response.data));
|
||||
dispatch(fetchAccountSuccess());
|
||||
}).catch(error => {
|
||||
|
@ -89,10 +89,10 @@ export function fetchAccount(id) {
|
|||
};
|
||||
}
|
||||
|
||||
export const lookupAccount = acct => (dispatch, getState) => {
|
||||
export const lookupAccount = acct => (dispatch) => {
|
||||
dispatch(lookupAccountRequest(acct));
|
||||
|
||||
api(getState).get('/api/v1/accounts/lookup', { params: { acct } }).then(response => {
|
||||
api().get('/api/v1/accounts/lookup', { params: { acct } }).then(response => {
|
||||
dispatch(fetchRelationships([response.data.id]));
|
||||
dispatch(importFetchedAccount(response.data));
|
||||
dispatch(lookupAccountSuccess());
|
||||
|
@ -146,7 +146,7 @@ export function followAccount(id, options = { reblogs: true }) {
|
|||
|
||||
dispatch(followAccountRequest({ id, locked }));
|
||||
|
||||
api(getState).post(`/api/v1/accounts/${id}/follow`, options).then(response => {
|
||||
api().post(`/api/v1/accounts/${id}/follow`, options).then(response => {
|
||||
dispatch(followAccountSuccess({relationship: response.data, alreadyFollowing}));
|
||||
}).catch(error => {
|
||||
dispatch(followAccountFail({ id, error, locked }));
|
||||
|
@ -158,7 +158,7 @@ export function unfollowAccount(id) {
|
|||
return (dispatch, getState) => {
|
||||
dispatch(unfollowAccountRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => {
|
||||
api().post(`/api/v1/accounts/${id}/unfollow`).then(response => {
|
||||
dispatch(unfollowAccountSuccess({relationship: response.data, statuses: getState().get('statuses')}));
|
||||
}).catch(error => {
|
||||
dispatch(unfollowAccountFail({ id, error }));
|
||||
|
@ -170,7 +170,7 @@ export function blockAccount(id) {
|
|||
return (dispatch, getState) => {
|
||||
dispatch(blockAccountRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/accounts/${id}/block`).then(response => {
|
||||
api().post(`/api/v1/accounts/${id}/block`).then(response => {
|
||||
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
|
||||
dispatch(blockAccountSuccess({ relationship: response.data, statuses: getState().get('statuses') }));
|
||||
}).catch(error => {
|
||||
|
@ -180,10 +180,10 @@ export function blockAccount(id) {
|
|||
}
|
||||
|
||||
export function unblockAccount(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(unblockAccountRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/accounts/${id}/unblock`).then(response => {
|
||||
api().post(`/api/v1/accounts/${id}/unblock`).then(response => {
|
||||
dispatch(unblockAccountSuccess({ relationship: response.data }));
|
||||
}).catch(error => {
|
||||
dispatch(unblockAccountFail({ id, error }));
|
||||
|
@ -223,7 +223,7 @@ export function muteAccount(id, notifications, duration=0) {
|
|||
return (dispatch, getState) => {
|
||||
dispatch(muteAccountRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications, duration }).then(response => {
|
||||
api().post(`/api/v1/accounts/${id}/mute`, { notifications, duration }).then(response => {
|
||||
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
|
||||
dispatch(muteAccountSuccess({ relationship: response.data, statuses: getState().get('statuses') }));
|
||||
}).catch(error => {
|
||||
|
@ -233,10 +233,10 @@ export function muteAccount(id, notifications, duration=0) {
|
|||
}
|
||||
|
||||
export function unmuteAccount(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(unmuteAccountRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/accounts/${id}/unmute`).then(response => {
|
||||
api().post(`/api/v1/accounts/${id}/unmute`).then(response => {
|
||||
dispatch(unmuteAccountSuccess({ relationship: response.data }));
|
||||
}).catch(error => {
|
||||
dispatch(unmuteAccountFail({ id, error }));
|
||||
|
@ -274,10 +274,10 @@ export function unmuteAccountFail(error) {
|
|||
|
||||
|
||||
export function fetchFollowers(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchFollowersRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${id}/followers`).then(response => {
|
||||
api().get(`/api/v1/accounts/${id}/followers`).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
|
@ -324,7 +324,7 @@ export function expandFollowers(id) {
|
|||
|
||||
dispatch(expandFollowersRequest(id));
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
|
@ -361,10 +361,10 @@ export function expandFollowersFail(id, error) {
|
|||
}
|
||||
|
||||
export function fetchFollowing(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchFollowingRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${id}/following`).then(response => {
|
||||
api().get(`/api/v1/accounts/${id}/following`).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
|
@ -411,7 +411,7 @@ export function expandFollowing(id) {
|
|||
|
||||
dispatch(expandFollowingRequest(id));
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
|
@ -460,7 +460,7 @@ export function fetchRelationships(accountIds) {
|
|||
|
||||
dispatch(fetchRelationshipsRequest(newAccountIds));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/relationships?with_suspended=true&${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
|
||||
api().get(`/api/v1/accounts/relationships?with_suspended=true&${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
|
||||
dispatch(fetchRelationshipsSuccess({ relationships: response.data }));
|
||||
}).catch(error => {
|
||||
dispatch(fetchRelationshipsFail(error));
|
||||
|
@ -486,10 +486,10 @@ export function fetchRelationshipsFail(error) {
|
|||
}
|
||||
|
||||
export function fetchFollowRequests() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchFollowRequestsRequest());
|
||||
|
||||
api(getState).get('/api/v1/follow_requests').then(response => {
|
||||
api().get('/api/v1/follow_requests').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null));
|
||||
|
@ -528,7 +528,7 @@ export function expandFollowRequests() {
|
|||
|
||||
dispatch(expandFollowRequestsRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null));
|
||||
|
@ -558,10 +558,10 @@ export function expandFollowRequestsFail(error) {
|
|||
}
|
||||
|
||||
export function authorizeFollowRequest(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(authorizeFollowRequestRequest(id));
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.post(`/api/v1/follow_requests/${id}/authorize`)
|
||||
.then(() => dispatch(authorizeFollowRequestSuccess({ id })))
|
||||
.catch(error => dispatch(authorizeFollowRequestFail(id, error)));
|
||||
|
@ -585,10 +585,10 @@ export function authorizeFollowRequestFail(id, error) {
|
|||
|
||||
|
||||
export function rejectFollowRequest(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(rejectFollowRequestRequest(id));
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.post(`/api/v1/follow_requests/${id}/reject`)
|
||||
.then(() => dispatch(rejectFollowRequestSuccess({ id })))
|
||||
.catch(error => dispatch(rejectFollowRequestFail(id, error)));
|
||||
|
@ -611,10 +611,10 @@ export function rejectFollowRequestFail(id, error) {
|
|||
}
|
||||
|
||||
export function pinAccount(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(pinAccountRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/accounts/${id}/pin`).then(response => {
|
||||
api().post(`/api/v1/accounts/${id}/pin`).then(response => {
|
||||
dispatch(pinAccountSuccess({ relationship: response.data }));
|
||||
}).catch(error => {
|
||||
dispatch(pinAccountFail(error));
|
||||
|
@ -623,10 +623,10 @@ export function pinAccount(id) {
|
|||
}
|
||||
|
||||
export function unpinAccount(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(unpinAccountRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/accounts/${id}/unpin`).then(response => {
|
||||
api().post(`/api/v1/accounts/${id}/unpin`).then(response => {
|
||||
dispatch(unpinAccountSuccess({ relationship: response.data }));
|
||||
}).catch(error => {
|
||||
dispatch(unpinAccountFail(error));
|
||||
|
@ -662,7 +662,7 @@ export function unpinAccountFail(error) {
|
|||
};
|
||||
}
|
||||
|
||||
export const updateAccount = ({ displayName, note, avatar, header, discoverable, indexable }) => (dispatch, getState) => {
|
||||
export const updateAccount = ({ displayName, note, avatar, header, discoverable, indexable }) => (dispatch) => {
|
||||
const data = new FormData();
|
||||
|
||||
data.append('display_name', displayName);
|
||||
|
@ -672,7 +672,7 @@ export const updateAccount = ({ displayName, note, avatar, header, discoverable,
|
|||
data.append('discoverable', discoverable);
|
||||
data.append('indexable', indexable);
|
||||
|
||||
return api(getState).patch('/api/v1/accounts/update_credentials', data).then(response => {
|
||||
return api().patch('/api/v1/accounts/update_credentials', data).then(response => {
|
||||
dispatch(importFetchedAccount(response.data));
|
||||
});
|
||||
};
|
||||
|
|
|
@ -26,10 +26,10 @@ export const ANNOUNCEMENTS_TOGGLE_SHOW = 'ANNOUNCEMENTS_TOGGLE_SHOW';
|
|||
|
||||
const noOp = () => {};
|
||||
|
||||
export const fetchAnnouncements = (done = noOp) => (dispatch, getState) => {
|
||||
export const fetchAnnouncements = (done = noOp) => (dispatch) => {
|
||||
dispatch(fetchAnnouncementsRequest());
|
||||
|
||||
api(getState).get('/api/v1/announcements').then(response => {
|
||||
api().get('/api/v1/announcements').then(response => {
|
||||
dispatch(fetchAnnouncementsSuccess(response.data.map(x => normalizeAnnouncement(x))));
|
||||
}).catch(error => {
|
||||
dispatch(fetchAnnouncementsFail(error));
|
||||
|
@ -61,10 +61,10 @@ export const updateAnnouncements = announcement => ({
|
|||
announcement: normalizeAnnouncement(announcement),
|
||||
});
|
||||
|
||||
export const dismissAnnouncement = announcementId => (dispatch, getState) => {
|
||||
export const dismissAnnouncement = announcementId => (dispatch) => {
|
||||
dispatch(dismissAnnouncementRequest(announcementId));
|
||||
|
||||
api(getState).post(`/api/v1/announcements/${announcementId}/dismiss`).then(() => {
|
||||
api().post(`/api/v1/announcements/${announcementId}/dismiss`).then(() => {
|
||||
dispatch(dismissAnnouncementSuccess(announcementId));
|
||||
}).catch(error => {
|
||||
dispatch(dismissAnnouncementFail(announcementId, error));
|
||||
|
@ -103,7 +103,7 @@ export const addReaction = (announcementId, name) => (dispatch, getState) => {
|
|||
dispatch(addReactionRequest(announcementId, name, alreadyAdded));
|
||||
}
|
||||
|
||||
api(getState).put(`/api/v1/announcements/${announcementId}/reactions/${encodeURIComponent(name)}`).then(() => {
|
||||
api().put(`/api/v1/announcements/${announcementId}/reactions/${encodeURIComponent(name)}`).then(() => {
|
||||
dispatch(addReactionSuccess(announcementId, name, alreadyAdded));
|
||||
}).catch(err => {
|
||||
if (!alreadyAdded) {
|
||||
|
@ -134,10 +134,10 @@ export const addReactionFail = (announcementId, name, error) => ({
|
|||
skipLoading: true,
|
||||
});
|
||||
|
||||
export const removeReaction = (announcementId, name) => (dispatch, getState) => {
|
||||
export const removeReaction = (announcementId, name) => (dispatch) => {
|
||||
dispatch(removeReactionRequest(announcementId, name));
|
||||
|
||||
api(getState).delete(`/api/v1/announcements/${announcementId}/reactions/${encodeURIComponent(name)}`).then(() => {
|
||||
api().delete(`/api/v1/announcements/${announcementId}/reactions/${encodeURIComponent(name)}`).then(() => {
|
||||
dispatch(removeReactionSuccess(announcementId, name));
|
||||
}).catch(err => {
|
||||
dispatch(removeReactionFail(announcementId, name, err));
|
||||
|
|
|
@ -13,10 +13,10 @@ export const BLOCKS_EXPAND_SUCCESS = 'BLOCKS_EXPAND_SUCCESS';
|
|||
export const BLOCKS_EXPAND_FAIL = 'BLOCKS_EXPAND_FAIL';
|
||||
|
||||
export function fetchBlocks() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchBlocksRequest());
|
||||
|
||||
api(getState).get('/api/v1/blocks').then(response => {
|
||||
api().get('/api/v1/blocks').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null));
|
||||
|
@ -56,7 +56,7 @@ export function expandBlocks() {
|
|||
|
||||
dispatch(expandBlocksRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(expandBlocksSuccess(response.data, next ? next.uri : null));
|
||||
|
|
|
@ -20,7 +20,7 @@ export function fetchBookmarkedStatuses() {
|
|||
|
||||
dispatch(fetchBookmarkedStatusesRequest());
|
||||
|
||||
api(getState).get('/api/v1/bookmarks').then(response => {
|
||||
api().get('/api/v1/bookmarks').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
|
||||
|
@ -61,7 +61,7 @@ export function expandBookmarkedStatuses() {
|
|||
|
||||
dispatch(expandBookmarkedStatusesRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
|
||||
|
|
|
@ -207,7 +207,7 @@ export function submitCompose(routerHistory) {
|
|||
});
|
||||
}
|
||||
|
||||
api(getState).request({
|
||||
api().request({
|
||||
url: statusId === null ? '/api/v1/statuses' : `/api/v1/statuses/${statusId}`,
|
||||
method: statusId === null ? 'post' : 'put',
|
||||
data: {
|
||||
|
@ -327,7 +327,7 @@ export function uploadCompose(files) {
|
|||
const data = new FormData();
|
||||
data.append('file', file);
|
||||
|
||||
api(getState).post('/api/v2/media', data, {
|
||||
api().post('/api/v2/media', data, {
|
||||
onUploadProgress: function({ loaded }){
|
||||
progress[i] = loaded;
|
||||
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total));
|
||||
|
@ -348,7 +348,7 @@ export function uploadCompose(files) {
|
|||
let tryCount = 1;
|
||||
|
||||
const poll = () => {
|
||||
api(getState).get(`/api/v1/media/${data.id}`).then(response => {
|
||||
api().get(`/api/v1/media/${data.id}`).then(response => {
|
||||
if (response.status === 200) {
|
||||
dispatch(uploadComposeSuccess(response.data, file));
|
||||
} else if (response.status === 206) {
|
||||
|
@ -370,7 +370,7 @@ export const uploadComposeProcessing = () => ({
|
|||
type: COMPOSE_UPLOAD_PROCESSING,
|
||||
});
|
||||
|
||||
export const uploadThumbnail = (id, file) => (dispatch, getState) => {
|
||||
export const uploadThumbnail = (id, file) => (dispatch) => {
|
||||
dispatch(uploadThumbnailRequest());
|
||||
|
||||
const total = file.size;
|
||||
|
@ -378,7 +378,7 @@ export const uploadThumbnail = (id, file) => (dispatch, getState) => {
|
|||
|
||||
data.append('thumbnail', file);
|
||||
|
||||
api(getState).put(`/api/v1/media/${id}`, data, {
|
||||
api().put(`/api/v1/media/${id}`, data, {
|
||||
onUploadProgress: ({ loaded }) => {
|
||||
dispatch(uploadThumbnailProgress(loaded, total));
|
||||
},
|
||||
|
@ -461,7 +461,7 @@ export function changeUploadCompose(id, params) {
|
|||
|
||||
dispatch(changeUploadComposeSuccess(data, true));
|
||||
} else {
|
||||
api(getState).put(`/api/v1/media/${id}`, params).then(response => {
|
||||
api().put(`/api/v1/media/${id}`, params).then(response => {
|
||||
dispatch(changeUploadComposeSuccess(response.data, false));
|
||||
}).catch(error => {
|
||||
dispatch(changeUploadComposeFail(id, error));
|
||||
|
@ -549,7 +549,7 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
|
|||
|
||||
fetchComposeSuggestionsAccountsController = new AbortController();
|
||||
|
||||
api(getState).get('/api/v1/accounts/search', {
|
||||
api().get('/api/v1/accounts/search', {
|
||||
signal: fetchComposeSuggestionsAccountsController.signal,
|
||||
|
||||
params: {
|
||||
|
@ -583,7 +583,7 @@ const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => {
|
|||
|
||||
fetchComposeSuggestionsTagsController = new AbortController();
|
||||
|
||||
api(getState).get('/api/v2/search', {
|
||||
api().get('/api/v2/search', {
|
||||
signal: fetchComposeSuggestionsTagsController.signal,
|
||||
|
||||
params: {
|
||||
|
|
|
@ -28,13 +28,13 @@ export const unmountConversations = () => ({
|
|||
type: CONVERSATIONS_UNMOUNT,
|
||||
});
|
||||
|
||||
export const markConversationRead = conversationId => (dispatch, getState) => {
|
||||
export const markConversationRead = conversationId => (dispatch) => {
|
||||
dispatch({
|
||||
type: CONVERSATIONS_READ,
|
||||
id: conversationId,
|
||||
});
|
||||
|
||||
api(getState).post(`/api/v1/conversations/${conversationId}/read`);
|
||||
api().post(`/api/v1/conversations/${conversationId}/read`);
|
||||
};
|
||||
|
||||
export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
|
||||
|
@ -48,7 +48,7 @@ export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
|
|||
|
||||
const isLoadingRecent = !!params.since_id;
|
||||
|
||||
api(getState).get('/api/v1/conversations', { params })
|
||||
api().get('/api/v1/conversations', { params })
|
||||
.then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
|
@ -88,10 +88,10 @@ export const updateConversations = conversation => dispatch => {
|
|||
});
|
||||
};
|
||||
|
||||
export const deleteConversation = conversationId => (dispatch, getState) => {
|
||||
export const deleteConversation = conversationId => (dispatch) => {
|
||||
dispatch(deleteConversationRequest(conversationId));
|
||||
|
||||
api(getState).delete(`/api/v1/conversations/${conversationId}`)
|
||||
api().delete(`/api/v1/conversations/${conversationId}`)
|
||||
.then(() => dispatch(deleteConversationSuccess(conversationId)))
|
||||
.catch(error => dispatch(deleteConversationFail(conversationId, error)));
|
||||
};
|
||||
|
|
|
@ -5,10 +5,10 @@ export const CUSTOM_EMOJIS_FETCH_SUCCESS = 'CUSTOM_EMOJIS_FETCH_SUCCESS';
|
|||
export const CUSTOM_EMOJIS_FETCH_FAIL = 'CUSTOM_EMOJIS_FETCH_FAIL';
|
||||
|
||||
export function fetchCustomEmojis() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchCustomEmojisRequest());
|
||||
|
||||
api(getState).get('/api/v1/custom_emojis').then(response => {
|
||||
api().get('/api/v1/custom_emojis').then(response => {
|
||||
dispatch(fetchCustomEmojisSuccess(response.data));
|
||||
}).catch(error => {
|
||||
dispatch(fetchCustomEmojisFail(error));
|
||||
|
|
|
@ -11,10 +11,10 @@ export const DIRECTORY_EXPAND_REQUEST = 'DIRECTORY_EXPAND_REQUEST';
|
|||
export const DIRECTORY_EXPAND_SUCCESS = 'DIRECTORY_EXPAND_SUCCESS';
|
||||
export const DIRECTORY_EXPAND_FAIL = 'DIRECTORY_EXPAND_FAIL';
|
||||
|
||||
export const fetchDirectory = params => (dispatch, getState) => {
|
||||
export const fetchDirectory = params => (dispatch) => {
|
||||
dispatch(fetchDirectoryRequest());
|
||||
|
||||
api(getState).get('/api/v1/directory', { params: { ...params, limit: 20 } }).then(({ data }) => {
|
||||
api().get('/api/v1/directory', { params: { ...params, limit: 20 } }).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
dispatch(fetchDirectorySuccess(data));
|
||||
dispatch(fetchRelationships(data.map(x => x.id)));
|
||||
|
@ -40,7 +40,7 @@ export const expandDirectory = params => (dispatch, getState) => {
|
|||
|
||||
const loadedItems = getState().getIn(['user_lists', 'directory', 'items']).size;
|
||||
|
||||
api(getState).get('/api/v1/directory', { params: { ...params, offset: loadedItems, limit: 20 } }).then(({ data }) => {
|
||||
api().get('/api/v1/directory', { params: { ...params, offset: loadedItems, limit: 20 } }).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
dispatch(expandDirectorySuccess(data));
|
||||
dispatch(fetchRelationships(data.map(x => x.id)));
|
||||
|
|
|
@ -24,7 +24,7 @@ export function blockDomain(domain) {
|
|||
return (dispatch, getState) => {
|
||||
dispatch(blockDomainRequest(domain));
|
||||
|
||||
api(getState).post('/api/v1/domain_blocks', { domain }).then(() => {
|
||||
api().post('/api/v1/domain_blocks', { domain }).then(() => {
|
||||
const at_domain = '@' + domain;
|
||||
const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
|
||||
|
||||
|
@ -54,7 +54,7 @@ export function unblockDomain(domain) {
|
|||
return (dispatch, getState) => {
|
||||
dispatch(unblockDomainRequest(domain));
|
||||
|
||||
api(getState).delete('/api/v1/domain_blocks', { params: { domain } }).then(() => {
|
||||
api().delete('/api/v1/domain_blocks', { params: { domain } }).then(() => {
|
||||
const at_domain = '@' + domain;
|
||||
const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
|
||||
dispatch(unblockDomainSuccess({ domain, accounts }));
|
||||
|
@ -80,10 +80,10 @@ export function unblockDomainFail(domain, error) {
|
|||
}
|
||||
|
||||
export function fetchDomainBlocks() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchDomainBlocksRequest());
|
||||
|
||||
api(getState).get('/api/v1/domain_blocks').then(response => {
|
||||
api().get('/api/v1/domain_blocks').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(fetchDomainBlocksSuccess(response.data, next ? next.uri : null));
|
||||
}).catch(err => {
|
||||
|
@ -123,7 +123,7 @@ export function expandDomainBlocks() {
|
|||
|
||||
dispatch(expandDomainBlocksRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(expandDomainBlocksSuccess(response.data, next ? next.uri : null));
|
||||
}).catch(err => {
|
||||
|
|
|
@ -20,7 +20,7 @@ export function fetchFavouritedStatuses() {
|
|||
|
||||
dispatch(fetchFavouritedStatusesRequest());
|
||||
|
||||
api(getState).get('/api/v1/favourites').then(response => {
|
||||
api().get('/api/v1/favourites').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchFavouritedStatusesSuccess(response.data, next ? next.uri : null));
|
||||
|
@ -64,7 +64,7 @@ export function expandFavouritedStatuses() {
|
|||
|
||||
dispatch(expandFavouritedStatusesRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(expandFavouritedStatusesSuccess(response.data, next ? next.uri : null));
|
||||
|
|
|
@ -11,7 +11,7 @@ export const fetchFeaturedTags = (id) => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchFeaturedTagsRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${id}/featured_tags`)
|
||||
api().get(`/api/v1/accounts/${id}/featured_tags`)
|
||||
.then(({ data }) => dispatch(fetchFeaturedTagsSuccess(id, data)))
|
||||
.catch(err => dispatch(fetchFeaturedTagsFail(id, err)));
|
||||
};
|
||||
|
|
|
@ -23,13 +23,13 @@ export const initAddFilter = (status, { contextType }) => dispatch =>
|
|||
},
|
||||
}));
|
||||
|
||||
export const fetchFilters = () => (dispatch, getState) => {
|
||||
export const fetchFilters = () => (dispatch) => {
|
||||
dispatch({
|
||||
type: FILTERS_FETCH_REQUEST,
|
||||
skipLoading: true,
|
||||
});
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.get('/api/v2/filters')
|
||||
.then(({ data }) => dispatch({
|
||||
type: FILTERS_FETCH_SUCCESS,
|
||||
|
@ -44,10 +44,10 @@ export const fetchFilters = () => (dispatch, getState) => {
|
|||
}));
|
||||
};
|
||||
|
||||
export const createFilterStatus = (params, onSuccess, onFail) => (dispatch, getState) => {
|
||||
export const createFilterStatus = (params, onSuccess, onFail) => (dispatch) => {
|
||||
dispatch(createFilterStatusRequest());
|
||||
|
||||
api(getState).post(`/api/v2/filters/${params.filter_id}/statuses`, params).then(response => {
|
||||
api().post(`/api/v2/filters/${params.filter_id}/statuses`, params).then(response => {
|
||||
dispatch(createFilterStatusSuccess(response.data));
|
||||
if (onSuccess) onSuccess();
|
||||
}).catch(error => {
|
||||
|
@ -70,10 +70,10 @@ export const createFilterStatusFail = error => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const createFilter = (params, onSuccess, onFail) => (dispatch, getState) => {
|
||||
export const createFilter = (params, onSuccess, onFail) => (dispatch) => {
|
||||
dispatch(createFilterRequest());
|
||||
|
||||
api(getState).post('/api/v2/filters', params).then(response => {
|
||||
api().post('/api/v2/filters', params).then(response => {
|
||||
dispatch(createFilterSuccess(response.data));
|
||||
if (onSuccess) onSuccess(response.data);
|
||||
}).catch(error => {
|
||||
|
|
|
@ -15,7 +15,7 @@ export const fetchHistory = statusId => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchHistoryRequest(statusId));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${statusId}/history`).then(({ data }) => {
|
||||
api().get(`/api/v1/statuses/${statusId}/history`).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data.map(x => x.account)));
|
||||
dispatch(fetchHistorySuccess(statusId, data));
|
||||
}).catch(error => dispatch(fetchHistoryFail(error)));
|
||||
|
|
|
@ -3,10 +3,6 @@ import api, { getLinks } from '../api';
|
|||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts, importFetchedStatus, importFetchedStatuses } from './importer';
|
||||
|
||||
export const REBLOG_REQUEST = 'REBLOG_REQUEST';
|
||||
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
|
||||
export const REBLOG_FAIL = 'REBLOG_FAIL';
|
||||
|
||||
export const REBLOGS_EXPAND_REQUEST = 'REBLOGS_EXPAND_REQUEST';
|
||||
export const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS';
|
||||
export const REBLOGS_EXPAND_FAIL = 'REBLOGS_EXPAND_FAIL';
|
||||
|
@ -19,10 +15,6 @@ export const EMOJIREACT_REQUEST = 'EMOJIREACT_REQUEST';
|
|||
export const EMOJIREACT_SUCCESS = 'EMOJIREACT_SUCCESS';
|
||||
export const EMOJIREACT_FAIL = 'EMOJIREACT_FAIL';
|
||||
|
||||
export const UNREBLOG_REQUEST = 'UNREBLOG_REQUEST';
|
||||
export const UNREBLOG_SUCCESS = 'UNREBLOG_SUCCESS';
|
||||
export const UNREBLOG_FAIL = 'UNREBLOG_FAIL';
|
||||
|
||||
export const UNFAVOURITE_REQUEST = 'UNFAVOURITE_REQUEST';
|
||||
export const UNFAVOURITE_SUCCESS = 'UNFAVOURITE_SUCCESS';
|
||||
export const UNFAVOURITE_FAIL = 'UNFAVOURITE_FAIL';
|
||||
|
@ -79,89 +71,13 @@ export const MENTIONED_USERS_EXPAND_REQUEST = 'MENTIONED_USERS_EXPAND_REQUEST';
|
|||
export const MENTIONED_USERS_EXPAND_SUCCESS = 'MENTIONED_USERS_EXPAND_SUCCESS';
|
||||
export const MENTIONED_USERS_EXPAND_FAIL = 'MENTIONED_USERS_EXPAND_FAIL';
|
||||
|
||||
export function reblog(status, visibility) {
|
||||
return function (dispatch, getState) {
|
||||
dispatch(reblogRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`, { visibility }).then(function (response) {
|
||||
// The reblog API method returns a new status wrapped around the original. In this case we are only
|
||||
// interested in how the original is modified, hence passing it skipping the wrapper
|
||||
dispatch(importFetchedStatus(response.data.reblog));
|
||||
dispatch(reblogSuccess(status));
|
||||
}).catch(function (error) {
|
||||
dispatch(reblogFail(status, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function unreblog(status) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(unreblogRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(unreblogSuccess(status));
|
||||
}).catch(error => {
|
||||
dispatch(unreblogFail(status, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function reblogRequest(status) {
|
||||
return {
|
||||
type: REBLOG_REQUEST,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function reblogSuccess(status) {
|
||||
return {
|
||||
type: REBLOG_SUCCESS,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function reblogFail(status, error) {
|
||||
return {
|
||||
type: REBLOG_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unreblogRequest(status) {
|
||||
return {
|
||||
type: UNREBLOG_REQUEST,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unreblogSuccess(status) {
|
||||
return {
|
||||
type: UNREBLOG_SUCCESS,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unreblogFail(status, error) {
|
||||
return {
|
||||
type: UNREBLOG_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
export * from "./interactions_typed";
|
||||
|
||||
export function favourite(status) {
|
||||
return function (dispatch, getState) {
|
||||
return function (dispatch) {
|
||||
dispatch(favouriteRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) {
|
||||
api().post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(favouriteSuccess(status));
|
||||
}).catch(function (error) {
|
||||
|
@ -171,10 +87,10 @@ export function favourite(status) {
|
|||
}
|
||||
|
||||
export function unfavourite(status) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(unfavouriteRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => {
|
||||
api().post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(unfavouriteSuccess(status));
|
||||
}).catch(error => {
|
||||
|
@ -319,10 +235,10 @@ export function unEmojiReactFail(status, emoji, error) {
|
|||
}
|
||||
|
||||
export function bookmark(status) {
|
||||
return function (dispatch, getState) {
|
||||
return function (dispatch) {
|
||||
dispatch(bookmarkRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then(function (response) {
|
||||
api().post(`/api/v1/statuses/${status.get('id')}/bookmark`).then(function (response) {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(bookmarkSuccess(status, response.data));
|
||||
}).catch(function (error) {
|
||||
|
@ -332,10 +248,10 @@ export function bookmark(status) {
|
|||
}
|
||||
|
||||
export function unbookmark(status) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(unbookmarkRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then(response => {
|
||||
api().post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(unbookmarkSuccess(status, response.data));
|
||||
}).catch(error => {
|
||||
|
@ -391,10 +307,10 @@ export function unbookmarkFail(status, error) {
|
|||
}
|
||||
|
||||
export function fetchReblogs(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchReblogsRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
|
||||
api().get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchReblogsSuccess(id, response.data, next ? next.uri : null));
|
||||
|
@ -438,7 +354,7 @@ export function expandReblogs(id) {
|
|||
|
||||
dispatch(expandReblogsRequest(id));
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
|
@ -473,10 +389,10 @@ export function expandReblogsFail(id, error) {
|
|||
}
|
||||
|
||||
export function fetchFavourites(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchFavouritesRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => {
|
||||
api().get(`/api/v1/statuses/${id}/favourited_by`).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchFavouritesSuccess(id, response.data, next ? next.uri : null));
|
||||
|
@ -520,7 +436,7 @@ export function expandFavourites(id) {
|
|||
|
||||
dispatch(expandFavouritesRequest(id));
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
|
@ -669,10 +585,10 @@ export function fetchStatusReferencesFail(id, error) {
|
|||
}
|
||||
|
||||
export function pin(status) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(pinRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then(response => {
|
||||
api().post(`/api/v1/statuses/${status.get('id')}/pin`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(pinSuccess(status));
|
||||
}).catch(error => {
|
||||
|
@ -707,10 +623,10 @@ export function pinFail(status, error) {
|
|||
}
|
||||
|
||||
export function unpin (status) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(unpinRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then(response => {
|
||||
api().post(`/api/v1/statuses/${status.get('id')}/unpin`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(unpinSuccess(status));
|
||||
}).catch(error => {
|
||||
|
|
35
app/javascript/mastodon/actions/interactions_typed.ts
Normal file
35
app/javascript/mastodon/actions/interactions_typed.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { apiReblog, apiUnreblog } from 'mastodon/api/interactions';
|
||||
import type { StatusVisibility } from 'mastodon/models/status';
|
||||
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
|
||||
|
||||
import { importFetchedStatus } from './importer';
|
||||
|
||||
export const reblog = createDataLoadingThunk(
|
||||
'status/reblog',
|
||||
({
|
||||
statusId,
|
||||
visibility,
|
||||
}: {
|
||||
statusId: string;
|
||||
visibility: StatusVisibility;
|
||||
}) => apiReblog(statusId, visibility),
|
||||
(data, { dispatch, discardLoadData }) => {
|
||||
// The reblog API method returns a new status wrapped around the original. In this case we are only
|
||||
// interested in how the original is modified, hence passing it skipping the wrapper
|
||||
dispatch(importFetchedStatus(data.reblog));
|
||||
|
||||
// The payload is not used in any actions
|
||||
return discardLoadData;
|
||||
},
|
||||
);
|
||||
|
||||
export const unreblog = createDataLoadingThunk(
|
||||
'status/unreblog',
|
||||
({ statusId }: { statusId: string }) => apiUnreblog(statusId),
|
||||
(data, { dispatch, discardLoadData }) => {
|
||||
dispatch(importFetchedStatus(data));
|
||||
|
||||
// The payload is not used in any actions
|
||||
return discardLoadData;
|
||||
},
|
||||
);
|
|
@ -59,7 +59,7 @@ export const fetchList = id => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchListRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/lists/${id}`)
|
||||
api().get(`/api/v1/lists/${id}`)
|
||||
.then(({ data }) => dispatch(fetchListSuccess(data)))
|
||||
.catch(err => dispatch(fetchListFail(id, err)));
|
||||
};
|
||||
|
@ -80,10 +80,10 @@ export const fetchListFail = (id, error) => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const fetchLists = () => (dispatch, getState) => {
|
||||
export const fetchLists = () => (dispatch) => {
|
||||
dispatch(fetchListsRequest());
|
||||
|
||||
api(getState).get('/api/v1/lists')
|
||||
api().get('/api/v1/lists')
|
||||
.then(({ data }) => dispatch(fetchListsSuccess(data)))
|
||||
.catch(err => dispatch(fetchListsFail(err)));
|
||||
};
|
||||
|
@ -127,10 +127,10 @@ export const changeListEditorTitle = value => ({
|
|||
value,
|
||||
});
|
||||
|
||||
export const createList = (title, shouldReset) => (dispatch, getState) => {
|
||||
export const createList = (title, shouldReset) => (dispatch) => {
|
||||
dispatch(createListRequest());
|
||||
|
||||
api(getState).post('/api/v1/lists', { title }).then(({ data }) => {
|
||||
api().post('/api/v1/lists', { title }).then(({ data }) => {
|
||||
dispatch(createListSuccess(data));
|
||||
|
||||
if (shouldReset) {
|
||||
|
@ -153,10 +153,10 @@ export const createListFail = error => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const updateList = (id, title, shouldReset, isExclusive, replies_policy, notify) => (dispatch, getState) => {
|
||||
export const updateList = (id, title, shouldReset, isExclusive, replies_policy, notify) => (dispatch) => {
|
||||
dispatch(updateListRequest(id));
|
||||
|
||||
api(getState).put(`/api/v1/lists/${id}`, {
|
||||
api().put(`/api/v1/lists/${id}`, {
|
||||
title,
|
||||
replies_policy,
|
||||
exclusive: typeof isExclusive === 'undefined' ? undefined : !!isExclusive,
|
||||
|
@ -190,10 +190,10 @@ export const resetListEditor = () => ({
|
|||
type: LIST_EDITOR_RESET,
|
||||
});
|
||||
|
||||
export const deleteList = id => (dispatch, getState) => {
|
||||
export const deleteList = id => (dispatch) => {
|
||||
dispatch(deleteListRequest(id));
|
||||
|
||||
api(getState).delete(`/api/v1/lists/${id}`)
|
||||
api().delete(`/api/v1/lists/${id}`)
|
||||
.then(() => dispatch(deleteListSuccess(id)))
|
||||
.catch(err => dispatch(deleteListFail(id, err)));
|
||||
};
|
||||
|
@ -214,10 +214,10 @@ export const deleteListFail = (id, error) => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const fetchListAccounts = listId => (dispatch, getState) => {
|
||||
export const fetchListAccounts = listId => (dispatch) => {
|
||||
dispatch(fetchListAccountsRequest(listId));
|
||||
|
||||
api(getState).get(`/api/v1/lists/${listId}/accounts`, { params: { limit: 0 } }).then(({ data }) => {
|
||||
api().get(`/api/v1/lists/${listId}/accounts`, { params: { limit: 0 } }).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
dispatch(fetchListAccountsSuccess(listId, data));
|
||||
}).catch(err => dispatch(fetchListAccountsFail(listId, err)));
|
||||
|
@ -241,14 +241,14 @@ export const fetchListAccountsFail = (id, error) => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const fetchListSuggestions = q => (dispatch, getState) => {
|
||||
export const fetchListSuggestions = q => (dispatch) => {
|
||||
const params = {
|
||||
q,
|
||||
resolve: false,
|
||||
following: true,
|
||||
};
|
||||
|
||||
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
|
||||
api().get('/api/v1/accounts/search', { params }).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
dispatch(fetchListSuggestionsReady(q, data));
|
||||
}).catch(error => dispatch(showAlertForError(error)));
|
||||
|
@ -273,10 +273,10 @@ export const addToListEditor = accountId => (dispatch, getState) => {
|
|||
dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId));
|
||||
};
|
||||
|
||||
export const addToList = (listId, accountId) => (dispatch, getState) => {
|
||||
export const addToList = (listId, accountId) => (dispatch) => {
|
||||
dispatch(addToListRequest(listId, accountId));
|
||||
|
||||
api(getState).post(`/api/v1/lists/${listId}/accounts`, { account_ids: [accountId] })
|
||||
api().post(`/api/v1/lists/${listId}/accounts`, { account_ids: [accountId] })
|
||||
.then(() => dispatch(addToListSuccess(listId, accountId)))
|
||||
.catch(err => dispatch(addToListFail(listId, accountId, err)));
|
||||
};
|
||||
|
@ -304,10 +304,10 @@ export const removeFromListEditor = accountId => (dispatch, getState) => {
|
|||
dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId));
|
||||
};
|
||||
|
||||
export const removeFromList = (listId, accountId) => (dispatch, getState) => {
|
||||
export const removeFromList = (listId, accountId) => (dispatch) => {
|
||||
dispatch(removeFromListRequest(listId, accountId));
|
||||
|
||||
api(getState).delete(`/api/v1/lists/${listId}/accounts`, { params: { account_ids: [accountId] } })
|
||||
api().delete(`/api/v1/lists/${listId}/accounts`, { params: { account_ids: [accountId] } })
|
||||
.then(() => dispatch(removeFromListSuccess(listId, accountId)))
|
||||
.catch(err => dispatch(removeFromListFail(listId, accountId, err)));
|
||||
};
|
||||
|
@ -344,10 +344,10 @@ export const setupListAdder = accountId => (dispatch, getState) => {
|
|||
dispatch(fetchAccountLists(accountId));
|
||||
};
|
||||
|
||||
export const fetchAccountLists = accountId => (dispatch, getState) => {
|
||||
export const fetchAccountLists = accountId => (dispatch) => {
|
||||
dispatch(fetchAccountListsRequest(accountId));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${accountId}/lists`)
|
||||
api().get(`/api/v1/accounts/${accountId}/lists`)
|
||||
.then(({ data }) => dispatch(fetchAccountListsSuccess(accountId, data)))
|
||||
.catch(err => dispatch(fetchAccountListsFail(accountId, err)));
|
||||
};
|
||||
|
@ -376,4 +376,3 @@ export const addToListAdder = listId => (dispatch, getState) => {
|
|||
export const removeFromListAdder = listId => (dispatch, getState) => {
|
||||
dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])));
|
||||
};
|
||||
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
import { debounce } from 'lodash';
|
||||
|
||||
import type { MarkerJSON } from 'mastodon/api_types/markers';
|
||||
import { getAccessToken } from 'mastodon/initial_state';
|
||||
import type { AppDispatch, RootState } from 'mastodon/store';
|
||||
import { createAppAsyncThunk } from 'mastodon/store/typed_functions';
|
||||
|
||||
import api, { authorizationTokenFromState } from '../api';
|
||||
import api from '../api';
|
||||
import { compareId } from '../compare_id';
|
||||
|
||||
export const synchronouslySubmitMarkers = createAppAsyncThunk(
|
||||
'markers/submit',
|
||||
async (_args, { getState }) => {
|
||||
const accessToken = authorizationTokenFromState(getState);
|
||||
const accessToken = getAccessToken();
|
||||
const params = buildPostMarkersParams(getState());
|
||||
|
||||
if (Object.keys(params).length === 0 || !accessToken) {
|
||||
if (
|
||||
Object.keys(params).length === 0 ||
|
||||
!accessToken ||
|
||||
accessToken === ''
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -96,14 +101,14 @@ export const submitMarkersAction = createAppAsyncThunk<{
|
|||
home: string | undefined;
|
||||
notifications: string | undefined;
|
||||
}>('markers/submitAction', async (_args, { getState }) => {
|
||||
const accessToken = authorizationTokenFromState(getState);
|
||||
const accessToken = getAccessToken();
|
||||
const params = buildPostMarkersParams(getState());
|
||||
|
||||
if (Object.keys(params).length === 0 || accessToken === '') {
|
||||
if (Object.keys(params).length === 0 || !accessToken || accessToken === '') {
|
||||
return { home: undefined, notifications: undefined };
|
||||
}
|
||||
|
||||
await api(getState).post<MarkerJSON>('/api/v1/markers', params);
|
||||
await api().post<MarkerJSON>('/api/v1/markers', params);
|
||||
|
||||
return {
|
||||
home: params.home?.last_read_id,
|
||||
|
@ -133,14 +138,11 @@ export const submitMarkers = createAppAsyncThunk(
|
|||
},
|
||||
);
|
||||
|
||||
export const fetchMarkers = createAppAsyncThunk(
|
||||
'markers/fetch',
|
||||
async (_args, { getState }) => {
|
||||
const response = await api(getState).get<Record<string, MarkerJSON>>(
|
||||
`/api/v1/markers`,
|
||||
{ params: { timeline: ['notifications'] } },
|
||||
);
|
||||
export const fetchMarkers = createAppAsyncThunk('markers/fetch', async () => {
|
||||
const response = await api().get<Record<string, MarkerJSON>>(
|
||||
`/api/v1/markers`,
|
||||
{ params: { timeline: ['notifications'] } },
|
||||
);
|
||||
|
||||
return { markers: response.data };
|
||||
},
|
||||
);
|
||||
return { markers: response.data };
|
||||
});
|
||||
|
|
|
@ -13,10 +13,10 @@ export const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS';
|
|||
export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL';
|
||||
|
||||
export function fetchMutes() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchMutesRequest());
|
||||
|
||||
api(getState).get('/api/v1/mutes').then(response => {
|
||||
api().get('/api/v1/mutes').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchMutesSuccess(response.data, next ? next.uri : null));
|
||||
|
@ -56,7 +56,7 @@ export function expandMutes() {
|
|||
|
||||
dispatch(expandMutesRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(expandMutesSuccess(response.data, next ? next.uri : null));
|
||||
|
|
|
@ -233,7 +233,7 @@ export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
|
|||
|
||||
dispatch(expandNotificationsRequest(isLoadingMore));
|
||||
|
||||
api(getState).get('/api/v1/notifications', { params, signal: expandNotificationsController.signal }).then(response => {
|
||||
api().get('/api/v1/notifications', { params, signal: expandNotificationsController.signal }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedAccounts(response.data.map(item => item.account)));
|
||||
|
@ -279,12 +279,12 @@ export function expandNotificationsFail(error, isLoadingMore) {
|
|||
}
|
||||
|
||||
export function clearNotifications() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_CLEAR,
|
||||
});
|
||||
|
||||
api(getState).post('/api/v1/notifications/clear');
|
||||
api().post('/api/v1/notifications/clear');
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -363,10 +363,10 @@ export function setBrowserPermission (value) {
|
|||
};
|
||||
}
|
||||
|
||||
export const fetchNotificationPolicy = () => (dispatch, getState) => {
|
||||
export const fetchNotificationPolicy = () => (dispatch) => {
|
||||
dispatch(fetchNotificationPolicyRequest());
|
||||
|
||||
api(getState).get('/api/v1/notifications/policy').then(({ data }) => {
|
||||
api().get('/api/v1/notifications/policy').then(({ data }) => {
|
||||
dispatch(fetchNotificationPolicySuccess(data));
|
||||
}).catch(err => {
|
||||
dispatch(fetchNotificationPolicyFail(err));
|
||||
|
@ -387,10 +387,10 @@ export const fetchNotificationPolicyFail = error => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const updateNotificationsPolicy = params => (dispatch, getState) => {
|
||||
export const updateNotificationsPolicy = params => (dispatch) => {
|
||||
dispatch(fetchNotificationPolicyRequest());
|
||||
|
||||
api(getState).put('/api/v1/notifications/policy', params).then(({ data }) => {
|
||||
api().put('/api/v1/notifications/policy', params).then(({ data }) => {
|
||||
dispatch(fetchNotificationPolicySuccess(data));
|
||||
}).catch(err => {
|
||||
dispatch(fetchNotificationPolicyFail(err));
|
||||
|
@ -410,7 +410,7 @@ export const fetchNotificationRequests = () => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchNotificationRequestsRequest());
|
||||
|
||||
api(getState).get('/api/v1/notifications/requests', { params }).then(response => {
|
||||
api().get('/api/v1/notifications/requests', { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
|
||||
dispatch(fetchNotificationRequestsSuccess(response.data, next ? next.uri : null));
|
||||
|
@ -443,7 +443,7 @@ export const expandNotificationRequests = () => (dispatch, getState) => {
|
|||
|
||||
dispatch(expandNotificationRequestsRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
|
||||
dispatch(expandNotificationRequestsSuccess(response.data, next?.uri));
|
||||
|
@ -476,7 +476,7 @@ export const fetchNotificationRequest = id => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchNotificationRequestRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/notifications/requests/${id}`).then(({ data }) => {
|
||||
api().get(`/api/v1/notifications/requests/${id}`).then(({ data }) => {
|
||||
dispatch(fetchNotificationRequestSuccess(data));
|
||||
}).catch(err => {
|
||||
dispatch(fetchNotificationRequestFail(id, err));
|
||||
|
@ -499,10 +499,10 @@ export const fetchNotificationRequestFail = (id, error) => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const acceptNotificationRequest = id => (dispatch, getState) => {
|
||||
export const acceptNotificationRequest = id => (dispatch) => {
|
||||
dispatch(acceptNotificationRequestRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/notifications/requests/${id}/accept`).then(() => {
|
||||
api().post(`/api/v1/notifications/requests/${id}/accept`).then(() => {
|
||||
dispatch(acceptNotificationRequestSuccess(id));
|
||||
}).catch(err => {
|
||||
dispatch(acceptNotificationRequestFail(id, err));
|
||||
|
@ -525,10 +525,10 @@ export const acceptNotificationRequestFail = (id, error) => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const dismissNotificationRequest = id => (dispatch, getState) => {
|
||||
export const dismissNotificationRequest = id => (dispatch) => {
|
||||
dispatch(dismissNotificationRequestRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/notifications/requests/${id}/dismiss`).then(() =>{
|
||||
api().post(`/api/v1/notifications/requests/${id}/dismiss`).then(() =>{
|
||||
dispatch(dismissNotificationRequestSuccess(id));
|
||||
}).catch(err => {
|
||||
dispatch(dismissNotificationRequestFail(id, err));
|
||||
|
@ -567,7 +567,7 @@ export const fetchNotificationsForRequest = accountId => (dispatch, getState) =>
|
|||
|
||||
dispatch(fetchNotificationsForRequestRequest());
|
||||
|
||||
api(getState).get('/api/v1/notifications', { params }).then(response => {
|
||||
api().get('/api/v1/notifications', { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data.map(item => item.account)));
|
||||
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
|
||||
|
@ -603,7 +603,7 @@ export const expandNotificationsForRequest = () => (dispatch, getState) => {
|
|||
|
||||
dispatch(expandNotificationsForRequestRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data.map(item => item.account)));
|
||||
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
|
||||
|
|
|
@ -8,10 +8,10 @@ export const PINNED_STATUSES_FETCH_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS';
|
|||
export const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL';
|
||||
|
||||
export function fetchPinnedStatuses() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchPinnedStatusesRequest());
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${me}/statuses`, { params: { pinned: true } }).then(response => {
|
||||
api().get(`/api/v1/accounts/${me}/statuses`, { params: { pinned: true } }).then(response => {
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchPinnedStatusesSuccess(response.data, null));
|
||||
}).catch(error => {
|
||||
|
|
|
@ -10,10 +10,10 @@ export const POLL_FETCH_REQUEST = 'POLL_FETCH_REQUEST';
|
|||
export const POLL_FETCH_SUCCESS = 'POLL_FETCH_SUCCESS';
|
||||
export const POLL_FETCH_FAIL = 'POLL_FETCH_FAIL';
|
||||
|
||||
export const vote = (pollId, choices) => (dispatch, getState) => {
|
||||
export const vote = (pollId, choices) => (dispatch) => {
|
||||
dispatch(voteRequest());
|
||||
|
||||
api(getState).post(`/api/v1/polls/${pollId}/votes`, { choices })
|
||||
api().post(`/api/v1/polls/${pollId}/votes`, { choices })
|
||||
.then(({ data }) => {
|
||||
dispatch(importFetchedPoll(data));
|
||||
dispatch(voteSuccess(data));
|
||||
|
@ -21,10 +21,10 @@ export const vote = (pollId, choices) => (dispatch, getState) => {
|
|||
.catch(err => dispatch(voteFail(err)));
|
||||
};
|
||||
|
||||
export const fetchPoll = pollId => (dispatch, getState) => {
|
||||
export const fetchPoll = pollId => (dispatch) => {
|
||||
dispatch(fetchPollRequest());
|
||||
|
||||
api(getState).get(`/api/v1/polls/${pollId}`)
|
||||
api().get(`/api/v1/polls/${pollId}`)
|
||||
.then(({ data }) => {
|
||||
dispatch(importFetchedPoll(data));
|
||||
dispatch(fetchPollSuccess(data));
|
||||
|
|
|
@ -15,10 +15,10 @@ export const initReport = (account, status) => dispatch =>
|
|||
},
|
||||
}));
|
||||
|
||||
export const submitReport = (params, onSuccess, onFail) => (dispatch, getState) => {
|
||||
export const submitReport = (params, onSuccess, onFail) => (dispatch) => {
|
||||
dispatch(submitReportRequest());
|
||||
|
||||
api(getState).post('/api/v1/reports', params).then(response => {
|
||||
api().post('/api/v1/reports', params).then(response => {
|
||||
dispatch(submitReportSuccess(response.data));
|
||||
if (onSuccess) onSuccess();
|
||||
}).catch(error => {
|
||||
|
|
|
@ -46,7 +46,7 @@ export function submitSearch(type) {
|
|||
|
||||
dispatch(fetchSearchRequest(type));
|
||||
|
||||
api(getState).get('/api/v2/search', {
|
||||
api().get('/api/v2/search', {
|
||||
params: {
|
||||
q: value,
|
||||
resolve: signedIn,
|
||||
|
@ -99,7 +99,7 @@ export const expandSearch = type => (dispatch, getState) => {
|
|||
|
||||
dispatch(expandSearchRequest(type));
|
||||
|
||||
api(getState).get('/api/v2/search', {
|
||||
api().get('/api/v2/search', {
|
||||
params: {
|
||||
q: value,
|
||||
type,
|
||||
|
@ -156,7 +156,7 @@ export const openURL = (value, history, onFailure) => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchSearchRequest());
|
||||
|
||||
api(getState).get('/api/v2/search', { params: { q: value, resolve: true } }).then(response => {
|
||||
api().get('/api/v2/search', { params: { q: value, resolve: true } }).then(response => {
|
||||
if (response.data.accounts?.length > 0) {
|
||||
dispatch(importFetchedAccounts(response.data.accounts));
|
||||
history.push(`/@${response.data.accounts[0].acct}`);
|
||||
|
|
|
@ -25,7 +25,7 @@ export const fetchServer = () => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchServerRequest());
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.get('/api/v2/instance').then(({ data }) => {
|
||||
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
|
@ -46,10 +46,10 @@ const fetchServerFail = error => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const fetchServerTranslationLanguages = () => (dispatch, getState) => {
|
||||
export const fetchServerTranslationLanguages = () => (dispatch) => {
|
||||
dispatch(fetchServerTranslationLanguagesRequest());
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.get('/api/v1/instance/translation_languages').then(({ data }) => {
|
||||
dispatch(fetchServerTranslationLanguagesSuccess(data));
|
||||
}).catch(err => dispatch(fetchServerTranslationLanguagesFail(err)));
|
||||
|
@ -76,7 +76,7 @@ export const fetchExtendedDescription = () => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchExtendedDescriptionRequest());
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.get('/api/v1/instance/extended_description')
|
||||
.then(({ data }) => dispatch(fetchExtendedDescriptionSuccess(data)))
|
||||
.catch(err => dispatch(fetchExtendedDescriptionFail(err)));
|
||||
|
@ -103,7 +103,7 @@ export const fetchDomainBlocks = () => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchDomainBlocksRequest());
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.get('/api/v1/instance/domain_blocks')
|
||||
.then(({ data }) => dispatch(fetchDomainBlocksSuccess(true, data)))
|
||||
.catch(err => {
|
||||
|
|
|
@ -20,7 +20,7 @@ export function changeSetting(path, value) {
|
|||
}
|
||||
|
||||
const debouncedSave = debounce((dispatch, getState) => {
|
||||
if (getState().getIn(['settings', 'saved'])) {
|
||||
if (getState().getIn(['settings', 'saved']) || !getState().getIn(['meta', 'me'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ export function fetchStatus(id, forceFetch = false) {
|
|||
|
||||
dispatch(fetchStatusRequest(id, skipLoading));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}`).then(response => {
|
||||
api().get(`/api/v1/statuses/${id}`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(fetchStatusSuccess(skipLoading));
|
||||
}).catch(error => {
|
||||
|
@ -104,7 +104,7 @@ export const editStatus = (id, routerHistory) => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchStatusSourceRequest());
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/source`).then(response => {
|
||||
api().get(`/api/v1/statuses/${id}/source`).then(response => {
|
||||
dispatch(fetchStatusSourceSuccess());
|
||||
ensureComposeIsVisible(getState, routerHistory);
|
||||
dispatch(setComposeToStatus(status, response.data.text, response.data.spoiler_text));
|
||||
|
@ -136,7 +136,7 @@ export function deleteStatus(id, routerHistory, withRedraft = false) {
|
|||
|
||||
dispatch(deleteStatusRequest(id));
|
||||
|
||||
api(getState).delete(`/api/v1/statuses/${id}`).then(response => {
|
||||
api().delete(`/api/v1/statuses/${id}`).then(response => {
|
||||
dispatch(deleteStatusSuccess(id));
|
||||
dispatch(deleteFromTimelines(id));
|
||||
dispatch(importFetchedAccount(response.data.account));
|
||||
|
@ -177,10 +177,10 @@ export const updateStatus = status => dispatch =>
|
|||
dispatch(importFetchedStatus(status));
|
||||
|
||||
export function fetchContext(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchContextRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/context?with_reference=1`).then(response => {
|
||||
api().get(`/api/v1/statuses/${id}/context?with_reference=1`).then(response => {
|
||||
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants).concat(response.data.references)));
|
||||
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants, response.data.references));
|
||||
|
||||
|
@ -222,10 +222,10 @@ export function fetchContextFail(id, error) {
|
|||
}
|
||||
|
||||
export function muteStatus(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(muteStatusRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${id}/mute`).then(() => {
|
||||
api().post(`/api/v1/statuses/${id}/mute`).then(() => {
|
||||
dispatch(muteStatusSuccess(id));
|
||||
}).catch(error => {
|
||||
dispatch(muteStatusFail(id, error));
|
||||
|
@ -256,10 +256,10 @@ export function muteStatusFail(id, error) {
|
|||
}
|
||||
|
||||
export function unmuteStatus(id) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(unmuteStatusRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${id}/unmute`).then(() => {
|
||||
api().post(`/api/v1/statuses/${id}/unmute`).then(() => {
|
||||
dispatch(unmuteStatusSuccess(id));
|
||||
}).catch(error => {
|
||||
dispatch(unmuteStatusFail(id, error));
|
||||
|
@ -319,10 +319,10 @@ export function toggleStatusCollapse(id, isCollapsed) {
|
|||
};
|
||||
}
|
||||
|
||||
export const translateStatus = id => (dispatch, getState) => {
|
||||
export const translateStatus = id => (dispatch) => {
|
||||
dispatch(translateStatusRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${id}/translate`).then(response => {
|
||||
api().post(`/api/v1/statuses/${id}/translate`).then(response => {
|
||||
dispatch(translateStatusSuccess(id, response.data));
|
||||
}).catch(error => {
|
||||
dispatch(translateStatusFail(id, error));
|
||||
|
|
|
@ -10,10 +10,10 @@ export const SUGGESTIONS_FETCH_FAIL = 'SUGGESTIONS_FETCH_FAIL';
|
|||
export const SUGGESTIONS_DISMISS = 'SUGGESTIONS_DISMISS';
|
||||
|
||||
export function fetchSuggestions(withRelationships = false) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch(fetchSuggestionsRequest());
|
||||
|
||||
api(getState).get('/api/v2/suggestions', { params: { limit: 20 } }).then(response => {
|
||||
api().get('/api/v2/suggestions', { params: { limit: 20 } }).then(response => {
|
||||
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
|
||||
dispatch(fetchSuggestionsSuccess(response.data));
|
||||
|
||||
|
@ -48,11 +48,11 @@ export function fetchSuggestionsFail(error) {
|
|||
};
|
||||
}
|
||||
|
||||
export const dismissSuggestion = accountId => (dispatch, getState) => {
|
||||
export const dismissSuggestion = accountId => (dispatch) => {
|
||||
dispatch({
|
||||
type: SUGGESTIONS_DISMISS,
|
||||
id: accountId,
|
||||
});
|
||||
|
||||
api(getState).delete(`/api/v1/suggestions/${accountId}`).catch(() => {});
|
||||
api().delete(`/api/v1/suggestions/${accountId}`).catch(() => {});
|
||||
};
|
||||
|
|
|
@ -20,10 +20,10 @@ export const HASHTAG_UNFOLLOW_REQUEST = 'HASHTAG_UNFOLLOW_REQUEST';
|
|||
export const HASHTAG_UNFOLLOW_SUCCESS = 'HASHTAG_UNFOLLOW_SUCCESS';
|
||||
export const HASHTAG_UNFOLLOW_FAIL = 'HASHTAG_UNFOLLOW_FAIL';
|
||||
|
||||
export const fetchHashtag = name => (dispatch, getState) => {
|
||||
export const fetchHashtag = name => (dispatch) => {
|
||||
dispatch(fetchHashtagRequest());
|
||||
|
||||
api(getState).get(`/api/v1/tags/${name}`).then(({ data }) => {
|
||||
api().get(`/api/v1/tags/${name}`).then(({ data }) => {
|
||||
dispatch(fetchHashtagSuccess(name, data));
|
||||
}).catch(err => {
|
||||
dispatch(fetchHashtagFail(err));
|
||||
|
@ -45,10 +45,10 @@ export const fetchHashtagFail = error => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const fetchFollowedHashtags = () => (dispatch, getState) => {
|
||||
export const fetchFollowedHashtags = () => (dispatch) => {
|
||||
dispatch(fetchFollowedHashtagsRequest());
|
||||
|
||||
api(getState).get('/api/v1/followed_tags').then(response => {
|
||||
api().get('/api/v1/followed_tags').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(fetchFollowedHashtagsSuccess(response.data, next ? next.uri : null));
|
||||
}).catch(err => {
|
||||
|
@ -87,7 +87,7 @@ export function expandFollowedHashtags() {
|
|||
|
||||
dispatch(expandFollowedHashtagsRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(expandFollowedHashtagsSuccess(response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
|
@ -117,10 +117,10 @@ export function expandFollowedHashtagsFail(error) {
|
|||
};
|
||||
}
|
||||
|
||||
export const followHashtag = name => (dispatch, getState) => {
|
||||
export const followHashtag = name => (dispatch) => {
|
||||
dispatch(followHashtagRequest(name));
|
||||
|
||||
api(getState).post(`/api/v1/tags/${name}/follow`).then(({ data }) => {
|
||||
api().post(`/api/v1/tags/${name}/follow`).then(({ data }) => {
|
||||
dispatch(followHashtagSuccess(name, data));
|
||||
}).catch(err => {
|
||||
dispatch(followHashtagFail(name, err));
|
||||
|
@ -144,10 +144,10 @@ export const followHashtagFail = (name, error) => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const unfollowHashtag = name => (dispatch, getState) => {
|
||||
export const unfollowHashtag = name => (dispatch) => {
|
||||
dispatch(unfollowHashtagRequest(name));
|
||||
|
||||
api(getState).post(`/api/v1/tags/${name}/unfollow`).then(({ data }) => {
|
||||
api().post(`/api/v1/tags/${name}/unfollow`).then(({ data }) => {
|
||||
dispatch(unfollowHashtagSuccess(name, data));
|
||||
}).catch(err => {
|
||||
dispatch(unfollowHashtagFail(name, err));
|
||||
|
|
|
@ -114,7 +114,7 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
|
|||
|
||||
dispatch(expandTimelineRequest(timelineId, isLoadingMore));
|
||||
|
||||
api(getState).get(path, { params }).then(response => {
|
||||
api().get(path, { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
|
|
|
@ -18,10 +18,10 @@ export const TRENDS_STATUSES_EXPAND_REQUEST = 'TRENDS_STATUSES_EXPAND_REQUEST';
|
|||
export const TRENDS_STATUSES_EXPAND_SUCCESS = 'TRENDS_STATUSES_EXPAND_SUCCESS';
|
||||
export const TRENDS_STATUSES_EXPAND_FAIL = 'TRENDS_STATUSES_EXPAND_FAIL';
|
||||
|
||||
export const fetchTrendingHashtags = () => (dispatch, getState) => {
|
||||
export const fetchTrendingHashtags = () => (dispatch) => {
|
||||
dispatch(fetchTrendingHashtagsRequest());
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.get('/api/v1/trends/tags')
|
||||
.then(({ data }) => dispatch(fetchTrendingHashtagsSuccess(data)))
|
||||
.catch(err => dispatch(fetchTrendingHashtagsFail(err)));
|
||||
|
@ -45,10 +45,10 @@ export const fetchTrendingHashtagsFail = error => ({
|
|||
skipAlert: true,
|
||||
});
|
||||
|
||||
export const fetchTrendingLinks = () => (dispatch, getState) => {
|
||||
export const fetchTrendingLinks = () => (dispatch) => {
|
||||
dispatch(fetchTrendingLinksRequest());
|
||||
|
||||
api(getState)
|
||||
api()
|
||||
.get('/api/v1/trends/links')
|
||||
.then(({ data }) => dispatch(fetchTrendingLinksSuccess(data)))
|
||||
.catch(err => dispatch(fetchTrendingLinksFail(err)));
|
||||
|
@ -79,7 +79,7 @@ export const fetchTrendingStatuses = () => (dispatch, getState) => {
|
|||
|
||||
dispatch(fetchTrendingStatusesRequest());
|
||||
|
||||
api(getState).get('/api/v1/trends/statuses').then(response => {
|
||||
api().get('/api/v1/trends/statuses').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(fetchTrendingStatusesSuccess(response.data, next ? next.uri : null));
|
||||
|
@ -115,7 +115,7 @@ export const expandTrendingStatuses = () => (dispatch, getState) => {
|
|||
|
||||
dispatch(expandTrendingStatusesRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
api().get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(expandTrendingStatusesSuccess(response.data, next ? next.uri : null));
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import type { AxiosResponse, RawAxiosRequestHeaders } from 'axios';
|
||||
import type { AxiosResponse, Method, RawAxiosRequestHeaders } from 'axios';
|
||||
import axios from 'axios';
|
||||
import LinkHeader from 'http-link-header';
|
||||
|
||||
import { getAccessToken } from './initial_state';
|
||||
import ready from './ready';
|
||||
import type { GetState } from './store';
|
||||
|
||||
export const getLinks = (response: AxiosResponse) => {
|
||||
const value = response.headers.link as string | undefined;
|
||||
|
@ -29,30 +29,22 @@ const setCSRFHeader = () => {
|
|||
|
||||
void ready(setCSRFHeader);
|
||||
|
||||
export const authorizationTokenFromState = (getState?: GetState) => {
|
||||
return (
|
||||
getState && (getState().meta.get('access_token', '') as string | false)
|
||||
);
|
||||
};
|
||||
const authorizationTokenFromInitialState = (): RawAxiosRequestHeaders => {
|
||||
const accessToken = getAccessToken();
|
||||
|
||||
const authorizationHeaderFromState = (getState?: GetState) => {
|
||||
const accessToken = authorizationTokenFromState(getState);
|
||||
|
||||
if (!accessToken) {
|
||||
return {};
|
||||
}
|
||||
if (!accessToken) return {};
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
} as RawAxiosRequestHeaders;
|
||||
};
|
||||
};
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function api(getState: GetState) {
|
||||
export default function api(withAuthorization = true) {
|
||||
return axios.create({
|
||||
headers: {
|
||||
...csrfHeader,
|
||||
...authorizationHeaderFromState(getState),
|
||||
...(withAuthorization ? authorizationTokenFromInitialState() : {}),
|
||||
},
|
||||
|
||||
transformResponse: [
|
||||
|
@ -66,3 +58,17 @@ export default function api(getState: GetState) {
|
|||
],
|
||||
});
|
||||
}
|
||||
|
||||
export async function apiRequest<ApiResponse = unknown>(
|
||||
method: Method,
|
||||
url: string,
|
||||
params?: Record<string, unknown>,
|
||||
) {
|
||||
const { data } = await api().request<ApiResponse>({
|
||||
method,
|
||||
url: '/api/' + url,
|
||||
data: params,
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
|
7
app/javascript/mastodon/api/accounts.ts
Normal file
7
app/javascript/mastodon/api/accounts.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { apiRequest } from 'mastodon/api';
|
||||
import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
|
||||
|
||||
export const apiSubmitAccountNote = (id: string, value: string) =>
|
||||
apiRequest<ApiRelationshipJSON>('post', `v1/accounts/${id}/note`, {
|
||||
comment: value,
|
||||
});
|
10
app/javascript/mastodon/api/interactions.ts
Normal file
10
app/javascript/mastodon/api/interactions.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { apiRequest } from 'mastodon/api';
|
||||
import type { Status, StatusVisibility } from 'mastodon/models/status';
|
||||
|
||||
export const apiReblog = (statusId: string, visibility: StatusVisibility) =>
|
||||
apiRequest<{ reblog: Status }>('post', `v1/statuses/${statusId}/reblog`, {
|
||||
visibility,
|
||||
});
|
||||
|
||||
export const apiUnreblog = (statusId: string) =>
|
||||
apiRequest<Status>('post', `v1/statuses/${statusId}/unreblog`);
|
|
@ -182,7 +182,6 @@ Account.propTypes = {
|
|||
onBlock: PropTypes.func,
|
||||
onMute: PropTypes.func,
|
||||
onMuteNotifications: PropTypes.func,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hidden: PropTypes.bool,
|
||||
hideButtons: PropTypes.bool,
|
||||
minimal: PropTypes.bool,
|
||||
|
|
|
@ -49,7 +49,7 @@ export default class Counter extends PureComponent {
|
|||
componentDidMount () {
|
||||
const { measure, start_at, end_at, params } = this.props;
|
||||
|
||||
api().post('/api/v1/admin/measures', { keys: [measure], start_at, end_at, [measure]: params }).then(res => {
|
||||
api(false).post('/api/v1/admin/measures', { keys: [measure], start_at, end_at, [measure]: params }).then(res => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: res.data,
|
||||
|
|
|
@ -27,7 +27,7 @@ export default class Dimension extends PureComponent {
|
|||
componentDidMount () {
|
||||
const { start_at, end_at, dimension, limit, params } = this.props;
|
||||
|
||||
api().post('/api/v1/admin/dimensions', { keys: [dimension], start_at, end_at, limit, [dimension]: params }).then(res => {
|
||||
api(false).post('/api/v1/admin/dimensions', { keys: [dimension], start_at, end_at, limit, [dimension]: params }).then(res => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: res.data,
|
||||
|
|
|
@ -27,7 +27,7 @@ export default class ImpactReport extends PureComponent {
|
|||
include_subdomains: true,
|
||||
};
|
||||
|
||||
api().post('/api/v1/admin/measures', {
|
||||
api(false).post('/api/v1/admin/measures', {
|
||||
keys: ['instance_accounts', 'instance_follows', 'instance_followers'],
|
||||
start_at: null,
|
||||
end_at: null,
|
||||
|
|
|
@ -105,7 +105,7 @@ class ReportReasonSelector extends PureComponent {
|
|||
};
|
||||
|
||||
componentDidMount() {
|
||||
api().get('/api/v1/instance').then(res => {
|
||||
api(false).get('/api/v1/instance').then(res => {
|
||||
this.setState({
|
||||
rules: res.data.rules,
|
||||
});
|
||||
|
@ -122,7 +122,7 @@ class ReportReasonSelector extends PureComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
api().put(`/api/v1/admin/reports/${id}`, {
|
||||
api(false).put(`/api/v1/admin/reports/${id}`, {
|
||||
category,
|
||||
rule_ids: category === 'violation' ? rule_ids : [],
|
||||
}).catch(err => {
|
||||
|
|
|
@ -34,7 +34,7 @@ export default class Retention extends PureComponent {
|
|||
componentDidMount () {
|
||||
const { start_at, end_at, frequency } = this.props;
|
||||
|
||||
api().post('/api/v1/admin/retention', { start_at, end_at, frequency }).then(res => {
|
||||
api(false).post('/api/v1/admin/retention', { start_at, end_at, frequency }).then(res => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: res.data,
|
||||
|
|
|
@ -22,7 +22,7 @@ export default class Trends extends PureComponent {
|
|||
componentDidMount () {
|
||||
const { limit } = this.props;
|
||||
|
||||
api().get('/api/v1/admin/trends/tags', { params: { limit } }).then(res => {
|
||||
api(false).get('/api/v1/admin/trends/tags', { params: { limit } }).then(res => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: res.data,
|
||||
|
|
|
@ -14,8 +14,10 @@ import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
|||
import SettingsIcon from '@/material-icons/400-24px/settings.svg?react';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { ButtonInTabsBar } from 'mastodon/features/ui/util/columns_context';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
|
||||
|
||||
import { useAppHistory } from './router';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -51,12 +53,8 @@ BackButton.propTypes = {
|
|||
};
|
||||
|
||||
class ColumnHeader extends PureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
intl: PropTypes.object.isRequired,
|
||||
title: PropTypes.node,
|
||||
icon: PropTypes.string,
|
||||
|
@ -171,7 +169,7 @@ class ColumnHeader extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
if (this.context.identity.signedIn && (children || (multiColumn && this.props.onPin))) {
|
||||
if (this.props.identity.signedIn && (children || (multiColumn && this.props.onPin))) {
|
||||
collapseButton = (
|
||||
<button
|
||||
className={collapsibleButtonClassName}
|
||||
|
@ -232,4 +230,4 @@ class ColumnHeader extends PureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default injectIntl(withRouter(ColumnHeader));
|
||||
export default injectIntl(withIdentity(withRouter(ColumnHeader)));
|
||||
|
|
|
@ -14,6 +14,7 @@ import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
|||
import { Icon } from 'mastodon/components/icon';
|
||||
import emojify from 'mastodon/features/emoji/emoji';
|
||||
import Motion from 'mastodon/features/ui/util/optional_motion';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
|
||||
import { RelativeTimestamp } from './relative_timestamp';
|
||||
|
||||
|
@ -38,12 +39,8 @@ const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => {
|
|||
}, {});
|
||||
|
||||
class Poll extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
poll: ImmutablePropTypes.map,
|
||||
lang: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
@ -235,7 +232,7 @@ class Poll extends ImmutablePureComponent {
|
|||
</ul>
|
||||
|
||||
<div className='poll__footer'>
|
||||
{!showResults && <button className='button button-secondary' disabled={disabled || !this.context.identity.signedIn} onClick={this.handleVote}><FormattedMessage id='poll.vote' defaultMessage='Vote' /></button>}
|
||||
{!showResults && <button className='button button-secondary' disabled={disabled || !this.props.identity.signedIn} onClick={this.handleVote}><FormattedMessage id='poll.vote' defaultMessage='Vote' /></button>}
|
||||
{!showResults && <><button className='poll__link' onClick={this.handleReveal}><FormattedMessage id='poll.reveal' defaultMessage='See results' /></button> · </>}
|
||||
{showResults && !this.props.disabled && <><button className='poll__link' onClick={this.handleRefresh}><FormattedMessage id='poll.refresh' defaultMessage='Refresh' /></button> · </>}
|
||||
{votesCount}
|
||||
|
@ -247,4 +244,4 @@ class Poll extends ImmutablePureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default injectIntl(Poll);
|
||||
export default injectIntl(withIdentity(Poll));
|
||||
|
|
|
@ -23,6 +23,7 @@ import RepeatActiveIcon from '@/svg-icons/repeat_active.svg?react';
|
|||
import RepeatDisabledIcon from '@/svg-icons/repeat_disabled.svg?react';
|
||||
import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg?react';
|
||||
import RepeatPrivateActiveIcon from '@/svg-icons/repeat_private_active.svg?react';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
|
||||
|
@ -85,12 +86,8 @@ const mapStateToProps = (state, { status }) => ({
|
|||
});
|
||||
|
||||
class StatusActionBar extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
relationship: ImmutablePropTypes.record,
|
||||
onReply: PropTypes.func,
|
||||
|
@ -134,7 +131,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
];
|
||||
|
||||
handleReplyClick = () => {
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
if (signedIn) {
|
||||
this.props.onReply(this.props.status, this.props.history);
|
||||
|
@ -152,7 +149,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
handleFavouriteClick = () => {
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
if (signedIn) {
|
||||
this.props.onFavourite(this.props.status);
|
||||
|
@ -174,7 +171,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
handleEmojiPickInnerButton = () => {};
|
||||
|
||||
handleReblogClick = e => {
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
if (signedIn) {
|
||||
this.props.onReblog(this.props.status, e);
|
||||
|
@ -306,7 +303,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
|
||||
render () {
|
||||
const { status, relationship, intl, withDismiss, withCounters, scrollKey } = this.props;
|
||||
const { signedIn, permissions } = this.context.identity;
|
||||
const { signedIn, permissions } = this.props.identity;
|
||||
|
||||
const publicStatus = ['public', 'unlisted', 'public_unlisted', 'login'].includes(status.get('visibility_ex'));
|
||||
const anonymousStatus = ['public', 'unlisted', 'public_unlisted'].includes(status.get('visibility_ex'));
|
||||
|
@ -546,4 +543,4 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default withRouter(connect(mapStateToProps)(injectIntl(StatusActionBar)));
|
||||
export default withRouter(withIdentity(connect(mapStateToProps)(injectIntl(StatusActionBar))));
|
||||
|
|
|
@ -12,8 +12,10 @@ import { connect } from 'react-redux';
|
|||
import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import PollContainer from 'mastodon/containers/poll_container';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||
|
||||
|
||||
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
|
||||
|
||||
/**
|
||||
|
@ -67,12 +69,8 @@ const mapStateToProps = state => ({
|
|||
});
|
||||
|
||||
class StatusContent extends PureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
statusContent: PropTypes.string,
|
||||
expanded: PropTypes.bool,
|
||||
|
@ -246,7 +244,7 @@ class StatusContent extends PureComponent {
|
|||
const contentLocale = intl.locale.replace(/[_-].*/, '');
|
||||
const targetLanguages = this.props.languages?.get(status.get('language') || 'und');
|
||||
const renderTranslate = this.props.onTranslate &&
|
||||
this.context.identity.signedIn &&
|
||||
this.props.identity.signedIn &&
|
||||
(['public', 'unlisted'].includes(status.get('visibility')) || status.getIn(['account', 'other_settings', 'translatable_private'])) &&
|
||||
status.get('search_index').trim().length > 0 &&
|
||||
status.get('language') &&
|
||||
|
@ -333,4 +331,4 @@ class StatusContent extends PureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default withRouter(connect(mapStateToProps)(injectIntl(StatusContent)));
|
||||
export default withRouter(withIdentity(connect(mapStateToProps)(injectIntl(StatusContent))));
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { PureComponent } from 'react';
|
||||
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
@ -16,6 +15,7 @@ import { connectUserStream } from 'mastodon/actions/streaming';
|
|||
import ErrorBoundary from 'mastodon/components/error_boundary';
|
||||
import { Router } from 'mastodon/components/router';
|
||||
import UI from 'mastodon/features/ui';
|
||||
import { IdentityContext, createIdentityContext } from 'mastodon/identity_context';
|
||||
import initialState, { title as siteTitle } from 'mastodon/initial_state';
|
||||
import { IntlProvider } from 'mastodon/locales';
|
||||
import { store } from 'mastodon/store';
|
||||
|
@ -32,33 +32,9 @@ if (initialState.meta.me) {
|
|||
store.dispatch(fetchCircles());
|
||||
}
|
||||
|
||||
const createIdentityContext = state => ({
|
||||
signedIn: !!state.meta.me,
|
||||
accountId: state.meta.me,
|
||||
disabledAccountId: state.meta.disabled_account_id,
|
||||
accessToken: state.meta.access_token,
|
||||
permissions: state.role ? state.role.permissions : 0,
|
||||
});
|
||||
|
||||
export default class Mastodon extends PureComponent {
|
||||
|
||||
static childContextTypes = {
|
||||
identity: PropTypes.shape({
|
||||
signedIn: PropTypes.bool.isRequired,
|
||||
accountId: PropTypes.string,
|
||||
disabledAccountId: PropTypes.string,
|
||||
accessToken: PropTypes.string,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
identity = createIdentityContext(initialState);
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
identity: this.identity,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.identity.signedIn) {
|
||||
this.disconnect = store.dispatch(connectUserStream());
|
||||
|
@ -78,19 +54,21 @@ export default class Mastodon extends PureComponent {
|
|||
|
||||
render () {
|
||||
return (
|
||||
<IntlProvider>
|
||||
<ReduxProvider store={store}>
|
||||
<ErrorBoundary>
|
||||
<Router>
|
||||
<ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}>
|
||||
<Route path='/' component={UI} />
|
||||
</ScrollContext>
|
||||
</Router>
|
||||
<IdentityContext.Provider value={this.identity}>
|
||||
<IntlProvider>
|
||||
<ReduxProvider store={store}>
|
||||
<ErrorBoundary>
|
||||
<Router>
|
||||
<ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}>
|
||||
<Route path='/' component={UI} />
|
||||
</ScrollContext>
|
||||
</Router>
|
||||
|
||||
<Helmet defaultTitle={title} titleTemplate={`%s - ${title}`} />
|
||||
</ErrorBoundary>
|
||||
</ReduxProvider>
|
||||
</IntlProvider>
|
||||
<Helmet defaultTitle={title} titleTemplate={`%s - ${title}`} />
|
||||
</ErrorBoundary>
|
||||
</ReduxProvider>
|
||||
</IntlProvider>
|
||||
</IdentityContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,9 +101,9 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
|
|||
|
||||
onModalReblog (status, privacy) {
|
||||
if (status.get('reblogged')) {
|
||||
dispatch(unreblog(status));
|
||||
dispatch(unreblog({ statusId: status.get('id') }));
|
||||
} else {
|
||||
dispatch(reblog(status, privacy));
|
||||
dispatch(reblog({ statusId: status.get('id'), visibility: privacy }));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import { IconButton } from 'mastodon/components/icon_button';
|
|||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||
import { ShortNumber } from 'mastodon/components/short_number';
|
||||
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { autoPlayGif, me, domain as localDomain, isShowItem } from 'mastodon/initial_state';
|
||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
|
@ -115,6 +116,7 @@ const dateFormatOptions = {
|
|||
class Header extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
account: ImmutablePropTypes.record,
|
||||
featuredTags: PropTypes.array,
|
||||
identity_props: ImmutablePropTypes.list,
|
||||
|
@ -144,10 +146,6 @@ class Header extends ImmutablePureComponent {
|
|||
...WithRouterPropTypes,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
setRef = c => {
|
||||
this.node = c;
|
||||
};
|
||||
|
@ -277,7 +275,7 @@ class Header extends ImmutablePureComponent {
|
|||
|
||||
render () {
|
||||
const { account, hidden, intl } = this.props;
|
||||
const { signedIn, permissions } = this.context.identity;
|
||||
const { signedIn, permissions } = this.props.identity;
|
||||
|
||||
if (!account) {
|
||||
return null;
|
||||
|
@ -554,4 +552,4 @@ class Header extends ImmutablePureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default withRouter(injectIntl(Header));
|
||||
export default withRouter(withIdentity(injectIntl(Header)));
|
||||
|
|
|
@ -11,7 +11,7 @@ const mapStateToProps = (state, { account }) => ({
|
|||
const mapDispatchToProps = (dispatch, { account }) => ({
|
||||
|
||||
onSave (value) {
|
||||
dispatch(submitAccountNote({ id: account.get('id'), value}));
|
||||
dispatch(submitAccountNote({ accountId: account.get('id'), note: value }));
|
||||
},
|
||||
|
||||
});
|
||||
|
|
|
@ -9,6 +9,7 @@ import { connect } from 'react-redux';
|
|||
|
||||
import PeopleIcon from '@/material-icons/400-24px/group.svg?react';
|
||||
import { DismissableBanner } from 'mastodon/components/dismissable_banner';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { domain } from 'mastodon/initial_state';
|
||||
|
||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||
|
@ -38,16 +39,12 @@ const mapStateToProps = (state, { columnId }) => {
|
|||
};
|
||||
|
||||
class CommunityTimeline extends PureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onlyMedia: false,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
columnId: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
@ -77,7 +74,7 @@ class CommunityTimeline extends PureComponent {
|
|||
|
||||
componentDidMount () {
|
||||
const { dispatch, onlyMedia } = this.props;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
dispatch(expandCommunityTimeline({ onlyMedia }));
|
||||
|
||||
|
@ -87,7 +84,7 @@ class CommunityTimeline extends PureComponent {
|
|||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
if (prevProps.onlyMedia !== this.props.onlyMedia) {
|
||||
const { dispatch, onlyMedia } = this.props;
|
||||
|
@ -161,4 +158,4 @@ class CommunityTimeline extends PureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(injectIntl(CommunityTimeline));
|
||||
export default withIdentity(connect(mapStateToProps)(injectIntl(CommunityTimeline)));
|
||||
|
|
|
@ -12,6 +12,7 @@ import CancelIcon from '@/material-icons/400-24px/cancel-fill.svg?react';
|
|||
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
||||
import SearchIcon from '@/material-icons/400-24px/search.svg?react';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { domain, searchEnabled } from 'mastodon/initial_state';
|
||||
import { HASHTAG_REGEX } from 'mastodon/utils/hashtags';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
|
@ -33,12 +34,8 @@ const labelForRecentSearch = search => {
|
|||
};
|
||||
|
||||
class Search extends PureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
value: PropTypes.string.isRequired,
|
||||
recent: ImmutablePropTypes.orderedSet,
|
||||
submitted: PropTypes.bool,
|
||||
|
@ -279,7 +276,7 @@ class Search extends PureComponent {
|
|||
}
|
||||
|
||||
_calculateOptions (value) {
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
const trimmedValue = value.trim();
|
||||
const options = [];
|
||||
|
||||
|
@ -321,7 +318,7 @@ class Search extends PureComponent {
|
|||
render () {
|
||||
const { intl, value, submitted, recent } = this.props;
|
||||
const { expanded, options, selectedOption } = this.state;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
const hasValue = value.length > 0 || submitted;
|
||||
|
||||
|
@ -405,4 +402,4 @@ class Search extends PureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default withRouter(injectIntl(Search));
|
||||
export default withRouter(withIdentity(injectIntl(Search)));
|
||||
|
|
|
@ -13,6 +13,7 @@ import SearchIcon from '@/material-icons/400-24px/search.svg?react';
|
|||
import Column from 'mastodon/components/column';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
import Search from 'mastodon/features/compose/containers/search_container';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { trendsEnabled } from 'mastodon/initial_state';
|
||||
|
||||
import Links from './links';
|
||||
|
@ -32,12 +33,8 @@ const mapStateToProps = state => ({
|
|||
});
|
||||
|
||||
class Explore extends PureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
intl: PropTypes.object.isRequired,
|
||||
multiColumn: PropTypes.bool,
|
||||
isSearching: PropTypes.bool,
|
||||
|
@ -53,7 +50,7 @@ class Explore extends PureComponent {
|
|||
|
||||
render() {
|
||||
const { intl, multiColumn, isSearching } = this.props;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
||||
|
@ -114,4 +111,4 @@ class Explore extends PureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(injectIntl(Explore));
|
||||
export default withIdentity(connect(mapStateToProps)(injectIntl(Explore)));
|
||||
|
|
|
@ -6,13 +6,14 @@ import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
|||
import { Helmet } from 'react-helmet';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { useIdentity } from '@/mastodon/identity_context';
|
||||
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
|
||||
import { addColumn } from 'mastodon/actions/columns';
|
||||
import { changeSetting } from 'mastodon/actions/settings';
|
||||
import { connectPublicStream, connectCommunityStream } from 'mastodon/actions/streaming';
|
||||
import { expandPublicTimeline, expandCommunityTimeline } from 'mastodon/actions/timelines';
|
||||
import { DismissableBanner } from 'mastodon/components/dismissable_banner';
|
||||
import initialState, { domain, enableLocalTimeline } from 'mastodon/initial_state';
|
||||
import { domain, enableLocalTimeline } from 'mastodon/initial_state';
|
||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
|
||||
import Column from '../../components/column';
|
||||
|
@ -24,15 +25,6 @@ const messages = defineMessages({
|
|||
title: { id: 'column.firehose', defaultMessage: 'Live feeds' },
|
||||
});
|
||||
|
||||
// TODO: use a proper React context later on
|
||||
const useIdentity = () => ({
|
||||
signedIn: !!initialState.meta.me,
|
||||
accountId: initialState.meta.me,
|
||||
disabledAccountId: initialState.meta.disabled_account_id,
|
||||
accessToken: initialState.meta.access_token,
|
||||
permissions: initialState.role ? initialState.role.permissions : 0,
|
||||
});
|
||||
|
||||
const ColumnSettings = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const settings = useAppSelector((state) => state.getIn(['settings', 'firehose']));
|
||||
|
|
|
@ -26,6 +26,7 @@ import { fetchFollowRequests } from 'mastodon/actions/accounts';
|
|||
import Column from 'mastodon/components/column';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
import LinkFooter from 'mastodon/features/ui/components/link_footer';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
|
||||
import { dtlTag, enableDtlMenu, me, showTrends } from '../../initial_state';
|
||||
import { NavigationBar } from '../compose/components/navigation_bar';
|
||||
|
@ -80,12 +81,8 @@ const badgeDisplay = (number, limit) => {
|
|||
};
|
||||
|
||||
class GettingStarted extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
intl: PropTypes.object.isRequired,
|
||||
myAccount: ImmutablePropTypes.record,
|
||||
multiColumn: PropTypes.bool,
|
||||
|
@ -96,7 +93,7 @@ class GettingStarted extends ImmutablePureComponent {
|
|||
|
||||
componentDidMount () {
|
||||
const { fetchFollowRequests } = this.props;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
if (!signedIn) {
|
||||
return;
|
||||
|
@ -107,7 +104,7 @@ class GettingStarted extends ImmutablePureComponent {
|
|||
|
||||
render () {
|
||||
const { intl, myAccount, multiColumn, unreadFollowRequests } = this.props;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
const navItems = [];
|
||||
|
||||
|
@ -183,4 +180,4 @@ class GettingStarted extends ImmutablePureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(GettingStarted));
|
||||
export default withIdentity(connect(mapStateToProps, mapDispatchToProps)(injectIntl(GettingStarted)));
|
||||
|
|
|
@ -17,6 +17,7 @@ import { fetchHashtag, followHashtag, unfollowHashtag } from 'mastodon/actions/t
|
|||
import { expandHashtagTimeline, clearTimeline } from 'mastodon/actions/timelines';
|
||||
import Column from 'mastodon/components/column';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
|
||||
import StatusListContainer from '../ui/containers/status_list_container';
|
||||
|
||||
|
@ -29,14 +30,10 @@ const mapStateToProps = (state, props) => ({
|
|||
});
|
||||
|
||||
class HashtagTimeline extends PureComponent {
|
||||
|
||||
disconnects = [];
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
params: PropTypes.object.isRequired,
|
||||
columnId: PropTypes.string,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
|
@ -94,7 +91,7 @@ class HashtagTimeline extends PureComponent {
|
|||
};
|
||||
|
||||
_subscribe (dispatch, id, tags = {}, local) {
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
if (!signedIn) {
|
||||
return;
|
||||
|
@ -168,7 +165,7 @@ class HashtagTimeline extends PureComponent {
|
|||
handleFollow = () => {
|
||||
const { dispatch, params, tag } = this.props;
|
||||
const { id } = params;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
if (!signedIn) {
|
||||
return;
|
||||
|
@ -185,7 +182,7 @@ class HashtagTimeline extends PureComponent {
|
|||
const { hasUnread, columnId, multiColumn, tag } = this.props;
|
||||
const { id, local } = this.props.params;
|
||||
const pinned = !!columnId;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={`#${id}`}>
|
||||
|
@ -225,4 +222,4 @@ class HashtagTimeline extends PureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(HashtagTimeline);
|
||||
export default connect(mapStateToProps)(withIdentity(HashtagTimeline));
|
||||
|
|
|
@ -14,6 +14,7 @@ import { fetchAnnouncements, toggleShowAnnouncements } from 'mastodon/actions/an
|
|||
import { IconWithBadge } from 'mastodon/components/icon_with_badge';
|
||||
import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator';
|
||||
import AnnouncementsContainer from 'mastodon/features/getting_started/containers/announcements_container';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { criticalUpdatesPending } from 'mastodon/initial_state';
|
||||
|
||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||
|
@ -40,12 +41,8 @@ const mapStateToProps = state => ({
|
|||
});
|
||||
|
||||
class HomeTimeline extends PureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hasUnread: PropTypes.bool,
|
||||
|
@ -126,7 +123,7 @@ class HomeTimeline extends PureComponent {
|
|||
render () {
|
||||
const { intl, hasUnread, columnId, multiColumn, hasAnnouncements, unreadAnnouncements, showAnnouncements } = this.props;
|
||||
const pinned = !!columnId;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
const banners = [];
|
||||
|
||||
let announcementsButton;
|
||||
|
@ -190,4 +187,4 @@ class HomeTimeline extends PureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(injectIntl(HomeTimeline));
|
||||
export default connect(mapStateToProps)(withIdentity(injectIntl(HomeTimeline)));
|
||||
|
|
|
@ -223,7 +223,7 @@ class ListTimeline extends PureComponent {
|
|||
<div className='setting-toggle'>
|
||||
<Toggle id={`list-${id}-exclusive`} checked={isExclusive} onChange={this.onExclusiveToggle} />
|
||||
<label htmlFor={`list-${id}-exclusive`} className='setting-toggle__label'>
|
||||
<FormattedMessage id='lists.exclusive' defaultMessage='Hide these posts from home' />
|
||||
<FormattedMessage id='lists.exclusive' defaultMessage='Hide list or antenna account posts from home' />
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -5,6 +5,7 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { enableEmojiReaction } from 'mastodon/initial_state';
|
||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_REPORTS } from 'mastodon/permissions';
|
||||
|
||||
|
@ -13,13 +14,9 @@ import ClearColumnButton from './clear_column_button';
|
|||
import GrantPermissionButton from './grant_permission_button';
|
||||
import SettingToggle from './setting_toggle';
|
||||
|
||||
export default class ColumnSettings extends PureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
class ColumnSettings extends PureComponent {
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
settings: ImmutablePropTypes.map.isRequired,
|
||||
pushSettings: ImmutablePropTypes.map.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
|
@ -258,7 +255,7 @@ export default class ColumnSettings extends PureComponent {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
{((this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) && (
|
||||
{((this.props.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) && (
|
||||
<section role='group' aria-labelledby='notifications-admin-sign-up'>
|
||||
<h3 id='notifications-status'><FormattedMessage id='notifications.column_settings.admin.sign_up' defaultMessage='New sign-ups:' /></h3>
|
||||
|
||||
|
@ -271,7 +268,7 @@ export default class ColumnSettings extends PureComponent {
|
|||
</section>
|
||||
)}
|
||||
|
||||
{((this.context.identity.permissions & PERMISSION_MANAGE_REPORTS) === PERMISSION_MANAGE_REPORTS) && (
|
||||
{((this.props.identity.permissions & PERMISSION_MANAGE_REPORTS) === PERMISSION_MANAGE_REPORTS) && (
|
||||
<section role='group' aria-labelledby='notifications-admin-report'>
|
||||
<h3 id='notifications-status'><FormattedMessage id='notifications.column_settings.admin.report' defaultMessage='New reports:' /></h3>
|
||||
|
||||
|
@ -288,3 +285,5 @@ export default class ColumnSettings extends PureComponent {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
export default withIdentity(ColumnSettings);
|
||||
|
|
|
@ -41,13 +41,13 @@ const messages = defineMessages({
|
|||
poll: { id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' },
|
||||
reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your status' },
|
||||
status: { id: 'notification.status', defaultMessage: '{name} just posted' },
|
||||
listStatus: { id: 'notification.list_status', defaultMessage: '{name} post is added on {listName}' },
|
||||
statusReference: { id: 'notification.status_reference', defaultMessage: '{name} refered your post' },
|
||||
listStatus: { id: 'notification.list_status', defaultMessage: '{name} post is added to {listName}' },
|
||||
statusReference: { id: 'notification.status_reference', defaultMessage: '{name} quoted your post' },
|
||||
update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
|
||||
adminSignUp: { id: 'notification.admin.sign_up', defaultMessage: '{name} signed up' },
|
||||
adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' },
|
||||
relationshipsSevered: { id: 'notification.relationships_severance_event', defaultMessage: 'Lost connections with {name}' },
|
||||
moderationWarning: { id: 'notification.moderation_warning', defaultMessage: 'Your have received a moderation warning' },
|
||||
moderationWarning: { id: 'notification.moderation_warning', defaultMessage: 'You have received a moderation warning' },
|
||||
});
|
||||
|
||||
const notificationForScreenReader = (intl, message, timestamp) => {
|
||||
|
@ -305,7 +305,7 @@ class Notification extends ImmutablePureComponent {
|
|||
</div>
|
||||
|
||||
<span title={notification.get('created_at')}>
|
||||
<FormattedMessage id='notification.status_reference' defaultMessage='{name} referenced your post' values={{ name: link }} />
|
||||
<FormattedMessage id='notification.status_reference' defaultMessage='{name} quoted your post' values={{ name: link }} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -40,12 +40,12 @@ const mapDispatchToProps = dispatch => ({
|
|||
},
|
||||
|
||||
onModalReblog (status, privacy) {
|
||||
dispatch(reblog(status, privacy));
|
||||
dispatch(reblog({ statusId: status.get('id'), visibility: privacy }));
|
||||
},
|
||||
|
||||
onReblog (status, e) {
|
||||
if (status.get('reblogged')) {
|
||||
dispatch(unreblog(status));
|
||||
dispatch(unreblog({ statusId: status.get('id') }));
|
||||
} else {
|
||||
if (e.shiftKey || !boostModal) {
|
||||
this.onModalReblog(status);
|
||||
|
|
|
@ -17,6 +17,7 @@ import NotificationsIcon from '@/material-icons/400-24px/notifications-fill.svg?
|
|||
import { compareId } from 'mastodon/compare_id';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
|
||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||
import { submitMarkers } from '../../actions/markers';
|
||||
|
@ -77,12 +78,8 @@ const mapStateToProps = state => ({
|
|||
});
|
||||
|
||||
class Notifications extends PureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
identity: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
columnId: PropTypes.string,
|
||||
notifications: ImmutablePropTypes.list.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
|
@ -190,7 +187,7 @@ class Notifications extends PureComponent {
|
|||
const { intl, notifications, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, lastReadId, canMarkAsRead, needsNotificationPermission } = this.props;
|
||||
const pinned = !!columnId;
|
||||
const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. When other people interact with you, you will see it here." />;
|
||||
const { signedIn } = this.context.identity;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
let scrollableContent = null;
|
||||
|
||||
|
@ -299,4 +296,4 @@ class Notifications extends PureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(injectIntl(Notifications));
|
||||
export default connect(mapStateToProps)(withIdentity(injectIntl(Notifications)));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue