Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a0f7453c6e | ||
|
46a1e16f21 | ||
|
f3f7a3840a | ||
|
7539254e96 | ||
|
456478c4e1 |
64
.babelrc
@@ -1,65 +1,7 @@
|
||||
{
|
||||
"presets": [
|
||||
"react",
|
||||
[
|
||||
"env",
|
||||
{
|
||||
"loose": true,
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"browsers": ["last 2 versions", "IE >= 11", "iOS >= 9"]
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"presets": ["es2015", "react"],
|
||||
"plugins": [
|
||||
"syntax-dynamic-import",
|
||||
["transform-object-rest-spread", { "useBuiltIns": true }],
|
||||
"transform-decorators-legacy",
|
||||
"transform-class-properties",
|
||||
[
|
||||
"react-intl",
|
||||
{
|
||||
"messagesDir": "./build/messages"
|
||||
}
|
||||
],
|
||||
"preval"
|
||||
],
|
||||
"env": {
|
||||
"development": {
|
||||
"plugins": [
|
||||
"transform-react-jsx-source",
|
||||
"transform-react-jsx-self"
|
||||
]
|
||||
},
|
||||
"production": {
|
||||
"plugins": [
|
||||
"lodash",
|
||||
[
|
||||
"transform-react-remove-prop-types",
|
||||
{
|
||||
"mode": "remove",
|
||||
"removeImport": true,
|
||||
"additionalLibraries": [
|
||||
"react-immutable-proptypes"
|
||||
]
|
||||
}
|
||||
],
|
||||
"transform-react-inline-elements",
|
||||
[
|
||||
"transform-runtime",
|
||||
{
|
||||
"helpers": true,
|
||||
"polyfill": false,
|
||||
"regenerator": false
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"test": {
|
||||
"plugins": [
|
||||
"transform-es2015-modules-commonjs"
|
||||
]
|
||||
}
|
||||
}
|
||||
"transform-object-rest-spread"
|
||||
]
|
||||
}
|
||||
|
@@ -1,3 +1,2 @@
|
||||
https://github.com/heroku/heroku-buildpack-apt
|
||||
https://github.com/Scalingo/nodejs-buildpack
|
||||
https://github.com/Scalingo/ruby-buildpack
|
||||
|
@@ -1,21 +1,14 @@
|
||||
engines:
|
||||
brakeman:
|
||||
enabled: true
|
||||
bundler-audit:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: false
|
||||
eslint:
|
||||
enabled: true
|
||||
rubocop:
|
||||
enabled: true
|
||||
scss-lint:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: false
|
||||
rubocop:
|
||||
enabled: true
|
||||
eslint:
|
||||
enabled: true
|
||||
ratings:
|
||||
paths:
|
||||
- "**.rb"
|
||||
- "**.js"
|
||||
- "**.scss"
|
||||
paths:
|
||||
- "**.rb"
|
||||
- "**.js"
|
||||
exclude_paths:
|
||||
- spec/
|
||||
- vendor/asset
|
||||
|
@@ -2,12 +2,10 @@
|
||||
.env.*
|
||||
public/system
|
||||
public/assets
|
||||
public/packs
|
||||
node_modules
|
||||
storybook
|
||||
neo4j
|
||||
vendor/bundle
|
||||
.DS_Store
|
||||
*.swp
|
||||
*~
|
||||
postgres
|
||||
redis
|
||||
|
111
.env.nanobox
@@ -1,111 +0,0 @@
|
||||
# Service dependencies
|
||||
# You may set REDIS_URL instead for more advanced options
|
||||
REDIS_HOST=$DATA_REDIS_HOST
|
||||
REDIS_PORT=6379
|
||||
# REDIS_DB=0
|
||||
|
||||
# You may set DATABASE_URL instead for more advanced options
|
||||
DB_HOST=$DATA_DB_HOST
|
||||
DB_USER=$DATA_DB_USER
|
||||
DB_NAME=gonano
|
||||
DB_PASS=$DATA_DB_PASS
|
||||
DB_PORT=5432
|
||||
|
||||
DATABASE_URL=postgresql://$DATA_DB_USER:$DATA_DB_PASS@$DATA_DB_HOST/gonano
|
||||
|
||||
# Federation
|
||||
# Note: Changing LOCAL_DOMAIN or LOCAL_HTTPS at a later time will cause unwanted side effects.
|
||||
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
|
||||
LOCAL_DOMAIN=${APP_NAME}.nanoapp.io
|
||||
LOCAL_HTTPS=false
|
||||
|
||||
# Use this only if you need to run mastodon on a different domain than the one used for federation.
|
||||
# You can read more about this option on https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Serving_a_different_domain.md
|
||||
# DO *NOT* USE THIS UNLESS YOU KNOW *EXACTLY* WHAT YOU ARE DOING.
|
||||
# WEB_DOMAIN=mastodon.example.com
|
||||
|
||||
# Use this if you want to have several aliases handler@example1.com
|
||||
# handler@example2.com etc. for the same user. LOCAL_DOMAIN should not
|
||||
# be added. Comma separated values
|
||||
# ALTERNATE_DOMAINS=example1.com,example2.com
|
||||
|
||||
# Application secrets
|
||||
# Generate each with the `rake secret` task (`nanobox run bundle exec rake secret`)
|
||||
PAPERCLIP_SECRET=$PAPERCLIP_SECRET
|
||||
SECRET_KEY_BASE=$SECRET_KEY_BASE
|
||||
OTP_SECRET=$OTP_SECRET
|
||||
|
||||
# Registrations
|
||||
# Single user mode will disable registrations and redirect frontpage to the first profile
|
||||
# SINGLE_USER_MODE=true
|
||||
# Prevent registrations with following e-mail domains
|
||||
# EMAIL_DOMAIN_BLACKLIST=example1.com|example2.de|etc
|
||||
# Only allow registrations with the following e-mail domains
|
||||
# EMAIL_DOMAIN_WHITELIST=example1.com|example2.de|etc
|
||||
|
||||
# Optionally change default language
|
||||
# DEFAULT_LOCALE=de
|
||||
|
||||
# E-mail configuration
|
||||
# Note: Mailgun and SparkPost (https://sparkpo.st/smtp) each have good free tiers
|
||||
# If you want to use an SMTP server without authentication (e.g local Postfix relay)
|
||||
# then set SMTP_AUTH_METHOD and SMTP_OPENSSL_VERIFY_MODE to 'none' and
|
||||
# *comment* SMTP_LOGIN and SMTP_PASSWORD (leaving them blank is not enough).
|
||||
SMTP_SERVER=$SMTP_SERVER
|
||||
SMTP_PORT=587
|
||||
SMTP_LOGIN=$SMTP_LOGIN
|
||||
SMTP_PASSWORD=$SMTP_PASSWORD
|
||||
SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
|
||||
#SMTP_DOMAIN= # defaults to LOCAL_DOMAIN
|
||||
#SMTP_DELIVERY_METHOD=smtp # delivery method can also be sendmail
|
||||
#SMTP_AUTH_METHOD=plain
|
||||
#SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt
|
||||
#SMTP_OPENSSL_VERIFY_MODE=peer
|
||||
#SMTP_ENABLE_STARTTLS_AUTO=true
|
||||
|
||||
|
||||
# Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files.
|
||||
# PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system
|
||||
# PAPERCLIP_ROOT_URL=/system
|
||||
|
||||
# Optional asset host for multi-server setups
|
||||
# CDN_HOST=https://assets.example.com
|
||||
|
||||
# S3 (optional)
|
||||
# S3_ENABLED=true
|
||||
# S3_BUCKET=
|
||||
# AWS_ACCESS_KEY_ID=
|
||||
# AWS_SECRET_ACCESS_KEY=
|
||||
# S3_REGION=
|
||||
# S3_PROTOCOL=http
|
||||
# S3_HOSTNAME=192.168.1.123:9000
|
||||
|
||||
# S3 (Minio Config (optional) Please check Minio instance for details)
|
||||
# S3_ENABLED=true
|
||||
# S3_BUCKET=
|
||||
# AWS_ACCESS_KEY_ID=
|
||||
# AWS_SECRET_ACCESS_KEY=
|
||||
# S3_REGION=
|
||||
# S3_PROTOCOL=https
|
||||
# S3_HOSTNAME=
|
||||
# S3_ENDPOINT=
|
||||
# S3_SIGNATURE_VERSION=
|
||||
|
||||
# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
|
||||
# S3_CLOUDFRONT_HOST=
|
||||
|
||||
# Streaming API integration
|
||||
# STREAMING_API_BASE_URL=
|
||||
|
||||
# Advanced settings
|
||||
# If you need to use pgBouncer, you need to disable prepared statements:
|
||||
# PREPARED_STATEMENTS=false
|
||||
|
||||
# Cluster number setting for streaming API server.
|
||||
# If you comment out following line, cluster number will be `numOfCpuCores - 1`.
|
||||
STREAMING_CLUSTER_NUM=1
|
||||
|
||||
# Docker mastodon user
|
||||
# If you use Docker, you may want to assign UID/GID manually.
|
||||
# UID=1000
|
||||
# GID=1000
|
@@ -1,8 +1,7 @@
|
||||
# Service dependencies
|
||||
# You may set REDIS_URL instead for more advanced options
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
# You may set DATABASE_URL instead for more advanced options
|
||||
# REDIS_DB=0
|
||||
DB_HOST=db
|
||||
DB_USER=postgres
|
||||
DB_NAME=postgres
|
||||
@@ -10,38 +9,19 @@ DB_PASS=
|
||||
DB_PORT=5432
|
||||
|
||||
# Federation
|
||||
# Note: Changing LOCAL_DOMAIN or LOCAL_HTTPS at a later time will cause unwanted side effects.
|
||||
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
|
||||
LOCAL_DOMAIN=example.com
|
||||
LOCAL_DOMAIN=example.com
|
||||
LOCAL_HTTPS=true
|
||||
|
||||
# Use this only if you need to run mastodon on a different domain than the one used for federation.
|
||||
# You can read more about this option on https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Serving_a_different_domain.md
|
||||
# DO *NOT* USE THIS UNLESS YOU KNOW *EXACTLY* WHAT YOU ARE DOING.
|
||||
# Do not use this unless you know exactly what you are doing.
|
||||
# WEB_DOMAIN=mastodon.example.com
|
||||
|
||||
# Use this if you want to have several aliases handler@example1.com
|
||||
# handler@example2.com etc. for the same user. LOCAL_DOMAIN should not
|
||||
# be added. Comma separated values
|
||||
# ALTERNATE_DOMAINS=example1.com,example2.com
|
||||
|
||||
# Application secrets
|
||||
# Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose)
|
||||
# Generate each with the `rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose)
|
||||
PAPERCLIP_SECRET=
|
||||
SECRET_KEY_BASE=
|
||||
OTP_SECRET=
|
||||
|
||||
# VAPID keys (used for push notifications
|
||||
# You can generate the keys using the following command (first is the private key, second is the public one)
|
||||
# You should only generate this once per instance. If you later decide to change it, all push subscription will
|
||||
# be invalidated, requiring the users to access the website again to resubscribe.
|
||||
#
|
||||
# Generate with `RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose)
|
||||
#
|
||||
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
|
||||
VAPID_PRIVATE_KEY=
|
||||
VAPID_PUBLIC_KEY=
|
||||
|
||||
# Registrations
|
||||
# Single user mode will disable registrations and redirect frontpage to the first profile
|
||||
# SINGLE_USER_MODE=true
|
||||
@@ -56,8 +36,8 @@ VAPID_PUBLIC_KEY=
|
||||
# E-mail configuration
|
||||
# Note: Mailgun and SparkPost (https://sparkpo.st/smtp) each have good free tiers
|
||||
# If you want to use an SMTP server without authentication (e.g local Postfix relay)
|
||||
# then set SMTP_AUTH_METHOD and SMTP_OPENSSL_VERIFY_MODE to 'none' and
|
||||
# *comment* SMTP_LOGIN and SMTP_PASSWORD (leaving them blank is not enough).
|
||||
# then set SMTP_AUTH_METHOD to 'none' and *comment* SMTP_LOGIN and SMTP_PASSWORD.
|
||||
# Leaving them blank is not enough for authentication method 'none'.
|
||||
SMTP_SERVER=smtp.mailgun.org
|
||||
SMTP_PORT=587
|
||||
SMTP_LOGIN=
|
||||
@@ -66,17 +46,16 @@ SMTP_FROM_ADDRESS=notifications@example.com
|
||||
#SMTP_DOMAIN= # defaults to LOCAL_DOMAIN
|
||||
#SMTP_DELIVERY_METHOD=smtp # delivery method can also be sendmail
|
||||
#SMTP_AUTH_METHOD=plain
|
||||
#SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt
|
||||
#SMTP_OPENSSL_VERIFY_MODE=peer
|
||||
#SMTP_ENABLE_STARTTLS_AUTO=true
|
||||
#SMTP_TLS=true
|
||||
|
||||
|
||||
# Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files.
|
||||
# PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system
|
||||
# PAPERCLIP_ROOT_URL=/system
|
||||
|
||||
# Optional asset host for multi-server setups
|
||||
# CDN_HOST=https://assets.example.com
|
||||
# CDN_HOST=assets.example.com
|
||||
|
||||
# S3 (optional)
|
||||
# S3_ENABLED=true
|
||||
@@ -98,23 +77,6 @@ SMTP_FROM_ADDRESS=notifications@example.com
|
||||
# S3_ENDPOINT=
|
||||
# S3_SIGNATURE_VERSION=
|
||||
|
||||
# Swift (optional)
|
||||
# SWIFT_ENABLED=true
|
||||
# SWIFT_USERNAME=
|
||||
# For Keystone V3, the value for SWIFT_TENANT should be the project name
|
||||
# SWIFT_TENANT=
|
||||
# SWIFT_PASSWORD=
|
||||
# Keystone V2 and V3 URLs are supported. Use a V3 URL if possible to avoid
|
||||
# issues with token rate-limiting during high load.
|
||||
# SWIFT_AUTH_URL=
|
||||
# SWIFT_CONTAINER=
|
||||
# SWIFT_OBJECT_URL=
|
||||
# SWIFT_REGION=
|
||||
# Defaults to 'default'
|
||||
# SWIFT_DOMAIN_NAME=
|
||||
# Defaults to 60 seconds. Set to 0 to disable
|
||||
# SWIFT_CACHE_TTL=
|
||||
|
||||
# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
|
||||
# S3_CLOUDFRONT_HOST=
|
||||
|
||||
@@ -128,8 +90,3 @@ SMTP_FROM_ADDRESS=notifications@example.com
|
||||
# Cluster number setting for streaming API server.
|
||||
# If you comment out following line, cluster number will be `numOfCpuCores - 1`.
|
||||
STREAMING_CLUSTER_NUM=1
|
||||
|
||||
# Docker mastodon user
|
||||
# If you use Docker, you may want to assign UID/GID manually.
|
||||
# UID=1000
|
||||
# GID=1000
|
||||
|
79
.eslintrc.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": false,
|
||||
"es6": true
|
||||
},
|
||||
|
||||
"parser": "babel-eslint",
|
||||
|
||||
"plugins": [
|
||||
"react",
|
||||
"jsx-a11y"
|
||||
],
|
||||
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
|
||||
"ecmaFeatures": {
|
||||
"arrowFunctions": true,
|
||||
"jsx": true,
|
||||
"destructuring": true,
|
||||
"modules": true,
|
||||
"spread": true
|
||||
}
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"no-cond-assign": 2,
|
||||
"no-console": 1,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-unreachable": 2,
|
||||
"valid-typeof": 2,
|
||||
"consistent-return": 2,
|
||||
"dot-notation": 2,
|
||||
"eqeqeq": 2,
|
||||
"no-fallthrough": 2,
|
||||
"no-unused-expressions": 2,
|
||||
"strict": 0,
|
||||
"no-catch-shadow": 2,
|
||||
"indent": [1, 2],
|
||||
"brace-style": 1,
|
||||
"comma-spacing": [1, {"before": false, "after": true}],
|
||||
"comma-style": [1, "last"],
|
||||
"no-mixed-spaces-and-tabs": 1,
|
||||
"no-nested-ternary": 1,
|
||||
"no-trailing-spaces": 1,
|
||||
|
||||
"react/jsx-wrap-multilines": 2,
|
||||
"react/self-closing-comp": 2,
|
||||
"react/prop-types": 2,
|
||||
"react/no-multi-comp": 0,
|
||||
|
||||
"jsx-a11y/accessible-emoji": 1,
|
||||
"jsx-a11y/anchor-has-content": 1,
|
||||
"jsx-a11y/aria-activedescendant-has-tabindex": 1,
|
||||
"jsx-a11y/aria-props": 1,
|
||||
"jsx-a11y/aria-proptypes": 1,
|
||||
"jsx-a11y/aria-role": 1,
|
||||
"jsx-a11y/aria-unsupported-elements": 1,
|
||||
"jsx-a11y/heading-has-content": 1,
|
||||
"jsx-a11y/href-no-hash": 1,
|
||||
"jsx-a11y/html-has-lang": 1,
|
||||
"jsx-a11y/iframe-has-title": 1,
|
||||
"jsx-a11y/img-has-alt": 1,
|
||||
"jsx-a11y/img-redundant-alt": 1,
|
||||
"jsx-a11y/label-has-for": 1,
|
||||
"jsx-a11y/mouse-events-have-key-events": 1,
|
||||
"jsx-a11y/no-access-key": 1,
|
||||
"jsx-a11y/no-distracting-elements": 1,
|
||||
"jsx-a11y/no-onchange": 1,
|
||||
"jsx-a11y/no-redundant-roles": 1,
|
||||
"jsx-a11y/onclick-has-focus": 1,
|
||||
"jsx-a11y/onclick-has-role": 1,
|
||||
"jsx-a11y/role-has-required-aria-props": 1,
|
||||
"jsx-a11y/role-supports-aria-props": 1,
|
||||
"jsx-a11y/scope": 1,
|
||||
"jsx-a11y/tabindex-no-positive": 1
|
||||
}
|
||||
}
|
127
.eslintrc.yml
@@ -1,127 +0,0 @@
|
||||
---
|
||||
root: true
|
||||
|
||||
env:
|
||||
browser: true
|
||||
node: true
|
||||
es6: true
|
||||
|
||||
parser: babel-eslint
|
||||
|
||||
plugins:
|
||||
- react
|
||||
- jsx-a11y
|
||||
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
ecmaFeatures:
|
||||
arrowFunctions: true
|
||||
jsx: true
|
||||
destructuring: true
|
||||
modules: true
|
||||
spread: true
|
||||
|
||||
rules:
|
||||
|
||||
brace-style: warn
|
||||
comma-dangle:
|
||||
- error
|
||||
- always-multiline
|
||||
comma-spacing:
|
||||
- warn
|
||||
- before: false
|
||||
after: true
|
||||
comma-style:
|
||||
- warn
|
||||
- last
|
||||
consistent-return: error
|
||||
dot-notation: error
|
||||
eqeqeq: error
|
||||
indent:
|
||||
- warn
|
||||
- 2
|
||||
jsx-quotes:
|
||||
- error
|
||||
- prefer-single
|
||||
no-catch-shadow: error
|
||||
no-cond-assign: error
|
||||
no-console:
|
||||
- warn
|
||||
- allow:
|
||||
- error
|
||||
- warn
|
||||
no-fallthrough: error
|
||||
no-irregular-whitespace: error
|
||||
no-mixed-spaces-and-tabs: warn
|
||||
no-nested-ternary: warn
|
||||
no-trailing-spaces: warn
|
||||
no-undef: error
|
||||
no-unreachable: error
|
||||
no-unused-expressions: error
|
||||
no-unused-vars:
|
||||
- error
|
||||
- vars: all
|
||||
args: after-used
|
||||
ignoreRestSiblings: true
|
||||
object-curly-spacing:
|
||||
- error
|
||||
- always
|
||||
padded-blocks:
|
||||
- error
|
||||
- classes: always
|
||||
quotes:
|
||||
- error
|
||||
- single
|
||||
semi: error
|
||||
strict: off
|
||||
valid-typeof: error
|
||||
|
||||
react/jsx-boolean-value: error
|
||||
react/jsx-closing-bracket-location:
|
||||
- error
|
||||
- line-aligned
|
||||
react/jsx-curly-spacing: error
|
||||
react/jsx-equals-spacing: error
|
||||
react/jsx-first-prop-new-line:
|
||||
- error
|
||||
- multiline-multiprop
|
||||
react/jsx-indent:
|
||||
- error
|
||||
- 2
|
||||
react/jsx-no-bind: error
|
||||
react/jsx-no-duplicate-props: error
|
||||
react/jsx-no-undef: error
|
||||
react/jsx-tag-spacing: error
|
||||
react/jsx-uses-react: error
|
||||
react/jsx-uses-vars: error
|
||||
react/jsx-wrap-multilines: error
|
||||
react/no-multi-comp: off
|
||||
react/no-string-refs: error
|
||||
react/prop-types: error
|
||||
react/self-closing-comp: error
|
||||
|
||||
jsx-a11y/accessible-emoji: warn
|
||||
jsx-a11y/anchor-has-content: warn
|
||||
jsx-a11y/aria-activedescendant-has-tabindex: warn
|
||||
jsx-a11y/aria-props: warn
|
||||
jsx-a11y/aria-proptypes: warn
|
||||
jsx-a11y/aria-role: warn
|
||||
jsx-a11y/aria-unsupported-elements: warn
|
||||
jsx-a11y/heading-has-content: warn
|
||||
jsx-a11y/href-no-hash: warn
|
||||
jsx-a11y/html-has-lang: warn
|
||||
jsx-a11y/iframe-has-title: warn
|
||||
jsx-a11y/img-has-alt: warn
|
||||
jsx-a11y/img-redundant-alt: warn
|
||||
jsx-a11y/label-has-for: off
|
||||
jsx-a11y/mouse-events-have-key-events: warn
|
||||
jsx-a11y/no-access-key: warn
|
||||
jsx-a11y/no-distracting-elements: warn
|
||||
jsx-a11y/no-onchange: warn
|
||||
jsx-a11y/no-redundant-roles: warn
|
||||
jsx-a11y/onclick-has-focus: warn
|
||||
jsx-a11y/onclick-has-role: warn
|
||||
jsx-a11y/role-has-required-aria-props: warn
|
||||
jsx-a11y/role-supports-aria-props: off
|
||||
jsx-a11y/scope: warn
|
||||
jsx-a11y/tabindex-no-positive: warn
|
14
.gitattributes
vendored
@@ -1,14 +0,0 @@
|
||||
* text=auto eol=lf
|
||||
*.eot -text
|
||||
*.gif -text
|
||||
*.gz -text
|
||||
*.ico -text
|
||||
*.jpg -text
|
||||
*.mp3 -text
|
||||
*.ogg -text
|
||||
*.png -text
|
||||
*.ttf -text
|
||||
*.webm -text
|
||||
*.woff -text
|
||||
*.woff2 -text
|
||||
spec/fixtures/requests/** -text !eol
|
16
.gitignore
vendored
@@ -19,12 +19,10 @@
|
||||
coverage
|
||||
public/system
|
||||
public/assets
|
||||
public/packs
|
||||
public/packs-test
|
||||
.env
|
||||
.env.production
|
||||
node_modules/
|
||||
build/
|
||||
neo4j/
|
||||
|
||||
# Ignore Vagrant files
|
||||
.vagrant/
|
||||
@@ -34,7 +32,6 @@ config/deploy/*
|
||||
|
||||
# Ignore IDE files
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# Ignore postgres + redis volume optionally created by docker-compose
|
||||
postgres
|
||||
@@ -46,14 +43,3 @@ redis
|
||||
# Ignore vim files
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# Ignore npm debug log
|
||||
npm-debug.log
|
||||
|
||||
# Ignore yarn log files
|
||||
yarn-error.log
|
||||
yarn-debug.log
|
||||
|
||||
# Ignore Docker option files
|
||||
docker-compose.override.yml
|
||||
|
||||
|
108
.haml-lint.yml
@@ -1,108 +0,0 @@
|
||||
# Whether to ignore frontmatter at the beginning of HAML documents for
|
||||
# frameworks such as Jekyll/Middleman
|
||||
skip_frontmatter: false
|
||||
|
||||
exclude:
|
||||
- 'vendor/**/*'
|
||||
- 'spec/**/*'
|
||||
- 'lib/templates/**/*'
|
||||
- 'app/views/kaminari/**/*'
|
||||
|
||||
linters:
|
||||
AltText:
|
||||
enabled: false
|
||||
|
||||
ClassAttributeWithStaticValue:
|
||||
enabled: true
|
||||
|
||||
ClassesBeforeIds:
|
||||
enabled: true
|
||||
|
||||
ConsecutiveComments:
|
||||
enabled: true
|
||||
|
||||
ConsecutiveSilentScripts:
|
||||
enabled: true
|
||||
max_consecutive: 2
|
||||
|
||||
EmptyObjectReference:
|
||||
enabled: true
|
||||
|
||||
EmptyScript:
|
||||
enabled: true
|
||||
|
||||
FinalNewline:
|
||||
enabled: true
|
||||
present: true
|
||||
|
||||
HtmlAttributes:
|
||||
enabled: true
|
||||
|
||||
ImplicitDiv:
|
||||
enabled: true
|
||||
|
||||
LeadingCommentSpace:
|
||||
enabled: true
|
||||
|
||||
LineLength:
|
||||
enabled: false
|
||||
max: 80
|
||||
|
||||
MultilinePipe:
|
||||
enabled: true
|
||||
|
||||
MultilineScript:
|
||||
enabled: true
|
||||
|
||||
ObjectReferenceAttributes:
|
||||
enabled: true
|
||||
|
||||
RuboCop:
|
||||
enabled: true
|
||||
# These cops are incredibly noisy when it comes to HAML templates, so we
|
||||
# ignore them.
|
||||
ignored_cops:
|
||||
- Lint/BlockAlignment
|
||||
- Lint/EndAlignment
|
||||
- Lint/Void
|
||||
- Metrics/BlockLength
|
||||
- Metrics/LineLength
|
||||
- Style/AlignParameters
|
||||
- Style/BlockNesting
|
||||
- Style/ElseAlignment
|
||||
- Style/EndOfLine
|
||||
- Style/FileName
|
||||
- Style/FinalNewline
|
||||
- Style/FrozenStringLiteralComment
|
||||
- Style/IfUnlessModifier
|
||||
- Style/IndentationWidth
|
||||
- Style/Next
|
||||
- Style/TrailingBlankLines
|
||||
- Style/TrailingWhitespace
|
||||
- Style/WhileUntilModifier
|
||||
|
||||
RubyComments:
|
||||
enabled: true
|
||||
|
||||
SpaceBeforeScript:
|
||||
enabled: true
|
||||
|
||||
SpaceInsideHashAttributes:
|
||||
enabled: true
|
||||
style: space
|
||||
|
||||
Indentation:
|
||||
enabled: true
|
||||
character: space # or tab
|
||||
|
||||
TagName:
|
||||
enabled: true
|
||||
|
||||
TrailingWhitespace:
|
||||
enabled: true
|
||||
|
||||
UnnecessaryInterpolation:
|
||||
enabled: true
|
||||
|
||||
UnnecessaryStringOutput:
|
||||
enabled: true
|
19
.nanoignore
@@ -1,19 +0,0 @@
|
||||
.DS_Store
|
||||
.git/
|
||||
.gitignore
|
||||
|
||||
.bundle/
|
||||
.cache/
|
||||
config/deploy/*
|
||||
coverage
|
||||
docs/
|
||||
.env
|
||||
log/*.log
|
||||
neo4j/
|
||||
node_modules/
|
||||
public/assets/
|
||||
public/system/
|
||||
spec/
|
||||
tmp/
|
||||
.vagrant/
|
||||
vendor/bundle/
|
@@ -1,9 +0,0 @@
|
||||
plugins:
|
||||
postcss-smart-import: {}
|
||||
precss: {}
|
||||
autoprefixer:
|
||||
browsers:
|
||||
- last 2 versions
|
||||
- IE >= 11
|
||||
- iOS >= 9
|
||||
postcss-object-fit-images: {}
|
1
.profile
@@ -1 +0,0 @@
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/app/.apt/lib/x86_64-linux-gnu:/app/.apt/usr/lib/x86_64-linux-gnu/mesa:/app/.apt/usr/lib/x86_64-linux-gnu/pulseaudio
|
117
.rubocop.yml
@@ -1,46 +1,14 @@
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.3
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- 'db/**/*'
|
||||
- 'app/views/**/*'
|
||||
- 'config/**/*'
|
||||
- 'bin/*'
|
||||
- 'Rakefile'
|
||||
- 'node_modules/**/*'
|
||||
- 'Vagrantfile'
|
||||
- 'vendor/**/*'
|
||||
- 'lib/json_ld/*'
|
||||
Rails:
|
||||
Enabled: true
|
||||
|
||||
Bundler/OrderedGems:
|
||||
Style/PerlBackrefs:
|
||||
AutoCorrect: false
|
||||
|
||||
Style/ClassAndModuleChildren:
|
||||
Enabled: false
|
||||
|
||||
Layout/AccessModifierIndentation:
|
||||
EnforcedStyle: indent
|
||||
|
||||
Layout/EmptyLineAfterMagicComment:
|
||||
Enabled: false
|
||||
|
||||
Layout/SpaceInsideHashLiteralBraces:
|
||||
EnforcedStyle: space
|
||||
|
||||
Metrics/AbcSize:
|
||||
Max: 100
|
||||
|
||||
Metrics/BlockLength:
|
||||
Max: 35
|
||||
Exclude:
|
||||
- 'lib/tasks/**/*'
|
||||
|
||||
Metrics/BlockNesting:
|
||||
Max: 3
|
||||
|
||||
Metrics/ClassLength:
|
||||
CountComments: false
|
||||
Max: 300
|
||||
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 25
|
||||
Max: 2
|
||||
|
||||
Metrics/LineLength:
|
||||
AllowURI: true
|
||||
@@ -48,30 +16,37 @@ Metrics/LineLength:
|
||||
|
||||
Metrics/MethodLength:
|
||||
CountComments: false
|
||||
Max: 10
|
||||
|
||||
Metrics/AbcSize:
|
||||
Max: 100
|
||||
|
||||
Metrics/BlockNesting:
|
||||
Max: 3
|
||||
|
||||
Metrics/ClassLength:
|
||||
CountComments: false
|
||||
Max: 200
|
||||
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 15
|
||||
|
||||
Metrics/MethodLength:
|
||||
Max: 55
|
||||
|
||||
Metrics/ModuleLength:
|
||||
CountComments: false
|
||||
Max: 200
|
||||
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 10
|
||||
|
||||
Metrics/ParameterLists:
|
||||
Max: 5
|
||||
Max: 4
|
||||
CountKeywordArgs: true
|
||||
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 20
|
||||
|
||||
Rails:
|
||||
Enabled: true
|
||||
|
||||
Rails/HasAndBelongsToMany:
|
||||
Enabled: false
|
||||
|
||||
Rails/SkipsModelValidations:
|
||||
Enabled: false
|
||||
|
||||
Style/ClassAndModuleChildren:
|
||||
Enabled: false
|
||||
Style/AccessModifierIndentation:
|
||||
EnforcedStyle: indent
|
||||
|
||||
Style/CollectionMethods:
|
||||
Enabled: true
|
||||
@@ -87,25 +62,29 @@ Style/DoubleNegation:
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: true
|
||||
|
||||
Style/GuardClause:
|
||||
Style/SpaceInsideHashLiteralBraces:
|
||||
EnforcedStyle: space
|
||||
|
||||
Style/TrailingCommaInLiteral:
|
||||
EnforcedStyleForMultiline: 'comma'
|
||||
|
||||
Style/RegexpLiteral:
|
||||
Enabled: false
|
||||
|
||||
Style/Lambda:
|
||||
Enabled: false
|
||||
|
||||
Style/PercentLiteralDelimiters:
|
||||
PreferredDelimiters:
|
||||
'%i': '()'
|
||||
'%w': '()'
|
||||
|
||||
Style/PerlBackrefs:
|
||||
AutoCorrect: false
|
||||
|
||||
Style/RegexpLiteral:
|
||||
Rails/HasAndBelongsToMany:
|
||||
Enabled: false
|
||||
|
||||
Style/SymbolArray:
|
||||
Enabled: false
|
||||
|
||||
Style/TrailingCommaInLiteral:
|
||||
EnforcedStyleForMultiline: 'comma'
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.3
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- 'db/**/*'
|
||||
- 'app/views/**/*'
|
||||
- 'config/**/*'
|
||||
- 'bin/*'
|
||||
- 'Rakefile'
|
||||
- 'node_modules/**/*'
|
||||
- 'Vagrantfile'
|
||||
|
264
.scss-lint.yml
@@ -1,264 +0,0 @@
|
||||
# Linter Documentation:
|
||||
# https://github.com/brigade/scss-lint/blob/v0.42.2/lib/scss_lint/linter/README.md
|
||||
|
||||
scss_files: 'app/javascript/styles/**/*.scss'
|
||||
|
||||
exclude:
|
||||
- app/javascript/styles/reset.scss
|
||||
|
||||
linters:
|
||||
# Reports when you use improper spacing around ! (the "bang") in !default,
|
||||
# !global, !important, and !optional flags.
|
||||
BangFormat:
|
||||
enabled: false
|
||||
|
||||
# Whether or not to prefer `border: 0` over `border: none`.
|
||||
BorderZero:
|
||||
enabled: false
|
||||
|
||||
# Reports when you define a rule set using a selector with chained classes
|
||||
# (a.k.a. adjoining classes).
|
||||
ChainedClasses:
|
||||
enabled: false
|
||||
|
||||
# Prefer hexadecimal color codes over color keywords.
|
||||
# (e.g. `color: green` is a color keyword)
|
||||
ColorKeyword:
|
||||
enabled: false
|
||||
|
||||
# Prefer color literals (keywords or hexadecimal codes) to be used only in
|
||||
# variable declarations. They should be referred to via variables everywhere
|
||||
# else.
|
||||
ColorVariable:
|
||||
enabled: true
|
||||
|
||||
# Which form of comments to prefer in CSS.
|
||||
Comment:
|
||||
enabled: false
|
||||
|
||||
# Reports @debug statements (which you probably left behind accidentally).
|
||||
DebugStatement:
|
||||
enabled: false
|
||||
|
||||
# Rule sets should be ordered as follows:
|
||||
# - @extend declarations
|
||||
# - @include declarations without inner @content
|
||||
# - properties, @include declarations with inner @content
|
||||
# - nested rule sets.
|
||||
DeclarationOrder:
|
||||
enabled: false
|
||||
|
||||
# `scss-lint:disable` control comments should be preceded by a comment
|
||||
# explaining why these linters are being disabled for this file.
|
||||
# See https://github.com/brigade/scss-lint#disabling-linters-via-source for
|
||||
# more information.
|
||||
DisableLinterReason:
|
||||
enabled: true
|
||||
|
||||
# Reports when you define the same property twice in a single rule set.
|
||||
DuplicateProperty:
|
||||
enabled: false
|
||||
|
||||
# Separate rule, function, and mixin declarations with empty lines.
|
||||
EmptyLineBetweenBlocks:
|
||||
enabled: true
|
||||
|
||||
# Reports when you have an empty rule set.
|
||||
EmptyRule:
|
||||
enabled: true
|
||||
|
||||
# Reports when you have an @extend directive.
|
||||
ExtendDirective:
|
||||
enabled: false
|
||||
|
||||
# Files should always have a final newline. This results in better diffs
|
||||
# when adding lines to the file, since SCM systems such as git won't
|
||||
# think that you touched the last line.
|
||||
FinalNewline:
|
||||
enabled: false
|
||||
|
||||
# HEX colors should use three-character values where possible.
|
||||
HexLength:
|
||||
enabled: false
|
||||
|
||||
# HEX color values should use lower-case colors to differentiate between
|
||||
# letters and numbers, e.g. `#E3E3E3` vs. `#e3e3e3`.
|
||||
HexNotation:
|
||||
enabled: true
|
||||
|
||||
# Avoid using ID selectors.
|
||||
IdSelector:
|
||||
enabled: false
|
||||
|
||||
# The basenames of @imported SCSS partials should not begin with an
|
||||
# underscore and should not include the filename extension.
|
||||
ImportPath:
|
||||
enabled: false
|
||||
|
||||
# Avoid using !important in properties. It is usually indicative of a
|
||||
# misunderstanding of CSS specificity and can lead to brittle code.
|
||||
ImportantRule:
|
||||
enabled: false
|
||||
|
||||
# Indentation should always be done in increments of 2 spaces.
|
||||
Indentation:
|
||||
enabled: true
|
||||
width: 2
|
||||
|
||||
# Don't write leading zeros for numeric values with a decimal point.
|
||||
LeadingZero:
|
||||
enabled: false
|
||||
|
||||
# Reports when you define the same selector twice in a single sheet.
|
||||
MergeableSelector:
|
||||
enabled: false
|
||||
|
||||
# Functions, mixins, variables, and placeholders should be declared
|
||||
# with all lowercase letters and hyphens instead of underscores.
|
||||
NameFormat:
|
||||
enabled: false
|
||||
|
||||
# Avoid nesting selectors too deeply.
|
||||
NestingDepth:
|
||||
enabled: false
|
||||
|
||||
# Always use placeholder selectors in @extend.
|
||||
PlaceholderInExtend:
|
||||
enabled: false
|
||||
|
||||
# Sort properties in a strict order.
|
||||
PropertySortOrder:
|
||||
enabled: false
|
||||
|
||||
# Reports when you use an unknown or disabled CSS property
|
||||
# (ignoring vendor-prefixed properties).
|
||||
PropertySpelling:
|
||||
enabled: false
|
||||
|
||||
# Configure which units are allowed for property values.
|
||||
PropertyUnits:
|
||||
enabled: false
|
||||
|
||||
# Pseudo-elements, like ::before, and ::first-letter, should be declared
|
||||
# with two colons. Pseudo-classes, like :hover and :first-child, should
|
||||
# be declared with one colon.
|
||||
PseudoElement:
|
||||
enabled: true
|
||||
|
||||
# Avoid qualifying elements in selectors (also known as "tag-qualifying").
|
||||
QualifyingElement:
|
||||
enabled: false
|
||||
|
||||
# Don't write selectors with a depth of applicability greater than 3.
|
||||
SelectorDepth:
|
||||
enabled: false
|
||||
|
||||
# Selectors should always use hyphenated-lowercase, rather than camelCase or
|
||||
# snake_case.
|
||||
SelectorFormat:
|
||||
enabled: false
|
||||
convention: hyphenated_lowercase
|
||||
|
||||
# Prefer the shortest shorthand form possible for properties that support it.
|
||||
Shorthand:
|
||||
enabled: true
|
||||
|
||||
# Each property should have its own line, except in the special case of
|
||||
# single line rulesets.
|
||||
SingleLinePerProperty:
|
||||
enabled: true
|
||||
allow_single_line_rule_sets: true
|
||||
|
||||
# Split selectors onto separate lines after each comma, and have each
|
||||
# individual selector occupy a single line.
|
||||
SingleLinePerSelector:
|
||||
enabled: true
|
||||
|
||||
# Commas in lists should be followed by a space.
|
||||
SpaceAfterComma:
|
||||
enabled: false
|
||||
|
||||
# Properties should be formatted with a single space separating the colon
|
||||
# from the property's value.
|
||||
SpaceAfterPropertyColon:
|
||||
enabled: true
|
||||
|
||||
# Properties should be formatted with no space between the name and the
|
||||
# colon.
|
||||
SpaceAfterPropertyName:
|
||||
enabled: true
|
||||
|
||||
# Variables should be formatted with a single space separating the colon
|
||||
# from the variable's value.
|
||||
SpaceAfterVariableColon:
|
||||
enabled: true
|
||||
|
||||
# Variables should be formatted with no space between the name and the
|
||||
# colon.
|
||||
SpaceAfterVariableName:
|
||||
enabled: false
|
||||
|
||||
# Operators should be formatted with a single space on both sides of an
|
||||
# infix operator.
|
||||
SpaceAroundOperator:
|
||||
enabled: true
|
||||
|
||||
# Opening braces should be preceded by a single space.
|
||||
SpaceBeforeBrace:
|
||||
enabled: true
|
||||
|
||||
# Parentheses should not be padded with spaces.
|
||||
SpaceBetweenParens:
|
||||
enabled: false
|
||||
|
||||
# Enforces that string literals should be written with a consistent form
|
||||
# of quotes (single or double).
|
||||
StringQuotes:
|
||||
enabled: false
|
||||
|
||||
# Property values, @extend, @include, and @import directives, and variable
|
||||
# declarations should always end with a semicolon.
|
||||
TrailingSemicolon:
|
||||
enabled: true
|
||||
|
||||
# Reports lines containing trailing whitespace.
|
||||
TrailingWhitespace:
|
||||
enabled: true
|
||||
|
||||
# Don't write trailing zeros for numeric values with a decimal point.
|
||||
TrailingZero:
|
||||
enabled: false
|
||||
|
||||
# Don't use the `all` keyword to specify transition properties.
|
||||
TransitionAll:
|
||||
enabled: false
|
||||
|
||||
# Numeric values should not contain unnecessary fractional portions.
|
||||
UnnecessaryMantissa:
|
||||
enabled: false
|
||||
|
||||
# Do not use parent selector references (&) when they would otherwise
|
||||
# be unnecessary.
|
||||
UnnecessaryParentReference:
|
||||
enabled: false
|
||||
|
||||
# URLs should be valid and not contain protocols or domain names.
|
||||
UrlFormat:
|
||||
enabled: true
|
||||
|
||||
# URLs should always be enclosed within quotes.
|
||||
UrlQuotes:
|
||||
enabled: true
|
||||
|
||||
# Properties, like color and font, are easier to read and maintain
|
||||
# when defined using variables rather than literals.
|
||||
VariableForProperty:
|
||||
enabled: false
|
||||
|
||||
# Avoid vendor prefixes. Or rather: don't write them yourself.
|
||||
VendorPrefix:
|
||||
enabled: false
|
||||
|
||||
# Omit length units on zero values, e.g. `0px` vs. `0`.
|
||||
ZeroUnit:
|
||||
enabled: true
|
@@ -2,3 +2,4 @@ node_modules/
|
||||
.cache/
|
||||
docs/
|
||||
spec/
|
||||
storybook/
|
||||
|
29
.travis.yml
@@ -3,12 +3,9 @@ cache:
|
||||
bundler: true
|
||||
yarn: true
|
||||
directories:
|
||||
- node_modules
|
||||
- public/assets
|
||||
- public/packs-test
|
||||
- tmp/cache/babel-loader
|
||||
- node_modules
|
||||
dist: trusty
|
||||
sudo: required
|
||||
sudo: false
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
@@ -18,10 +15,7 @@ env:
|
||||
- LOCAL_DOMAIN=cb6e6126.ngrok.io
|
||||
- LOCAL_HTTPS=true
|
||||
- RAILS_ENV=test
|
||||
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
|
||||
- PARALLEL_TEST_PROCESSORS=2
|
||||
- "PATH=$HOME:$PATH"
|
||||
|
||||
- CXX=g++-4.8
|
||||
addons:
|
||||
postgresql: 9.4
|
||||
apt:
|
||||
@@ -29,11 +23,8 @@ addons:
|
||||
- ubuntu-toolchain-r-test
|
||||
- trusty-media
|
||||
packages:
|
||||
- g++-4.8
|
||||
- ffmpeg
|
||||
- g++-6
|
||||
- libprotobuf-dev
|
||||
- protobuf-compiler
|
||||
- libicu-dev
|
||||
|
||||
rvm:
|
||||
- 2.3.4
|
||||
@@ -42,18 +33,18 @@ rvm:
|
||||
services:
|
||||
- redis-server
|
||||
|
||||
bundler_args: --without development production --retry=3 --jobs=3
|
||||
|
||||
install:
|
||||
- nvm install
|
||||
- npm install -g yarn
|
||||
- bundle install --path=vendor/bundle --without development production --retry=3 --jobs=16
|
||||
- bundle install
|
||||
- yarn install
|
||||
|
||||
before_script:
|
||||
- bundle exec rake parallel:create parallel:load_schema parallel:prepare
|
||||
- bundle exec rails assets:precompile
|
||||
- ln -s /usr/bin/x86_64-linux-gnu-g++-6 "$HOME/g++"
|
||||
- bundle exec rails db:create db:migrate
|
||||
|
||||
script:
|
||||
- travis_retry bundle exec parallel_test spec/ --group-by filesize --type rspec
|
||||
- bundle exec rspec
|
||||
- npm test
|
||||
- bundle exec i18n-tasks unused
|
||||
- i18n-tasks unused
|
||||
|
10
Aptfile
@@ -1,10 +0,0 @@
|
||||
ffmpeg
|
||||
libicu[0-9][0-9]
|
||||
libicu-dev
|
||||
libidn11
|
||||
libidn11-dev
|
||||
libpq-dev
|
||||
libprotobuf-dev
|
||||
libxdamage1
|
||||
libxfixes3
|
||||
protobuf-compiler
|
15
CODEOWNERS
@@ -1,15 +0,0 @@
|
||||
# CODEOWNERS for tootsuite/mastodon
|
||||
|
||||
# Translators
|
||||
# To add translator, copy these lines, replace `fr` with appropriate language code and replace `@żelipapą` with user's GitHub nickname preceded by `@` sign or e-mail address.
|
||||
# /app/javascript/mastodon/locales/fr.json @żelipapą
|
||||
# /app/views/user_mailer/*.fr.html.erb @żelipapą
|
||||
# /app/views/user_mailer/*.fr.text.erb @żelipapą
|
||||
# /config/locales/*.fr.yml @żelipapą
|
||||
# /config/locales/fr.yml @żelipapą
|
||||
|
||||
/app/javascript/mastodon/locales/pl.json @m4sk1n
|
||||
/app/views/user_mailer/*.pl.html.erb @m4sk1n
|
||||
/app/views/user_mailer/*.pl.text.erb @m4sk1n
|
||||
/config/locales/*.pl.yml @m4sk1n
|
||||
/config/locales/pl.yml @m4sk1n
|
2
Capfile
@@ -1,4 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
require 'capistrano/setup'
|
||||
require 'capistrano/deploy'
|
||||
require 'capistrano/scm/git'
|
||||
@@ -9,6 +8,7 @@ require 'capistrano/rbenv'
|
||||
require 'capistrano/bundler'
|
||||
require 'capistrano/yarn'
|
||||
require 'capistrano/rails/assets'
|
||||
require 'capistrano/faster_assets'
|
||||
require 'capistrano/rails/migrations'
|
||||
|
||||
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
|
||||
|
85
Dockerfile
@@ -1,69 +1,44 @@
|
||||
FROM ruby:2.4.1-alpine3.6
|
||||
FROM ruby:2.4.1-alpine
|
||||
|
||||
LABEL maintainer="https://github.com/tootsuite/mastodon" \
|
||||
description="A GNU Social-compatible microblogging server"
|
||||
|
||||
ENV UID=991 GID=991 \
|
||||
RAILS_SERVE_STATIC_FILES=true \
|
||||
RAILS_ENV=production NODE_ENV=production
|
||||
|
||||
ARG LIBICONV_VERSION=1.15
|
||||
ARG LIBICONV_DOWNLOAD_SHA256=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
|
||||
ENV RAILS_ENV=production \
|
||||
NODE_ENV=production
|
||||
|
||||
EXPOSE 3000 4000
|
||||
|
||||
WORKDIR /mastodon
|
||||
|
||||
RUN apk -U upgrade \
|
||||
&& apk add -t build-dependencies \
|
||||
build-base \
|
||||
icu-dev \
|
||||
libidn-dev \
|
||||
libtool \
|
||||
postgresql-dev \
|
||||
protobuf-dev \
|
||||
python \
|
||||
&& apk add \
|
||||
ca-certificates \
|
||||
ffmpeg \
|
||||
file \
|
||||
git \
|
||||
icu-libs \
|
||||
imagemagick \
|
||||
libidn \
|
||||
libpq \
|
||||
nodejs-npm \
|
||||
nodejs \
|
||||
protobuf \
|
||||
su-exec \
|
||||
tini \
|
||||
yarn \
|
||||
&& update-ca-certificates \
|
||||
&& wget -O libiconv.tar.gz "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-$LIBICONV_VERSION.tar.gz" \
|
||||
&& echo "$LIBICONV_DOWNLOAD_SHA256 *libiconv.tar.gz" | sha256sum -c - \
|
||||
&& mkdir -p /tmp/src \
|
||||
&& tar -xzf libiconv.tar.gz -C /tmp/src \
|
||||
&& rm libiconv.tar.gz \
|
||||
&& cd /tmp/src/libiconv-$LIBICONV_VERSION \
|
||||
&& ./configure --prefix=/usr/local \
|
||||
&& make -j$(getconf _NPROCESSORS_ONLN)\
|
||||
&& make install \
|
||||
&& libtool --finish /usr/local/lib \
|
||||
&& cd /mastodon \
|
||||
&& rm -rf /tmp/* /var/cache/apk/*
|
||||
|
||||
COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/
|
||||
|
||||
RUN bundle config build.nokogiri --with-iconv-lib=/usr/local/lib --with-iconv-include=/usr/local/include \
|
||||
&& bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without test development \
|
||||
&& yarn --ignore-optional --pure-lockfile
|
||||
RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \
|
||||
&& BUILD_DEPS=" \
|
||||
postgresql-dev \
|
||||
libxml2-dev \
|
||||
libxslt-dev \
|
||||
python \
|
||||
build-base" \
|
||||
&& apk -U upgrade && apk add \
|
||||
$BUILD_DEPS \
|
||||
nodejs@edge \
|
||||
nodejs-npm@edge \
|
||||
libpq \
|
||||
libxml2 \
|
||||
libxslt \
|
||||
ffmpeg \
|
||||
file \
|
||||
imagemagick@edge \
|
||||
ca-certificates \
|
||||
&& npm install -g npm@3 && npm install -g yarn \
|
||||
&& bundle install --deployment --without test development \
|
||||
&& yarn --ignore-optional \
|
||||
&& yarn cache clean \
|
||||
&& npm -g cache clean \
|
||||
&& update-ca-certificates \
|
||||
&& apk del $BUILD_DEPS \
|
||||
&& rm -rf /tmp/* /var/cache/apk/*
|
||||
|
||||
COPY . /mastodon
|
||||
|
||||
COPY docker_entrypoint.sh /usr/local/bin/run
|
||||
|
||||
RUN chmod +x /usr/local/bin/run
|
||||
|
||||
VOLUME /mastodon/public/system /mastodon/public/assets /mastodon/public/packs
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/run"]
|
||||
VOLUME /mastodon/public/system /mastodon/public/assets
|
||||
|
172
Gemfile
@@ -3,116 +3,104 @@
|
||||
source 'https://rubygems.org'
|
||||
ruby '>= 2.3.0', '< 2.5.0'
|
||||
|
||||
gem 'pkg-config', '~> 1.2'
|
||||
gem 'pkg-config'
|
||||
|
||||
gem 'puma', '~> 3.10'
|
||||
gem 'rails', '~> 5.1.4'
|
||||
gem 'uglifier', '~> 3.2'
|
||||
gem 'rails', '~> 5.0.2'
|
||||
gem 'sass-rails', '~> 5.0'
|
||||
gem 'uglifier', '>= 1.3.0'
|
||||
gem 'jquery-rails'
|
||||
gem 'puma'
|
||||
|
||||
gem 'hamlit-rails', '~> 0.2'
|
||||
gem 'pg', '~> 0.20'
|
||||
gem 'pghero', '~> 1.7'
|
||||
gem 'dotenv-rails', '~> 2.2'
|
||||
gem 'hamlit-rails'
|
||||
gem 'pg'
|
||||
gem 'pghero'
|
||||
gem 'dotenv-rails'
|
||||
gem 'font-awesome-rails'
|
||||
gem 'best_in_place', '~> 3.0.1'
|
||||
|
||||
gem 'aws-sdk', '~> 2.9'
|
||||
gem 'fog-openstack', '~> 0.1'
|
||||
gem 'paperclip', '~> 5.1'
|
||||
gem 'paperclip-av-transcoder', '~> 0.6'
|
||||
gem 'paperclip-av-transcoder'
|
||||
gem 'aws-sdk', '>= 2.0'
|
||||
|
||||
gem 'active_model_serializers', '~> 0.10'
|
||||
gem 'addressable', '~> 2.5'
|
||||
gem 'bootsnap'
|
||||
gem 'browser'
|
||||
gem 'charlock_holmes', '~> 0.7.5'
|
||||
gem 'iso-639'
|
||||
gem 'cld3', '~> 3.2.0'
|
||||
gem 'devise', '~> 4.2'
|
||||
gem 'devise-two-factor', '~> 3.0'
|
||||
gem 'doorkeeper', '~> 4.2'
|
||||
gem 'fast_blank', '~> 1.0'
|
||||
gem 'goldfinger', '~> 2.0'
|
||||
gem 'hiredis', '~> 0.6'
|
||||
gem 'redis-namespace', '~> 1.5'
|
||||
gem 'htmlentities', '~> 4.3'
|
||||
gem 'http', '~> 2.2'
|
||||
gem 'http_accept_language', '~> 2.1'
|
||||
gem 'httplog', '~> 0.99'
|
||||
gem 'idn-ruby', require: 'idn'
|
||||
gem 'kaminari', '~> 1.0'
|
||||
gem 'link_header', '~> 0.0'
|
||||
gem 'mime-types', '~> 3.1'
|
||||
gem 'nokogiri', '~> 1.7'
|
||||
gem 'oj', '~> 3.0'
|
||||
gem 'addressable'
|
||||
gem 'devise'
|
||||
gem 'devise-two-factor'
|
||||
gem 'doorkeeper'
|
||||
gem 'fast_blank'
|
||||
gem 'goldfinger'
|
||||
gem 'hiredis'
|
||||
gem 'htmlentities'
|
||||
gem 'http'
|
||||
gem 'http_accept_language'
|
||||
gem 'httplog'
|
||||
gem 'kaminari'
|
||||
gem 'link_header'
|
||||
gem 'local_time'
|
||||
gem 'nokogiri'
|
||||
gem 'oj'
|
||||
gem 'ostatus2', '~> 2.0'
|
||||
gem 'ox', '~> 2.5'
|
||||
gem 'pundit', '~> 1.1'
|
||||
gem 'rabl', '~> 0.13'
|
||||
gem 'rack-attack', '~> 5.0'
|
||||
gem 'rack-cors', '~> 0.4', require: 'rack/cors'
|
||||
gem 'rack-timeout', '~> 0.4'
|
||||
gem 'rails-i18n', '~> 5.0'
|
||||
gem 'rails-settings-cached', '~> 0.6'
|
||||
gem 'redis', '~> 3.3', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
||||
gem 'rqrcode', '~> 0.10'
|
||||
gem 'ruby-oembed', '~> 0.12', require: 'oembed'
|
||||
gem 'sanitize', '~> 4.4'
|
||||
gem 'sidekiq', '~> 5.0'
|
||||
gem 'sidekiq-scheduler', '~> 2.1'
|
||||
gem 'sidekiq-unique-jobs', '~> 5.0'
|
||||
gem 'sidekiq-bulk', '~>0.1.1'
|
||||
gem 'simple-navigation', '~> 4.0'
|
||||
gem 'simple_form', '~> 3.4'
|
||||
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
|
||||
gem 'statsd-instrument', '~> 2.1'
|
||||
gem 'twitter-text', '~> 1.14'
|
||||
gem 'tzinfo-data', '~> 1.2017'
|
||||
gem 'webpacker', '~> 2.0'
|
||||
gem 'webpush'
|
||||
gem 'ox'
|
||||
gem 'rabl'
|
||||
gem 'rack-attack'
|
||||
gem 'rack-cors', require: 'rack/cors'
|
||||
gem 'rack-timeout'
|
||||
gem 'rails-i18n'
|
||||
gem 'rails-settings-cached'
|
||||
gem 'redis', '~>3.2', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'rqrcode'
|
||||
gem 'ruby-oembed', require: 'oembed'
|
||||
gem 'sanitize'
|
||||
gem 'sidekiq'
|
||||
gem 'sidekiq-scheduler'
|
||||
gem 'sidekiq-unique-jobs'
|
||||
gem 'simple-navigation'
|
||||
gem 'simple_form'
|
||||
gem 'sprockets-rails', require: 'sprockets/railtie'
|
||||
gem 'statsd-instrument'
|
||||
gem 'twitter-text'
|
||||
gem 'tzinfo-data'
|
||||
gem 'whatlanguage'
|
||||
|
||||
gem 'json-ld-preloaded', '~> 2.2.1'
|
||||
gem 'rdf-normalize', '~> 0.3.1'
|
||||
gem 'react-rails'
|
||||
gem 'browserify-rails'
|
||||
gem 'autoprefixer-rails'
|
||||
|
||||
group :development, :test do
|
||||
gem 'fabrication', '~> 2.16'
|
||||
gem 'fuubar', '~> 2.2'
|
||||
gem 'i18n-tasks', '~> 0.9', require: false
|
||||
gem 'pry-rails', '~> 0.3'
|
||||
gem 'rspec-rails', '~> 3.6'
|
||||
gem 'rspec-rails'
|
||||
gem 'pry-rails'
|
||||
gem 'fuubar'
|
||||
gem 'fabrication'
|
||||
gem 'i18n-tasks', '~> 0.9.6'
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem 'capybara', '~> 2.14'
|
||||
gem 'climate_control', '~> 0.2'
|
||||
gem 'faker', '~> 1.7'
|
||||
gem 'microformats', '~> 4.0'
|
||||
gem 'rails-controller-testing', '~> 1.0'
|
||||
gem 'rspec-sidekiq', '~> 3.0'
|
||||
gem 'simplecov', '~> 0.14', require: false
|
||||
gem 'webmock', '~> 3.0'
|
||||
gem 'parallel_tests', '~> 2.14'
|
||||
gem 'capybara'
|
||||
gem 'faker'
|
||||
gem 'microformats2'
|
||||
gem 'rails-controller-testing'
|
||||
gem 'rspec-sidekiq'
|
||||
gem 'simplecov', require: false
|
||||
gem 'webmock'
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'active_record_query_trace', '~> 1.5'
|
||||
gem 'annotate', '~> 2.7'
|
||||
gem 'better_errors', '~> 2.1'
|
||||
gem 'binding_of_caller', '~> 0.7'
|
||||
gem 'bullet', '~> 5.5'
|
||||
gem 'letter_opener', '~> 1.4'
|
||||
gem 'letter_opener_web', '~> 1.3'
|
||||
gem 'rubocop', require: false
|
||||
gem 'brakeman', '~> 3.6', require: false
|
||||
gem 'bundler-audit', '~> 0.5', require: false
|
||||
gem 'scss_lint', '~> 0.53', require: false
|
||||
gem 'better_errors'
|
||||
gem 'binding_of_caller'
|
||||
gem 'letter_opener'
|
||||
gem 'letter_opener_web'
|
||||
gem 'bullet'
|
||||
gem 'active_record_query_trace'
|
||||
|
||||
gem 'capistrano', '~> 3.8'
|
||||
gem 'capistrano-rails', '~> 1.2'
|
||||
gem 'capistrano-rbenv', '~> 2.1'
|
||||
gem 'capistrano-yarn', '~> 2.0'
|
||||
gem 'capistrano', '3.8.0'
|
||||
gem 'capistrano-rails'
|
||||
gem 'capistrano-rbenv'
|
||||
gem 'capistrano-yarn'
|
||||
gem 'capistrano-faster-assets', '~> 1.0'
|
||||
end
|
||||
|
||||
group :production do
|
||||
gem 'lograge', '~> 0.5'
|
||||
gem 'redis-rails', '~> 5.0'
|
||||
gem 'rails_12factor'
|
||||
gem 'redis-rails'
|
||||
gem 'lograge'
|
||||
end
|
||||
|
593
Gemfile.lock
@@ -1,89 +1,87 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (5.1.4)
|
||||
actionpack (= 5.1.4)
|
||||
nio4r (~> 2.0)
|
||||
actioncable (5.0.2)
|
||||
actionpack (= 5.0.2)
|
||||
nio4r (>= 1.2, < 3.0)
|
||||
websocket-driver (~> 0.6.1)
|
||||
actionmailer (5.1.4)
|
||||
actionpack (= 5.1.4)
|
||||
actionview (= 5.1.4)
|
||||
activejob (= 5.1.4)
|
||||
actionmailer (5.0.2)
|
||||
actionpack (= 5.0.2)
|
||||
actionview (= 5.0.2)
|
||||
activejob (= 5.0.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.1.4)
|
||||
actionview (= 5.1.4)
|
||||
activesupport (= 5.1.4)
|
||||
actionpack (5.0.2)
|
||||
actionview (= 5.0.2)
|
||||
activesupport (= 5.0.2)
|
||||
rack (~> 2.0)
|
||||
rack-test (>= 0.6.3)
|
||||
rack-test (~> 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (5.1.4)
|
||||
activesupport (= 5.1.4)
|
||||
actionview (5.0.2)
|
||||
activesupport (= 5.0.2)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
active_model_serializers (0.10.6)
|
||||
actionpack (>= 4.1, < 6)
|
||||
activemodel (>= 4.1, < 6)
|
||||
case_transform (>= 0.2)
|
||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
|
||||
active_record_query_trace (1.5.4)
|
||||
activejob (5.1.4)
|
||||
activesupport (= 5.1.4)
|
||||
activejob (5.0.2)
|
||||
activesupport (= 5.0.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.1.4)
|
||||
activesupport (= 5.1.4)
|
||||
activerecord (5.1.4)
|
||||
activemodel (= 5.1.4)
|
||||
activesupport (= 5.1.4)
|
||||
arel (~> 8.0)
|
||||
activesupport (5.1.4)
|
||||
activemodel (5.0.2)
|
||||
activesupport (= 5.0.2)
|
||||
activerecord (5.0.2)
|
||||
activemodel (= 5.0.2)
|
||||
activesupport (= 5.0.2)
|
||||
arel (~> 7.0)
|
||||
activesupport (5.0.2)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.5.2)
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
airbrussh (1.3.0)
|
||||
addressable (2.5.1)
|
||||
public_suffix (~> 2.0, >= 2.0.2)
|
||||
airbrussh (1.2.0)
|
||||
sshkit (>= 1.6.1, != 1.7.0)
|
||||
annotate (2.7.2)
|
||||
activerecord (>= 3.2, < 6.0)
|
||||
rake (>= 10.4, < 13.0)
|
||||
arel (8.0.0)
|
||||
arel (7.1.4)
|
||||
ast (2.3.0)
|
||||
attr_encrypted (3.0.3)
|
||||
encryptor (~> 3.0.0)
|
||||
autoprefixer-rails (6.7.7.2)
|
||||
execjs
|
||||
av (0.9.0)
|
||||
cocaine (~> 0.5.3)
|
||||
aws-sdk (2.10.21)
|
||||
aws-sdk-resources (= 2.10.21)
|
||||
aws-sdk-core (2.10.21)
|
||||
aws-sdk (2.9.12)
|
||||
aws-sdk-resources (= 2.9.12)
|
||||
aws-sdk-core (2.9.12)
|
||||
aws-sigv4 (~> 1.0)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-resources (2.10.21)
|
||||
aws-sdk-core (= 2.10.21)
|
||||
aws-sigv4 (1.0.1)
|
||||
aws-sdk-resources (2.9.12)
|
||||
aws-sdk-core (= 2.9.12)
|
||||
aws-sigv4 (1.0.0)
|
||||
babel-source (5.8.35)
|
||||
babel-transpiler (0.7.0)
|
||||
babel-source (>= 4.0, < 6)
|
||||
execjs (~> 2.0)
|
||||
bcrypt (3.1.11)
|
||||
best_in_place (3.0.3)
|
||||
actionpack (>= 3.2)
|
||||
railties (>= 3.2)
|
||||
better_errors (2.1.1)
|
||||
coderay (>= 1.0.0)
|
||||
erubis (>= 2.6.6)
|
||||
rack (>= 0.9.0)
|
||||
binding_of_caller (0.7.2)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bootsnap (1.1.2)
|
||||
msgpack (~> 1.0)
|
||||
brakeman (3.7.2)
|
||||
browser (2.4.0)
|
||||
browserify-rails (4.1.0)
|
||||
addressable (>= 2.4.0)
|
||||
railties (>= 4.0.0, < 5.1)
|
||||
sprockets (>= 3.6.0)
|
||||
builder (3.2.3)
|
||||
bullet (5.5.1)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.10.0)
|
||||
bundler-audit (0.6.0)
|
||||
bundler (~> 1.2)
|
||||
thor (~> 0.18)
|
||||
capistrano (3.8.2)
|
||||
capistrano (3.8.0)
|
||||
airbrussh (>= 1.0.0)
|
||||
i18n
|
||||
rake (>= 10.0.0)
|
||||
@@ -91,7 +89,9 @@ GEM
|
||||
capistrano-bundler (1.2.0)
|
||||
capistrano (~> 3.1)
|
||||
sshkit (~> 1.2)
|
||||
capistrano-rails (1.3.0)
|
||||
capistrano-faster-assets (1.0.2)
|
||||
capistrano (>= 3.1)
|
||||
capistrano-rails (1.2.3)
|
||||
capistrano (~> 3.1)
|
||||
capistrano-bundler (~> 1.1)
|
||||
capistrano-rbenv (2.1.1)
|
||||
@@ -99,34 +99,36 @@ GEM
|
||||
sshkit (~> 1.3)
|
||||
capistrano-yarn (2.0.2)
|
||||
capistrano (~> 3.0)
|
||||
capybara (2.14.4)
|
||||
capybara (2.13.0)
|
||||
addressable
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
case_transform (0.2)
|
||||
activesupport
|
||||
charlock_holmes (0.7.5)
|
||||
chunky_png (1.3.8)
|
||||
cld3 (3.2.0)
|
||||
ffi (>= 1.1.0, < 1.10.0)
|
||||
climate_control (0.2.0)
|
||||
climate_control (0.1.0)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
coderay (1.1.1)
|
||||
coffee-rails (4.2.1)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (>= 4.0.0, < 5.2.x)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.12.2)
|
||||
colorize (0.8.1)
|
||||
concurrent-ruby (1.0.5)
|
||||
connection_pool (2.2.1)
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
crass (1.0.2)
|
||||
debug_inspector (0.0.3)
|
||||
devise (4.3.0)
|
||||
debug_inspector (0.0.2)
|
||||
devise (4.2.1)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 4.1.0, < 5.2)
|
||||
railties (>= 4.1.0, < 5.1)
|
||||
responders
|
||||
warden (~> 1.2.3)
|
||||
devise-two-factor (3.0.0)
|
||||
@@ -139,51 +141,37 @@ GEM
|
||||
docile (1.1.5)
|
||||
domain_name (0.5.20170404)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
doorkeeper (4.2.6)
|
||||
doorkeeper (4.2.5)
|
||||
railties (>= 4.2)
|
||||
dotenv (2.2.1)
|
||||
dotenv-rails (2.2.1)
|
||||
dotenv (= 2.2.1)
|
||||
railties (>= 3.2, < 5.2)
|
||||
dotenv (2.2.0)
|
||||
dotenv-rails (2.2.0)
|
||||
dotenv (= 2.2.0)
|
||||
railties (>= 3.2, < 5.1)
|
||||
easy_translate (0.5.0)
|
||||
json
|
||||
thread
|
||||
thread_safe
|
||||
encryptor (3.0.0)
|
||||
erubi (1.6.1)
|
||||
erubis (2.7.0)
|
||||
et-orbi (1.0.5)
|
||||
et-orbi (1.0.3)
|
||||
tzinfo
|
||||
excon (0.58.0)
|
||||
execjs (2.7.0)
|
||||
fabrication (2.16.2)
|
||||
fabrication (2.16.1)
|
||||
faker (1.7.3)
|
||||
i18n (~> 0.5)
|
||||
fast_blank (1.0.0)
|
||||
ffi (1.9.18)
|
||||
fog-core (1.45.0)
|
||||
builder
|
||||
excon (~> 0.58)
|
||||
formatador (~> 0.2)
|
||||
fog-json (1.0.2)
|
||||
fog-core (~> 1.0)
|
||||
multi_json (~> 1.10)
|
||||
fog-openstack (0.1.21)
|
||||
fog-core (>= 1.40)
|
||||
fog-json (>= 1.0)
|
||||
ipaddress (>= 0.8)
|
||||
formatador (0.2.5)
|
||||
font-awesome-rails (4.7.0.1)
|
||||
railties (>= 3.2, < 5.1)
|
||||
fuubar (2.2.0)
|
||||
rspec-core (~> 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
globalid (0.4.0)
|
||||
activesupport (>= 4.2.0)
|
||||
goldfinger (2.0.1)
|
||||
addressable (~> 2.5)
|
||||
http (~> 2.2)
|
||||
nokogiri (~> 1.8)
|
||||
oj (~> 3.0)
|
||||
hamlit (2.8.4)
|
||||
goldfinger (1.2.0)
|
||||
addressable (~> 2.4)
|
||||
http (~> 2.0)
|
||||
nokogiri (~> 1.6)
|
||||
hamlit (2.8.1)
|
||||
temple (>= 0.8.0)
|
||||
thor
|
||||
tilt
|
||||
@@ -192,12 +180,9 @@ GEM
|
||||
activesupport (>= 4.0.1)
|
||||
hamlit (>= 1.2.0)
|
||||
railties (>= 4.0.1)
|
||||
hamster (3.0.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
hashdiff (0.3.5)
|
||||
hashdiff (0.3.2)
|
||||
highline (1.7.8)
|
||||
hiredis (0.6.1)
|
||||
hkdf (0.3.0)
|
||||
htmlentities (4.3.4)
|
||||
http (2.2.2)
|
||||
addressable (~> 2.3)
|
||||
@@ -206,14 +191,14 @@ GEM
|
||||
http_parser.rb (~> 0.6.0)
|
||||
http-cookie (1.0.3)
|
||||
domain_name (~> 0.5)
|
||||
http-form_data (1.0.3)
|
||||
http_accept_language (2.1.1)
|
||||
http-form_data (1.0.1)
|
||||
http_accept_language (2.1.0)
|
||||
http_parser.rb (0.6.0)
|
||||
httplog (0.99.7)
|
||||
httplog (0.99.3)
|
||||
colorize
|
||||
rack
|
||||
i18n (0.8.6)
|
||||
i18n-tasks (0.9.16)
|
||||
i18n (0.8.1)
|
||||
i18n-tasks (0.9.13)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
easy_translate (>= 0.5.0)
|
||||
@@ -223,20 +208,12 @@ GEM
|
||||
parser (>= 2.2.3.0)
|
||||
rainbow (~> 2.2)
|
||||
terminal-table (>= 1.5.1)
|
||||
idn-ruby (0.1.0)
|
||||
ipaddress (0.8.3)
|
||||
iso-639 (0.2.8)
|
||||
jmespath (1.3.1)
|
||||
jquery-rails (4.3.1)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
json (2.1.0)
|
||||
json-ld (2.1.5)
|
||||
multi_json (~> 1.12)
|
||||
rdf (~> 2.2)
|
||||
json-ld-preloaded (2.2.1)
|
||||
json-ld (~> 2.1, >= 2.1.5)
|
||||
multi_json (~> 1.11)
|
||||
rdf (~> 2.2)
|
||||
jsonapi-renderer (0.1.3)
|
||||
jwt (1.5.6)
|
||||
kaminari (1.0.1)
|
||||
activesupport (>= 4.1.0)
|
||||
kaminari-actionview (= 1.0.1)
|
||||
@@ -258,45 +235,44 @@ GEM
|
||||
letter_opener (~> 1.0)
|
||||
railties (>= 3.2)
|
||||
link_header (0.0.8)
|
||||
lograge (0.5.1)
|
||||
actionpack (>= 4, < 5.2)
|
||||
activesupport (>= 4, < 5.2)
|
||||
railties (>= 4, < 5.2)
|
||||
local_time (1.0.3)
|
||||
coffee-rails
|
||||
lograge (0.4.1)
|
||||
actionpack (>= 4, < 5.1)
|
||||
activesupport (>= 4, < 5.1)
|
||||
railties (>= 4, < 5.1)
|
||||
loofah (2.0.3)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.6.6)
|
||||
mail (2.6.5)
|
||||
mime-types (>= 1.16, < 4)
|
||||
mario-redis-lock (1.2.0)
|
||||
redis (~> 3, >= 3.0.5)
|
||||
method_source (0.8.2)
|
||||
microformats (4.0.7)
|
||||
microformats2 (2.1.0)
|
||||
activesupport
|
||||
json
|
||||
nokogiri
|
||||
mime-types (3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2016.0521)
|
||||
mimemagic (0.3.2)
|
||||
mini_portile2 (2.2.0)
|
||||
minitest (5.10.3)
|
||||
msgpack (1.1.0)
|
||||
multi_json (1.12.1)
|
||||
mini_portile2 (2.1.0)
|
||||
minitest (5.10.1)
|
||||
net-scp (1.2.1)
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (4.1.0)
|
||||
nio4r (2.1.0)
|
||||
nokogiri (1.8.0)
|
||||
mini_portile2 (~> 2.2.0)
|
||||
nokogumbo (1.4.13)
|
||||
nio4r (2.0.0)
|
||||
nokogiri (1.7.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
nokogumbo (1.4.10)
|
||||
nokogiri
|
||||
oj (3.3.4)
|
||||
openssl (2.0.4)
|
||||
oj (3.0.2)
|
||||
openssl (2.0.3)
|
||||
orm_adapter (0.5.0)
|
||||
ostatus2 (2.0.1)
|
||||
ostatus2 (2.0.0)
|
||||
addressable (~> 2.4)
|
||||
http (~> 2.0)
|
||||
nokogiri (~> 1.6)
|
||||
openssl (~> 2.0)
|
||||
ox (2.5.0)
|
||||
ox (2.4.13)
|
||||
paperclip (5.1.0)
|
||||
activemodel (>= 4.2.0)
|
||||
activesupport (>= 4.2.0)
|
||||
@@ -306,15 +282,12 @@ GEM
|
||||
paperclip-av-transcoder (0.6.4)
|
||||
av (~> 0.9.0)
|
||||
paperclip (>= 2.5.2)
|
||||
parallel (1.11.2)
|
||||
parallel_tests (2.14.2)
|
||||
parallel
|
||||
parser (2.4.0.0)
|
||||
ast (~> 2.2)
|
||||
pg (0.21.0)
|
||||
pghero (1.7.0)
|
||||
pg (0.20.0)
|
||||
pghero (1.6.5)
|
||||
activerecord
|
||||
pkg-config (1.2.4)
|
||||
pkg-config (1.2.0)
|
||||
powerpack (0.1.1)
|
||||
pry (0.10.4)
|
||||
coderay (~> 1.1.0)
|
||||
@@ -322,71 +295,73 @@ GEM
|
||||
slop (~> 3.4)
|
||||
pry-rails (0.3.6)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (3.0.0)
|
||||
puma (3.10.0)
|
||||
pundit (1.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
public_suffix (2.0.5)
|
||||
puma (3.8.2)
|
||||
rabl (0.13.1)
|
||||
activesupport (>= 2.3.14)
|
||||
rack (2.0.3)
|
||||
rack (2.0.1)
|
||||
rack-attack (5.0.1)
|
||||
rack
|
||||
rack-cors (0.4.1)
|
||||
rack-protection (2.0.0)
|
||||
rack-protection (1.5.3)
|
||||
rack
|
||||
rack-test (0.7.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rack-timeout (0.4.2)
|
||||
rails (5.1.4)
|
||||
actioncable (= 5.1.4)
|
||||
actionmailer (= 5.1.4)
|
||||
actionpack (= 5.1.4)
|
||||
actionview (= 5.1.4)
|
||||
activejob (= 5.1.4)
|
||||
activemodel (= 5.1.4)
|
||||
activerecord (= 5.1.4)
|
||||
activesupport (= 5.1.4)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 5.1.4)
|
||||
rails (5.0.2)
|
||||
actioncable (= 5.0.2)
|
||||
actionmailer (= 5.0.2)
|
||||
actionpack (= 5.0.2)
|
||||
actionview (= 5.0.2)
|
||||
activejob (= 5.0.2)
|
||||
activemodel (= 5.0.2)
|
||||
activerecord (= 5.0.2)
|
||||
activesupport (= 5.0.2)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 5.0.2)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-controller-testing (1.0.2)
|
||||
actionpack (~> 5.x, >= 5.0.1)
|
||||
actionview (~> 5.x, >= 5.0.1)
|
||||
rails-controller-testing (1.0.1)
|
||||
actionpack (~> 5.x)
|
||||
actionview (~> 5.x)
|
||||
activesupport (~> 5.x)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-dom-testing (2.0.2)
|
||||
activesupport (>= 4.2.0, < 6.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
rails-i18n (5.0.4)
|
||||
rails-i18n (5.0.3)
|
||||
i18n (~> 0.7)
|
||||
railties (~> 5.0)
|
||||
rails-settings-cached (0.6.6)
|
||||
rails-settings-cached (0.6.5)
|
||||
rails (>= 4.2.0)
|
||||
railties (5.1.4)
|
||||
actionpack (= 5.1.4)
|
||||
activesupport (= 5.1.4)
|
||||
rails_12factor (0.0.3)
|
||||
rails_serve_static_assets
|
||||
rails_stdout_logging
|
||||
rails_serve_static_assets (0.0.5)
|
||||
rails_stdout_logging (0.0.5)
|
||||
railties (5.0.2)
|
||||
actionpack (= 5.0.2)
|
||||
activesupport (= 5.0.2)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.2.2)
|
||||
rake
|
||||
rake (12.0.0)
|
||||
rdf (2.2.8)
|
||||
hamster (~> 3.0)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
rdf-normalize (0.3.2)
|
||||
rdf (~> 2.0)
|
||||
react-rails (1.11.0)
|
||||
babel-transpiler (>= 0.7.0)
|
||||
connection_pool
|
||||
execjs
|
||||
railties (>= 3.2)
|
||||
tilt
|
||||
redis (3.3.3)
|
||||
redis-actionpack (5.0.1)
|
||||
actionpack (>= 4.0, < 6)
|
||||
redis-rack (>= 1, < 3)
|
||||
redis-store (>= 1.1.0, < 1.4.0)
|
||||
redis-activesupport (5.0.3)
|
||||
redis-activesupport (5.0.2)
|
||||
activesupport (>= 3, < 6)
|
||||
redis-store (~> 1.3.0)
|
||||
redis-namespace (1.5.3)
|
||||
redis (~> 3.0, >= 3.0.4)
|
||||
redis-rack (2.0.2)
|
||||
rack (>= 1.5, < 3)
|
||||
redis-store (>= 1.2, < 1.4)
|
||||
@@ -396,34 +371,32 @@ GEM
|
||||
redis-store (>= 1.2, < 2)
|
||||
redis-store (1.3.0)
|
||||
redis (>= 2.2)
|
||||
responders (2.4.0)
|
||||
actionpack (>= 4.2.0, < 5.3)
|
||||
railties (>= 4.2.0, < 5.3)
|
||||
responders (2.3.0)
|
||||
railties (>= 4.2.0, < 5.1)
|
||||
rotp (2.1.2)
|
||||
rqrcode (0.10.1)
|
||||
chunky_png (~> 1.0)
|
||||
rspec-core (3.6.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-expectations (3.6.0)
|
||||
rspec-core (3.5.4)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-expectations (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-mocks (3.6.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-mocks (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-rails (3.6.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-rails (3.5.2)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.6.0)
|
||||
rspec-expectations (~> 3.6.0)
|
||||
rspec-mocks (~> 3.6.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-sidekiq (3.0.3)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-sidekiq (3.0.0)
|
||||
rspec-core (~> 3.0, >= 3.0.0)
|
||||
sidekiq (>= 2.4.0)
|
||||
rspec-support (3.6.0)
|
||||
rubocop (0.49.1)
|
||||
parallel (~> 1.10)
|
||||
rspec-support (3.5.0)
|
||||
rubocop (0.48.1)
|
||||
parser (>= 2.3.3.1, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
@@ -431,63 +404,63 @@ GEM
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
ruby-oembed (0.12.0)
|
||||
ruby-progressbar (1.8.1)
|
||||
rufus-scheduler (3.4.2)
|
||||
rufus-scheduler (3.4.0)
|
||||
et-orbi (~> 1.0)
|
||||
safe_yaml (1.0.4)
|
||||
sanitize (4.5.0)
|
||||
sanitize (4.4.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.4.4)
|
||||
nokogumbo (~> 1.4.1)
|
||||
sass (3.4.24)
|
||||
scss_lint (0.54.0)
|
||||
rake (>= 0.9, < 13)
|
||||
sass (~> 3.4.20)
|
||||
sidekiq (5.0.4)
|
||||
sass (3.4.23)
|
||||
sass-rails (5.0.6)
|
||||
railties (>= 4.0.0, < 6)
|
||||
sass (~> 3.1)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
sidekiq (4.2.10)
|
||||
concurrent-ruby (~> 1.0)
|
||||
connection_pool (~> 2.2, >= 2.2.0)
|
||||
rack-protection (>= 1.5.0)
|
||||
redis (~> 3.3, >= 3.3.3)
|
||||
sidekiq-bulk (0.1.1)
|
||||
activesupport
|
||||
sidekiq
|
||||
sidekiq-scheduler (2.1.8)
|
||||
redis (~> 3.2, >= 3.2.1)
|
||||
sidekiq-scheduler (2.1.4)
|
||||
redis (~> 3)
|
||||
rufus-scheduler (~> 3.2)
|
||||
sidekiq (>= 3)
|
||||
tilt (>= 1.4.0)
|
||||
sidekiq-unique-jobs (5.0.9)
|
||||
sidekiq (>= 4.0, <= 6.0)
|
||||
thor (~> 0)
|
||||
sidekiq-unique-jobs (5.0.0)
|
||||
sidekiq (>= 4.0)
|
||||
thor
|
||||
simple-navigation (4.0.5)
|
||||
activesupport (>= 2.3.2)
|
||||
simple_form (3.5.0)
|
||||
actionpack (> 4, < 5.2)
|
||||
activemodel (> 4, < 5.2)
|
||||
simple_form (3.4.0)
|
||||
actionpack (> 4, < 5.1)
|
||||
activemodel (> 4, < 5.1)
|
||||
simplecov (0.14.1)
|
||||
docile (~> 1.1.0)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.1)
|
||||
simplecov-html (0.10.0)
|
||||
slop (3.6.0)
|
||||
sprockets (3.7.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.2.1)
|
||||
sprockets-rails (3.2.0)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
sshkit (1.13.1)
|
||||
net-scp (>= 1.1.2)
|
||||
net-ssh (>= 2.8.0)
|
||||
statsd-instrument (2.1.4)
|
||||
statsd-instrument (2.1.2)
|
||||
temple (0.8.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thor (0.20.0)
|
||||
terminal-table (1.7.3)
|
||||
unicode-display_width (~> 1.1.1)
|
||||
thor (0.19.4)
|
||||
thread (0.2.2)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.8)
|
||||
twitter-text (1.14.7)
|
||||
tilt (2.0.7)
|
||||
twitter-text (1.14.5)
|
||||
unf (~> 0.1.0)
|
||||
tzinfo (1.2.3)
|
||||
thread_safe (~> 0.1)
|
||||
@@ -498,7 +471,7 @@ GEM
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.4)
|
||||
unicode-display_width (1.3.0)
|
||||
unicode-display_width (1.1.3)
|
||||
uniform_notifier (1.10.0)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
@@ -506,121 +479,103 @@ GEM
|
||||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff
|
||||
webpacker (2.0)
|
||||
activesupport (>= 4.2)
|
||||
multi_json (~> 1.2)
|
||||
railties (>= 4.2)
|
||||
webpush (0.3.2)
|
||||
hkdf (~> 0.2)
|
||||
jwt
|
||||
websocket-driver (0.6.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.2)
|
||||
xpath (2.1.0)
|
||||
whatlanguage (1.0.6)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
active_model_serializers (~> 0.10)
|
||||
active_record_query_trace (~> 1.5)
|
||||
addressable (~> 2.5)
|
||||
annotate (~> 2.7)
|
||||
aws-sdk (~> 2.9)
|
||||
better_errors (~> 2.1)
|
||||
binding_of_caller (~> 0.7)
|
||||
bootsnap
|
||||
brakeman (~> 3.6)
|
||||
browser
|
||||
bullet (~> 5.5)
|
||||
bundler-audit (~> 0.5)
|
||||
capistrano (~> 3.8)
|
||||
capistrano-rails (~> 1.2)
|
||||
capistrano-rbenv (~> 2.1)
|
||||
capistrano-yarn (~> 2.0)
|
||||
capybara (~> 2.14)
|
||||
charlock_holmes (~> 0.7.5)
|
||||
cld3 (~> 3.2.0)
|
||||
climate_control (~> 0.2)
|
||||
devise (~> 4.2)
|
||||
devise-two-factor (~> 3.0)
|
||||
doorkeeper (~> 4.2)
|
||||
dotenv-rails (~> 2.2)
|
||||
fabrication (~> 2.16)
|
||||
faker (~> 1.7)
|
||||
fast_blank (~> 1.0)
|
||||
fog-openstack (~> 0.1)
|
||||
fuubar (~> 2.2)
|
||||
goldfinger (~> 2.0)
|
||||
hamlit-rails (~> 0.2)
|
||||
hiredis (~> 0.6)
|
||||
htmlentities (~> 4.3)
|
||||
http (~> 2.2)
|
||||
http_accept_language (~> 2.1)
|
||||
httplog (~> 0.99)
|
||||
i18n-tasks (~> 0.9)
|
||||
idn-ruby
|
||||
iso-639
|
||||
json-ld-preloaded (~> 2.2.1)
|
||||
kaminari (~> 1.0)
|
||||
letter_opener (~> 1.4)
|
||||
letter_opener_web (~> 1.3)
|
||||
link_header (~> 0.0)
|
||||
lograge (~> 0.5)
|
||||
mario-redis-lock (~> 1.2)
|
||||
microformats (~> 4.0)
|
||||
mime-types (~> 3.1)
|
||||
nokogiri (~> 1.7)
|
||||
oj (~> 3.0)
|
||||
active_record_query_trace
|
||||
addressable
|
||||
autoprefixer-rails
|
||||
aws-sdk (>= 2.0)
|
||||
best_in_place (~> 3.0.1)
|
||||
better_errors
|
||||
binding_of_caller
|
||||
browserify-rails
|
||||
bullet
|
||||
capistrano (= 3.8.0)
|
||||
capistrano-faster-assets (~> 1.0)
|
||||
capistrano-rails
|
||||
capistrano-rbenv
|
||||
capistrano-yarn
|
||||
capybara
|
||||
devise
|
||||
devise-two-factor
|
||||
doorkeeper
|
||||
dotenv-rails
|
||||
fabrication
|
||||
faker
|
||||
fast_blank
|
||||
font-awesome-rails
|
||||
fuubar
|
||||
goldfinger
|
||||
hamlit-rails
|
||||
hiredis
|
||||
htmlentities
|
||||
http
|
||||
http_accept_language
|
||||
httplog
|
||||
i18n-tasks (~> 0.9.6)
|
||||
jquery-rails
|
||||
kaminari
|
||||
letter_opener
|
||||
letter_opener_web
|
||||
link_header
|
||||
local_time
|
||||
lograge
|
||||
microformats2
|
||||
nokogiri
|
||||
oj
|
||||
ostatus2 (~> 2.0)
|
||||
ox (~> 2.5)
|
||||
ox
|
||||
paperclip (~> 5.1)
|
||||
paperclip-av-transcoder (~> 0.6)
|
||||
parallel_tests (~> 2.14)
|
||||
pg (~> 0.20)
|
||||
pghero (~> 1.7)
|
||||
pkg-config (~> 1.2)
|
||||
pry-rails (~> 0.3)
|
||||
puma (~> 3.10)
|
||||
pundit (~> 1.1)
|
||||
rabl (~> 0.13)
|
||||
rack-attack (~> 5.0)
|
||||
rack-cors (~> 0.4)
|
||||
rack-timeout (~> 0.4)
|
||||
rails (~> 5.1.4)
|
||||
rails-controller-testing (~> 1.0)
|
||||
rails-i18n (~> 5.0)
|
||||
rails-settings-cached (~> 0.6)
|
||||
rdf-normalize (~> 0.3.1)
|
||||
redis (~> 3.3)
|
||||
redis-namespace (~> 1.5)
|
||||
redis-rails (~> 5.0)
|
||||
rqrcode (~> 0.10)
|
||||
rspec-rails (~> 3.6)
|
||||
rspec-sidekiq (~> 3.0)
|
||||
paperclip-av-transcoder
|
||||
pg
|
||||
pghero
|
||||
pkg-config
|
||||
pry-rails
|
||||
puma
|
||||
rabl
|
||||
rack-attack
|
||||
rack-cors
|
||||
rack-timeout
|
||||
rails (~> 5.0.2)
|
||||
rails-controller-testing
|
||||
rails-i18n
|
||||
rails-settings-cached
|
||||
rails_12factor
|
||||
react-rails
|
||||
redis (~> 3.2)
|
||||
redis-rails
|
||||
rqrcode
|
||||
rspec-rails
|
||||
rspec-sidekiq
|
||||
rubocop
|
||||
ruby-oembed (~> 0.12)
|
||||
sanitize (~> 4.4)
|
||||
scss_lint (~> 0.53)
|
||||
sidekiq (~> 5.0)
|
||||
sidekiq-bulk (~> 0.1.1)
|
||||
sidekiq-scheduler (~> 2.1)
|
||||
sidekiq-unique-jobs (~> 5.0)
|
||||
simple-navigation (~> 4.0)
|
||||
simple_form (~> 3.4)
|
||||
simplecov (~> 0.14)
|
||||
sprockets-rails (~> 3.2)
|
||||
statsd-instrument (~> 2.1)
|
||||
twitter-text (~> 1.14)
|
||||
tzinfo-data (~> 1.2017)
|
||||
uglifier (~> 3.2)
|
||||
webmock (~> 3.0)
|
||||
webpacker (~> 2.0)
|
||||
webpush
|
||||
ruby-oembed
|
||||
sanitize
|
||||
sass-rails (~> 5.0)
|
||||
sidekiq
|
||||
sidekiq-scheduler
|
||||
sidekiq-unique-jobs
|
||||
simple-navigation
|
||||
simple_form
|
||||
simplecov
|
||||
sprockets-rails
|
||||
statsd-instrument
|
||||
twitter-text
|
||||
tzinfo-data
|
||||
uglifier (>= 1.3.0)
|
||||
webmock
|
||||
whatlanguage
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.4.1p111
|
||||
|
||||
BUNDLED WITH
|
||||
1.15.4
|
||||
1.14.6
|
||||
|
@@ -1,4 +0,0 @@
|
||||
web: PORT=3000 bundle exec puma -C config/puma.rb
|
||||
sidekiq: PORT=3000 bundle exec sidekiq
|
||||
stream: PORT=4000 yarn run start
|
||||
webpack: ./bin/webpack-dev-server --host 0.0.0.0
|
12
README.md
@@ -1,4 +1,4 @@
|
||||

|
||||
Mastodon
|
||||
========
|
||||
|
||||
[][travis]
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
Mastodon is a free, open-source social network server. A decentralized solution to commercial platforms, it avoids the risks of a single company monopolizing your communication. Anyone can run Mastodon and participate in the social network seamlessly.
|
||||
|
||||
An alternative implementation of the GNU social project. Based on [ActivityStreams](https://en.wikipedia.org/wiki/Activity_Streams_(format)), [Webfinger](https://en.wikipedia.org/wiki/WebFinger), [WebSub](https://en.wikipedia.org/wiki/WebSub) and [Salmon](https://en.wikipedia.org/wiki/Salmon_(protocol)).
|
||||
An alternative implementation of the GNU social project. Based on [ActivityStreams](https://en.wikipedia.org/wiki/Activity_Streams_(format)), [Webfinger](https://en.wikipedia.org/wiki/WebFinger), [PubsubHubbub](https://en.wikipedia.org/wiki/PubSubHubbub) and [Salmon](https://en.wikipedia.org/wiki/Salmon_(protocol)).
|
||||
|
||||
Click on the screenshot to watch a demo of the UI:
|
||||
|
||||
[][youtube_demo]
|
||||
[][youtube_demo]
|
||||
|
||||
[youtube_demo]: https://www.youtube.com/watch?v=YO1jQ8_rAMU
|
||||
|
||||
@@ -34,7 +34,7 @@ If you would like, you can [support the development of this project on Patreon][
|
||||
## Features
|
||||
|
||||
- **Fully interoperable with GNU social and any OStatus platform**
|
||||
Whatever implements Atom feeds, ActivityStreams, Salmon, WebSub and Webfinger is part of the network
|
||||
Whatever implements Atom feeds, ActivityStreams, Salmon, PubSubHubbub and Webfinger is part of the network
|
||||
- **Real-time timeline updates**
|
||||
See the updates of people you're following appear in real-time in the UI via WebSockets
|
||||
- **Federated thread resolving**
|
||||
@@ -47,10 +47,6 @@ If you would like, you can [support the development of this project on Patreon][
|
||||
Mastodon tries to be as fast and responsive as possible, so all long-running tasks that can be delegated to background processing, are
|
||||
- **Deployable via Docker**
|
||||
You don't need to mess with dependencies and configuration if you want to try Mastodon, if you have Docker and Docker Compose the deployment is extremely easy
|
||||
|
||||
## Development
|
||||
|
||||
Please follow the [development guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md) from the documentation repository.
|
||||
|
||||
## Deployment
|
||||
|
||||
|
37
Vagrantfile
vendored
@@ -1,8 +1,6 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
ENV["PORT"] ||= "3000"
|
||||
|
||||
$provision = <<SCRIPT
|
||||
|
||||
cd /vagrant # This is where the host folder/repo is mounted
|
||||
@@ -12,10 +10,10 @@ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
||||
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
|
||||
|
||||
# Add repo for NodeJS
|
||||
curl -sL https://deb.nodesource.com/setup_6.x | sudo bash -
|
||||
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -
|
||||
|
||||
# Add firewall rule to redirect 80 to PORT and save
|
||||
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
|
||||
# Add firewall rule to redirect 80 to 3000 and save
|
||||
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000
|
||||
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections
|
||||
echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections
|
||||
sudo apt-get install iptables-persistent -y
|
||||
@@ -33,45 +31,38 @@ sudo apt-get install \
|
||||
redis-tools \
|
||||
postgresql \
|
||||
postgresql-contrib \
|
||||
protobuf-compiler \
|
||||
yarn \
|
||||
libicu-dev \
|
||||
libidn11-dev \
|
||||
libprotobuf-dev \
|
||||
libreadline-dev \
|
||||
-y
|
||||
|
||||
# Install rvm
|
||||
cd /vagrant
|
||||
read RUBY_VERSION < .ruby-version
|
||||
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
|
||||
curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION
|
||||
curl -sSL https://get.rvm.io | bash -s stable --ruby=$RUBY_VERSION
|
||||
source /home/vagrant/.rvm/scripts/rvm
|
||||
|
||||
# Install Ruby
|
||||
rvm install ruby-$RUBY_VERSION
|
||||
|
||||
# Configure database
|
||||
sudo -u postgres createuser -U postgres vagrant -s
|
||||
sudo -u postgres createdb -U postgres mastodon_development
|
||||
|
||||
# Install gems and node modules
|
||||
gem install bundler foreman
|
||||
gem install bundler
|
||||
bundle install
|
||||
yarn install
|
||||
|
||||
# Build Mastodon
|
||||
export $(cat ".env.vagrant" | xargs)
|
||||
bundle exec rails db:setup
|
||||
|
||||
# Configure automatic loading of environment variable
|
||||
echo 'export $(cat "/vagrant/.env.vagrant" | xargs)' >> ~/.bash_profile
|
||||
bundle exec rails assets:precompile
|
||||
|
||||
SCRIPT
|
||||
|
||||
$start = <<SCRIPT
|
||||
|
||||
echo 'To start server'
|
||||
echo ' $ vagrant ssh -c "cd /vagrant && foreman start"'
|
||||
cd /vagrant
|
||||
export $(cat ".env.vagrant" | xargs)
|
||||
rails s -d -b 0.0.0.0
|
||||
|
||||
SCRIPT
|
||||
|
||||
@@ -83,7 +74,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
|
||||
config.vm.provider :virtualbox do |vb|
|
||||
vb.name = "mastodon"
|
||||
vb.customize ["modifyvm", :id, "--memory", "2048"]
|
||||
vb.customize ["modifyvm", :id, "--memory", "1024"]
|
||||
|
||||
# Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions.
|
||||
# https://github.com/mitchellh/vagrant/issues/1172
|
||||
@@ -113,10 +104,8 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
config.vm.synced_folder ".", "/vagrant"
|
||||
end
|
||||
|
||||
# Otherwise, you can access the site at http://localhost:3000 and http://localhost:4000 , http://localhost:8080
|
||||
config.vm.network :forwarded_port, guest: 3000, host: 3000
|
||||
config.vm.network :forwarded_port, guest: 4000, host: 4000
|
||||
config.vm.network :forwarded_port, guest: 8080, host: 8080
|
||||
# Otherwise, you can access the site at http://localhost:3000
|
||||
config.vm.network :forwarded_port, guest: 80, host: 3000
|
||||
|
||||
# Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision'
|
||||
config.vm.provision :shell, inline: $provision, privileged: false
|
||||
|
5
app.json
@@ -2,7 +2,7 @@
|
||||
"name": "Mastodon",
|
||||
"description": "A GNU Social-compatible microblogging server",
|
||||
"repository": "https://github.com/tootsuite/mastodon",
|
||||
"logo": "https://github.com/tootsuite.png",
|
||||
"logo": "https://github.com/tootsuite/mastodon/raw/master/app/assets/images/logo.png",
|
||||
"env": {
|
||||
"HEROKU": {
|
||||
"description": "Leave this as true",
|
||||
@@ -94,9 +94,6 @@
|
||||
}
|
||||
},
|
||||
"buildpacks": [
|
||||
{
|
||||
"url": "https://github.com/heroku/heroku-buildpack-apt"
|
||||
},
|
||||
{
|
||||
"url": "heroku/nodejs"
|
||||
},
|
||||
|
BIN
app/assets/fonts/montserrat/Montserrat-Regular.eot
Normal file
BIN
app/assets/fonts/roboto-mono/robotomono-regular-webfont.eot
Normal file
Before Width: | Height: | Size: 339 KiB After Width: | Height: | Size: 339 KiB |
BIN
app/assets/fonts/roboto/roboto-bold-webfont.eot
Normal file
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
BIN
app/assets/fonts/roboto/roboto-italic-webfont.eot
Normal file
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
BIN
app/assets/fonts/roboto/roboto-medium-webfont.eot
Normal file
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
BIN
app/assets/fonts/roboto/roboto-regular-webfont.eot
Normal file
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
BIN
app/assets/images/background-photo.jpg
Normal file
After Width: | Height: | Size: 258 KiB |
BIN
app/assets/images/boost_sprite.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
BIN
app/assets/images/fluffy-elephant-friend.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
app/assets/images/logo.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
1
app/assets/images/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000" height="1000" width="1000"><path d="M500 0a500 500 0 0 0-353.553 146.447 500 500 0 1 0 707.106 707.106A500 500 0 0 0 500 0zm-.059 280.05h107.12c-19.071 13.424-26.187 51.016-27.12 73.843V562.05c0 44.32-35.68 80-80 80s-80-35.68-80-80v-202c0-44.32 35.68-80 80-80zm-.441 52c-15.464 0-28 12.537-28 28 0 15.465 12.536 28 28 28s28-12.535 28-28c0-15.463-12.536-28-28-28zm-279.059 7.9c44.32 0 80 35.68 80 80v206.157c.933 22.827 8.049 60.42 27.12 73.842H220.44c-44.32 0-80-35.68-80-80v-200c0-44.32 35.68-80 80-80zm559.12 0c44.32 0 80 35.68 80 80v200c0 44.32-35.68 80-80 80H672.44c19.071-13.424 26.187-51.016 27.12-73.843V419.95c0-44.32 35.68-80 80-80zM220 392c-15.464 0-28 12.536-28 28s12.536 28 28 28 28-12.536 28-28-12.536-28-28-28zm560 0c-15.464 0-28 12.536-28 28s12.536 28 28 28 28-12.536 28-28-12.536-28-28-28zm-280.5 40.05c-15.464 0-28 12.537-28 28 0 15.465 12.536 28 28 28s28-12.535 28-28c0-15.463-12.536-28-28-28zM220 491.95c-15.464 0-28 12.535-28 28 0 15.463 12.536 28 28 28s28-12.537 28-28c0-15.465-12.536-28-28-28zm560 0c-15.464 0-28 12.535-28 28 0 15.463 12.536 28 28 28s28-12.537 28-28c0-15.465-12.536-28-28-28zM499.5 532c-15.464 0-28 12.536-28 28s12.536 28 28 28 28-12.536 28-28-12.536-28-28-28zM220 591.95c-15.464 0-28 12.535-28 28 0 15.463 12.536 28 28 28s28-12.537 28-28c0-15.465-12.536-28-28-28zm560 0c-15.464 0-28 12.535-28 28 0 15.463 12.536 28 28 28s28-12.537 28-28c0-15.465-12.536-28-28-28z" fill="#189efc"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
BIN
app/assets/images/mastodon.jpg
Normal file
After Width: | Height: | Size: 131 KiB |
BIN
app/assets/images/mastodon_small.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
app/assets/images/screenshot.png
Normal file
After Width: | Height: | Size: 244 KiB |
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 174 B |
15
app/assets/javascripts/application.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
||||
// listed below.
|
||||
//
|
||||
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
||||
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
||||
//
|
||||
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||
// compiled file.
|
||||
//
|
||||
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
||||
// about supported directives.
|
||||
//
|
||||
//= require jquery2
|
||||
//= require jquery_ujs
|
||||
//= require components
|
9
app/assets/javascripts/application_public.js
Normal file
@@ -0,0 +1,9 @@
|
||||
//= require jquery2
|
||||
//= require jquery_ujs
|
||||
//= require extras
|
||||
//= require best_in_place
|
||||
//= require local_time
|
||||
|
||||
$(function () {
|
||||
$(".best_in_place").best_in_place();
|
||||
});
|
15
app/assets/javascripts/components.js
Normal file
@@ -0,0 +1,15 @@
|
||||
//= require_self
|
||||
//= require react_ujs
|
||||
|
||||
window.React = require('react');
|
||||
window.ReactDOM = require('react-dom');
|
||||
window.Perf = require('react-addons-perf');
|
||||
|
||||
if (!window.Intl) {
|
||||
require('intl');
|
||||
require('intl/locale-data/jsonp/en.js');
|
||||
}
|
||||
|
||||
//= require_tree ./components
|
||||
|
||||
window.Mastodon = require('./components/containers/mastodon');
|
0
app/assets/javascripts/components/.gitkeep
Normal file
@@ -1,4 +1,5 @@
|
||||
import api, { getLinks } from '../api';
|
||||
import api, { getLinks } from '../api'
|
||||
import Immutable from 'immutable';
|
||||
|
||||
export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
|
||||
export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS';
|
||||
@@ -28,6 +29,14 @@ export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
|
||||
export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS';
|
||||
export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
|
||||
|
||||
export const ACCOUNT_TIMELINE_FETCH_REQUEST = 'ACCOUNT_TIMELINE_FETCH_REQUEST';
|
||||
export const ACCOUNT_TIMELINE_FETCH_SUCCESS = 'ACCOUNT_TIMELINE_FETCH_SUCCESS';
|
||||
export const ACCOUNT_TIMELINE_FETCH_FAIL = 'ACCOUNT_TIMELINE_FETCH_FAIL';
|
||||
|
||||
export const ACCOUNT_TIMELINE_EXPAND_REQUEST = 'ACCOUNT_TIMELINE_EXPAND_REQUEST';
|
||||
export const ACCOUNT_TIMELINE_EXPAND_SUCCESS = 'ACCOUNT_TIMELINE_EXPAND_SUCCESS';
|
||||
export const ACCOUNT_TIMELINE_EXPAND_FAIL = 'ACCOUNT_TIMELINE_EXPAND_FAIL';
|
||||
|
||||
export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
|
||||
export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS';
|
||||
export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL';
|
||||
@@ -82,17 +91,60 @@ export function fetchAccount(id) {
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchAccountTimeline(id, replace = false) {
|
||||
return (dispatch, getState) => {
|
||||
const ids = getState().getIn(['timelines', 'accounts_timelines', id, 'items'], Immutable.List());
|
||||
const newestId = ids.size > 0 ? ids.first() : null;
|
||||
|
||||
let params = '';
|
||||
let skipLoading = false;
|
||||
|
||||
if (newestId !== null && !replace) {
|
||||
params = `?since_id=${newestId}`;
|
||||
skipLoading = true;
|
||||
}
|
||||
|
||||
dispatch(fetchAccountTimelineRequest(id, skipLoading));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${id}/statuses${params}`).then(response => {
|
||||
dispatch(fetchAccountTimelineSuccess(id, response.data, replace, skipLoading));
|
||||
}).catch(error => {
|
||||
dispatch(fetchAccountTimelineFail(id, error, skipLoading));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function expandAccountTimeline(id) {
|
||||
return (dispatch, getState) => {
|
||||
const lastId = getState().getIn(['timelines', 'accounts_timelines', id, 'items'], Immutable.List()).last();
|
||||
|
||||
dispatch(expandAccountTimelineRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${id}/statuses`, {
|
||||
params: {
|
||||
limit: 10,
|
||||
max_id: lastId
|
||||
}
|
||||
}).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(expandAccountTimelineSuccess(id, response.data, next));
|
||||
}).catch(error => {
|
||||
dispatch(expandAccountTimelineFail(id, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchAccountRequest(id) {
|
||||
return {
|
||||
type: ACCOUNT_FETCH_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchAccountSuccess(account) {
|
||||
return {
|
||||
type: ACCOUNT_FETCH_SUCCESS,
|
||||
account,
|
||||
account
|
||||
};
|
||||
};
|
||||
|
||||
@@ -101,7 +153,7 @@ export function fetchAccountFail(id, error) {
|
||||
type: ACCOUNT_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipAlert: true,
|
||||
skipAlert: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -126,48 +178,100 @@ export function unfollowAccount(id) {
|
||||
}).catch(error => {
|
||||
dispatch(unfollowAccountFail(error));
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export function followAccountRequest(id) {
|
||||
return {
|
||||
type: ACCOUNT_FOLLOW_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
export function followAccountSuccess(relationship) {
|
||||
return {
|
||||
type: ACCOUNT_FOLLOW_SUCCESS,
|
||||
relationship,
|
||||
relationship
|
||||
};
|
||||
};
|
||||
|
||||
export function followAccountFail(error) {
|
||||
return {
|
||||
type: ACCOUNT_FOLLOW_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
export function unfollowAccountRequest(id) {
|
||||
return {
|
||||
type: ACCOUNT_UNFOLLOW_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
export function unfollowAccountSuccess(relationship) {
|
||||
return {
|
||||
type: ACCOUNT_UNFOLLOW_SUCCESS,
|
||||
relationship,
|
||||
relationship
|
||||
};
|
||||
};
|
||||
|
||||
export function unfollowAccountFail(error) {
|
||||
return {
|
||||
type: ACCOUNT_UNFOLLOW_FAIL,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchAccountTimelineRequest(id, skipLoading) {
|
||||
return {
|
||||
type: ACCOUNT_TIMELINE_FETCH_REQUEST,
|
||||
id,
|
||||
skipLoading
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchAccountTimelineSuccess(id, statuses, replace, skipLoading) {
|
||||
return {
|
||||
type: ACCOUNT_TIMELINE_FETCH_SUCCESS,
|
||||
id,
|
||||
statuses,
|
||||
replace,
|
||||
skipLoading
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchAccountTimelineFail(id, error, skipLoading) {
|
||||
return {
|
||||
type: ACCOUNT_TIMELINE_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipLoading,
|
||||
skipAlert: error.response.status === 404
|
||||
};
|
||||
};
|
||||
|
||||
export function expandAccountTimelineRequest(id) {
|
||||
return {
|
||||
type: ACCOUNT_TIMELINE_EXPAND_REQUEST,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
export function expandAccountTimelineSuccess(id, statuses, next) {
|
||||
return {
|
||||
type: ACCOUNT_TIMELINE_EXPAND_SUCCESS,
|
||||
id,
|
||||
statuses,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function expandAccountTimelineFail(id, error) {
|
||||
return {
|
||||
type: ACCOUNT_TIMELINE_EXPAND_FAIL,
|
||||
id,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -199,7 +303,7 @@ export function unblockAccount(id) {
|
||||
export function blockAccountRequest(id) {
|
||||
return {
|
||||
type: ACCOUNT_BLOCK_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -207,35 +311,35 @@ export function blockAccountSuccess(relationship, statuses) {
|
||||
return {
|
||||
type: ACCOUNT_BLOCK_SUCCESS,
|
||||
relationship,
|
||||
statuses,
|
||||
statuses
|
||||
};
|
||||
};
|
||||
|
||||
export function blockAccountFail(error) {
|
||||
return {
|
||||
type: ACCOUNT_BLOCK_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
export function unblockAccountRequest(id) {
|
||||
return {
|
||||
type: ACCOUNT_UNBLOCK_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
export function unblockAccountSuccess(relationship) {
|
||||
return {
|
||||
type: ACCOUNT_UNBLOCK_SUCCESS,
|
||||
relationship,
|
||||
relationship
|
||||
};
|
||||
};
|
||||
|
||||
export function unblockAccountFail(error) {
|
||||
return {
|
||||
type: ACCOUNT_UNBLOCK_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -268,7 +372,7 @@ export function unmuteAccount(id) {
|
||||
export function muteAccountRequest(id) {
|
||||
return {
|
||||
type: ACCOUNT_MUTE_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -276,35 +380,35 @@ export function muteAccountSuccess(relationship, statuses) {
|
||||
return {
|
||||
type: ACCOUNT_MUTE_SUCCESS,
|
||||
relationship,
|
||||
statuses,
|
||||
statuses
|
||||
};
|
||||
};
|
||||
|
||||
export function muteAccountFail(error) {
|
||||
return {
|
||||
type: ACCOUNT_MUTE_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
export function unmuteAccountRequest(id) {
|
||||
return {
|
||||
type: ACCOUNT_UNMUTE_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
export function unmuteAccountSuccess(relationship) {
|
||||
return {
|
||||
type: ACCOUNT_UNMUTE_SUCCESS,
|
||||
relationship,
|
||||
relationship
|
||||
};
|
||||
};
|
||||
|
||||
export function unmuteAccountFail(error) {
|
||||
return {
|
||||
type: ACCOUNT_UNMUTE_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -327,7 +431,7 @@ export function fetchFollowers(id) {
|
||||
export function fetchFollowersRequest(id) {
|
||||
return {
|
||||
type: FOLLOWERS_FETCH_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -336,7 +440,7 @@ export function fetchFollowersSuccess(id, accounts, next) {
|
||||
type: FOLLOWERS_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
@@ -344,7 +448,7 @@ export function fetchFollowersFail(id, error) {
|
||||
return {
|
||||
type: FOLLOWERS_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -372,7 +476,7 @@ export function expandFollowers(id) {
|
||||
export function expandFollowersRequest(id) {
|
||||
return {
|
||||
type: FOLLOWERS_EXPAND_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -381,7 +485,7 @@ export function expandFollowersSuccess(id, accounts, next) {
|
||||
type: FOLLOWERS_EXPAND_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
@@ -389,7 +493,7 @@ export function expandFollowersFail(id, error) {
|
||||
return {
|
||||
type: FOLLOWERS_EXPAND_FAIL,
|
||||
id,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -411,7 +515,7 @@ export function fetchFollowing(id) {
|
||||
export function fetchFollowingRequest(id) {
|
||||
return {
|
||||
type: FOLLOWING_FETCH_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -420,7 +524,7 @@ export function fetchFollowingSuccess(id, accounts, next) {
|
||||
type: FOLLOWING_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
@@ -428,7 +532,7 @@ export function fetchFollowingFail(id, error) {
|
||||
return {
|
||||
type: FOLLOWING_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -456,7 +560,7 @@ export function expandFollowing(id) {
|
||||
export function expandFollowingRequest(id) {
|
||||
return {
|
||||
type: FOLLOWING_EXPAND_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -465,7 +569,7 @@ export function expandFollowingSuccess(id, accounts, next) {
|
||||
type: FOLLOWING_EXPAND_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
@@ -473,7 +577,7 @@ export function expandFollowingFail(id, error) {
|
||||
return {
|
||||
type: FOLLOWING_EXPAND_FAIL,
|
||||
id,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -500,7 +604,7 @@ export function fetchRelationshipsRequest(ids) {
|
||||
return {
|
||||
type: RELATIONSHIPS_FETCH_REQUEST,
|
||||
ids,
|
||||
skipLoading: true,
|
||||
skipLoading: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -508,7 +612,7 @@ export function fetchRelationshipsSuccess(relationships) {
|
||||
return {
|
||||
type: RELATIONSHIPS_FETCH_SUCCESS,
|
||||
relationships,
|
||||
skipLoading: true,
|
||||
skipLoading: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -516,7 +620,7 @@ export function fetchRelationshipsFail(error) {
|
||||
return {
|
||||
type: RELATIONSHIPS_FETCH_FAIL,
|
||||
error,
|
||||
skipLoading: true,
|
||||
skipLoading: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -526,14 +630,14 @@ export function fetchFollowRequests() {
|
||||
|
||||
api(getState).get('/api/v1/follow_requests').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null))
|
||||
}).catch(error => dispatch(fetchFollowRequestsFail(error)));
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchFollowRequestsRequest() {
|
||||
return {
|
||||
type: FOLLOW_REQUESTS_FETCH_REQUEST,
|
||||
type: FOLLOW_REQUESTS_FETCH_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -541,14 +645,14 @@ export function fetchFollowRequestsSuccess(accounts, next) {
|
||||
return {
|
||||
type: FOLLOW_REQUESTS_FETCH_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchFollowRequestsFail(error) {
|
||||
return {
|
||||
type: FOLLOW_REQUESTS_FETCH_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -564,14 +668,14 @@ export function expandFollowRequests() {
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null))
|
||||
}).catch(error => dispatch(expandFollowRequestsFail(error)));
|
||||
};
|
||||
};
|
||||
|
||||
export function expandFollowRequestsRequest() {
|
||||
return {
|
||||
type: FOLLOW_REQUESTS_EXPAND_REQUEST,
|
||||
type: FOLLOW_REQUESTS_EXPAND_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -579,14 +683,14 @@ export function expandFollowRequestsSuccess(accounts, next) {
|
||||
return {
|
||||
type: FOLLOW_REQUESTS_EXPAND_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function expandFollowRequestsFail(error) {
|
||||
return {
|
||||
type: FOLLOW_REQUESTS_EXPAND_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -596,7 +700,7 @@ export function authorizeFollowRequest(id) {
|
||||
|
||||
api(getState)
|
||||
.post(`/api/v1/follow_requests/${id}/authorize`)
|
||||
.then(() => dispatch(authorizeFollowRequestSuccess(id)))
|
||||
.then(response => dispatch(authorizeFollowRequestSuccess(id)))
|
||||
.catch(error => dispatch(authorizeFollowRequestFail(id, error)));
|
||||
};
|
||||
};
|
||||
@@ -604,14 +708,14 @@ export function authorizeFollowRequest(id) {
|
||||
export function authorizeFollowRequestRequest(id) {
|
||||
return {
|
||||
type: FOLLOW_REQUEST_AUTHORIZE_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
export function authorizeFollowRequestSuccess(id) {
|
||||
return {
|
||||
type: FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -619,7 +723,7 @@ export function authorizeFollowRequestFail(id, error) {
|
||||
return {
|
||||
type: FOLLOW_REQUEST_AUTHORIZE_FAIL,
|
||||
id,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -630,7 +734,7 @@ export function rejectFollowRequest(id) {
|
||||
|
||||
api(getState)
|
||||
.post(`/api/v1/follow_requests/${id}/reject`)
|
||||
.then(() => dispatch(rejectFollowRequestSuccess(id)))
|
||||
.then(response => dispatch(rejectFollowRequestSuccess(id)))
|
||||
.catch(error => dispatch(rejectFollowRequestFail(id, error)));
|
||||
};
|
||||
};
|
||||
@@ -638,14 +742,14 @@ export function rejectFollowRequest(id) {
|
||||
export function rejectFollowRequestRequest(id) {
|
||||
return {
|
||||
type: FOLLOW_REQUEST_REJECT_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
export function rejectFollowRequestSuccess(id) {
|
||||
return {
|
||||
type: FOLLOW_REQUEST_REJECT_SUCCESS,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -653,6 +757,6 @@ export function rejectFollowRequestFail(id, error) {
|
||||
return {
|
||||
type: FOLLOW_REQUEST_REJECT_FAIL,
|
||||
id,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
@@ -5,13 +5,13 @@ export const ALERT_CLEAR = 'ALERT_CLEAR';
|
||||
export function dismissAlert(alert) {
|
||||
return {
|
||||
type: ALERT_DISMISS,
|
||||
alert,
|
||||
alert
|
||||
};
|
||||
};
|
||||
|
||||
export function clearAlert() {
|
||||
return {
|
||||
type: ALERT_CLEAR,
|
||||
type: ALERT_CLEAR
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,6 +19,6 @@ export function showAlert(title, message) {
|
||||
return {
|
||||
type: ALERT_SHOW,
|
||||
title,
|
||||
message,
|
||||
message
|
||||
};
|
||||
};
|
@@ -1,4 +1,4 @@
|
||||
import api, { getLinks } from '../api';
|
||||
import api, { getLinks } from '../api'
|
||||
import { fetchRelationships } from './accounts';
|
||||
|
||||
export const BLOCKS_FETCH_REQUEST = 'BLOCKS_FETCH_REQUEST';
|
||||
@@ -23,7 +23,7 @@ export function fetchBlocks() {
|
||||
|
||||
export function fetchBlocksRequest() {
|
||||
return {
|
||||
type: BLOCKS_FETCH_REQUEST,
|
||||
type: BLOCKS_FETCH_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -31,14 +31,14 @@ export function fetchBlocksSuccess(accounts, next) {
|
||||
return {
|
||||
type: BLOCKS_FETCH_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchBlocksFail(error) {
|
||||
return {
|
||||
type: BLOCKS_FETCH_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ export function expandBlocks() {
|
||||
|
||||
export function expandBlocksRequest() {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_REQUEST,
|
||||
type: BLOCKS_EXPAND_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -70,13 +70,13 @@ export function expandBlocksSuccess(accounts, next) {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function expandBlocksFail(error) {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
@@ -28,7 +28,7 @@ export function fetchStatusCardRequest(id) {
|
||||
return {
|
||||
type: STATUS_CARD_FETCH_REQUEST,
|
||||
id,
|
||||
skipLoading: true,
|
||||
skipLoading: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ export function fetchStatusCardSuccess(id, card) {
|
||||
type: STATUS_CARD_FETCH_SUCCESS,
|
||||
id,
|
||||
card,
|
||||
skipLoading: true,
|
||||
skipLoading: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -47,6 +47,6 @@ export function fetchStatusCardFail(id, error) {
|
||||
id,
|
||||
error,
|
||||
skipLoading: true,
|
||||
skipAlert: true,
|
||||
skipAlert: true
|
||||
};
|
||||
};
|
@@ -1,11 +1,8 @@
|
||||
import api from '../api';
|
||||
|
||||
import {
|
||||
updateTimeline,
|
||||
refreshHomeTimeline,
|
||||
refreshCommunityTimeline,
|
||||
refreshPublicTimeline,
|
||||
} from './timelines';
|
||||
import { updateTimeline } from './timelines';
|
||||
|
||||
import * as emojione from 'emojione';
|
||||
|
||||
export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
|
||||
export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
|
||||
@@ -32,14 +29,13 @@ export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
|
||||
export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
|
||||
export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
|
||||
export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE';
|
||||
export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE';
|
||||
|
||||
export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT';
|
||||
|
||||
export function changeCompose(text) {
|
||||
return {
|
||||
type: COMPOSE_CHANGE,
|
||||
text: text,
|
||||
text: text
|
||||
};
|
||||
};
|
||||
|
||||
@@ -47,7 +43,7 @@ export function replyCompose(status, router) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: COMPOSE_REPLY,
|
||||
status: status,
|
||||
status: status
|
||||
});
|
||||
|
||||
if (!getState().getIn(['compose', 'mounted'])) {
|
||||
@@ -58,7 +54,7 @@ export function replyCompose(status, router) {
|
||||
|
||||
export function cancelReplyCompose() {
|
||||
return {
|
||||
type: COMPOSE_REPLY_CANCEL,
|
||||
type: COMPOSE_REPLY_CANCEL
|
||||
};
|
||||
};
|
||||
|
||||
@@ -66,7 +62,7 @@ export function mentionCompose(account, router) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: COMPOSE_MENTION,
|
||||
account: account,
|
||||
account: account
|
||||
});
|
||||
|
||||
if (!getState().getIn(['compose', 'mounted'])) {
|
||||
@@ -77,43 +73,36 @@ export function mentionCompose(account, router) {
|
||||
|
||||
export function submitCompose() {
|
||||
return function (dispatch, getState) {
|
||||
const status = getState().getIn(['compose', 'text'], '');
|
||||
|
||||
const status = emojione.shortnameToUnicode(getState().getIn(['compose', 'text'], ''));
|
||||
if (!status || !status.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(submitComposeRequest());
|
||||
|
||||
api(getState).post('/api/v1/statuses', {
|
||||
status,
|
||||
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
||||
media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
|
||||
sensitive: getState().getIn(['compose', 'sensitive']),
|
||||
spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
|
||||
visibility: getState().getIn(['compose', 'privacy']),
|
||||
visibility: getState().getIn(['compose', 'privacy'])
|
||||
}, {
|
||||
headers: {
|
||||
'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
|
||||
},
|
||||
'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey'])
|
||||
}
|
||||
}).then(function (response) {
|
||||
dispatch(submitComposeSuccess({ ...response.data }));
|
||||
|
||||
// To make the app more responsive, immediately get the status into the columns
|
||||
|
||||
const insertOrRefresh = (timelineId, refreshAction) => {
|
||||
if (getState().getIn(['timelines', timelineId, 'online'])) {
|
||||
dispatch(updateTimeline(timelineId, { ...response.data }));
|
||||
} else if (getState().getIn(['timelines', timelineId, 'loaded'])) {
|
||||
dispatch(refreshAction());
|
||||
}
|
||||
};
|
||||
|
||||
insertOrRefresh('home', refreshHomeTimeline);
|
||||
dispatch(updateTimeline('home', { ...response.data }));
|
||||
|
||||
if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
||||
insertOrRefresh('community', refreshCommunityTimeline);
|
||||
insertOrRefresh('public', refreshPublicTimeline);
|
||||
if (getState().getIn(['timelines', 'community', 'loaded'])) {
|
||||
dispatch(updateTimeline('community', { ...response.data }));
|
||||
}
|
||||
|
||||
if (getState().getIn(['timelines', 'public', 'loaded'])) {
|
||||
dispatch(updateTimeline('public', { ...response.data }));
|
||||
}
|
||||
}
|
||||
}).catch(function (error) {
|
||||
dispatch(submitComposeFail(error));
|
||||
@@ -123,21 +112,21 @@ export function submitCompose() {
|
||||
|
||||
export function submitComposeRequest() {
|
||||
return {
|
||||
type: COMPOSE_SUBMIT_REQUEST,
|
||||
type: COMPOSE_SUBMIT_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
export function submitComposeSuccess(status) {
|
||||
return {
|
||||
type: COMPOSE_SUBMIT_SUCCESS,
|
||||
status: status,
|
||||
status: status
|
||||
};
|
||||
};
|
||||
|
||||
export function submitComposeFail(error) {
|
||||
return {
|
||||
type: COMPOSE_SUBMIT_FAIL,
|
||||
error: error,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -155,7 +144,7 @@ export function uploadCompose(files) {
|
||||
api(getState).post('/api/v1/media', data, {
|
||||
onUploadProgress: function (e) {
|
||||
dispatch(uploadComposeProgress(e.loaded, e.total));
|
||||
},
|
||||
}
|
||||
}).then(function (response) {
|
||||
dispatch(uploadComposeSuccess(response.data));
|
||||
}).catch(function (error) {
|
||||
@@ -167,7 +156,7 @@ export function uploadCompose(files) {
|
||||
export function uploadComposeRequest() {
|
||||
return {
|
||||
type: COMPOSE_UPLOAD_REQUEST,
|
||||
skipLoading: true,
|
||||
skipLoading: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -175,7 +164,7 @@ export function uploadComposeProgress(loaded, total) {
|
||||
return {
|
||||
type: COMPOSE_UPLOAD_PROGRESS,
|
||||
loaded: loaded,
|
||||
total: total,
|
||||
total: total
|
||||
};
|
||||
};
|
||||
|
||||
@@ -183,7 +172,7 @@ export function uploadComposeSuccess(media) {
|
||||
return {
|
||||
type: COMPOSE_UPLOAD_SUCCESS,
|
||||
media: media,
|
||||
skipLoading: true,
|
||||
skipLoading: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -191,20 +180,20 @@ export function uploadComposeFail(error) {
|
||||
return {
|
||||
type: COMPOSE_UPLOAD_FAIL,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
skipLoading: true
|
||||
};
|
||||
};
|
||||
|
||||
export function undoUploadCompose(media_id) {
|
||||
return {
|
||||
type: COMPOSE_UPLOAD_UNDO,
|
||||
media_id: media_id,
|
||||
media_id: media_id
|
||||
};
|
||||
};
|
||||
|
||||
export function clearComposeSuggestions() {
|
||||
return {
|
||||
type: COMPOSE_SUGGESTIONS_CLEAR,
|
||||
type: COMPOSE_SUGGESTIONS_CLEAR
|
||||
};
|
||||
};
|
||||
|
||||
@@ -214,8 +203,8 @@ export function fetchComposeSuggestions(token) {
|
||||
params: {
|
||||
q: token,
|
||||
resolve: false,
|
||||
limit: 4,
|
||||
},
|
||||
limit: 4
|
||||
}
|
||||
}).then(response => {
|
||||
dispatch(readyComposeSuggestions(token, response.data));
|
||||
});
|
||||
@@ -226,7 +215,7 @@ export function readyComposeSuggestions(token, accounts) {
|
||||
return {
|
||||
type: COMPOSE_SUGGESTIONS_READY,
|
||||
token,
|
||||
accounts,
|
||||
accounts
|
||||
};
|
||||
};
|
||||
|
||||
@@ -238,20 +227,20 @@ export function selectComposeSuggestion(position, token, accountId) {
|
||||
type: COMPOSE_SUGGESTION_SELECT,
|
||||
position,
|
||||
token,
|
||||
completion,
|
||||
completion
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function mountCompose() {
|
||||
return {
|
||||
type: COMPOSE_MOUNT,
|
||||
type: COMPOSE_MOUNT
|
||||
};
|
||||
};
|
||||
|
||||
export function unmountCompose() {
|
||||
return {
|
||||
type: COMPOSE_UNMOUNT,
|
||||
type: COMPOSE_UNMOUNT
|
||||
};
|
||||
};
|
||||
|
||||
@@ -263,21 +252,21 @@ export function changeComposeSensitivity() {
|
||||
|
||||
export function changeComposeSpoilerness() {
|
||||
return {
|
||||
type: COMPOSE_SPOILERNESS_CHANGE,
|
||||
type: COMPOSE_SPOILERNESS_CHANGE
|
||||
};
|
||||
};
|
||||
|
||||
export function changeComposeSpoilerText(text) {
|
||||
return {
|
||||
type: COMPOSE_SPOILER_TEXT_CHANGE,
|
||||
text,
|
||||
text
|
||||
};
|
||||
};
|
||||
|
||||
export function changeComposeVisibility(value) {
|
||||
return {
|
||||
type: COMPOSE_VISIBILITY_CHANGE,
|
||||
value,
|
||||
value
|
||||
};
|
||||
};
|
||||
|
||||
@@ -285,13 +274,6 @@ export function insertEmojiCompose(position, emoji) {
|
||||
return {
|
||||
type: COMPOSE_EMOJI_INSERT,
|
||||
position,
|
||||
emoji,
|
||||
emoji
|
||||
};
|
||||
};
|
||||
|
||||
export function changeComposing(value) {
|
||||
return {
|
||||
type: COMPOSE_COMPOSING_CHANGE,
|
||||
value,
|
||||
};
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
import api, { getLinks } from '../api';
|
||||
import api, { getLinks } from '../api'
|
||||
|
||||
export const FAVOURITED_STATUSES_FETCH_REQUEST = 'FAVOURITED_STATUSES_FETCH_REQUEST';
|
||||
export const FAVOURITED_STATUSES_FETCH_SUCCESS = 'FAVOURITED_STATUSES_FETCH_SUCCESS';
|
||||
@@ -23,7 +23,7 @@ export function fetchFavouritedStatuses() {
|
||||
|
||||
export function fetchFavouritedStatusesRequest() {
|
||||
return {
|
||||
type: FAVOURITED_STATUSES_FETCH_REQUEST,
|
||||
type: FAVOURITED_STATUSES_FETCH_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -31,14 +31,14 @@ export function fetchFavouritedStatusesSuccess(statuses, next) {
|
||||
return {
|
||||
type: FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||
statuses,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchFavouritedStatusesFail(error) {
|
||||
return {
|
||||
type: FAVOURITED_STATUSES_FETCH_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ export function expandFavouritedStatuses() {
|
||||
|
||||
export function expandFavouritedStatusesRequest() {
|
||||
return {
|
||||
type: FAVOURITED_STATUSES_EXPAND_REQUEST,
|
||||
type: FAVOURITED_STATUSES_EXPAND_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -71,13 +71,13 @@ export function expandFavouritedStatusesSuccess(statuses, next) {
|
||||
return {
|
||||
type: FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||
statuses,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function expandFavouritedStatusesFail(error) {
|
||||
return {
|
||||
type: FAVOURITED_STATUSES_EXPAND_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
@@ -1,4 +1,4 @@
|
||||
import api from '../api';
|
||||
import api from '../api'
|
||||
|
||||
export const REBLOG_REQUEST = 'REBLOG_REQUEST';
|
||||
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
|
||||
@@ -24,14 +24,6 @@ export const FAVOURITES_FETCH_REQUEST = 'FAVOURITES_FETCH_REQUEST';
|
||||
export const FAVOURITES_FETCH_SUCCESS = 'FAVOURITES_FETCH_SUCCESS';
|
||||
export const FAVOURITES_FETCH_FAIL = 'FAVOURITES_FETCH_FAIL';
|
||||
|
||||
export const PIN_REQUEST = 'PIN_REQUEST';
|
||||
export const PIN_SUCCESS = 'PIN_SUCCESS';
|
||||
export const PIN_FAIL = 'PIN_FAIL';
|
||||
|
||||
export const UNPIN_REQUEST = 'UNPIN_REQUEST';
|
||||
export const UNPIN_SUCCESS = 'UNPIN_SUCCESS';
|
||||
export const UNPIN_FAIL = 'UNPIN_FAIL';
|
||||
|
||||
export function reblog(status) {
|
||||
return function (dispatch, getState) {
|
||||
dispatch(reblogRequest(status));
|
||||
@@ -61,7 +53,7 @@ export function unreblog(status) {
|
||||
export function reblogRequest(status) {
|
||||
return {
|
||||
type: REBLOG_REQUEST,
|
||||
status: status,
|
||||
status: status
|
||||
};
|
||||
};
|
||||
|
||||
@@ -69,7 +61,7 @@ export function reblogSuccess(status, response) {
|
||||
return {
|
||||
type: REBLOG_SUCCESS,
|
||||
status: status,
|
||||
response: response,
|
||||
response: response
|
||||
};
|
||||
};
|
||||
|
||||
@@ -77,14 +69,14 @@ export function reblogFail(status, error) {
|
||||
return {
|
||||
type: REBLOG_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
export function unreblogRequest(status) {
|
||||
return {
|
||||
type: UNREBLOG_REQUEST,
|
||||
status: status,
|
||||
status: status
|
||||
};
|
||||
};
|
||||
|
||||
@@ -92,7 +84,7 @@ export function unreblogSuccess(status, response) {
|
||||
return {
|
||||
type: UNREBLOG_SUCCESS,
|
||||
status: status,
|
||||
response: response,
|
||||
response: response
|
||||
};
|
||||
};
|
||||
|
||||
@@ -100,7 +92,7 @@ export function unreblogFail(status, error) {
|
||||
return {
|
||||
type: UNREBLOG_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -131,7 +123,7 @@ export function unfavourite(status) {
|
||||
export function favouriteRequest(status) {
|
||||
return {
|
||||
type: FAVOURITE_REQUEST,
|
||||
status: status,
|
||||
status: status
|
||||
};
|
||||
};
|
||||
|
||||
@@ -139,7 +131,7 @@ export function favouriteSuccess(status, response) {
|
||||
return {
|
||||
type: FAVOURITE_SUCCESS,
|
||||
status: status,
|
||||
response: response,
|
||||
response: response
|
||||
};
|
||||
};
|
||||
|
||||
@@ -147,14 +139,14 @@ export function favouriteFail(status, error) {
|
||||
return {
|
||||
type: FAVOURITE_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
export function unfavouriteRequest(status) {
|
||||
return {
|
||||
type: UNFAVOURITE_REQUEST,
|
||||
status: status,
|
||||
status: status
|
||||
};
|
||||
};
|
||||
|
||||
@@ -162,7 +154,7 @@ export function unfavouriteSuccess(status, response) {
|
||||
return {
|
||||
type: UNFAVOURITE_SUCCESS,
|
||||
status: status,
|
||||
response: response,
|
||||
response: response
|
||||
};
|
||||
};
|
||||
|
||||
@@ -170,7 +162,7 @@ export function unfavouriteFail(status, error) {
|
||||
return {
|
||||
type: UNFAVOURITE_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -189,7 +181,7 @@ export function fetchReblogs(id) {
|
||||
export function fetchReblogsRequest(id) {
|
||||
return {
|
||||
type: REBLOGS_FETCH_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -197,14 +189,14 @@ export function fetchReblogsSuccess(id, accounts) {
|
||||
return {
|
||||
type: REBLOGS_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
accounts
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchReblogsFail(id, error) {
|
||||
return {
|
||||
type: REBLOGS_FETCH_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -223,7 +215,7 @@ export function fetchFavourites(id) {
|
||||
export function fetchFavouritesRequest(id) {
|
||||
return {
|
||||
type: FAVOURITES_FETCH_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -231,83 +223,13 @@ export function fetchFavouritesSuccess(id, accounts) {
|
||||
return {
|
||||
type: FAVOURITES_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
accounts
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchFavouritesFail(id, error) {
|
||||
return {
|
||||
type: FAVOURITES_FETCH_FAIL,
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export function pin(status) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(pinRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then(response => {
|
||||
dispatch(pinSuccess(status, response.data));
|
||||
}).catch(error => {
|
||||
dispatch(pinFail(status, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function pinRequest(status) {
|
||||
return {
|
||||
type: PIN_REQUEST,
|
||||
status,
|
||||
};
|
||||
};
|
||||
|
||||
export function pinSuccess(status, response) {
|
||||
return {
|
||||
type: PIN_SUCCESS,
|
||||
status,
|
||||
response,
|
||||
};
|
||||
};
|
||||
|
||||
export function pinFail(status, error) {
|
||||
return {
|
||||
type: PIN_FAIL,
|
||||
status,
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export function unpin (status) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(unpinRequest(status));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then(response => {
|
||||
dispatch(unpinSuccess(status, response.data));
|
||||
}).catch(error => {
|
||||
dispatch(unpinFail(status, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function unpinRequest(status) {
|
||||
return {
|
||||
type: UNPIN_REQUEST,
|
||||
status,
|
||||
};
|
||||
};
|
||||
|
||||
export function unpinSuccess(status, response) {
|
||||
return {
|
||||
type: UNPIN_SUCCESS,
|
||||
status,
|
||||
response,
|
||||
};
|
||||
};
|
||||
|
||||
export function unpinFail(status, error) {
|
||||
return {
|
||||
type: UNPIN_FAIL,
|
||||
status,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
@@ -5,12 +5,12 @@ export function openModal(type, props) {
|
||||
return {
|
||||
type: MODAL_OPEN,
|
||||
modalType: type,
|
||||
modalProps: props,
|
||||
modalProps: props
|
||||
};
|
||||
};
|
||||
|
||||
export function closeModal() {
|
||||
return {
|
||||
type: MODAL_CLOSE,
|
||||
type: MODAL_CLOSE
|
||||
};
|
||||
};
|
@@ -1,4 +1,4 @@
|
||||
import api, { getLinks } from '../api';
|
||||
import api, { getLinks } from '../api'
|
||||
import { fetchRelationships } from './accounts';
|
||||
|
||||
export const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST';
|
||||
@@ -23,7 +23,7 @@ export function fetchMutes() {
|
||||
|
||||
export function fetchMutesRequest() {
|
||||
return {
|
||||
type: MUTES_FETCH_REQUEST,
|
||||
type: MUTES_FETCH_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -31,14 +31,14 @@ export function fetchMutesSuccess(accounts, next) {
|
||||
return {
|
||||
type: MUTES_FETCH_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchMutesFail(error) {
|
||||
return {
|
||||
type: MUTES_FETCH_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ export function expandMutes() {
|
||||
|
||||
export function expandMutesRequest() {
|
||||
return {
|
||||
type: MUTES_EXPAND_REQUEST,
|
||||
type: MUTES_EXPAND_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -70,13 +70,13 @@ export function expandMutesSuccess(accounts, next) {
|
||||
return {
|
||||
type: MUTES_EXPAND_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function expandMutesFail(error) {
|
||||
return {
|
||||
type: MUTES_EXPAND_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
@@ -1,8 +1,8 @@
|
||||
import api, { getLinks } from '../api';
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
import api, { getLinks } from '../api'
|
||||
import Immutable from 'immutable';
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
|
||||
|
||||
@@ -17,10 +17,6 @@ export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
|
||||
export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
|
||||
export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
|
||||
|
||||
defineMessages({
|
||||
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
|
||||
});
|
||||
|
||||
const fetchRelatedRelationships = (dispatch, notifications) => {
|
||||
const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id);
|
||||
|
||||
@@ -29,12 +25,6 @@ const fetchRelatedRelationships = (dispatch, notifications) => {
|
||||
}
|
||||
};
|
||||
|
||||
const unescapeHTML = (html) => {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = html;
|
||||
return wrapper.textContent;
|
||||
};
|
||||
|
||||
export function updateNotifications(notification, intlMessages, intlLocale) {
|
||||
return (dispatch, getState) => {
|
||||
const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true);
|
||||
@@ -45,7 +35,7 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
|
||||
notification,
|
||||
account: notification.account,
|
||||
status: notification.status,
|
||||
meta: playSound ? { sound: 'boop' } : undefined,
|
||||
meta: playSound ? { sound: 'boop' } : undefined
|
||||
});
|
||||
|
||||
fetchRelatedRelationships(dispatch, [notification]);
|
||||
@@ -53,13 +43,9 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
|
||||
// Desktop notifications
|
||||
if (typeof window.Notification !== 'undefined' && showAlert) {
|
||||
const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username });
|
||||
const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : unescapeHTML(notification.status ? notification.status.content : '');
|
||||
const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : $('<p>').html(notification.status ? notification.status.content : '').text();
|
||||
|
||||
const notify = new Notification(title, { body, icon: notification.account.avatar, tag: notification.id });
|
||||
notify.addEventListener('click', () => {
|
||||
window.focus();
|
||||
notify.close();
|
||||
});
|
||||
new Notification(title, { body, icon: notification.account.avatar, tag: notification.id });
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -68,78 +54,68 @@ const excludeTypesFromSettings = state => state.getIn(['settings', 'notification
|
||||
|
||||
export function refreshNotifications() {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(refreshNotificationsRequest());
|
||||
|
||||
const params = {};
|
||||
const ids = getState().getIn(['notifications', 'items']);
|
||||
|
||||
let skipLoading = false;
|
||||
|
||||
if (ids.size > 0) {
|
||||
params.since_id = ids.first().get('id');
|
||||
}
|
||||
|
||||
if (getState().getIn(['notifications', 'loaded'])) {
|
||||
skipLoading = true;
|
||||
}
|
||||
|
||||
params.exclude_types = excludeTypesFromSettings(getState());
|
||||
|
||||
dispatch(refreshNotificationsRequest(skipLoading));
|
||||
|
||||
api(getState).get('/api/v1/notifications', { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(refreshNotificationsSuccess(response.data, skipLoading, next ? next.uri : null));
|
||||
dispatch(refreshNotificationsSuccess(response.data, next ? next.uri : null));
|
||||
fetchRelatedRelationships(dispatch, response.data);
|
||||
}).catch(error => {
|
||||
dispatch(refreshNotificationsFail(error, skipLoading));
|
||||
dispatch(refreshNotificationsFail(error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function refreshNotificationsRequest(skipLoading) {
|
||||
export function refreshNotificationsRequest() {
|
||||
return {
|
||||
type: NOTIFICATIONS_REFRESH_REQUEST,
|
||||
skipLoading,
|
||||
type: NOTIFICATIONS_REFRESH_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
export function refreshNotificationsSuccess(notifications, skipLoading, next) {
|
||||
export function refreshNotificationsSuccess(notifications, next) {
|
||||
return {
|
||||
type: NOTIFICATIONS_REFRESH_SUCCESS,
|
||||
notifications,
|
||||
accounts: notifications.map(item => item.account),
|
||||
statuses: notifications.map(item => item.status).filter(status => !!status),
|
||||
skipLoading,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function refreshNotificationsFail(error, skipLoading) {
|
||||
export function refreshNotificationsFail(error) {
|
||||
return {
|
||||
type: NOTIFICATIONS_REFRESH_FAIL,
|
||||
error,
|
||||
skipLoading,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
export function expandNotifications() {
|
||||
return (dispatch, getState) => {
|
||||
const items = getState().getIn(['notifications', 'items'], ImmutableList());
|
||||
const url = getState().getIn(['notifications', 'next'], null);
|
||||
|
||||
if (getState().getIn(['notifications', 'isLoading']) || items.size === 0) {
|
||||
if (url === null || getState().getIn(['notifications', 'isLoading'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = {
|
||||
max_id: items.last().get('id'),
|
||||
limit: 20,
|
||||
exclude_types: excludeTypesFromSettings(getState()),
|
||||
};
|
||||
|
||||
dispatch(expandNotificationsRequest());
|
||||
|
||||
api(getState).get('/api/v1/notifications', { params }).then(response => {
|
||||
const params = {};
|
||||
|
||||
params.exclude_types = excludeTypesFromSettings(getState());
|
||||
|
||||
api(getState).get(url, params).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null));
|
||||
fetchRelatedRelationships(dispatch, response.data);
|
||||
}).catch(error => {
|
||||
@@ -150,7 +126,7 @@ export function expandNotifications() {
|
||||
|
||||
export function expandNotificationsRequest() {
|
||||
return {
|
||||
type: NOTIFICATIONS_EXPAND_REQUEST,
|
||||
type: NOTIFICATIONS_EXPAND_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -160,21 +136,21 @@ export function expandNotificationsSuccess(notifications, next) {
|
||||
notifications,
|
||||
accounts: notifications.map(item => item.account),
|
||||
statuses: notifications.map(item => item.status).filter(status => !!status),
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
export function expandNotificationsFail(error) {
|
||||
return {
|
||||
type: NOTIFICATIONS_EXPAND_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
export function clearNotifications() {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_CLEAR,
|
||||
type: NOTIFICATIONS_CLEAR
|
||||
});
|
||||
|
||||
api(getState).post('/api/v1/notifications/clear');
|
||||
@@ -184,6 +160,6 @@ export function clearNotifications() {
|
||||
export function scrollTopNotifications(top) {
|
||||
return {
|
||||
type: NOTIFICATIONS_SCROLL_TOP,
|
||||
top,
|
||||
top
|
||||
};
|
||||
};
|
@@ -1,5 +1,4 @@
|
||||
import api from '../api';
|
||||
import { openModal, closeModal } from './modal';
|
||||
|
||||
export const REPORT_INIT = 'REPORT_INIT';
|
||||
export const REPORT_CANCEL = 'REPORT_CANCEL';
|
||||
@@ -12,20 +11,16 @@ export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE';
|
||||
export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE';
|
||||
|
||||
export function initReport(account, status) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: REPORT_INIT,
|
||||
account,
|
||||
status,
|
||||
});
|
||||
|
||||
dispatch(openModal('REPORT'));
|
||||
return {
|
||||
type: REPORT_INIT,
|
||||
account,
|
||||
status
|
||||
};
|
||||
};
|
||||
|
||||
export function cancelReport() {
|
||||
return {
|
||||
type: REPORT_CANCEL,
|
||||
type: REPORT_CANCEL
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,37 +39,34 @@ export function submitReport() {
|
||||
api(getState).post('/api/v1/reports', {
|
||||
account_id: getState().getIn(['reports', 'new', 'account_id']),
|
||||
status_ids: getState().getIn(['reports', 'new', 'status_ids']),
|
||||
comment: getState().getIn(['reports', 'new', 'comment']),
|
||||
}).then(response => {
|
||||
dispatch(closeModal());
|
||||
dispatch(submitReportSuccess(response.data));
|
||||
}).catch(error => dispatch(submitReportFail(error)));
|
||||
comment: getState().getIn(['reports', 'new', 'comment'])
|
||||
}).then(response => dispatch(submitReportSuccess(response.data))).catch(error => dispatch(submitReportFail(error)));
|
||||
};
|
||||
};
|
||||
|
||||
export function submitReportRequest() {
|
||||
return {
|
||||
type: REPORT_SUBMIT_REQUEST,
|
||||
type: REPORT_SUBMIT_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
export function submitReportSuccess(report) {
|
||||
return {
|
||||
type: REPORT_SUBMIT_SUCCESS,
|
||||
report,
|
||||
report
|
||||
};
|
||||
};
|
||||
|
||||
export function submitReportFail(error) {
|
||||
return {
|
||||
type: REPORT_SUBMIT_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
export function changeReportComment(comment) {
|
||||
return {
|
||||
type: REPORT_COMMENT_CHANGE,
|
||||
comment,
|
||||
comment
|
||||
};
|
||||
};
|
@@ -1,4 +1,4 @@
|
||||
import api from '../api';
|
||||
import api from '../api'
|
||||
|
||||
export const SEARCH_CHANGE = 'SEARCH_CHANGE';
|
||||
export const SEARCH_CLEAR = 'SEARCH_CLEAR';
|
||||
@@ -11,13 +11,13 @@ export const SEARCH_FETCH_FAIL = 'SEARCH_FETCH_FAIL';
|
||||
export function changeSearch(value) {
|
||||
return {
|
||||
type: SEARCH_CHANGE,
|
||||
value,
|
||||
value
|
||||
};
|
||||
};
|
||||
|
||||
export function clearSearch() {
|
||||
return {
|
||||
type: SEARCH_CLEAR,
|
||||
type: SEARCH_CLEAR
|
||||
};
|
||||
};
|
||||
|
||||
@@ -34,8 +34,8 @@ export function submitSearch() {
|
||||
api(getState).get('/api/v1/search', {
|
||||
params: {
|
||||
q: value,
|
||||
resolve: true,
|
||||
},
|
||||
resolve: true
|
||||
}
|
||||
}).then(response => {
|
||||
dispatch(fetchSearchSuccess(response.data));
|
||||
}).catch(error => {
|
||||
@@ -46,7 +46,7 @@ export function submitSearch() {
|
||||
|
||||
export function fetchSearchRequest() {
|
||||
return {
|
||||
type: SEARCH_FETCH_REQUEST,
|
||||
type: SEARCH_FETCH_REQUEST
|
||||
};
|
||||
};
|
||||
|
||||
@@ -55,19 +55,19 @@ export function fetchSearchSuccess(results) {
|
||||
type: SEARCH_FETCH_SUCCESS,
|
||||
results,
|
||||
accounts: results.accounts,
|
||||
statuses: results.statuses,
|
||||
statuses: results.statuses
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchSearchFail(error) {
|
||||
return {
|
||||
type: SEARCH_FETCH_FAIL,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
export function showSearch() {
|
||||
return {
|
||||
type: SEARCH_SHOW,
|
||||
type: SEARCH_SHOW
|
||||
};
|
||||
};
|
@@ -3,21 +3,17 @@ import axios from 'axios';
|
||||
export const SETTING_CHANGE = 'SETTING_CHANGE';
|
||||
|
||||
export function changeSetting(key, value) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: SETTING_CHANGE,
|
||||
key,
|
||||
value,
|
||||
});
|
||||
|
||||
dispatch(saveSettings());
|
||||
return {
|
||||
type: SETTING_CHANGE,
|
||||
key,
|
||||
value
|
||||
};
|
||||
};
|
||||
|
||||
export function saveSettings() {
|
||||
return (_, getState) => {
|
||||
axios.put('/api/web/settings', {
|
||||
data: getState().get('settings').toJS(),
|
||||
data: getState().get('settings').toJS()
|
||||
});
|
||||
};
|
||||
};
|
@@ -15,19 +15,11 @@ export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST';
|
||||
export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS';
|
||||
export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL';
|
||||
|
||||
export const STATUS_MUTE_REQUEST = 'STATUS_MUTE_REQUEST';
|
||||
export const STATUS_MUTE_SUCCESS = 'STATUS_MUTE_SUCCESS';
|
||||
export const STATUS_MUTE_FAIL = 'STATUS_MUTE_FAIL';
|
||||
|
||||
export const STATUS_UNMUTE_REQUEST = 'STATUS_UNMUTE_REQUEST';
|
||||
export const STATUS_UNMUTE_SUCCESS = 'STATUS_UNMUTE_SUCCESS';
|
||||
export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
|
||||
|
||||
export function fetchStatusRequest(id, skipLoading) {
|
||||
return {
|
||||
type: STATUS_FETCH_REQUEST,
|
||||
id,
|
||||
skipLoading,
|
||||
skipLoading
|
||||
};
|
||||
};
|
||||
|
||||
@@ -56,7 +48,7 @@ export function fetchStatusSuccess(status, skipLoading) {
|
||||
return {
|
||||
type: STATUS_FETCH_SUCCESS,
|
||||
status,
|
||||
skipLoading,
|
||||
skipLoading
|
||||
};
|
||||
};
|
||||
|
||||
@@ -66,7 +58,7 @@ export function fetchStatusFail(id, error, skipLoading) {
|
||||
id,
|
||||
error,
|
||||
skipLoading,
|
||||
skipAlert: true,
|
||||
skipAlert: true
|
||||
};
|
||||
};
|
||||
|
||||
@@ -74,7 +66,7 @@ export function deleteStatus(id) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(deleteStatusRequest(id));
|
||||
|
||||
api(getState).delete(`/api/v1/statuses/${id}`).then(() => {
|
||||
api(getState).delete(`/api/v1/statuses/${id}`).then(response => {
|
||||
dispatch(deleteStatusSuccess(id));
|
||||
dispatch(deleteFromTimelines(id));
|
||||
}).catch(error => {
|
||||
@@ -86,14 +78,14 @@ export function deleteStatus(id) {
|
||||
export function deleteStatusRequest(id) {
|
||||
return {
|
||||
type: STATUS_DELETE_REQUEST,
|
||||
id: id,
|
||||
id: id
|
||||
};
|
||||
};
|
||||
|
||||
export function deleteStatusSuccess(id) {
|
||||
return {
|
||||
type: STATUS_DELETE_SUCCESS,
|
||||
id: id,
|
||||
id: id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -101,7 +93,7 @@ export function deleteStatusFail(id, error) {
|
||||
return {
|
||||
type: STATUS_DELETE_FAIL,
|
||||
id: id,
|
||||
error: error,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -113,7 +105,7 @@ export function fetchContext(id) {
|
||||
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants));
|
||||
|
||||
}).catch(error => {
|
||||
if (error.response && error.response.status === 404) {
|
||||
if (error.response.status === 404) {
|
||||
dispatch(deleteFromTimelines(id));
|
||||
}
|
||||
|
||||
@@ -125,7 +117,7 @@ export function fetchContext(id) {
|
||||
export function fetchContextRequest(id) {
|
||||
return {
|
||||
type: CONTEXT_FETCH_REQUEST,
|
||||
id,
|
||||
id
|
||||
};
|
||||
};
|
||||
|
||||
@@ -135,7 +127,7 @@ export function fetchContextSuccess(id, ancestors, descendants) {
|
||||
id,
|
||||
ancestors,
|
||||
descendants,
|
||||
statuses: ancestors.concat(descendants),
|
||||
statuses: ancestors.concat(descendants)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -144,74 +136,6 @@ export function fetchContextFail(id, error) {
|
||||
type: CONTEXT_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipAlert: true,
|
||||
};
|
||||
};
|
||||
|
||||
export function muteStatus(id) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(muteStatusRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${id}/mute`).then(() => {
|
||||
dispatch(muteStatusSuccess(id));
|
||||
}).catch(error => {
|
||||
dispatch(muteStatusFail(id, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function muteStatusRequest(id) {
|
||||
return {
|
||||
type: STATUS_MUTE_REQUEST,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function muteStatusSuccess(id) {
|
||||
return {
|
||||
type: STATUS_MUTE_SUCCESS,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function muteStatusFail(id, error) {
|
||||
return {
|
||||
type: STATUS_MUTE_FAIL,
|
||||
id,
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export function unmuteStatus(id) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(unmuteStatusRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${id}/unmute`).then(() => {
|
||||
dispatch(unmuteStatusSuccess(id));
|
||||
}).catch(error => {
|
||||
dispatch(unmuteStatusFail(id, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function unmuteStatusRequest(id) {
|
||||
return {
|
||||
type: STATUS_UNMUTE_REQUEST,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function unmuteStatusSuccess(id) {
|
||||
return {
|
||||
type: STATUS_UNMUTE_SUCCESS,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function unmuteStatusFail(id, error) {
|
||||
return {
|
||||
type: STATUS_UNMUTE_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipAlert: true
|
||||
};
|
||||
};
|
@@ -1,11 +1,10 @@
|
||||
import { Iterable, fromJS } from 'immutable';
|
||||
import Immutable from 'immutable';
|
||||
|
||||
export const STORE_HYDRATE = 'STORE_HYDRATE';
|
||||
export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY';
|
||||
|
||||
const convertState = rawState =>
|
||||
fromJS(rawState, (k, v) =>
|
||||
Iterable.isIndexed(v) ? v.toList() : v.toMap().mapKeys(x =>
|
||||
Immutable.fromJS(rawState, (k, v) =>
|
||||
Immutable.Iterable.isIndexed(v) ? v.toList() : v.toMap().mapKeys(x =>
|
||||
Number.isNaN(x * 1) ? x : x * 1));
|
||||
|
||||
export function hydrateStore(rawState) {
|
||||
@@ -13,6 +12,6 @@ export function hydrateStore(rawState) {
|
||||
|
||||
return {
|
||||
type: STORE_HYDRATE,
|
||||
state,
|
||||
state
|
||||
};
|
||||
};
|
@@ -1,5 +1,5 @@
|
||||
import api, { getLinks } from '../api';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
import api, { getLinks } from '../api'
|
||||
import Immutable from 'immutable';
|
||||
|
||||
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
|
||||
export const TIMELINE_DELETE = 'TIMELINE_DELETE';
|
||||
@@ -23,7 +23,7 @@ export function refreshTimelineSuccess(timeline, statuses, skipLoading, next) {
|
||||
timeline,
|
||||
statuses,
|
||||
skipLoading,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ export function updateTimeline(timeline, status) {
|
||||
type: TIMELINE_UPDATE,
|
||||
timeline,
|
||||
status,
|
||||
references,
|
||||
references
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -51,98 +51,98 @@ export function deleteFromTimelines(id) {
|
||||
id,
|
||||
accountId,
|
||||
references,
|
||||
reblogOf,
|
||||
reblogOf
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function refreshTimelineRequest(timeline, skipLoading) {
|
||||
export function refreshTimelineRequest(timeline, id, skipLoading) {
|
||||
return {
|
||||
type: TIMELINE_REFRESH_REQUEST,
|
||||
timeline,
|
||||
skipLoading,
|
||||
id,
|
||||
skipLoading
|
||||
};
|
||||
};
|
||||
|
||||
export function refreshTimeline(timelineId, path, params = {}) {
|
||||
export function refreshTimeline(timeline, id = null) {
|
||||
return function (dispatch, getState) {
|
||||
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
|
||||
|
||||
if (timeline.get('isLoading') || timeline.get('online')) {
|
||||
if (getState().getIn(['timelines', timeline, 'isLoading'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ids = timeline.get('items', ImmutableList());
|
||||
const ids = getState().getIn(['timelines', timeline, 'items'], Immutable.List());
|
||||
const newestId = ids.size > 0 ? ids.first() : null;
|
||||
let params = getState().getIn(['timelines', timeline, 'params'], {});
|
||||
const path = getState().getIn(['timelines', timeline, 'path'])(id);
|
||||
|
||||
let skipLoading = timeline.get('loaded');
|
||||
let skipLoading = false;
|
||||
|
||||
if (newestId !== null) {
|
||||
params.since_id = newestId;
|
||||
if (newestId !== null && getState().getIn(['timelines', timeline, 'loaded']) && (id === null || getState().getIn(['timelines', timeline, 'id']) === id)) {
|
||||
if (id === null && getState().getIn(['timelines', timeline, 'online'])) {
|
||||
// Skip refreshing when timeline is live anyway
|
||||
return;
|
||||
}
|
||||
|
||||
params = { ...params, since_id: newestId };
|
||||
skipLoading = true;
|
||||
}
|
||||
|
||||
dispatch(refreshTimelineRequest(timelineId, skipLoading));
|
||||
dispatch(refreshTimelineRequest(timeline, id, skipLoading));
|
||||
|
||||
api(getState).get(path, { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null));
|
||||
dispatch(refreshTimelineSuccess(timeline, response.data, skipLoading, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(refreshTimelineFail(timelineId, error, skipLoading));
|
||||
dispatch(refreshTimelineFail(timeline, error, skipLoading));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const refreshHomeTimeline = () => refreshTimeline('home', '/api/v1/timelines/home');
|
||||
export const refreshPublicTimeline = () => refreshTimeline('public', '/api/v1/timelines/public');
|
||||
export const refreshCommunityTimeline = () => refreshTimeline('community', '/api/v1/timelines/public', { local: true });
|
||||
export const refreshAccountTimeline = accountId => refreshTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`);
|
||||
export const refreshAccountMediaTimeline = accountId => refreshTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true });
|
||||
export const refreshHashtagTimeline = hashtag => refreshTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`);
|
||||
|
||||
export function refreshTimelineFail(timeline, error, skipLoading) {
|
||||
return {
|
||||
type: TIMELINE_REFRESH_FAIL,
|
||||
timeline,
|
||||
error,
|
||||
skipLoading,
|
||||
skipAlert: error.response && error.response.status === 404,
|
||||
skipLoading
|
||||
};
|
||||
};
|
||||
|
||||
export function expandTimeline(timelineId, path, params = {}) {
|
||||
export function expandTimeline(timeline) {
|
||||
return (dispatch, getState) => {
|
||||
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
|
||||
const ids = timeline.get('items', ImmutableList());
|
||||
|
||||
if (timeline.get('isLoading') || ids.size === 0) {
|
||||
if (getState().getIn(['timelines', timeline, 'isLoading'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
params.max_id = ids.last();
|
||||
params.limit = 10;
|
||||
if (getState().getIn(['timelines', timeline, 'items']).size === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(expandTimelineRequest(timelineId));
|
||||
const path = getState().getIn(['timelines', timeline, 'path'])(getState().getIn(['timelines', timeline, 'id']));
|
||||
const params = getState().getIn(['timelines', timeline, 'params'], {});
|
||||
const lastId = getState().getIn(['timelines', timeline, 'items']).last();
|
||||
|
||||
api(getState).get(path, { params }).then(response => {
|
||||
dispatch(expandTimelineRequest(timeline));
|
||||
|
||||
api(getState).get(path, {
|
||||
params: {
|
||||
...params,
|
||||
max_id: lastId,
|
||||
limit: 10
|
||||
}
|
||||
}).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null));
|
||||
dispatch(expandTimelineSuccess(timeline, response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(expandTimelineFail(timelineId, error));
|
||||
dispatch(expandTimelineFail(timeline, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const expandHomeTimeline = () => expandTimeline('home', '/api/v1/timelines/home');
|
||||
export const expandPublicTimeline = () => expandTimeline('public', '/api/v1/timelines/public');
|
||||
export const expandCommunityTimeline = () => expandTimeline('community', '/api/v1/timelines/public', { local: true });
|
||||
export const expandAccountTimeline = accountId => expandTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`);
|
||||
export const expandAccountMediaTimeline = accountId => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true });
|
||||
export const expandHashtagTimeline = hashtag => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`);
|
||||
|
||||
export function expandTimelineRequest(timeline) {
|
||||
return {
|
||||
type: TIMELINE_EXPAND_REQUEST,
|
||||
timeline,
|
||||
timeline
|
||||
};
|
||||
};
|
||||
|
||||
@@ -151,7 +151,7 @@ export function expandTimelineSuccess(timeline, statuses, next) {
|
||||
type: TIMELINE_EXPAND_SUCCESS,
|
||||
timeline,
|
||||
statuses,
|
||||
next,
|
||||
next
|
||||
};
|
||||
};
|
||||
|
||||
@@ -159,7 +159,7 @@ export function expandTimelineFail(timeline, error) {
|
||||
return {
|
||||
type: TIMELINE_EXPAND_FAIL,
|
||||
timeline,
|
||||
error,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
@@ -167,20 +167,20 @@ export function scrollTopTimeline(timeline, top) {
|
||||
return {
|
||||
type: TIMELINE_SCROLL_TOP,
|
||||
timeline,
|
||||
top,
|
||||
top
|
||||
};
|
||||
};
|
||||
|
||||
export function connectTimeline(timeline) {
|
||||
return {
|
||||
type: TIMELINE_CONNECT,
|
||||
timeline,
|
||||
timeline
|
||||
};
|
||||
};
|
||||
|
||||
export function disconnectTimeline(timeline) {
|
||||
return {
|
||||
type: TIMELINE_DISCONNECT,
|
||||
timeline,
|
||||
timeline
|
||||
};
|
||||
};
|
@@ -13,7 +13,7 @@ export const getLinks = response => {
|
||||
|
||||
export default getState => axios.create({
|
||||
headers: {
|
||||
'Authorization': `Bearer ${getState().getIn(['meta', 'access_token'], '')}`,
|
||||
'Authorization': `Bearer ${getState().getIn(['meta', 'access_token'], '')}`
|
||||
},
|
||||
|
||||
transformResponse: [function (data) {
|
||||
@@ -22,5 +22,5 @@ export default getState => axios.create({
|
||||
} catch(Exception) {
|
||||
return data;
|
||||
}
|
||||
}],
|
||||
}]
|
||||
});
|
@@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import Avatar from './avatar';
|
||||
@@ -6,57 +5,43 @@ import DisplayName from './display_name';
|
||||
import Permalink from './permalink';
|
||||
import IconButton from './icon_button';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const messages = defineMessages({
|
||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' },
|
||||
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
|
||||
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
|
||||
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }
|
||||
});
|
||||
|
||||
@injectIntl
|
||||
export default class Account extends ImmutablePureComponent {
|
||||
class Account extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
me: PropTypes.number.isRequired,
|
||||
onFollow: PropTypes.func.isRequired,
|
||||
onBlock: PropTypes.func.isRequired,
|
||||
onMute: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hidden: PropTypes.bool,
|
||||
};
|
||||
constructor (props, context) {
|
||||
super(props, context);
|
||||
this.handleFollow = this.handleFollow.bind(this);
|
||||
this.handleBlock = this.handleBlock.bind(this);
|
||||
this.handleMute = this.handleMute.bind(this);
|
||||
}
|
||||
|
||||
handleFollow = () => {
|
||||
handleFollow () {
|
||||
this.props.onFollow(this.props.account);
|
||||
}
|
||||
|
||||
handleBlock = () => {
|
||||
handleBlock () {
|
||||
this.props.onBlock(this.props.account);
|
||||
}
|
||||
|
||||
handleMute = () => {
|
||||
handleMute () {
|
||||
this.props.onMute(this.props.account);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { account, me, intl, hidden } = this.props;
|
||||
const { account, me, intl } = this.props;
|
||||
|
||||
if (!account) {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
if (hidden) {
|
||||
return (
|
||||
<div>
|
||||
{account.get('display_name')}
|
||||
{account.get('username')}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let buttons;
|
||||
|
||||
if (account.get('id') !== me && account.get('relationship', null) !== null) {
|
||||
@@ -66,11 +51,11 @@ export default class Account extends ImmutablePureComponent {
|
||||
const muting = account.getIn(['relationship', 'muting']);
|
||||
|
||||
if (requested) {
|
||||
buttons = <IconButton disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />;
|
||||
buttons = <IconButton disabled={true} icon='hourglass' title={intl.formatMessage(messages.requested)} />
|
||||
} else if (blocking) {
|
||||
buttons = <IconButton active icon='unlock-alt' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />;
|
||||
buttons = <IconButton active={true} icon='unlock-alt' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />;
|
||||
} else if (muting) {
|
||||
buttons = <IconButton active icon='volume-up' title={intl.formatMessage(messages.unmute, { name: account.get('username') })} onClick={this.handleMute} />;
|
||||
buttons = <IconButton active={true} icon='volume-up' title={intl.formatMessage(messages.unmute, { name: account.get('username') })} onClick={this.handleMute} />;
|
||||
} else {
|
||||
buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />;
|
||||
}
|
||||
@@ -80,7 +65,7 @@ export default class Account extends ImmutablePureComponent {
|
||||
<div className='account'>
|
||||
<div className='account__wrapper'>
|
||||
<Permalink key={account.get('id')} className='account__display-name' href={account.get('url')} to={`/accounts/${account.get('id')}`}>
|
||||
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
|
||||
<div className='account__avatar-wrapper'><Avatar src={account.get('avatar')} staticSrc={account.get('avatar_static')} size={36} /></div>
|
||||
<DisplayName account={account} />
|
||||
</Permalink>
|
||||
|
||||
@@ -93,3 +78,14 @@ export default class Account extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Account.propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
me: PropTypes.number.isRequired,
|
||||
onFollow: PropTypes.func.isRequired,
|
||||
onBlock: PropTypes.func.isRequired,
|
||||
onMute: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default injectIntl(Account);
|
@@ -1,14 +1,8 @@
|
||||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
const filename = url => url.split('/').pop().split('#')[0].split('?')[0];
|
||||
|
||||
export default class AttachmentList extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
media: ImmutablePropTypes.list.isRequired,
|
||||
};
|
||||
class AttachmentList extends React.PureComponent {
|
||||
|
||||
render () {
|
||||
const { media } = this.props;
|
||||
@@ -29,5 +23,10 @@ export default class AttachmentList extends ImmutablePureComponent {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AttachmentList.propTypes = {
|
||||
media: ImmutablePropTypes.list.isRequired
|
||||
};
|
||||
|
||||
export default AttachmentList;
|
@@ -1,10 +1,7 @@
|
||||
import React from 'react';
|
||||
import AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isRtl } from '../rtl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import Textarea from 'react-textarea-autosize';
|
||||
|
||||
const textAtCursorMatchesToken = (str, caretPosition) => {
|
||||
let word;
|
||||
@@ -31,35 +28,25 @@ const textAtCursorMatchesToken = (str, caretPosition) => {
|
||||
}
|
||||
};
|
||||
|
||||
export default class AutosuggestTextarea extends ImmutablePureComponent {
|
||||
class AutosuggestTextarea extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
suggestions: ImmutablePropTypes.list,
|
||||
disabled: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
onSuggestionSelected: PropTypes.func.isRequired,
|
||||
onSuggestionsClearRequested: PropTypes.func.isRequired,
|
||||
onSuggestionsFetchRequested: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onKeyUp: PropTypes.func,
|
||||
onKeyDown: PropTypes.func,
|
||||
onPaste: PropTypes.func.isRequired,
|
||||
autoFocus: PropTypes.bool,
|
||||
};
|
||||
constructor (props, context) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
suggestionsHidden: false,
|
||||
selectedSuggestion: 0,
|
||||
lastToken: null,
|
||||
tokenStart: 0
|
||||
};
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
this.onBlur = this.onBlur.bind(this);
|
||||
this.onSuggestionClick = this.onSuggestionClick.bind(this);
|
||||
this.setTextarea = this.setTextarea.bind(this);
|
||||
this.onPaste = this.onPaste.bind(this);
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
autoFocus: true,
|
||||
};
|
||||
|
||||
state = {
|
||||
suggestionsHidden: false,
|
||||
selectedSuggestion: 0,
|
||||
lastToken: null,
|
||||
tokenStart: 0,
|
||||
};
|
||||
|
||||
onChange = (e) => {
|
||||
onChange (e) {
|
||||
const [ tokenStart, token ] = textAtCursorMatchesToken(e.target.value, e.target.selectionStart);
|
||||
|
||||
if (token !== null && this.state.lastToken !== token) {
|
||||
@@ -70,10 +57,14 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
|
||||
this.props.onSuggestionsClearRequested();
|
||||
}
|
||||
|
||||
// auto-resize textarea
|
||||
e.target.style.height = 'auto';
|
||||
e.target.style.height = `${e.target.scrollHeight}px`;
|
||||
|
||||
this.props.onChange(e);
|
||||
}
|
||||
|
||||
onKeyDown = (e) => {
|
||||
onKeyDown (e) {
|
||||
const { suggestions, disabled } = this.props;
|
||||
const { selectedSuggestion, suggestionsHidden } = this.state;
|
||||
|
||||
@@ -123,12 +114,17 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
|
||||
this.props.onKeyDown(e);
|
||||
}
|
||||
|
||||
onBlur = () => {
|
||||
this.setState({ suggestionsHidden: true });
|
||||
onBlur () {
|
||||
// If we hide the suggestions immediately, then this will prevent the
|
||||
// onClick for the suggestions themselves from firing.
|
||||
// Setting a short window for that to take place before hiding the
|
||||
// suggestions ensures that can't happen.
|
||||
setTimeout(() => {
|
||||
this.setState({ suggestionsHidden: true });
|
||||
}, 100);
|
||||
}
|
||||
|
||||
onSuggestionClick = (e) => {
|
||||
const suggestion = Number(e.currentTarget.getAttribute('data-index'));
|
||||
onSuggestionClick (suggestion, e) {
|
||||
e.preventDefault();
|
||||
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion);
|
||||
this.textarea.focus();
|
||||
@@ -140,19 +136,19 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
setTextarea = (c) => {
|
||||
setTextarea (c) {
|
||||
this.textarea = c;
|
||||
}
|
||||
|
||||
onPaste = (e) => {
|
||||
onPaste (e) {
|
||||
if (e.clipboardData && e.clipboardData.files.length === 1) {
|
||||
this.props.onPaste(e.clipboardData.files);
|
||||
this.props.onPaste(e.clipboardData.files)
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus } = this.props;
|
||||
const { value, suggestions, disabled, placeholder, onKeyUp } = this.props;
|
||||
const { suggestionsHidden, selectedSuggestion } = this.state;
|
||||
const style = { direction: 'ltr' };
|
||||
|
||||
@@ -162,34 +158,29 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<div className='autosuggest-textarea'>
|
||||
<label>
|
||||
<span style={{ display: 'none' }}>{placeholder}</span>
|
||||
<Textarea
|
||||
inputRef={this.setTextarea}
|
||||
className='autosuggest-textarea__textarea'
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
autoFocus={autoFocus}
|
||||
value={value}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={onKeyUp}
|
||||
onBlur={this.onBlur}
|
||||
onPaste={this.onPaste}
|
||||
style={style}
|
||||
/>
|
||||
</label>
|
||||
<textarea
|
||||
ref={this.setTextarea}
|
||||
className='autosuggest-textarea__textarea'
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
autoFocus={true}
|
||||
value={value}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={onKeyUp}
|
||||
onBlur={this.onBlur}
|
||||
onPaste={this.onPaste}
|
||||
style={style}
|
||||
/>
|
||||
|
||||
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
|
||||
<div style={{ display: (suggestions.size > 0 && !suggestionsHidden) ? 'block' : 'none' }} className='autosuggest-textarea__suggestions'>
|
||||
{suggestions.map((suggestion, i) => (
|
||||
<div
|
||||
role='button'
|
||||
tabIndex='0'
|
||||
key={suggestion}
|
||||
data-index={suggestion}
|
||||
className={`autosuggest-textarea__suggestions__item ${i === selectedSuggestion ? 'selected' : ''}`}
|
||||
onMouseDown={this.onSuggestionClick}
|
||||
>
|
||||
onClick={this.onSuggestionClick.bind(this, suggestion)}>
|
||||
<AutosuggestAccountContainer id={suggestion} />
|
||||
</div>
|
||||
))}
|
||||
@@ -198,4 +189,20 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
AutosuggestTextarea.propTypes = {
|
||||
value: PropTypes.string,
|
||||
suggestions: ImmutablePropTypes.list,
|
||||
disabled: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
onSuggestionSelected: PropTypes.func.isRequired,
|
||||
onSuggestionsClearRequested: PropTypes.func.isRequired,
|
||||
onSuggestionsFetchRequested: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onKeyUp: PropTypes.func,
|
||||
onKeyDown: PropTypes.func,
|
||||
onPaste: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default AutosuggestTextarea;
|
63
app/assets/javascripts/components/components/avatar.jsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class Avatar extends React.PureComponent {
|
||||
|
||||
constructor (props, context) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
hovering: false
|
||||
};
|
||||
this.handleMouseEnter = this.handleMouseEnter.bind(this);
|
||||
this.handleMouseLeave = this.handleMouseLeave.bind(this);
|
||||
}
|
||||
|
||||
handleMouseEnter () {
|
||||
this.setState({ hovering: true });
|
||||
}
|
||||
|
||||
handleMouseLeave () {
|
||||
this.setState({ hovering: false });
|
||||
}
|
||||
|
||||
render () {
|
||||
const { src, size, staticSrc, animate } = this.props;
|
||||
const { hovering } = this.state;
|
||||
|
||||
const style = {
|
||||
...this.props.style,
|
||||
width: `${size}px`,
|
||||
height: `${size}px`,
|
||||
backgroundSize: `${size}px ${size}px`
|
||||
};
|
||||
|
||||
if (hovering || animate) {
|
||||
style.backgroundImage = `url(${src})`;
|
||||
} else {
|
||||
style.backgroundImage = `url(${staticSrc})`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className='account__avatar'
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Avatar.propTypes = {
|
||||
src: PropTypes.string.isRequired,
|
||||
staticSrc: PropTypes.string,
|
||||
size: PropTypes.number.isRequired,
|
||||
style: PropTypes.object,
|
||||
animate: PropTypes.bool
|
||||
};
|
||||
|
||||
Avatar.defaultProps = {
|
||||
animate: false
|
||||
};
|
||||
|
||||
export default Avatar;
|
49
app/assets/javascripts/components/components/button.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class Button extends React.PureComponent {
|
||||
|
||||
constructor (props, context) {
|
||||
super(props, context);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
handleClick (e) {
|
||||
if (!this.props.disabled) {
|
||||
this.props.onClick();
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const style = {
|
||||
display: this.props.block ? 'block' : 'inline-block',
|
||||
width: this.props.block ? '100%' : 'auto',
|
||||
padding: `0 ${this.props.size / 2.25}px`,
|
||||
height: `${this.props.size}px`,
|
||||
lineHeight: `${this.props.size}px`
|
||||
};
|
||||
|
||||
return (
|
||||
<button className={`button ${this.props.secondary ? 'button-secondary' : ''}`} disabled={this.props.disabled} onClick={this.handleClick} style={{ ...style, ...this.props.style }}>
|
||||
{this.props.text || this.props.children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Button.propTypes = {
|
||||
text: PropTypes.node,
|
||||
onClick: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
block: PropTypes.bool,
|
||||
secondary: PropTypes.bool,
|
||||
size: PropTypes.number,
|
||||
style: PropTypes.object,
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
Button.defaultProps = {
|
||||
size: 36
|
||||
};
|
||||
|
||||
export default Button;
|
@@ -1,6 +1,4 @@
|
||||
import React from 'react';
|
||||
import Motion from 'react-motion/lib/Motion';
|
||||
import spring from 'react-motion/lib/spring';
|
||||
import { Motion, spring } from 'react-motion';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const Collapsable = ({ fullHeight, isVisible, children }) => (
|
||||
@@ -16,7 +14,7 @@ const Collapsable = ({ fullHeight, isVisible, children }) => (
|
||||
Collapsable.propTypes = {
|
||||
fullHeight: PropTypes.number.isRequired,
|
||||
isVisible: PropTypes.bool.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
children: PropTypes.node.isRequired
|
||||
};
|
||||
|
||||
export default Collapsable;
|
@@ -0,0 +1,31 @@
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class ColumnBackButton extends React.PureComponent {
|
||||
|
||||
constructor (props, context) {
|
||||
super(props, context);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
handleClick () {
|
||||
if (window.history && window.history.length === 1) this.context.router.push("/");
|
||||
else this.context.router.goBack();
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div role='button' tabIndex='0' onClick={this.handleClick} className='column-back-button'>
|
||||
<i className='fa fa-fw fa-chevron-left column-back-button__icon'/>
|
||||
<FormattedMessage id='column_back_button.label' defaultMessage='Back' />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ColumnBackButton.contextTypes = {
|
||||
router: PropTypes.object
|
||||
};
|
||||
|
||||
export default ColumnBackButton;
|