1 Commits

Author SHA1 Message Date
Zoë Bijl d1a4aafabf [build] update mini-css-extract-plugin dependencies 2025-10-08 15:49:15 +02:00
992 changed files with 39743 additions and 38420 deletions
+13
View File
@@ -0,0 +1,13 @@
/build/**
/coverage/**
/db/**
/lib/**
/log/**
/node_modules/**
/nonobox/**
/public/**
!/public/embed.js
/spec/**
/tmp/**
/vendor/**
!.eslintrc.js
+402
View File
@@ -0,0 +1,402 @@
module.exports = {
root: true,
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'plugin:import/recommended',
'plugin:promise/recommended',
'plugin:jsdoc/recommended',
],
env: {
browser: true,
node: true,
es6: true,
},
globals: {
ATTACHMENT_HOST: false,
},
parser: '@typescript-eslint/parser',
plugins: [
'react',
'jsx-a11y',
'import',
'promise',
'@typescript-eslint',
'formatjs',
],
parserOptions: {
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2021,
requireConfigFile: false,
babelOptions: {
configFile: false,
presets: ['@babel/react', '@babel/env'],
},
},
settings: {
react: {
version: 'detect',
},
'import/ignore': [
'node_modules',
'\\.(css|scss|json)$',
],
'import/resolver': {
typescript: {},
},
},
rules: {
'consistent-return': 'error',
'dot-notation': 'error',
eqeqeq: ['error', 'always', { 'null': 'ignore' }],
'indent': ['error', 2],
'jsx-quotes': ['error', 'prefer-single'],
'semi': ['error', 'always'],
'no-case-declarations': 'off',
'no-catch-shadow': 'error',
'no-console': [
'warn',
{
allow: [
'error',
'warn',
],
},
],
'no-empty': 'off',
'no-restricted-properties': [
'error',
{ property: 'substring', message: 'Use .slice instead of .substring.' },
{ property: 'substr', message: 'Use .slice instead of .substr.' },
],
'no-restricted-syntax': [
'error',
{
// eslint-disable-next-line no-restricted-syntax
selector: 'Literal[value=/•/], JSXText[value=/•/]',
// eslint-disable-next-line no-restricted-syntax
message: "Use '·' (middle dot) instead of '•' (bullet)",
},
],
'no-self-assign': 'off',
'no-unused-expressions': 'error',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
vars: 'all',
args: 'after-used',
destructuredArrayIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'valid-typeof': 'error',
'react/jsx-filename-extension': ['error', { extensions: ['.jsx', 'tsx'] }],
'react/jsx-boolean-value': 'error',
'react/display-name': 'off',
'react/jsx-fragments': ['error', 'syntax'],
'react/jsx-equals-spacing': 'error',
'react/jsx-no-bind': 'error',
'react/jsx-no-useless-fragment': 'error',
'react/jsx-no-target-blank': 'off',
'react/jsx-tag-spacing': 'error',
'react/jsx-uses-react': 'off', // not needed with new JSX transform
'react/jsx-wrap-multilines': 'error',
'react/no-deprecated': 'off',
'react/no-unknown-property': 'off',
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
'react/self-closing-comp': 'error',
// recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/index.js
'jsx-a11y/accessible-emoji': 'warn',
'jsx-a11y/click-events-have-key-events': 'off',
'jsx-a11y/label-has-associated-control': 'off',
'jsx-a11y/media-has-caption': 'off',
'jsx-a11y/no-autofocus': 'off',
// recommended rule is:
// 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
// 'error',
// {
// tr: ['none', 'presentation'],
// canvas: ['img'],
// },
// ],
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off',
// recommended rule is:
// 'jsx-a11y/no-noninteractive-element-interactions': [
// 'error',
// {
// body: ['onError', 'onLoad'],
// iframe: ['onError', 'onLoad'],
// img: ['onError', 'onLoad'],
// },
// ],
'jsx-a11y/no-noninteractive-element-interactions': [
'warn',
{
handlers: [
'onClick',
],
},
],
// recommended rule is:
// 'jsx-a11y/no-noninteractive-tabindex': [
// 'error',
// {
// tags: [],
// roles: ['tabpanel'],
// allowExpressionValues: true,
// },
// ],
'jsx-a11y/no-noninteractive-tabindex': 'off',
'jsx-a11y/no-onchange': 'warn',
// recommended is full 'error'
'jsx-a11y/no-static-element-interactions': [
'warn',
{
handlers: [
'onClick',
],
},
],
// See https://github.com/import-js/eslint-plugin-import/blob/main/config/recommended.js
'import/extensions': [
'error',
'always',
{
js: 'never',
jsx: 'never',
mjs: 'never',
ts: 'never',
tsx: 'never',
},
],
'import/first': 'error',
'import/newline-after-import': 'error',
'import/no-anonymous-default-export': 'error',
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: [
'config/webpack/**',
'app/javascript/mastodon/performance.js',
'app/javascript/mastodon/test_setup.js',
'app/javascript/**/__tests__/**',
],
},
],
'import/no-amd': 'error',
'import/no-commonjs': 'error',
'import/no-import-module-exports': 'error',
'import/no-relative-packages': 'error',
'import/no-self-import': 'error',
'import/no-useless-path-segments': 'error',
'import/no-webpack-loader-syntax': 'error',
'import/order': [
'error',
{
alphabetize: { order: 'asc' },
'newlines-between': 'always',
groups: [
'builtin',
'external',
'internal',
'parent',
['index', 'sibling'],
'object',
],
pathGroups: [
// React core packages
{
pattern: '{react,react-dom,react-dom/client,prop-types}',
group: 'builtin',
position: 'after',
},
// I18n
{
pattern: '{react-intl,intl-messageformat}',
group: 'builtin',
position: 'after',
},
// Common React utilities
{
pattern: '{classnames,react-helmet,react-router-dom}',
group: 'external',
position: 'before',
},
// Immutable / Redux / data store
{
pattern: '{immutable,react-redux,react-immutable-proptypes,react-immutable-pure-component,reselect}',
group: 'external',
position: 'before',
},
// Internal packages
{
pattern: '{mastodon/**}',
group: 'internal',
position: 'after',
},
{
pattern: '{flavours/glitch-soc/**}',
group: 'internal',
position: 'after',
},
],
pathGroupsExcludedImportTypes: [],
},
],
// Forbid imports from vanilla in glitch flavour
'import/no-restricted-paths': [
'error',
{
zones: [{
target: 'app/javascript/flavours/glitch/',
from: 'app/javascript/mastodon/',
message: 'Import from /flavours/glitch/ instead'
}]
}
],
'promise/always-return': 'off',
'promise/catch-or-return': [
'error',
{
allowFinally: true,
},
],
'promise/no-callback-in-promise': 'off',
'promise/no-nesting': 'off',
'promise/no-promise-in-callback': 'off',
'formatjs/blocklist-elements': 'error',
'formatjs/enforce-default-message': ['error', 'literal'],
'formatjs/enforce-description': 'off', // description values not currently used
'formatjs/enforce-id': 'off', // Explicit IDs are used in the project
'formatjs/enforce-placeholders': 'off', // Issues in short_number.jsx
'formatjs/enforce-plural-rules': 'error',
'formatjs/no-camel-case': 'off', // disabledAccount is only non-conforming
'formatjs/no-complex-selectors': 'error',
'formatjs/no-emoji': 'error',
'formatjs/no-id': 'off', // IDs are used for translation keys
'formatjs/no-invalid-icu': 'error',
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
'formatjs/no-multiple-plurals': 'off', // Only used by hashtag.jsx
'formatjs/no-multiple-whitespaces': 'error',
'formatjs/no-offset': 'error',
'formatjs/no-useless-message': 'error',
'formatjs/prefer-formatted-message': 'error',
'formatjs/prefer-pound-in-plural': 'error',
'jsdoc/check-types': 'off',
'jsdoc/no-undefined-types': 'off',
'jsdoc/require-jsdoc': 'off',
'jsdoc/require-param-description': 'off',
'jsdoc/require-property-description': 'off',
'jsdoc/require-returns-description': 'off',
'jsdoc/require-returns': 'off',
},
overrides: [
{
files: [
'*.config.js',
'.*rc.js',
'ide-helper.js',
'config/webpack/**/*',
'config/formatjs-formatter.js',
],
env: {
commonjs: true,
},
parserOptions: {
sourceType: 'script',
},
rules: {
'import/no-commonjs': 'off',
},
},
{
files: [
'**/*.ts',
'**/*.tsx',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/strict-type-checked',
'plugin:@typescript-eslint/stylistic-type-checked',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:promise/recommended',
'plugin:jsdoc/recommended-typescript',
'plugin:prettier/recommended',
],
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
},
rules: {
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
'@typescript-eslint/consistent-type-exports': 'error',
'@typescript-eslint/consistent-type-imports': 'error',
"@typescript-eslint/prefer-nullish-coalescing": ['error', {ignorePrimitives: {boolean: true}}],
'jsdoc/require-jsdoc': 'off',
// Those rules set stricter rules for TS files
// to enforce better practices when converting from JS
'import/no-default-export': 'warn',
'react/prefer-stateless-function': 'warn',
'react/function-component-definition': ['error', { namedComponents: 'arrow-function' }],
'react/jsx-uses-react': 'off', // not needed with new JSX transform
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
'react/prop-types': 'off',
},
},
{
files: [
'**/__tests__/*.js',
'**/__tests__/*.jsx',
],
env: {
jest: true,
},
},
{
files: [
'streaming/**/*',
],
rules: {
'import/no-commonjs': 'off',
},
},
],
};
-34
View File
@@ -1,34 +0,0 @@
name: Build and Push Masto Image
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Generate timestamp
id: vars
run: echo "TAG=$(date +%Y%m%d-%H%M)" >> $GITHUB_ENV
- name: Login to Docker Hub
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login \
-u "${{ secrets.DOCKER_USERNAME }}" \
--password-stdin
- name: Build image
run: |
docker build \
-t domoel/masto:latest \
-t domoel/masto:${TAG} \
.
- name: Push image
run: |
docker push domoel/masto:latest
docker push domoel/masto:${TAG}
-3
View File
@@ -55,9 +55,6 @@ npm-debug.log
yarn-error.log yarn-error.log
yarn-debug.log yarn-debug.log
# Ignore yarn state file
.yarn/install-state.gz
# Ignore vagrant log files # Ignore vagrant log files
*-cloudimg-console.log *-cloudimg-console.log
+1
View File
@@ -0,0 +1 @@
20.8
+2 -2
View File
@@ -1,4 +1,4 @@
module.exports = { module.exports = {
singleQuote: true, singleQuote: true,
jsxSingleQuote: true, jsxSingleQuote: true
}; }
+5 -5
View File
@@ -1,23 +1,23 @@
steps: steps:
lint: lint:
image: docker.io/superseriousbusiness/masto-fe-standalone-woodpecker-build:0.1.0 image: node:22-alpine
pull: true pull: true
# https://woodpecker-ci.org/docs/usage/volumes # https://woodpecker-ci.org/docs/usage/volumes
volumes: volumes:
- /woodpecker/masto-fe-standalone/node_modules:/woodpecker/src/codeberg.org/superseriousbusiness/masto-fe-standalone/node_modules - /woodpecker/masto-fe-standalone/node_modules:/woodpecker/src/codeberg.org/superseriousbusiness/masto-fe-standalone/node_modules
- /woodpecker/masto-fe-standalone/.eslintcache:/woodpecker/src/codeberg.org/superseriousbusiness/masto-fe-standalone/.eslintcache - /woodpecker/masto-fe-standalone/.eslintcache:/woodpecker/src/codeberg.org/superseriousbusiness/masto-fe-standalone/.eslintcache
# https://woodpecker-ci.org/docs/administration/configuration/backends/docker#run-user # https://woodpecker-ci.org/docs/administration/configuration/backends/docker#run-user
backend_options: backend_options:
docker: docker:
user: 1000:1000 user: 1000:1000
# https://woodpecker-ci.org/docs/usage/workflow-syntax#commands # https://woodpecker-ci.org/docs/usage/workflow-syntax#commands
commands: commands:
- yarn - yarn
- yarn lint:js - yarn lint:js
# https://woodpecker-ci.org/docs/usage/workflow-syntax#when---conditional-execution # https://woodpecker-ci.org/docs/usage/workflow-syntax#when---conditional-execution
when: when:
- event: pull_request - event: pull_request
-1
View File
@@ -1 +0,0 @@
nodeLinker: node-modules
+1884 -15
View File
File diff suppressed because it is too large Load Diff
+3199 -70
View File
File diff suppressed because it is too large Load Diff
+1 -5
View File
@@ -4,11 +4,7 @@
## Dependencies ## Dependencies
To work on the code, you must have Node installed. To work on the code decently, you should have Node and Yarn installed. To avoid fuckery, Node Version Manager is **highly recommended**: https://github.com/nvm-sh/nvm.
To avoid fuckery, Node Version Manager is **highly recommended**: https://github.com/nvm-sh/nvm. You can then install the latest `lts` version of node with `nvm install --lts && nvm use --lts`.
You should install yarn as described [here](https://yarnpkg.com/getting-started/install) and/or [here](https://yarnpkg.com/migration/guide).
## Testing Locally ## Testing Locally
+12 -16
View File
@@ -1,17 +1,13 @@
### BUILDER IMAGE ### ### BUILDER IMAGE ###
FROM docker.io/superseriousbusiness/masto-fe-standalone-woodpecker-build:0.1.0 AS builder FROM node:lts-alpine AS builder
# Prepare the build directory, copy
# relevant source + config files over.
WORKDIR /build WORKDIR /build
COPY app /build/app
USER root COPY config /build/config
RUN mkdir -p /build/.yarn && chown -R node:node /build COPY public /build/public
USER node COPY \
COPY --chown=node:node app /build/app
COPY --chown=node:node config /build/config
COPY --chown=node:node public /build/public
COPY --chown=node:node \
.browserslistrc \ .browserslistrc \
babel.config.js \ babel.config.js \
jsconfig.json \ jsconfig.json \
@@ -20,19 +16,19 @@ COPY --chown=node:node \
yarn.lock \ yarn.lock \
/build/ /build/
# Create a production build of the frontend.
RUN yarn && yarn build:production RUN yarn && yarn build:production
### RUNTIME IMAGE ### ### RUNTIME IMAGE ###
FROM docker.io/nginx:alpine AS runtime FROM nginx:1.28.0-alpine AS runtime
# Copy bigger nested stuff.
COPY --from=builder /build/public/packs/js/flavours/glitch /usr/share/nginx/html/packs/js/flavours/glitch COPY --from=builder /build/public/packs/js/flavours/glitch /usr/share/nginx/html/packs/js/flavours/glitch
COPY --from=builder /build/public/packs/js/flavours/vanilla /usr/share/nginx/html/packs/js/flavours/vanilla COPY --from=builder /build/public/packs/js/flavours/vanilla /usr/share/nginx/html/packs/js/flavours/vanilla
# Copy remaining files.
COPY --from=builder /build/public /usr/share/nginx/html/ COPY --from=builder /build/public /usr/share/nginx/html/
# Set up nginx.
COPY nginx.conf /etc/nginx/nginx.conf COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80 EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
+76 -82
View File
@@ -1,49 +1,49 @@
// This file will be loaded on admin pages, regardless of theme. // This file will be loaded on admin pages, regardless of theme.
import "packs/public-path"; import 'packs/public-path';
import Rails from "@rails/ujs"; import { delegate } from '@rails/ujs';
import ready from "../mastodon/ready"; import ready from '../mastodon/ready';
const setAnnouncementEndsAttributes = (target) => { const setAnnouncementEndsAttributes = (target) => {
const valid = target?.value && target?.validity?.valid; const valid = target?.value && target?.validity?.valid;
const element = document.querySelector("input[type=\"datetime-local\"]#announcement_ends_at"); const element = document.querySelector('input[type="datetime-local"]#announcement_ends_at');
if (valid) { if (valid) {
element.classList.remove("optional"); element.classList.remove('optional');
element.required = true; element.required = true;
element.min = target.value; element.min = target.value;
} else { } else {
element.classList.add("optional"); element.classList.add('optional');
element.removeAttribute("required"); element.removeAttribute('required');
element.removeAttribute("min"); element.removeAttribute('min');
} }
}; };
Rails.delegate(document, "input[type=\"datetime-local\"]#announcement_starts_at", "change", ({ target }) => { delegate(document, 'input[type="datetime-local"]#announcement_starts_at', 'change', ({ target }) => {
setAnnouncementEndsAttributes(target); setAnnouncementEndsAttributes(target);
}); });
const batchCheckboxClassName = ".batch-checkbox input[type=\"checkbox\"]"; const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]';
const showSelectAll = () => { const showSelectAll = () => {
const selectAllMatchingElement = document.querySelector(".batch-table__select-all"); const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
selectAllMatchingElement.classList.add("active"); selectAllMatchingElement.classList.add('active');
}; };
const hideSelectAll = () => { const hideSelectAll = () => {
const selectAllMatchingElement = document.querySelector(".batch-table__select-all"); const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
const hiddenField = document.querySelector("#select_all_matching"); const hiddenField = document.querySelector('#select_all_matching');
const selectedMsg = document.querySelector(".batch-table__select-all .selected"); const selectedMsg = document.querySelector('.batch-table__select-all .selected');
const notSelectedMsg = document.querySelector(".batch-table__select-all .not-selected"); const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected');
selectAllMatchingElement.classList.remove("active"); selectAllMatchingElement.classList.remove('active');
selectedMsg.classList.remove("active"); selectedMsg.classList.remove('active');
notSelectedMsg.classList.add("active"); notSelectedMsg.classList.add('active');
hiddenField.value = "0"; hiddenField.value = '0';
}; };
Rails.delegate(document, "#batch_checkbox_all", "change", ({ target }) => { delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
const selectAllMatchingElement = document.querySelector(".batch-table__select-all"); const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
[].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => { [].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => {
content.checked = target.checked; content.checked = target.checked;
@@ -58,26 +58,26 @@ Rails.delegate(document, "#batch_checkbox_all", "change", ({ target }) => {
} }
}); });
Rails.delegate(document, ".batch-table__select-all button", "click", () => { delegate(document, '.batch-table__select-all button', 'click', () => {
const hiddenField = document.querySelector("#select_all_matching"); const hiddenField = document.querySelector('#select_all_matching');
const active = hiddenField.value === "1"; const active = hiddenField.value === '1';
const selectedMsg = document.querySelector(".batch-table__select-all .selected"); const selectedMsg = document.querySelector('.batch-table__select-all .selected');
const notSelectedMsg = document.querySelector(".batch-table__select-all .not-selected"); const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected');
if (active) { if (active) {
hiddenField.value = "0"; hiddenField.value = '0';
selectedMsg.classList.remove("active"); selectedMsg.classList.remove('active');
notSelectedMsg.classList.add("active"); notSelectedMsg.classList.add('active');
} else { } else {
hiddenField.value = "1"; hiddenField.value = '1';
notSelectedMsg.classList.remove("active"); notSelectedMsg.classList.remove('active');
selectedMsg.classList.add("active"); selectedMsg.classList.add('active');
} }
}); });
Rails.delegate(document, batchCheckboxClassName, "change", () => { delegate(document, batchCheckboxClassName, 'change', () => {
const checkAllElement = document.querySelector("#batch_checkbox_all"); const checkAllElement = document.querySelector('#batch_checkbox_all');
const selectAllMatchingElement = document.querySelector(".batch-table__select-all"); const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
if (checkAllElement) { if (checkAllElement) {
checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked);
@@ -93,78 +93,78 @@ Rails.delegate(document, batchCheckboxClassName, "change", () => {
} }
}); });
Rails.delegate(document, ".media-spoiler-show-button", "click", () => { delegate(document, '.media-spoiler-show-button', 'click', () => {
[].forEach.call(document.querySelectorAll("button.media-spoiler"), (element) => { [].forEach.call(document.querySelectorAll('button.media-spoiler'), (element) => {
element.click(); element.click();
}); });
}); });
Rails.delegate(document, ".media-spoiler-hide-button", "click", () => { delegate(document, '.media-spoiler-hide-button', 'click', () => {
[].forEach.call(document.querySelectorAll(".spoiler-button.spoiler-button--visible button"), (element) => { [].forEach.call(document.querySelectorAll('.spoiler-button.spoiler-button--visible button'), (element) => {
element.click(); element.click();
}); });
}); });
Rails.delegate(document, ".filter-subset--with-select select", "change", ({ target }) => { delegate(document, '.filter-subset--with-select select', 'change', ({ target }) => {
target.form.submit(); target.form.submit();
}); });
const onDomainBlockSeverityChange = (target) => { const onDomainBlockSeverityChange = (target) => {
const rejectMediaDiv = document.querySelector(".input.with_label.domain_block_reject_media"); const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media');
const rejectReportsDiv = document.querySelector(".input.with_label.domain_block_reject_reports"); const rejectReportsDiv = document.querySelector('.input.with_label.domain_block_reject_reports');
if (rejectMediaDiv) { if (rejectMediaDiv) {
rejectMediaDiv.style.display = (target.value === "suspend") ? "none" : "block"; rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
} }
if (rejectReportsDiv) { if (rejectReportsDiv) {
rejectReportsDiv.style.display = (target.value === "suspend") ? "none" : "block"; rejectReportsDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
} }
}; };
Rails.delegate(document, "#domain_block_severity", "change", ({ target }) => onDomainBlockSeverityChange(target)); delegate(document, '#domain_block_severity', 'change', ({ target }) => onDomainBlockSeverityChange(target));
const onEnableBootstrapTimelineAccountsChange = (target) => { const onEnableBootstrapTimelineAccountsChange = (target) => {
const bootstrapTimelineAccountsField = document.querySelector("#form_admin_settings_bootstrap_timeline_accounts"); const bootstrapTimelineAccountsField = document.querySelector('#form_admin_settings_bootstrap_timeline_accounts');
if (bootstrapTimelineAccountsField) { if (bootstrapTimelineAccountsField) {
bootstrapTimelineAccountsField.disabled = !target.checked; bootstrapTimelineAccountsField.disabled = !target.checked;
if (target.checked) { if (target.checked) {
bootstrapTimelineAccountsField.parentElement.classList.remove("disabled"); bootstrapTimelineAccountsField.parentElement.classList.remove('disabled');
bootstrapTimelineAccountsField.parentElement.parentElement.classList.remove("disabled"); bootstrapTimelineAccountsField.parentElement.parentElement.classList.remove('disabled');
} else { } else {
bootstrapTimelineAccountsField.parentElement.classList.add("disabled"); bootstrapTimelineAccountsField.parentElement.classList.add('disabled');
bootstrapTimelineAccountsField.parentElement.parentElement.classList.add("disabled"); bootstrapTimelineAccountsField.parentElement.parentElement.classList.add('disabled');
} }
} }
}; };
Rails.delegate(document, "#form_admin_settings_enable_bootstrap_timeline_accounts", "change", ({ target }) => onEnableBootstrapTimelineAccountsChange(target)); delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target));
const onChangeRegistrationMode = (target) => { const onChangeRegistrationMode = (target) => {
const enabled = target.value === "approved"; const enabled = target.value === 'approved';
[].forEach.call(document.querySelectorAll("#form_admin_settings_require_invite_text"), (input) => { [].forEach.call(document.querySelectorAll('#form_admin_settings_require_invite_text'), (input) => {
input.disabled = !enabled; input.disabled = !enabled;
if (enabled) { if (enabled) {
let element = input; let element = input;
do { do {
element.classList.remove("disabled"); element.classList.remove('disabled');
element = element.parentElement; element = element.parentElement;
} while (element && !element.classList.contains("fields-group")); } while (element && !element.classList.contains('fields-group'));
} else { } else {
let element = input; let element = input;
do { do {
element.classList.add("disabled"); element.classList.add('disabled');
element = element.parentElement; element = element.parentElement;
} while (element && !element.classList.contains("fields-group")); } while (element && !element.classList.contains('fields-group'));
} }
}); });
}; };
const convertUTCDateTimeToLocal = (value) => { const convertUTCDateTimeToLocal = (value) => {
const date = new Date(value + "Z"); const date = new Date(value + 'Z');
const twoChars = (x) => (x.toString().padStart(2, "0")); const twoChars = (x) => (x.toString().padStart(2, '0'));
return `${date.getFullYear()}-${twoChars(date.getMonth()+1)}-${twoChars(date.getDate())}T${twoChars(date.getHours())}:${twoChars(date.getMinutes())}`; return `${date.getFullYear()}-${twoChars(date.getMonth()+1)}-${twoChars(date.getDate())}T${twoChars(date.getHours())}:${twoChars(date.getMinutes())}`;
}; };
@@ -173,44 +173,38 @@ const convertLocalDatetimeToUTC = (value) => {
const match = re.exec(value); const match = re.exec(value);
const date = new Date(match[1], match[2] - 1, match[3], match[4], match[5]); const date = new Date(match[1], match[2] - 1, match[3], match[4], match[5]);
const fullISO8601 = date.toISOString(); const fullISO8601 = date.toISOString();
return fullISO8601.slice(0, fullISO8601.indexOf("T") + 6); return fullISO8601.slice(0, fullISO8601.indexOf('T') + 6);
}; };
Rails.delegate(document, "#form_admin_settings_registrations_mode", "change", ({ target }) => onChangeRegistrationMode(target)); delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target));
ready(() => { ready(() => {
const domainBlockSeverityInput = document.getElementById("domain_block_severity"); const domainBlockSeverityInput = document.getElementById('domain_block_severity');
if (domainBlockSeverityInput) { if (domainBlockSeverityInput) onDomainBlockSeverityChange(domainBlockSeverityInput);
onDomainBlockSeverityChange(domainBlockSeverityInput);
}
const enableBootstrapTimelineAccounts = document.getElementById("form_admin_settings_enable_bootstrap_timeline_accounts"); const enableBootstrapTimelineAccounts = document.getElementById('form_admin_settings_enable_bootstrap_timeline_accounts');
if (enableBootstrapTimelineAccounts) { if (enableBootstrapTimelineAccounts) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts);
onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts);
}
const registrationMode = document.getElementById("form_admin_settings_registrations_mode"); const registrationMode = document.getElementById('form_admin_settings_registrations_mode');
if (registrationMode) { if (registrationMode) onChangeRegistrationMode(registrationMode);
onChangeRegistrationMode(registrationMode);
}
const checkAllElement = document.querySelector("#batch_checkbox_all"); const checkAllElement = document.querySelector('#batch_checkbox_all');
if (checkAllElement) { if (checkAllElement) {
checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked);
checkAllElement.indeterminate = !checkAllElement.checked && [].some.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); checkAllElement.indeterminate = !checkAllElement.checked && [].some.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked);
} }
document.querySelector("a#add-instance-button")?.addEventListener("click", (e) => { document.querySelector('a#add-instance-button')?.addEventListener('click', (e) => {
const domain = document.querySelector("input[type=\"text\"]#by_domain")?.value; const domain = document.querySelector('input[type="text"]#by_domain')?.value;
if (domain) { if (domain) {
const url = new URL(event.target.href); const url = new URL(event.target.href);
url.searchParams.set("_domain", domain); url.searchParams.set('_domain', domain);
e.target.href = url; e.target.href = url;
} }
}); });
[].forEach.call(document.querySelectorAll("input[type=\"datetime-local\"]"), element => { [].forEach.call(document.querySelectorAll('input[type="datetime-local"]'), element => {
if (element.value) { if (element.value) {
element.value = convertUTCDateTimeToLocal(element.value); element.value = convertUTCDateTimeToLocal(element.value);
} }
@@ -219,15 +213,15 @@ ready(() => {
} }
}); });
Rails.delegate(document, "form", "submit", ({ target }) => { delegate(document, 'form', 'submit', ({ target }) => {
[].forEach.call(target.querySelectorAll("input[type=\"datetime-local\"]"), element => { [].forEach.call(target.querySelectorAll('input[type="datetime-local"]'), element => {
if (element.value && element.validity.valid) { if (element.value && element.validity.valid) {
element.value = convertLocalDatetimeToUTC(element.value); element.value = convertLocalDatetimeToUTC(element.value);
} }
}); });
}); });
const announcementStartsAt = document.querySelector("input[type=\"datetime-local\"]#announcement_starts_at"); const announcementStartsAt = document.querySelector('input[type="datetime-local"]#announcement_starts_at');
if (announcementStartsAt) { if (announcementStartsAt) {
setAnnouncementEndsAttributes(announcementStartsAt); setAnnouncementEndsAttributes(announcementStartsAt);
} }
+3 -3
View File
@@ -1,3 +1,3 @@
import "packs/public-path"; import 'packs/public-path';
import "./settings"; import './settings';
import "./two_factor_authentication"; import './two_factor_authentication';
+3 -3
View File
@@ -1,6 +1,6 @@
// This file will be loaded on all pages, regardless of theme. // This file will be loaded on all pages, regardless of theme.
import "packs/public-path"; import 'packs/public-path';
import "font-awesome/css/font-awesome.css"; import 'font-awesome/css/font-awesome.css';
require.context("../images/", true); require.context('../images/', true);
+8 -8
View File
@@ -1,25 +1,25 @@
// This file will be loaded on embed pages, regardless of theme. // This file will be loaded on embed pages, regardless of theme.
import "packs/public-path"; import 'packs/public-path';
window.addEventListener("message", e => { window.addEventListener('message', e => {
const data = e.data || {}; const data = e.data || {};
if (!window.parent || data.type !== "setHeight") { if (!window.parent || data.type !== 'setHeight') {
return; return;
} }
function setEmbedHeight () { function setEmbedHeight () {
window.parent.postMessage({ window.parent.postMessage({
type: "setHeight", type: 'setHeight',
id: data.id, id: data.id,
height: document.getElementsByTagName("html")[0].scrollHeight, height: document.getElementsByTagName('html')[0].scrollHeight,
}, "*"); }, '*');
} }
if (["interactive", "complete"].includes(document.readyState)) { if (['interactive', 'complete'].includes(document.readyState)) {
setEmbedHeight(); setEmbedHeight();
} else { } else {
document.addEventListener("DOMContentLoaded", setEmbedHeight); document.addEventListener('DOMContentLoaded', setEmbedHeight);
} }
}); });
+2 -2
View File
@@ -1,3 +1,3 @@
import "../styles/mailer.scss"; import '../styles/mailer.scss';
require.context("../icons"); require.context('../icons');
@@ -8,29 +8,29 @@ and performs no other task.
*/ */
import "packs/public-path"; import 'packs/public-path';
import axios from "axios"; import axios from 'axios';
interface JRDLink { interface JRDLink {
rel: string, rel: string;
template?: string, template?: string;
href?: string, href?: string;
} }
const isJRDLink = (link: unknown): link is JRDLink => const isJRDLink = (link: unknown): link is JRDLink =>
typeof link === "object" && typeof link === 'object' &&
link !== null && link !== null &&
"rel" in link && 'rel' in link &&
typeof link.rel === "string" && typeof link.rel === 'string' &&
(!("template" in link) || typeof link.template === "string") && (!('template' in link) || typeof link.template === 'string') &&
(!("href" in link) || typeof link.href === "string"); (!('href' in link) || typeof link.href === 'string');
const findLink = (rel: string, data: unknown): JRDLink | undefined => { const findLink = (rel: string, data: unknown): JRDLink | undefined => {
if ( if (
typeof data === "object" && typeof data === 'object' &&
data !== null && data !== null &&
"links" in data && 'links' in data &&
data.links instanceof Array data.links instanceof Array
) { ) {
return data.links.find( return data.links.find(
@@ -42,7 +42,7 @@ const findLink = (rel: string, data: unknown): JRDLink | undefined => {
}; };
const findTemplateLink = (data: unknown) => const findTemplateLink = (data: unknown) =>
findLink("http://ostatus.org/schema/1.0/subscribe", data)?.template; findLink('http://ostatus.org/schema/1.0/subscribe', data)?.template;
const fetchInteractionURLSuccess = ( const fetchInteractionURLSuccess = (
uri_or_domain: string, uri_or_domain: string,
@@ -50,7 +50,7 @@ const fetchInteractionURLSuccess = (
) => { ) => {
window.parent.postMessage( window.parent.postMessage(
{ {
type: "fetchInteractionURL-success", type: 'fetchInteractionURL-success',
uri_or_domain, uri_or_domain,
template, template,
}, },
@@ -61,14 +61,14 @@ const fetchInteractionURLSuccess = (
const fetchInteractionURLFailure = () => { const fetchInteractionURLFailure = () => {
window.parent.postMessage( window.parent.postMessage(
{ {
type: "fetchInteractionURL-failure", type: 'fetchInteractionURL-failure',
}, },
window.origin, window.origin,
); );
}; };
const isValidDomain = (value: string) => { const isValidDomain = (value: string) => {
const url = new URL("https:///path"); const url = new URL('https:///path');
url.hostname = value; url.hostname = value;
return url.hostname === value; return url.hostname === value;
}; };
@@ -112,9 +112,9 @@ const fromURL = (url: string) => {
// Attempt to find a remote interaction URL from a `user@domain` string // Attempt to find a remote interaction URL from a `user@domain` string
const fromAcct = (acct: string) => { const fromAcct = (acct: string) => {
acct = acct.replace(/^@/, ""); acct = acct.replace(/^@/, '');
const segments = acct.split("@"); const segments = acct.split('@');
if (segments.length !== 2 || !segments[0] || !isValidDomain(segments[1])) { if (segments.length !== 2 || !segments[0] || !isValidDomain(segments[1])) {
fetchInteractionURLFailure(); fetchInteractionURLFailure();
@@ -140,18 +140,18 @@ const fromAcct = (acct: string) => {
}; };
const fetchInteractionURL = (uri_or_domain: string) => { const fetchInteractionURL = (uri_or_domain: string) => {
if (uri_or_domain === "") { if (uri_or_domain === '') {
fetchInteractionURLFailure(); fetchInteractionURLFailure();
} else if (/^https?:\/\//.test(uri_or_domain)) { } else if (/^https?:\/\//.test(uri_or_domain)) {
fromURL(uri_or_domain); fromURL(uri_or_domain);
} else if (uri_or_domain.includes("@")) { } else if (uri_or_domain.includes('@')) {
fromAcct(uri_or_domain); fromAcct(uri_or_domain);
} else { } else {
fromDomain(uri_or_domain); fromDomain(uri_or_domain);
} }
}; };
window.addEventListener("message", (event: MessageEvent<unknown>) => { window.addEventListener('message', (event: MessageEvent<unknown>) => {
// Check message origin // Check message origin
if ( if (
!window.origin || !window.origin ||
@@ -163,11 +163,11 @@ window.addEventListener("message", (event: MessageEvent<unknown>) => {
if ( if (
event.data && event.data &&
typeof event.data === "object" && typeof event.data === 'object' &&
"type" in event.data && 'type' in event.data &&
event.data.type === "fetchInteractionURL" && event.data.type === 'fetchInteractionURL' &&
"uri_or_domain" in event.data && 'uri_or_domain' in event.data &&
typeof event.data.uri_or_domain === "string" typeof event.data.uri_or_domain === 'string'
) { ) {
fetchInteractionURL(event.data.uri_or_domain); fetchInteractionURL(event.data.uri_or_domain);
} }
+10 -10
View File
@@ -1,24 +1,24 @@
// This file will be loaded on settings pages, regardless of theme. // This file will be loaded on settings pages, regardless of theme.
import "packs/public-path"; import 'packs/public-path';
import Rails from "@rails/ujs"; import { delegate } from '@rails/ujs';
Rails.delegate(document, "#edit_profile input[type=file]", "change", ({ target }) => { delegate(document, '#edit_profile input[type=file]', 'change', ({ target }) => {
const avatar = document.getElementById(target.id + "-preview"); const avatar = document.getElementById(target.id + '-preview');
const [file] = target.files || []; const [file] = target.files || [];
const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc; const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
avatar.src = url; avatar.src = url;
}); });
Rails.delegate(document, ".input-copy input", "click", ({ target }) => { delegate(document, '.input-copy input', 'click', ({ target }) => {
target.focus(); target.focus();
target.select(); target.select();
target.setSelectionRange(0, target.value.length); target.setSelectionRange(0, target.value.length);
}); });
Rails.delegate(document, ".input-copy button", "click", ({ target }) => { delegate(document, '.input-copy button', 'click', ({ target }) => {
const input = target.parentNode.querySelector(".input-copy__wrapper input"); const input = target.parentNode.querySelector('.input-copy__wrapper input');
const oldReadOnly = input.readonly; const oldReadOnly = input.readonly;
@@ -28,12 +28,12 @@ Rails.delegate(document, ".input-copy button", "click", ({ target }) => {
input.setSelectionRange(0, input.value.length); input.setSelectionRange(0, input.value.length);
try { try {
if (document.execCommand("copy")) { if (document.execCommand('copy')) {
input.blur(); input.blur();
target.parentNode.classList.add("copied"); target.parentNode.classList.add('copied');
setTimeout(() => { setTimeout(() => {
target.parentNode.classList.remove("copied"); target.parentNode.classList.remove('copied');
}, 700); }, 700);
} }
} catch (err) { } catch (err) {
@@ -1,40 +1,40 @@
import "packs/public-path"; import 'packs/public-path';
import * as WebAuthnJSON from "@github/webauthn-json"; import * as WebAuthnJSON from '@github/webauthn-json';
import axios from "axios"; import axios from 'axios';
import ready from "../mastodon/ready"; import ready from '../mastodon/ready';
import "regenerator-runtime/runtime"; import 'regenerator-runtime/runtime';
function getCSRFToken() { function getCSRFToken() {
var CSRFSelector = document.querySelector("meta[name=\"csrf-token\"]"); var CSRFSelector = document.querySelector('meta[name="csrf-token"]');
if (CSRFSelector) { if (CSRFSelector) {
return CSRFSelector.getAttribute("content"); return CSRFSelector.getAttribute('content');
} else { } else {
return null; return null;
} }
} }
function hideFlashMessages() { function hideFlashMessages() {
Array.from(document.getElementsByClassName("flash-message")).forEach(function(flashMessage) { Array.from(document.getElementsByClassName('flash-message')).forEach(function(flashMessage) {
flashMessage.classList.add("hidden"); flashMessage.classList.add('hidden');
}); });
} }
function callback(url, body) { function callback(url, body) {
axios.post(url, JSON.stringify(body), { axios.post(url, JSON.stringify(body), {
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Accept": "application/json", 'Accept': 'application/json',
"X-CSRF-Token": getCSRFToken(), 'X-CSRF-Token': getCSRFToken(),
}, },
credentials: "same-origin", credentials: 'same-origin',
}).then(function(response) { }).then(function(response) {
window.location.replace(response.data.redirect_path); window.location.replace(response.data.redirect_path);
}).catch(function(error) { }).catch(function(error) {
if (error.response.status === 422) { if (error.response.status === 422) {
const errorMessage = document.getElementById("security-key-error-message"); const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove("hidden"); errorMessage.classList.remove('hidden');
console.error(error.response.data.error); console.error(error.response.data.error);
} else { } else {
console.error(error); console.error(error);
@@ -44,31 +44,31 @@ function callback(url, body) {
ready(() => { ready(() => {
if (!WebAuthnJSON.supported()) { if (!WebAuthnJSON.supported()) {
const unsupported_browser_message = document.getElementById("unsupported-browser-message"); const unsupported_browser_message = document.getElementById('unsupported-browser-message');
if (unsupported_browser_message) { if (unsupported_browser_message) {
unsupported_browser_message.classList.remove("hidden"); unsupported_browser_message.classList.remove('hidden');
document.querySelector(".btn.js-webauthn").disabled = true; document.querySelector('.btn.js-webauthn').disabled = true;
} }
} }
const webAuthnCredentialRegistrationForm = document.getElementById("new_webauthn_credential"); const webAuthnCredentialRegistrationForm = document.getElementById('new_webauthn_credential');
if (webAuthnCredentialRegistrationForm) { if (webAuthnCredentialRegistrationForm) {
webAuthnCredentialRegistrationForm.addEventListener("submit", (event) => { webAuthnCredentialRegistrationForm.addEventListener('submit', (event) => {
event.preventDefault(); event.preventDefault();
var nickname = event.target.querySelector("input[name=\"new_webauthn_credential[nickname]\"]"); var nickname = event.target.querySelector('input[name="new_webauthn_credential[nickname]"]');
if (nickname.value) { if (nickname.value) {
axios.get("/settings/security_keys/options") axios.get('/settings/security_keys/options')
.then((response) => { .then((response) => {
const credentialOptions = response.data; const credentialOptions = response.data;
WebAuthnJSON.create({ "publicKey": credentialOptions }).then((credential) => { WebAuthnJSON.create({ 'publicKey': credentialOptions }).then((credential) => {
var params = { "credential": credential, "nickname": nickname.value }; var params = { 'credential': credential, 'nickname': nickname.value };
callback("/settings/security_keys", params); callback('/settings/security_keys', params);
}).catch((error) => { }).catch((error) => {
const errorMessage = document.getElementById("security-key-error-message"); const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove("hidden"); errorMessage.classList.remove('hidden');
console.error(error); console.error(error);
}); });
}).catch((error) => { }).catch((error) => {
@@ -80,21 +80,21 @@ ready(() => {
}); });
} }
const webAuthnCredentialAuthenticationForm = document.getElementById("webauthn-form"); const webAuthnCredentialAuthenticationForm = document.getElementById('webauthn-form');
if (webAuthnCredentialAuthenticationForm) { if (webAuthnCredentialAuthenticationForm) {
webAuthnCredentialAuthenticationForm.addEventListener("submit", (event) => { webAuthnCredentialAuthenticationForm.addEventListener('submit', (event) => {
event.preventDefault(); event.preventDefault();
axios.get("sessions/security_key_options") axios.get('sessions/security_key_options')
.then((response) => { .then((response) => {
const credentialOptions = response.data; const credentialOptions = response.data;
WebAuthnJSON.get({ "publicKey": credentialOptions }).then((credential) => { WebAuthnJSON.get({ 'publicKey': credentialOptions }).then((credential) => {
var params = { "user": { "credential": credential } }; var params = { 'user': { 'credential': credential } };
callback("sign_in", params); callback('sign_in', params);
}).catch((error) => { }).catch((error) => {
const errorMessage = document.getElementById("security-key-error-message"); const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove("hidden"); errorMessage.classList.remove('hidden');
console.error(error); console.error(error);
}); });
}).catch((error) => { }).catch((error) => {
@@ -102,19 +102,19 @@ ready(() => {
}); });
}); });
const otpAuthenticationForm = document.getElementById("otp-authentication-form"); const otpAuthenticationForm = document.getElementById('otp-authentication-form');
const linkToOtp = document.getElementById("link-to-otp"); const linkToOtp = document.getElementById('link-to-otp');
linkToOtp.addEventListener("click", () => { linkToOtp.addEventListener('click', () => {
webAuthnCredentialAuthenticationForm.classList.add("hidden"); webAuthnCredentialAuthenticationForm.classList.add('hidden');
otpAuthenticationForm.classList.remove("hidden"); otpAuthenticationForm.classList.remove('hidden');
hideFlashMessages(); hideFlashMessages();
}); });
const linkToWebAuthn = document.getElementById("link-to-webauthn"); const linkToWebAuthn = document.getElementById('link-to-webauthn');
linkToWebAuthn.addEventListener("click", () => { linkToWebAuthn.addEventListener('click', () => {
otpAuthenticationForm.classList.add("hidden"); otpAuthenticationForm.classList.add('hidden');
webAuthnCredentialAuthenticationForm.classList.remove("hidden"); webAuthnCredentialAuthenticationForm.classList.remove('hidden');
hideFlashMessages(); hideFlashMessages();
}); });
} }
@@ -1,22 +1,22 @@
import api from "../api"; import api from '../api';
export const ACCOUNT_NOTE_SUBMIT_REQUEST = "ACCOUNT_NOTE_SUBMIT_REQUEST"; export const ACCOUNT_NOTE_SUBMIT_REQUEST = 'ACCOUNT_NOTE_SUBMIT_REQUEST';
export const ACCOUNT_NOTE_SUBMIT_SUCCESS = "ACCOUNT_NOTE_SUBMIT_SUCCESS"; export const ACCOUNT_NOTE_SUBMIT_SUCCESS = 'ACCOUNT_NOTE_SUBMIT_SUCCESS';
export const ACCOUNT_NOTE_SUBMIT_FAIL = "ACCOUNT_NOTE_SUBMIT_FAIL"; export const ACCOUNT_NOTE_SUBMIT_FAIL = 'ACCOUNT_NOTE_SUBMIT_FAIL';
export const ACCOUNT_NOTE_INIT_EDIT = "ACCOUNT_NOTE_INIT_EDIT"; export const ACCOUNT_NOTE_INIT_EDIT = 'ACCOUNT_NOTE_INIT_EDIT';
export const ACCOUNT_NOTE_CANCEL = "ACCOUNT_NOTE_CANCEL"; export const ACCOUNT_NOTE_CANCEL = 'ACCOUNT_NOTE_CANCEL';
export const ACCOUNT_NOTE_CHANGE_COMMENT = "ACCOUNT_NOTE_CHANGE_COMMENT"; export const ACCOUNT_NOTE_CHANGE_COMMENT = 'ACCOUNT_NOTE_CHANGE_COMMENT';
export function submitAccountNote() { export function submitAccountNote() {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(submitAccountNoteRequest()); dispatch(submitAccountNoteRequest());
const id = getState().getIn(["account_notes", "edit", "account_id"]); const id = getState().getIn(['account_notes', 'edit', 'account_id']);
api(getState).post(`/api/v1/accounts/${id}/note`, { api(getState).post(`/api/v1/accounts/${id}/note`, {
comment: getState().getIn(["account_notes", "edit", "comment"]), comment: getState().getIn(['account_notes', 'edit', 'comment']),
}).then(response => { }).then(response => {
dispatch(submitAccountNoteSuccess(response.data)); dispatch(submitAccountNoteSuccess(response.data));
}).catch(error => dispatch(submitAccountNoteFail(error))); }).catch(error => dispatch(submitAccountNoteFail(error)));
@@ -45,7 +45,7 @@ export function submitAccountNoteFail(error) {
export function initEditAccountNote(account) { export function initEditAccountNote(account) {
return (dispatch, getState) => { return (dispatch, getState) => {
const comment = getState().getIn(["relationships", account.get("id"), "note"]); const comment = getState().getIn(['relationships', account.get('id'), 'note']);
dispatch({ dispatch({
type: ACCOUNT_NOTE_INIT_EDIT, type: ACCOUNT_NOTE_INIT_EDIT,
@@ -1,104 +1,104 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { importFetchedAccount, importFetchedAccounts } from "./importer"; import { importFetchedAccount, importFetchedAccounts } from './importer';
export const ACCOUNT_FETCH_REQUEST = "ACCOUNT_FETCH_REQUEST"; export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
export const ACCOUNT_FETCH_SUCCESS = "ACCOUNT_FETCH_SUCCESS"; export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS';
export const ACCOUNT_FETCH_FAIL = "ACCOUNT_FETCH_FAIL"; export const ACCOUNT_FETCH_FAIL = 'ACCOUNT_FETCH_FAIL';
export const ACCOUNT_LOOKUP_REQUEST = "ACCOUNT_LOOKUP_REQUEST"; export const ACCOUNT_LOOKUP_REQUEST = 'ACCOUNT_LOOKUP_REQUEST';
export const ACCOUNT_LOOKUP_SUCCESS = "ACCOUNT_LOOKUP_SUCCESS"; export const ACCOUNT_LOOKUP_SUCCESS = 'ACCOUNT_LOOKUP_SUCCESS';
export const ACCOUNT_LOOKUP_FAIL = "ACCOUNT_LOOKUP_FAIL"; export const ACCOUNT_LOOKUP_FAIL = 'ACCOUNT_LOOKUP_FAIL';
export const ACCOUNT_FOLLOW_REQUEST = "ACCOUNT_FOLLOW_REQUEST"; export const ACCOUNT_FOLLOW_REQUEST = 'ACCOUNT_FOLLOW_REQUEST';
export const ACCOUNT_FOLLOW_SUCCESS = "ACCOUNT_FOLLOW_SUCCESS"; export const ACCOUNT_FOLLOW_SUCCESS = 'ACCOUNT_FOLLOW_SUCCESS';
export const ACCOUNT_FOLLOW_FAIL = "ACCOUNT_FOLLOW_FAIL"; export const ACCOUNT_FOLLOW_FAIL = 'ACCOUNT_FOLLOW_FAIL';
export const ACCOUNT_UNFOLLOW_REQUEST = "ACCOUNT_UNFOLLOW_REQUEST"; export const ACCOUNT_UNFOLLOW_REQUEST = 'ACCOUNT_UNFOLLOW_REQUEST';
export const ACCOUNT_UNFOLLOW_SUCCESS = "ACCOUNT_UNFOLLOW_SUCCESS"; export const ACCOUNT_UNFOLLOW_SUCCESS = 'ACCOUNT_UNFOLLOW_SUCCESS';
export const ACCOUNT_UNFOLLOW_FAIL = "ACCOUNT_UNFOLLOW_FAIL"; export const ACCOUNT_UNFOLLOW_FAIL = 'ACCOUNT_UNFOLLOW_FAIL';
export const ACCOUNT_BLOCK_REQUEST = "ACCOUNT_BLOCK_REQUEST"; export const ACCOUNT_BLOCK_REQUEST = 'ACCOUNT_BLOCK_REQUEST';
export const ACCOUNT_BLOCK_SUCCESS = "ACCOUNT_BLOCK_SUCCESS"; export const ACCOUNT_BLOCK_SUCCESS = 'ACCOUNT_BLOCK_SUCCESS';
export const ACCOUNT_BLOCK_FAIL = "ACCOUNT_BLOCK_FAIL"; export const ACCOUNT_BLOCK_FAIL = 'ACCOUNT_BLOCK_FAIL';
export const ACCOUNT_UNBLOCK_REQUEST = "ACCOUNT_UNBLOCK_REQUEST"; export const ACCOUNT_UNBLOCK_REQUEST = 'ACCOUNT_UNBLOCK_REQUEST';
export const ACCOUNT_UNBLOCK_SUCCESS = "ACCOUNT_UNBLOCK_SUCCESS"; export const ACCOUNT_UNBLOCK_SUCCESS = 'ACCOUNT_UNBLOCK_SUCCESS';
export const ACCOUNT_UNBLOCK_FAIL = "ACCOUNT_UNBLOCK_FAIL"; export const ACCOUNT_UNBLOCK_FAIL = 'ACCOUNT_UNBLOCK_FAIL';
export const ACCOUNT_MUTE_REQUEST = "ACCOUNT_MUTE_REQUEST"; export const ACCOUNT_MUTE_REQUEST = 'ACCOUNT_MUTE_REQUEST';
export const ACCOUNT_MUTE_SUCCESS = "ACCOUNT_MUTE_SUCCESS"; export const ACCOUNT_MUTE_SUCCESS = 'ACCOUNT_MUTE_SUCCESS';
export const ACCOUNT_MUTE_FAIL = "ACCOUNT_MUTE_FAIL"; export const ACCOUNT_MUTE_FAIL = 'ACCOUNT_MUTE_FAIL';
export const ACCOUNT_UNMUTE_REQUEST = "ACCOUNT_UNMUTE_REQUEST"; export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
export const ACCOUNT_UNMUTE_SUCCESS = "ACCOUNT_UNMUTE_SUCCESS"; export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS';
export const ACCOUNT_UNMUTE_FAIL = "ACCOUNT_UNMUTE_FAIL"; export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
export const ACCOUNT_PIN_REQUEST = "ACCOUNT_PIN_REQUEST"; export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST';
export const ACCOUNT_PIN_SUCCESS = "ACCOUNT_PIN_SUCCESS"; export const ACCOUNT_PIN_SUCCESS = 'ACCOUNT_PIN_SUCCESS';
export const ACCOUNT_PIN_FAIL = "ACCOUNT_PIN_FAIL"; export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL';
export const ACCOUNT_UNPIN_REQUEST = "ACCOUNT_UNPIN_REQUEST"; export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
export const ACCOUNT_UNPIN_SUCCESS = "ACCOUNT_UNPIN_SUCCESS"; export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
export const ACCOUNT_UNPIN_FAIL = "ACCOUNT_UNPIN_FAIL"; export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
export const FOLLOWERS_FETCH_REQUEST = "FOLLOWERS_FETCH_REQUEST"; export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
export const FOLLOWERS_FETCH_SUCCESS = "FOLLOWERS_FETCH_SUCCESS"; export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS';
export const FOLLOWERS_FETCH_FAIL = "FOLLOWERS_FETCH_FAIL"; export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL';
export const FOLLOWERS_EXPAND_REQUEST = "FOLLOWERS_EXPAND_REQUEST"; export const FOLLOWERS_EXPAND_REQUEST = 'FOLLOWERS_EXPAND_REQUEST';
export const FOLLOWERS_EXPAND_SUCCESS = "FOLLOWERS_EXPAND_SUCCESS"; export const FOLLOWERS_EXPAND_SUCCESS = 'FOLLOWERS_EXPAND_SUCCESS';
export const FOLLOWERS_EXPAND_FAIL = "FOLLOWERS_EXPAND_FAIL"; export const FOLLOWERS_EXPAND_FAIL = 'FOLLOWERS_EXPAND_FAIL';
export const FOLLOWING_FETCH_REQUEST = "FOLLOWING_FETCH_REQUEST"; export const FOLLOWING_FETCH_REQUEST = 'FOLLOWING_FETCH_REQUEST';
export const FOLLOWING_FETCH_SUCCESS = "FOLLOWING_FETCH_SUCCESS"; export const FOLLOWING_FETCH_SUCCESS = 'FOLLOWING_FETCH_SUCCESS';
export const FOLLOWING_FETCH_FAIL = "FOLLOWING_FETCH_FAIL"; export const FOLLOWING_FETCH_FAIL = 'FOLLOWING_FETCH_FAIL';
export const FOLLOWING_EXPAND_REQUEST = "FOLLOWING_EXPAND_REQUEST"; export const FOLLOWING_EXPAND_REQUEST = 'FOLLOWING_EXPAND_REQUEST';
export const FOLLOWING_EXPAND_SUCCESS = "FOLLOWING_EXPAND_SUCCESS"; export const FOLLOWING_EXPAND_SUCCESS = 'FOLLOWING_EXPAND_SUCCESS';
export const FOLLOWING_EXPAND_FAIL = "FOLLOWING_EXPAND_FAIL"; export const FOLLOWING_EXPAND_FAIL = 'FOLLOWING_EXPAND_FAIL';
export const RELATIONSHIPS_FETCH_REQUEST = "RELATIONSHIPS_FETCH_REQUEST"; export const RELATIONSHIPS_FETCH_REQUEST = 'RELATIONSHIPS_FETCH_REQUEST';
export const RELATIONSHIPS_FETCH_SUCCESS = "RELATIONSHIPS_FETCH_SUCCESS"; export const RELATIONSHIPS_FETCH_SUCCESS = 'RELATIONSHIPS_FETCH_SUCCESS';
export const RELATIONSHIPS_FETCH_FAIL = "RELATIONSHIPS_FETCH_FAIL"; export const RELATIONSHIPS_FETCH_FAIL = 'RELATIONSHIPS_FETCH_FAIL';
export const FOLLOW_REQUESTS_FETCH_REQUEST = "FOLLOW_REQUESTS_FETCH_REQUEST"; export const FOLLOW_REQUESTS_FETCH_REQUEST = 'FOLLOW_REQUESTS_FETCH_REQUEST';
export const FOLLOW_REQUESTS_FETCH_SUCCESS = "FOLLOW_REQUESTS_FETCH_SUCCESS"; export const FOLLOW_REQUESTS_FETCH_SUCCESS = 'FOLLOW_REQUESTS_FETCH_SUCCESS';
export const FOLLOW_REQUESTS_FETCH_FAIL = "FOLLOW_REQUESTS_FETCH_FAIL"; export const FOLLOW_REQUESTS_FETCH_FAIL = 'FOLLOW_REQUESTS_FETCH_FAIL';
export const FOLLOW_REQUESTS_EXPAND_REQUEST = "FOLLOW_REQUESTS_EXPAND_REQUEST"; export const FOLLOW_REQUESTS_EXPAND_REQUEST = 'FOLLOW_REQUESTS_EXPAND_REQUEST';
export const FOLLOW_REQUESTS_EXPAND_SUCCESS = "FOLLOW_REQUESTS_EXPAND_SUCCESS"; export const FOLLOW_REQUESTS_EXPAND_SUCCESS = 'FOLLOW_REQUESTS_EXPAND_SUCCESS';
export const FOLLOW_REQUESTS_EXPAND_FAIL = "FOLLOW_REQUESTS_EXPAND_FAIL"; export const FOLLOW_REQUESTS_EXPAND_FAIL = 'FOLLOW_REQUESTS_EXPAND_FAIL';
export const FOLLOW_REQUEST_AUTHORIZE_REQUEST = "FOLLOW_REQUEST_AUTHORIZE_REQUEST"; export const FOLLOW_REQUEST_AUTHORIZE_REQUEST = 'FOLLOW_REQUEST_AUTHORIZE_REQUEST';
export const FOLLOW_REQUEST_AUTHORIZE_SUCCESS = "FOLLOW_REQUEST_AUTHORIZE_SUCCESS"; export const FOLLOW_REQUEST_AUTHORIZE_SUCCESS = 'FOLLOW_REQUEST_AUTHORIZE_SUCCESS';
export const FOLLOW_REQUEST_AUTHORIZE_FAIL = "FOLLOW_REQUEST_AUTHORIZE_FAIL"; export const FOLLOW_REQUEST_AUTHORIZE_FAIL = 'FOLLOW_REQUEST_AUTHORIZE_FAIL';
export const FOLLOW_REQUEST_REJECT_REQUEST = "FOLLOW_REQUEST_REJECT_REQUEST"; export const FOLLOW_REQUEST_REJECT_REQUEST = 'FOLLOW_REQUEST_REJECT_REQUEST';
export const FOLLOW_REQUEST_REJECT_SUCCESS = "FOLLOW_REQUEST_REJECT_SUCCESS"; export const FOLLOW_REQUEST_REJECT_SUCCESS = 'FOLLOW_REQUEST_REJECT_SUCCESS';
export const FOLLOW_REQUEST_REJECT_FAIL = "FOLLOW_REQUEST_REJECT_FAIL"; export const FOLLOW_REQUEST_REJECT_FAIL = 'FOLLOW_REQUEST_REJECT_FAIL';
export const PINNED_ACCOUNTS_FETCH_REQUEST = "PINNED_ACCOUNTS_FETCH_REQUEST"; export const PINNED_ACCOUNTS_FETCH_REQUEST = 'PINNED_ACCOUNTS_FETCH_REQUEST';
export const PINNED_ACCOUNTS_FETCH_SUCCESS = "PINNED_ACCOUNTS_FETCH_SUCCESS"; export const PINNED_ACCOUNTS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_FETCH_SUCCESS';
export const PINNED_ACCOUNTS_FETCH_FAIL = "PINNED_ACCOUNTS_FETCH_FAIL"; export const PINNED_ACCOUNTS_FETCH_FAIL = 'PINNED_ACCOUNTS_FETCH_FAIL';
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_REQUEST = "PINNED_ACCOUNTS_SUGGESTIONS_FETCH_REQUEST"; export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_REQUEST = 'PINNED_ACCOUNTS_SUGGESTIONS_FETCH_REQUEST';
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_SUCCESS = "PINNED_ACCOUNTS_SUGGESTIONS_FETCH_SUCCESS"; export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_SUGGESTIONS_FETCH_SUCCESS';
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_FAIL = "PINNED_ACCOUNTS_SUGGESTIONS_FETCH_FAIL"; export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_FAIL = 'PINNED_ACCOUNTS_SUGGESTIONS_FETCH_FAIL';
export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CLEAR = "PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CLEAR"; export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CLEAR = 'PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CLEAR';
export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE = "PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE"; export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE = 'PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE';
export const PINNED_ACCOUNTS_EDITOR_RESET = "PINNED_ACCOUNTS_EDITOR_RESET"; export const PINNED_ACCOUNTS_EDITOR_RESET = 'PINNED_ACCOUNTS_EDITOR_RESET';
export const ACCOUNT_REVEAL = "ACCOUNT_REVEAL"; export const ACCOUNT_REVEAL = 'ACCOUNT_REVEAL';
export function fetchAccount(id) { export function fetchAccount(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchRelationships([id])); dispatch(fetchRelationships([id]));
if (getState().getIn(["accounts", id], null) !== null) { if (getState().getIn(['accounts', id], null) !== null) {
return; return;
} }
@@ -117,7 +117,7 @@ export function fetchAccount(id) {
export const lookupAccount = acct => (dispatch, getState) => { export const lookupAccount = acct => (dispatch, getState) => {
dispatch(lookupAccountRequest(acct)); dispatch(lookupAccountRequest(acct));
api(getState).get("/api/v1/accounts/lookup", { params: { acct } }).then(response => { api(getState).get('/api/v1/accounts/lookup', { params: { acct } }).then(response => {
dispatch(fetchRelationships([response.data.id])); dispatch(fetchRelationships([response.data.id]));
dispatch(importFetchedAccount(response.data)); dispatch(importFetchedAccount(response.data));
dispatch(lookupAccountSuccess()); dispatch(lookupAccountSuccess());
@@ -166,8 +166,8 @@ export function fetchAccountFail(id, error) {
export function followAccount(id, options = { reblogs: true }) { export function followAccount(id, options = { reblogs: true }) {
return (dispatch, getState) => { return (dispatch, getState) => {
const alreadyFollowing = getState().getIn(["relationships", id, "following"]); const alreadyFollowing = getState().getIn(['relationships', id, 'following']);
const locked = getState().getIn(["accounts", id, "locked"], false); const locked = getState().getIn(['accounts', id, 'locked'], false);
dispatch(followAccountRequest(id, locked)); dispatch(followAccountRequest(id, locked));
@@ -184,7 +184,7 @@ export function unfollowAccount(id) {
dispatch(unfollowAccountRequest(id)); dispatch(unfollowAccountRequest(id));
api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => { api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => {
dispatch(unfollowAccountSuccess(response.data, getState().get("statuses"))); dispatch(unfollowAccountSuccess(response.data, getState().get('statuses')));
}).catch(error => { }).catch(error => {
dispatch(unfollowAccountFail(error)); dispatch(unfollowAccountFail(error));
}); });
@@ -249,7 +249,7 @@ export function blockAccount(id) {
api(getState).post(`/api/v1/accounts/${id}/block`).then(response => { api(getState).post(`/api/v1/accounts/${id}/block`).then(response => {
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers // Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
dispatch(blockAccountSuccess(response.data, getState().get("statuses"))); dispatch(blockAccountSuccess(response.data, getState().get('statuses')));
}).catch(error => { }).catch(error => {
dispatch(blockAccountFail(id, error)); dispatch(blockAccountFail(id, error));
}); });
@@ -318,7 +318,7 @@ export function muteAccount(id, notifications, duration=0) {
api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications, duration }).then(response => { api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications, duration }).then(response => {
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers // Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
dispatch(muteAccountSuccess(response.data, getState().get("statuses"))); dispatch(muteAccountSuccess(response.data, getState().get('statuses')));
}).catch(error => { }).catch(error => {
dispatch(muteAccountFail(id, error)); dispatch(muteAccountFail(id, error));
}); });
@@ -386,7 +386,7 @@ export function fetchFollowers(id) {
dispatch(fetchFollowersRequest(id)); dispatch(fetchFollowersRequest(id));
api(getState).get(`/api/v1/accounts/${id}/followers`).then(response => { api(getState).get(`/api/v1/accounts/${id}/followers`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchFollowersSuccess(id, response.data, next ? next.uri : null)); dispatch(fetchFollowersSuccess(id, response.data, next ? next.uri : null));
@@ -424,7 +424,7 @@ export function fetchFollowersFail(id, error) {
export function expandFollowers(id) { export function expandFollowers(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["user_lists", "followers", id, "next"]); const url = getState().getIn(['user_lists', 'followers', id, 'next']);
if (url === null) { if (url === null) {
return; return;
@@ -433,7 +433,7 @@ export function expandFollowers(id) {
dispatch(expandFollowersRequest(id)); dispatch(expandFollowersRequest(id));
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(expandFollowersSuccess(id, response.data, next ? next.uri : null)); dispatch(expandFollowersSuccess(id, response.data, next ? next.uri : null));
@@ -473,7 +473,7 @@ export function fetchFollowing(id) {
dispatch(fetchFollowingRequest(id)); dispatch(fetchFollowingRequest(id));
api(getState).get(`/api/v1/accounts/${id}/following`).then(response => { api(getState).get(`/api/v1/accounts/${id}/following`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchFollowingSuccess(id, response.data, next ? next.uri : null)); dispatch(fetchFollowingSuccess(id, response.data, next ? next.uri : null));
@@ -511,7 +511,7 @@ export function fetchFollowingFail(id, error) {
export function expandFollowing(id) { export function expandFollowing(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["user_lists", "following", id, "next"]); const url = getState().getIn(['user_lists', 'following', id, 'next']);
if (url === null) { if (url === null) {
return; return;
@@ -520,7 +520,7 @@ export function expandFollowing(id) {
dispatch(expandFollowingRequest(id)); dispatch(expandFollowingRequest(id));
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(expandFollowingSuccess(id, response.data, next ? next.uri : null)); dispatch(expandFollowingSuccess(id, response.data, next ? next.uri : null));
@@ -558,9 +558,9 @@ export function expandFollowingFail(id, error) {
export function fetchRelationships(accountIds) { export function fetchRelationships(accountIds) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const loadedRelationships = state.get("relationships"); const loadedRelationships = state.get('relationships');
const newAccountIds = accountIds.filter(id => loadedRelationships.get(id, null) === null); const newAccountIds = accountIds.filter(id => loadedRelationships.get(id, null) === null);
const signedIn = !!state.getIn(["meta", "me"]); const signedIn = !!state.getIn(['meta', 'me']);
if (!signedIn || newAccountIds.length === 0) { if (!signedIn || newAccountIds.length === 0) {
return; return;
@@ -568,7 +568,7 @@ export function fetchRelationships(accountIds) {
dispatch(fetchRelationshipsRequest(newAccountIds)); dispatch(fetchRelationshipsRequest(newAccountIds));
api(getState).get(`/api/v1/accounts/relationships?${newAccountIds.map(id => `id[]=${id}`).join("&")}`).then(response => { api(getState).get(`/api/v1/accounts/relationships?${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
dispatch(fetchRelationshipsSuccess(response.data)); dispatch(fetchRelationshipsSuccess(response.data));
}).catch(error => { }).catch(error => {
dispatch(fetchRelationshipsFail(error)); dispatch(fetchRelationshipsFail(error));
@@ -605,8 +605,8 @@ export function fetchFollowRequests() {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchFollowRequestsRequest()); dispatch(fetchFollowRequestsRequest());
api(getState).get("/api/v1/follow_requests").then(response => { api(getState).get('/api/v1/follow_requests').then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null)); dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null));
}).catch(error => dispatch(fetchFollowRequestsFail(error))); }).catch(error => dispatch(fetchFollowRequestsFail(error)));
@@ -636,7 +636,7 @@ export function fetchFollowRequestsFail(error) {
export function expandFollowRequests() { export function expandFollowRequests() {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["user_lists", "follow_requests", "next"]); const url = getState().getIn(['user_lists', 'follow_requests', 'next']);
if (url === null) { if (url === null) {
return; return;
@@ -645,7 +645,7 @@ export function expandFollowRequests() {
dispatch(expandFollowRequestsRequest()); dispatch(expandFollowRequestsRequest());
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null)); dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null));
}).catch(error => dispatch(expandFollowRequestsFail(error))); }).catch(error => dispatch(expandFollowRequestsFail(error)));
@@ -815,7 +815,7 @@ export function fetchPinnedAccounts() {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchPinnedAccountsRequest()); dispatch(fetchPinnedAccountsRequest());
api(getState).get("/api/v1/endorsements", { params: { limit: 0 } }).then(response => { api(getState).get('/api/v1/endorsements', { params: { limit: 0 } }).then(response => {
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchPinnedAccountsSuccess(response.data)); dispatch(fetchPinnedAccountsSuccess(response.data));
}).catch(err => dispatch(fetchPinnedAccountsFail(err))); }).catch(err => dispatch(fetchPinnedAccountsFail(err)));
@@ -854,7 +854,7 @@ export function fetchPinnedAccountsSuggestions(q) {
following: true, following: true,
}; };
api(getState).get("/api/v1/accounts/search", { params }).then(response => { api(getState).get('/api/v1/accounts/search', { params }).then(response => {
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchPinnedAccountsSuggestionsSuccess(q, response.data)); dispatch(fetchPinnedAccountsSuggestionsSuccess(q, response.data));
}).catch(err => dispatch(fetchPinnedAccountsSuggestionsFail(err))); }).catch(err => dispatch(fetchPinnedAccountsSuggestionsFail(err)));
@@ -1,16 +1,16 @@
import { defineMessages } from "react-intl"; import { defineMessages } from 'react-intl';
const messages = defineMessages({ const messages = defineMessages({
unexpectedTitle: { id: "alert.unexpected.title", defaultMessage: "Oops!" }, unexpectedTitle: { id: 'alert.unexpected.title', defaultMessage: 'Oops!' },
unexpectedMessage: { id: "alert.unexpected.message", defaultMessage: "An unexpected error occurred." }, unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'An unexpected error occurred.' },
rateLimitedTitle: { id: "alert.rate_limited.title", defaultMessage: "Rate limited" }, rateLimitedTitle: { id: 'alert.rate_limited.title', defaultMessage: 'Rate limited' },
rateLimitedMessage: { id: "alert.rate_limited.message", defaultMessage: "Please retry after {retry_time, time, medium}." }, rateLimitedMessage: { id: 'alert.rate_limited.message', defaultMessage: 'Please retry after {retry_time, time, medium}.' },
}); });
export const ALERT_SHOW = "ALERT_SHOW"; export const ALERT_SHOW = 'ALERT_SHOW';
export const ALERT_DISMISS = "ALERT_DISMISS"; export const ALERT_DISMISS = 'ALERT_DISMISS';
export const ALERT_CLEAR = "ALERT_CLEAR"; export const ALERT_CLEAR = 'ALERT_CLEAR';
export const ALERT_NOOP = "ALERT_NOOP"; export const ALERT_NOOP = 'ALERT_NOOP';
export function dismissAlert(alert) { export function dismissAlert(alert) {
return { return {
@@ -43,9 +43,9 @@ export function showAlertForError(error, skipNotFound = false) {
return { type: ALERT_NOOP }; return { type: ALERT_NOOP };
} }
if (status === 429 && headers["x-ratelimit-reset"]) { if (status === 429 && headers['x-ratelimit-reset']) {
const reset_date = new Date(headers["x-ratelimit-reset"]); const reset_date = new Date(headers['x-ratelimit-reset']);
return showAlert(messages.rateLimitedTitle, messages.rateLimitedMessage, { "retry_time": reset_date }); return showAlert(messages.rateLimitedTitle, messages.rateLimitedMessage, { 'retry_time': reset_date });
} }
let message = statusText; let message = statusText;
@@ -1,35 +1,35 @@
import api from "../api"; import api from '../api';
import { normalizeAnnouncement } from "./importer/normalizer"; import { normalizeAnnouncement } from './importer/normalizer';
export const ANNOUNCEMENTS_FETCH_REQUEST = "ANNOUNCEMENTS_FETCH_REQUEST"; export const ANNOUNCEMENTS_FETCH_REQUEST = 'ANNOUNCEMENTS_FETCH_REQUEST';
export const ANNOUNCEMENTS_FETCH_SUCCESS = "ANNOUNCEMENTS_FETCH_SUCCESS"; export const ANNOUNCEMENTS_FETCH_SUCCESS = 'ANNOUNCEMENTS_FETCH_SUCCESS';
export const ANNOUNCEMENTS_FETCH_FAIL = "ANNOUNCEMENTS_FETCH_FAIL"; export const ANNOUNCEMENTS_FETCH_FAIL = 'ANNOUNCEMENTS_FETCH_FAIL';
export const ANNOUNCEMENTS_UPDATE = "ANNOUNCEMENTS_UPDATE"; export const ANNOUNCEMENTS_UPDATE = 'ANNOUNCEMENTS_UPDATE';
export const ANNOUNCEMENTS_DELETE = "ANNOUNCEMENTS_DELETE"; export const ANNOUNCEMENTS_DELETE = 'ANNOUNCEMENTS_DELETE';
export const ANNOUNCEMENTS_DISMISS_REQUEST = "ANNOUNCEMENTS_DISMISS_REQUEST"; export const ANNOUNCEMENTS_DISMISS_REQUEST = 'ANNOUNCEMENTS_DISMISS_REQUEST';
export const ANNOUNCEMENTS_DISMISS_SUCCESS = "ANNOUNCEMENTS_DISMISS_SUCCESS"; export const ANNOUNCEMENTS_DISMISS_SUCCESS = 'ANNOUNCEMENTS_DISMISS_SUCCESS';
export const ANNOUNCEMENTS_DISMISS_FAIL = "ANNOUNCEMENTS_DISMISS_FAIL"; export const ANNOUNCEMENTS_DISMISS_FAIL = 'ANNOUNCEMENTS_DISMISS_FAIL';
export const ANNOUNCEMENTS_REACTION_ADD_REQUEST = "ANNOUNCEMENTS_REACTION_ADD_REQUEST"; export const ANNOUNCEMENTS_REACTION_ADD_REQUEST = 'ANNOUNCEMENTS_REACTION_ADD_REQUEST';
export const ANNOUNCEMENTS_REACTION_ADD_SUCCESS = "ANNOUNCEMENTS_REACTION_ADD_SUCCESS"; export const ANNOUNCEMENTS_REACTION_ADD_SUCCESS = 'ANNOUNCEMENTS_REACTION_ADD_SUCCESS';
export const ANNOUNCEMENTS_REACTION_ADD_FAIL = "ANNOUNCEMENTS_REACTION_ADD_FAIL"; export const ANNOUNCEMENTS_REACTION_ADD_FAIL = 'ANNOUNCEMENTS_REACTION_ADD_FAIL';
export const ANNOUNCEMENTS_REACTION_REMOVE_REQUEST = "ANNOUNCEMENTS_REACTION_REMOVE_REQUEST"; export const ANNOUNCEMENTS_REACTION_REMOVE_REQUEST = 'ANNOUNCEMENTS_REACTION_REMOVE_REQUEST';
export const ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS = "ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS"; export const ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS = 'ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS';
export const ANNOUNCEMENTS_REACTION_REMOVE_FAIL = "ANNOUNCEMENTS_REACTION_REMOVE_FAIL"; export const ANNOUNCEMENTS_REACTION_REMOVE_FAIL = 'ANNOUNCEMENTS_REACTION_REMOVE_FAIL';
export const ANNOUNCEMENTS_REACTION_UPDATE = "ANNOUNCEMENTS_REACTION_UPDATE"; export const ANNOUNCEMENTS_REACTION_UPDATE = 'ANNOUNCEMENTS_REACTION_UPDATE';
export const ANNOUNCEMENTS_TOGGLE_SHOW = "ANNOUNCEMENTS_TOGGLE_SHOW"; export const ANNOUNCEMENTS_TOGGLE_SHOW = 'ANNOUNCEMENTS_TOGGLE_SHOW';
const noOp = () => {}; const noOp = () => {};
export const fetchAnnouncements = (done = noOp) => (dispatch, getState) => { export const fetchAnnouncements = (done = noOp) => (dispatch, getState) => {
dispatch(fetchAnnouncementsRequest()); dispatch(fetchAnnouncementsRequest());
api(getState).get("/api/v1/announcements").then(response => { api(getState).get('/api/v1/announcements').then(response => {
dispatch(fetchAnnouncementsSuccess(response.data.map(x => normalizeAnnouncement(x)))); dispatch(fetchAnnouncementsSuccess(response.data.map(x => normalizeAnnouncement(x))));
}).catch(error => { }).catch(error => {
dispatch(fetchAnnouncementsFail(error)); dispatch(fetchAnnouncementsFail(error));
@@ -88,13 +88,13 @@ export const dismissAnnouncementFail = (announcementId, error) => ({
}); });
export const addReaction = (announcementId, name) => (dispatch, getState) => { export const addReaction = (announcementId, name) => (dispatch, getState) => {
const announcement = getState().getIn(["announcements", "items"]).find(x => x.get("id") === announcementId); const announcement = getState().getIn(['announcements', 'items']).find(x => x.get('id') === announcementId);
let alreadyAdded = false; let alreadyAdded = false;
if (announcement) { if (announcement) {
const reaction = announcement.get("reactions").find(x => x.get("name") === name); const reaction = announcement.get('reactions').find(x => x.get('name') === name);
if (reaction && reaction.get("me")) { if (reaction && reaction.get('me')) {
alreadyAdded = true; alreadyAdded = true;
} }
} }
@@ -1,9 +1,9 @@
import { createAction } from "@reduxjs/toolkit"; import { createAction } from '@reduxjs/toolkit';
import { type LayoutType } from "../is_mobile"; import type { LayoutType } from '../is_mobile';
interface ChangeLayoutPayload { interface ChangeLayoutPayload {
layout: LayoutType, layout: LayoutType;
} }
export const changeLayout = export const changeLayout =
createAction<ChangeLayoutPayload>("APP_LAYOUT_CHANGE"); createAction<ChangeLayoutPayload>('APP_LAYOUT_CHANGE');
@@ -1,25 +1,25 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { fetchRelationships } from "./accounts"; import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from "./importer"; import { importFetchedAccounts } from './importer';
import { openModal } from "./modal"; import { openModal } from './modal';
export const BLOCKS_FETCH_REQUEST = "BLOCKS_FETCH_REQUEST"; export const BLOCKS_FETCH_REQUEST = 'BLOCKS_FETCH_REQUEST';
export const BLOCKS_FETCH_SUCCESS = "BLOCKS_FETCH_SUCCESS"; export const BLOCKS_FETCH_SUCCESS = 'BLOCKS_FETCH_SUCCESS';
export const BLOCKS_FETCH_FAIL = "BLOCKS_FETCH_FAIL"; export const BLOCKS_FETCH_FAIL = 'BLOCKS_FETCH_FAIL';
export const BLOCKS_EXPAND_REQUEST = "BLOCKS_EXPAND_REQUEST"; export const BLOCKS_EXPAND_REQUEST = 'BLOCKS_EXPAND_REQUEST';
export const BLOCKS_EXPAND_SUCCESS = "BLOCKS_EXPAND_SUCCESS"; export const BLOCKS_EXPAND_SUCCESS = 'BLOCKS_EXPAND_SUCCESS';
export const BLOCKS_EXPAND_FAIL = "BLOCKS_EXPAND_FAIL"; export const BLOCKS_EXPAND_FAIL = 'BLOCKS_EXPAND_FAIL';
export const BLOCKS_INIT_MODAL = "BLOCKS_INIT_MODAL"; export const BLOCKS_INIT_MODAL = 'BLOCKS_INIT_MODAL';
export function fetchBlocks() { export function fetchBlocks() {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchBlocksRequest()); dispatch(fetchBlocksRequest());
api(getState).get("/api/v1/blocks").then(response => { api(getState).get('/api/v1/blocks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null)); dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -50,7 +50,7 @@ export function fetchBlocksFail(error) {
export function expandBlocks() { export function expandBlocks() {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["user_lists", "blocks", "next"]); const url = getState().getIn(['user_lists', 'blocks', 'next']);
if (url === null) { if (url === null) {
return; return;
@@ -59,7 +59,7 @@ export function expandBlocks() {
dispatch(expandBlocksRequest()); dispatch(expandBlocksRequest());
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(expandBlocksSuccess(response.data, next ? next.uri : null)); dispatch(expandBlocksSuccess(response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -95,6 +95,6 @@ export function initBlockModal(account) {
account, account,
}); });
dispatch(openModal({ modalType: "BLOCK" })); dispatch(openModal({ modalType: 'BLOCK' }));
}; };
} }
@@ -1,25 +1,25 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { importFetchedStatuses } from "./importer"; import { importFetchedStatuses } from './importer';
export const BOOKMARKED_STATUSES_FETCH_REQUEST = "BOOKMARKED_STATUSES_FETCH_REQUEST"; export const BOOKMARKED_STATUSES_FETCH_REQUEST = 'BOOKMARKED_STATUSES_FETCH_REQUEST';
export const BOOKMARKED_STATUSES_FETCH_SUCCESS = "BOOKMARKED_STATUSES_FETCH_SUCCESS"; export const BOOKMARKED_STATUSES_FETCH_SUCCESS = 'BOOKMARKED_STATUSES_FETCH_SUCCESS';
export const BOOKMARKED_STATUSES_FETCH_FAIL = "BOOKMARKED_STATUSES_FETCH_FAIL"; export const BOOKMARKED_STATUSES_FETCH_FAIL = 'BOOKMARKED_STATUSES_FETCH_FAIL';
export const BOOKMARKED_STATUSES_EXPAND_REQUEST = "BOOKMARKED_STATUSES_EXPAND_REQUEST"; export const BOOKMARKED_STATUSES_EXPAND_REQUEST = 'BOOKMARKED_STATUSES_EXPAND_REQUEST';
export const BOOKMARKED_STATUSES_EXPAND_SUCCESS = "BOOKMARKED_STATUSES_EXPAND_SUCCESS"; export const BOOKMARKED_STATUSES_EXPAND_SUCCESS = 'BOOKMARKED_STATUSES_EXPAND_SUCCESS';
export const BOOKMARKED_STATUSES_EXPAND_FAIL = "BOOKMARKED_STATUSES_EXPAND_FAIL"; export const BOOKMARKED_STATUSES_EXPAND_FAIL = 'BOOKMARKED_STATUSES_EXPAND_FAIL';
export function fetchBookmarkedStatuses() { export function fetchBookmarkedStatuses() {
return (dispatch, getState) => { return (dispatch, getState) => {
if (getState().getIn(["status_lists", "bookmarks", "isLoading"])) { if (getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
return; return;
} }
dispatch(fetchBookmarkedStatusesRequest()); dispatch(fetchBookmarkedStatusesRequest());
api(getState).get("/api/v1/bookmarks").then(response => { api(getState).get('/api/v1/bookmarks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => { }).catch(error => {
@@ -51,16 +51,16 @@ export function fetchBookmarkedStatusesFail(error) {
export function expandBookmarkedStatuses() { export function expandBookmarkedStatuses() {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["status_lists", "bookmarks", "next"], null); const url = getState().getIn(['status_lists', 'bookmarks', 'next'], null);
if (url === null || getState().getIn(["status_lists", "bookmarks", "isLoading"])) { if (url === null || getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
return; return;
} }
dispatch(expandBookmarkedStatusesRequest()); dispatch(expandBookmarkedStatusesRequest());
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => { }).catch(error => {
@@ -1,13 +1,13 @@
import { openModal } from "./modal"; import { openModal } from './modal';
export const BOOSTS_INIT_MODAL = "BOOSTS_INIT_MODAL"; export const BOOSTS_INIT_MODAL = 'BOOSTS_INIT_MODAL';
export const BOOSTS_CHANGE_PRIVACY = "BOOSTS_CHANGE_PRIVACY"; export const BOOSTS_CHANGE_PRIVACY = 'BOOSTS_CHANGE_PRIVACY';
export function initBoostModal(props) { export function initBoostModal(props) {
return (dispatch, getState) => { return (dispatch, getState) => {
const default_privacy = getState().getIn(["compose", "default_privacy"]); const default_privacy = getState().getIn(['compose', 'default_privacy']);
const privacy = props.status.get("visibility") === "private" ? "private" : default_privacy; const privacy = props.status.get('visibility') === 'private' ? 'private' : default_privacy;
dispatch({ dispatch({
type: BOOSTS_INIT_MODAL, type: BOOSTS_INIT_MODAL,
@@ -15,7 +15,7 @@ export function initBoostModal(props) {
}); });
dispatch(openModal({ dispatch(openModal({
modalType: "BOOST", modalType: 'BOOST',
modalProps: props, modalProps: props,
})); }));
}; };
@@ -1,6 +1,6 @@
export const BUNDLE_FETCH_REQUEST = "BUNDLE_FETCH_REQUEST"; export const BUNDLE_FETCH_REQUEST = 'BUNDLE_FETCH_REQUEST';
export const BUNDLE_FETCH_SUCCESS = "BUNDLE_FETCH_SUCCESS"; export const BUNDLE_FETCH_SUCCESS = 'BUNDLE_FETCH_SUCCESS';
export const BUNDLE_FETCH_FAIL = "BUNDLE_FETCH_FAIL"; export const BUNDLE_FETCH_FAIL = 'BUNDLE_FETCH_FAIL';
export function fetchBundleRequest(skipLoading) { export function fetchBundleRequest(skipLoading) {
return { return {
@@ -1,9 +1,9 @@
import { saveSettings } from "./settings"; import { saveSettings } from './settings';
export const COLUMN_ADD = "COLUMN_ADD"; export const COLUMN_ADD = 'COLUMN_ADD';
export const COLUMN_REMOVE = "COLUMN_REMOVE"; export const COLUMN_REMOVE = 'COLUMN_REMOVE';
export const COLUMN_MOVE = "COLUMN_MOVE"; export const COLUMN_MOVE = 'COLUMN_MOVE';
export const COLUMN_PARAMS_CHANGE = "COLUMN_PARAMS_CHANGE"; export const COLUMN_PARAMS_CHANGE = 'COLUMN_PARAMS_CHANGE';
export function addColumn(id, params) { export function addColumn(id, params) {
return dispatch => { return dispatch => {
+132 -134
View File
@@ -1,99 +1,99 @@
import { defineMessages } from "react-intl"; import { defineMessages } from 'react-intl';
import axios from "axios"; import axios from 'axios';
import { throttle } from "lodash"; import { throttle } from 'lodash';
import api from "flavours/glitch/api"; import api from 'flavours/glitch/api';
import { search as emojiSearch } from "flavours/glitch/features/emoji/emoji_mart_search_light"; import { search as emojiSearch } from 'flavours/glitch/features/emoji/emoji_mart_search_light';
import { maxMediaAttachments } from "flavours/glitch/initial_state"; import { maxMediaAttachments } from 'flavours/glitch/initial_state';
import { tagHistory } from "flavours/glitch/settings"; import { tagHistory } from 'flavours/glitch/settings';
import { recoverHashtags } from "flavours/glitch/utils/hashtag"; import { recoverHashtags } from 'flavours/glitch/utils/hashtag';
import resizeImage from "flavours/glitch/utils/resize_image"; import resizeImage from 'flavours/glitch/utils/resize_image';
import { showAlert, showAlertForError } from "./alerts"; import { showAlert, showAlertForError } from './alerts';
import { useEmoji } from "./emojis"; import { useEmoji } from './emojis';
import { importFetchedAccounts, importFetchedStatus } from "./importer"; import { importFetchedAccounts, importFetchedStatus } from './importer';
import { openModal } from "./modal"; import { openModal } from './modal';
import { updateTimeline } from "./timelines"; import { updateTimeline } from './timelines';
/** @type {AbortController | undefined} */ /** @type {AbortController | undefined} */
let fetchComposeSuggestionsAccountsController; let fetchComposeSuggestionsAccountsController;
/** @type {AbortController | undefined} */ /** @type {AbortController | undefined} */
let fetchComposeSuggestionsTagsController; let fetchComposeSuggestionsTagsController;
export const COMPOSE_CHANGE = "COMPOSE_CHANGE"; export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
export const COMPOSE_CYCLE_ELEFRIEND = "COMPOSE_CYCLE_ELEFRIEND"; export const COMPOSE_CYCLE_ELEFRIEND = 'COMPOSE_CYCLE_ELEFRIEND';
export const COMPOSE_SUBMIT_REQUEST = "COMPOSE_SUBMIT_REQUEST"; export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
export const COMPOSE_SUBMIT_SUCCESS = "COMPOSE_SUBMIT_SUCCESS"; export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS';
export const COMPOSE_SUBMIT_FAIL = "COMPOSE_SUBMIT_FAIL"; export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL';
export const COMPOSE_REPLY = "COMPOSE_REPLY"; export const COMPOSE_REPLY = 'COMPOSE_REPLY';
export const COMPOSE_REPLY_CANCEL = "COMPOSE_REPLY_CANCEL"; export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
export const COMPOSE_DIRECT = "COMPOSE_DIRECT"; export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
export const COMPOSE_MENTION = "COMPOSE_MENTION"; export const COMPOSE_MENTION = 'COMPOSE_MENTION';
export const COMPOSE_RESET = "COMPOSE_RESET"; export const COMPOSE_RESET = 'COMPOSE_RESET';
export const COMPOSE_UPLOAD_REQUEST = "COMPOSE_UPLOAD_REQUEST"; export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST';
export const COMPOSE_UPLOAD_SUCCESS = "COMPOSE_UPLOAD_SUCCESS"; export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS';
export const COMPOSE_UPLOAD_FAIL = "COMPOSE_UPLOAD_FAIL"; export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL';
export const COMPOSE_UPLOAD_PROGRESS = "COMPOSE_UPLOAD_PROGRESS"; export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS';
export const COMPOSE_UPLOAD_PROCESSING = "COMPOSE_UPLOAD_PROCESSING"; export const COMPOSE_UPLOAD_PROCESSING = 'COMPOSE_UPLOAD_PROCESSING';
export const COMPOSE_UPLOAD_UNDO = "COMPOSE_UPLOAD_UNDO"; export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO';
export const THUMBNAIL_UPLOAD_REQUEST = "THUMBNAIL_UPLOAD_REQUEST"; export const THUMBNAIL_UPLOAD_REQUEST = 'THUMBNAIL_UPLOAD_REQUEST';
export const THUMBNAIL_UPLOAD_SUCCESS = "THUMBNAIL_UPLOAD_SUCCESS"; export const THUMBNAIL_UPLOAD_SUCCESS = 'THUMBNAIL_UPLOAD_SUCCESS';
export const THUMBNAIL_UPLOAD_FAIL = "THUMBNAIL_UPLOAD_FAIL"; export const THUMBNAIL_UPLOAD_FAIL = 'THUMBNAIL_UPLOAD_FAIL';
export const THUMBNAIL_UPLOAD_PROGRESS = "THUMBNAIL_UPLOAD_PROGRESS"; export const THUMBNAIL_UPLOAD_PROGRESS = 'THUMBNAIL_UPLOAD_PROGRESS';
export const COMPOSE_SUGGESTIONS_CLEAR = "COMPOSE_SUGGESTIONS_CLEAR"; export const COMPOSE_SUGGESTIONS_CLEAR = 'COMPOSE_SUGGESTIONS_CLEAR';
export const COMPOSE_SUGGESTIONS_READY = "COMPOSE_SUGGESTIONS_READY"; export const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY';
export const COMPOSE_SUGGESTION_SELECT = "COMPOSE_SUGGESTION_SELECT"; export const COMPOSE_SUGGESTION_SELECT = 'COMPOSE_SUGGESTION_SELECT';
export const COMPOSE_SUGGESTION_IGNORE = "COMPOSE_SUGGESTION_IGNORE"; export const COMPOSE_SUGGESTION_IGNORE = 'COMPOSE_SUGGESTION_IGNORE';
export const COMPOSE_SUGGESTION_TAGS_UPDATE = "COMPOSE_SUGGESTION_TAGS_UPDATE"; export const COMPOSE_SUGGESTION_TAGS_UPDATE = 'COMPOSE_SUGGESTION_TAGS_UPDATE';
export const COMPOSE_TAG_HISTORY_UPDATE = "COMPOSE_TAG_HISTORY_UPDATE"; export const COMPOSE_TAG_HISTORY_UPDATE = 'COMPOSE_TAG_HISTORY_UPDATE';
export const COMPOSE_MOUNT = "COMPOSE_MOUNT"; export const COMPOSE_MOUNT = 'COMPOSE_MOUNT';
export const COMPOSE_UNMOUNT = "COMPOSE_UNMOUNT"; export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
export const COMPOSE_ADVANCED_OPTIONS_CHANGE = "COMPOSE_ADVANCED_OPTIONS_CHANGE"; export const COMPOSE_ADVANCED_OPTIONS_CHANGE = 'COMPOSE_ADVANCED_OPTIONS_CHANGE';
export const COMPOSE_SENSITIVITY_CHANGE = "COMPOSE_SENSITIVITY_CHANGE"; export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
export const COMPOSE_SPOILERNESS_CHANGE = "COMPOSE_SPOILERNESS_CHANGE"; export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
export const COMPOSE_SPOILER_TEXT_CHANGE = "COMPOSE_SPOILER_TEXT_CHANGE"; export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
export const COMPOSE_VISIBILITY_CHANGE = "COMPOSE_VISIBILITY_CHANGE"; export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
export const COMPOSE_LISTABILITY_CHANGE = "COMPOSE_LISTABILITY_CHANGE"; export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE';
export const COMPOSE_CONTENT_TYPE_CHANGE = "COMPOSE_CONTENT_TYPE_CHANGE"; export const COMPOSE_CONTENT_TYPE_CHANGE = 'COMPOSE_CONTENT_TYPE_CHANGE';
export const COMPOSE_LANGUAGE_CHANGE = "COMPOSE_LANGUAGE_CHANGE"; export const COMPOSE_LANGUAGE_CHANGE = 'COMPOSE_LANGUAGE_CHANGE';
export const COMPOSE_EMOJI_INSERT = "COMPOSE_EMOJI_INSERT"; export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT';
export const COMPOSE_UPLOAD_CHANGE_REQUEST = "COMPOSE_UPLOAD_UPDATE_REQUEST"; export const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST';
export const COMPOSE_UPLOAD_CHANGE_SUCCESS = "COMPOSE_UPLOAD_UPDATE_SUCCESS"; export const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS';
export const COMPOSE_UPLOAD_CHANGE_FAIL = "COMPOSE_UPLOAD_UPDATE_FAIL"; export const COMPOSE_UPLOAD_CHANGE_FAIL = 'COMPOSE_UPLOAD_UPDATE_FAIL';
export const COMPOSE_DOODLE_SET = "COMPOSE_DOODLE_SET"; export const COMPOSE_DOODLE_SET = 'COMPOSE_DOODLE_SET';
export const COMPOSE_POLL_ADD = "COMPOSE_POLL_ADD"; export const COMPOSE_POLL_ADD = 'COMPOSE_POLL_ADD';
export const COMPOSE_POLL_REMOVE = "COMPOSE_POLL_REMOVE"; export const COMPOSE_POLL_REMOVE = 'COMPOSE_POLL_REMOVE';
export const COMPOSE_POLL_OPTION_ADD = "COMPOSE_POLL_OPTION_ADD"; export const COMPOSE_POLL_OPTION_ADD = 'COMPOSE_POLL_OPTION_ADD';
export const COMPOSE_POLL_OPTION_CHANGE = "COMPOSE_POLL_OPTION_CHANGE"; export const COMPOSE_POLL_OPTION_CHANGE = 'COMPOSE_POLL_OPTION_CHANGE';
export const COMPOSE_POLL_OPTION_REMOVE = "COMPOSE_POLL_OPTION_REMOVE"; export const COMPOSE_POLL_OPTION_REMOVE = 'COMPOSE_POLL_OPTION_REMOVE';
export const COMPOSE_POLL_SETTINGS_CHANGE = "COMPOSE_POLL_SETTINGS_CHANGE"; export const COMPOSE_POLL_SETTINGS_CHANGE = 'COMPOSE_POLL_SETTINGS_CHANGE';
export const INIT_MEDIA_EDIT_MODAL = "INIT_MEDIA_EDIT_MODAL"; export const INIT_MEDIA_EDIT_MODAL = 'INIT_MEDIA_EDIT_MODAL';
export const COMPOSE_CHANGE_MEDIA_DESCRIPTION = "COMPOSE_CHANGE_MEDIA_DESCRIPTION"; export const COMPOSE_CHANGE_MEDIA_DESCRIPTION = 'COMPOSE_CHANGE_MEDIA_DESCRIPTION';
export const COMPOSE_CHANGE_MEDIA_FOCUS = "COMPOSE_CHANGE_MEDIA_FOCUS"; export const COMPOSE_CHANGE_MEDIA_FOCUS = 'COMPOSE_CHANGE_MEDIA_FOCUS';
export const COMPOSE_SET_STATUS = "COMPOSE_SET_STATUS"; export const COMPOSE_SET_STATUS = 'COMPOSE_SET_STATUS';
const messages = defineMessages({ const messages = defineMessages({
uploadErrorLimit: { id: "upload_error.limit", defaultMessage: "File upload limit exceeded." }, uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
uploadErrorPoll: { id: "upload_error.poll", defaultMessage: "File upload not allowed with polls." }, uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
}); });
export const ensureComposeIsVisible = (getState, routerHistory) => { export const ensureComposeIsVisible = (getState, routerHistory) => {
if (!getState().getIn(["compose", "mounted"])) { if (!getState().getIn(['compose', 'mounted'])) {
routerHistory.push("/publish"); routerHistory.push('/publish');
} }
}; };
@@ -122,7 +122,7 @@ export function cycleElefriendCompose() {
export function replyCompose(status, routerHistory) { export function replyCompose(status, routerHistory) {
return (dispatch, getState) => { return (dispatch, getState) => {
const prependCWRe = getState().getIn(["local_settings", "prepend_cw_re"]); const prependCWRe = getState().getIn(['local_settings', 'prepend_cw_re']);
dispatch({ dispatch({
type: COMPOSE_REPLY, type: COMPOSE_REPLY,
status: status, status: status,
@@ -169,11 +169,11 @@ export function directCompose(account, routerHistory) {
export function submitCompose(routerHistory) { export function submitCompose(routerHistory) {
return function (dispatch, getState) { return function (dispatch, getState) {
let status = getState().getIn(["compose", "text"], ""); let status = getState().getIn(['compose', 'text'], '');
const media = getState().getIn(["compose", "media_attachments"]); const media = getState().getIn(['compose', 'media_attachments']);
const statusId = getState().getIn(["compose", "id"], null); const statusId = getState().getIn(['compose', 'id'], null);
const spoilers = getState().getIn(["compose", "spoiler"]) || getState().getIn(["local_settings", "always_show_spoilers_field"]); const spoilers = getState().getIn(['compose', 'spoiler']) || getState().getIn(['local_settings', 'always_show_spoilers_field']);
let spoilerText = spoilers ? getState().getIn(["compose", "spoiler_text"], "") : ""; let spoilerText = spoilers ? getState().getIn(['compose', 'spoiler_text'], '') : '';
if ((!status || !status.length) && media.size === 0) { if ((!status || !status.length) && media.size === 0) {
return; return;
@@ -189,42 +189,42 @@ export function submitCompose(routerHistory) {
media_attributes = media.map(item => { media_attributes = media.map(item => {
let focus; let focus;
if (item.getIn(["meta", "focus"])) { if (item.getIn(['meta', 'focus'])) {
focus = `${item.getIn(["meta", "focus", "x"]).toFixed(2)},${item.getIn(["meta", "focus", "y"]).toFixed(2)}`; focus = `${item.getIn(['meta', 'focus', 'x']).toFixed(2)},${item.getIn(['meta', 'focus', 'y']).toFixed(2)}`;
} }
return { return {
id: item.get("id"), id: item.get('id'),
description: item.get("description"), description: item.get('description'),
focus, focus,
}; };
}); });
} }
api(getState).request({ api(getState).request({
url: statusId === null ? "/api/v1/statuses" : `/api/v1/statuses/${statusId}`, url: statusId === null ? '/api/v1/statuses' : `/api/v1/statuses/${statusId}`,
method: statusId === null ? "post" : "put", method: statusId === null ? 'post' : 'put',
data: { data: {
status, status,
content_type: getState().getIn(["compose", "content_type"]), content_type: getState().getIn(['compose', 'content_type']),
in_reply_to_id: getState().getIn(["compose", "in_reply_to"], null), in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
media_ids: media.map(item => item.get("id")), media_ids: media.map(item => item.get('id')),
media_attributes, media_attributes,
sensitive: getState().getIn(["compose", "sensitive"]) || (spoilerText.length > 0 && media.size !== 0), sensitive: getState().getIn(['compose', 'sensitive']) || (spoilerText.length > 0 && media.size !== 0),
spoiler_text: spoilerText, spoiler_text: spoilerText,
visibility: getState().getIn(["compose", "privacy"]), visibility: getState().getIn(['compose', 'privacy']),
poll: getState().getIn(["compose", "poll"], null), poll: getState().getIn(['compose', 'poll'], null),
language: getState().getIn(["compose", "language"]), language: getState().getIn(['compose', 'language']),
local_only: getState().getIn(["compose", "advanced_options", "do_not_federate"]), local_only: getState().getIn(['compose', 'advanced_options', 'do_not_federate']),
}, },
headers: { headers: {
"Idempotency-Key": getState().getIn(["compose", "idempotencyKey"]), 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
}, },
}).then(function (response) { }).then(function (response) {
if (routerHistory if (routerHistory
&& (routerHistory.location.pathname === "/publish" || routerHistory.location.pathname === "/statuses/new") && (routerHistory.location.pathname === '/publish' || routerHistory.location.pathname === '/statuses/new')
&& window.history.state && window.history.state
&& !getState().getIn(["compose", "advanced_options", "threaded_mode"])) { && !getState().getIn(['compose', 'advanced_options', 'threaded_mode'])) {
routerHistory.goBack(); routerHistory.goBack();
} }
@@ -239,9 +239,9 @@ export function submitCompose(routerHistory) {
// To make the app more responsive, immediately get the status into the columns // To make the app more responsive, immediately get the status into the columns
const insertIfOnline = (timelineId) => { const insertIfOnline = (timelineId) => {
const timeline = getState().getIn(["timelines", timelineId]); const timeline = getState().getIn(['timelines', timelineId]);
if (timeline && timeline.get("items").size > 0 && timeline.getIn(["items", 0]) !== null && timeline.get("online")) { if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
dispatch(updateTimeline(timelineId, { ...response.data })); dispatch(updateTimeline(timelineId, { ...response.data }));
} }
}; };
@@ -251,16 +251,16 @@ export function submitCompose(routerHistory) {
} }
if (statusId === null) { if (statusId === null) {
insertIfOnline("home"); insertIfOnline('home');
} }
if (statusId === null && response.data.in_reply_to_id === null && response.data.visibility === "public") { if (statusId === null && response.data.in_reply_to_id === null && response.data.visibility === 'public') {
insertIfOnline("community"); insertIfOnline('community');
if (!response.data.local_only) { if (!response.data.local_only) {
insertIfOnline("public"); insertIfOnline('public');
} }
} else if (statusId === null && response.data.visibility === "direct") { } else if (statusId === null && response.data.visibility === 'direct') {
insertIfOnline("direct"); insertIfOnline('direct');
} }
}).catch(function (error) { }).catch(function (error) {
dispatch(submitComposeFail(error)); dispatch(submitComposeFail(error));
@@ -298,8 +298,8 @@ export function doodleSet(options) {
export function uploadCompose(files) { export function uploadCompose(files) {
return function (dispatch, getState) { return function (dispatch, getState) {
const uploadLimit = maxMediaAttachments; const uploadLimit = maxMediaAttachments;
const media = getState().getIn(["compose", "media_attachments"]); const media = getState().getIn(['compose', 'media_attachments']);
const pending = getState().getIn(["compose", "pending_media_attachments"]); const pending = getState().getIn(['compose', 'pending_media_attachments']);
const progress = new Array(files.length).fill(0); const progress = new Array(files.length).fill(0);
let total = Array.from(files).reduce((a, v) => a + v.size, 0); let total = Array.from(files).reduce((a, v) => a + v.size, 0);
@@ -308,7 +308,7 @@ export function uploadCompose(files) {
return; return;
} }
if (getState().getIn(["compose", "poll"])) { if (getState().getIn(['compose', 'poll'])) {
dispatch(showAlert(undefined, messages.uploadErrorPoll)); dispatch(showAlert(undefined, messages.uploadErrorPoll));
return; return;
} }
@@ -316,17 +316,15 @@ export function uploadCompose(files) {
dispatch(uploadComposeRequest()); dispatch(uploadComposeRequest());
for (const [i, f] of Array.from(files).entries()) { for (const [i, f] of Array.from(files).entries()) {
if (media.size + i >= uploadLimit) { if (media.size + i >= uploadLimit) break;
break;
}
resizeImage(f).then(file => { resizeImage(f).then(file => {
const data = new FormData(); const data = new FormData();
data.append("file", file); data.append('file', file);
// Account for disparity in size of original image and resized data // Account for disparity in size of original image and resized data
total += file.size - f.size; total += file.size - f.size;
return api(getState).post("/api/v2/media", data, { return api(getState).post('/api/v2/media', data, {
onUploadProgress: function({ loaded }){ onUploadProgress: function({ loaded }){
progress[i] = loaded; progress[i] = loaded;
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total)); dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total));
@@ -372,7 +370,7 @@ export const uploadThumbnail = (id, file) => (dispatch, getState) => {
const total = file.size; const total = file.size;
const data = new FormData(); const data = new FormData();
data.append("thumbnail", file); data.append('thumbnail', file);
api(getState).put(`/api/v1/media/${id}`, data, { api(getState).put(`/api/v1/media/${id}`, data, {
onUploadProgress: ({ loaded }) => { onUploadProgress: ({ loaded }) => {
@@ -417,7 +415,7 @@ export function initMediaEditModal(id) {
}); });
dispatch(openModal({ dispatch(openModal({
modalType: "FOCAL_POINT", modalType: 'FOCAL_POINT',
modalProps: { id }, modalProps: { id },
})); }));
}; };
@@ -442,16 +440,16 @@ export function changeUploadCompose(id, params) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(changeUploadComposeRequest()); dispatch(changeUploadComposeRequest());
let media = getState().getIn(["compose", "media_attachments"]).find((item) => item.get("id") === id); let media = getState().getIn(['compose', 'media_attachments']).find((item) => item.get('id') === id);
// Editing already-attached media is deferred to editing the post itself. // Editing already-attached media is deferred to editing the post itself.
// For simplicity's sake, fake an API reply. // For simplicity's sake, fake an API reply.
if (media && !media.get("unattached")) { if (media && !media.get('unattached')) {
const { focus, ...other } = params; const { focus, ...other } = params;
const data = { ...media.toJS(), ...other }; const data = { ...media.toJS(), ...other };
if (focus) { if (focus) {
const [x, y] = focus.split(","); const [x, y] = focus.split(',');
data.meta = { focus: { x: parseFloat(x), y: parseFloat(y) } }; data.meta = { focus: { x: parseFloat(x), y: parseFloat(y) } };
} }
@@ -545,7 +543,7 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
fetchComposeSuggestionsAccountsController = new AbortController(); fetchComposeSuggestionsAccountsController = new AbortController();
api(getState).get("/api/v1/accounts/search", { api(getState).get('/api/v1/accounts/search', {
signal: fetchComposeSuggestionsAccountsController.signal, signal: fetchComposeSuggestionsAccountsController.signal,
params: { params: {
@@ -566,7 +564,7 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
}, 200, { leading: true, trailing: true }); }, 200, { leading: true, trailing: true });
const fetchComposeSuggestionsEmojis = (dispatch, getState, token) => { const fetchComposeSuggestionsEmojis = (dispatch, getState, token) => {
const results = emojiSearch(token.replace(":", ""), { maxResults: 5 }); const results = emojiSearch(token.replace(':', ''), { maxResults: 5 });
dispatch(readyComposeSuggestionsEmojis(token, results)); dispatch(readyComposeSuggestionsEmojis(token, results));
}; };
@@ -579,11 +577,11 @@ const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => {
fetchComposeSuggestionsTagsController = new AbortController(); fetchComposeSuggestionsTagsController = new AbortController();
api(getState).get("/api/v2/search", { api(getState).get('/api/v2/search', {
signal: fetchComposeSuggestionsTagsController.signal, signal: fetchComposeSuggestionsTagsController.signal,
params: { params: {
type: "hashtags", type: 'hashtags',
q: token.slice(1), q: token.slice(1),
resolve: false, resolve: false,
limit: 4, limit: 4,
@@ -602,15 +600,15 @@ const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => {
export function fetchComposeSuggestions(token) { export function fetchComposeSuggestions(token) {
return (dispatch, getState) => { return (dispatch, getState) => {
switch (token[0]) { switch (token[0]) {
case ":": case ':':
fetchComposeSuggestionsEmojis(dispatch, getState, token); fetchComposeSuggestionsEmojis(dispatch, getState, token);
break; break;
case "#": case '#':
fetchComposeSuggestionsTags(dispatch, getState, token); fetchComposeSuggestionsTags(dispatch, getState, token);
break; break;
default: default:
fetchComposeSuggestionsAccounts(dispatch, getState, token); fetchComposeSuggestionsAccounts(dispatch, getState, token);
break; break;
} }
}; };
} }
@@ -640,18 +638,18 @@ export const readyComposeSuggestionsTags = (token, tags) => ({
export function selectComposeSuggestion(position, token, suggestion, path) { export function selectComposeSuggestion(position, token, suggestion, path) {
return (dispatch, getState) => { return (dispatch, getState) => {
let completion; let completion;
if (suggestion.type === "emoji") { if (suggestion.type === 'emoji') {
dispatch(useEmoji(suggestion)); dispatch(useEmoji(suggestion));
completion = suggestion.native || suggestion.colons; completion = suggestion.native || suggestion.colons;
} else if (suggestion.type === "hashtag") { } else if (suggestion.type === 'hashtag') {
completion = `#${suggestion.name}`; completion = `#${suggestion.name}`;
} else if (suggestion.type === "account") { } else if (suggestion.type === 'account') {
completion = "@" + getState().getIn(["accounts", suggestion.id, "acct"]); completion = '@' + getState().getIn(['accounts', suggestion.id, 'acct']);
} }
// We don't want to replace hashtags that vary only in case due to accessibility, but we need to fire off an event so that // We don't want to replace hashtags that vary only in case due to accessibility, but we need to fire off an event so that
// the suggestions are dismissed and the cursor moves forward. // the suggestions are dismissed and the cursor moves forward.
if (suggestion.type !== "hashtag" || token.slice(1).localeCompare(suggestion.name, undefined, { sensitivity: "accent" }) !== 0) { if (suggestion.type !== 'hashtag' || token.slice(1).localeCompare(suggestion.name, undefined, { sensitivity: 'accent' }) !== 0) {
dispatch({ dispatch({
type: COMPOSE_SUGGESTION_SELECT, type: COMPOSE_SUGGESTION_SELECT,
position, position,
@@ -687,7 +685,7 @@ export function updateTagHistory(tags) {
export function hydrateCompose() { export function hydrateCompose() {
return (dispatch, getState) => { return (dispatch, getState) => {
const me = getState().getIn(["meta", "me"]); const me = getState().getIn(['meta', 'me']);
const history = tagHistory.get(me); const history = tagHistory.get(me);
if (history !== null) { if (history !== null) {
@@ -699,8 +697,8 @@ export function hydrateCompose() {
function insertIntoTagHistory(recognizedTags, text) { function insertIntoTagHistory(recognizedTags, text) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const oldHistory = state.getIn(["compose", "tagHistory"]); const oldHistory = state.getIn(['compose', 'tagHistory']);
const me = state.getIn(["meta", "me"]); const me = state.getIn(['meta', 'me']);
const names = recoverHashtags(recognizedTags, text); const names = recoverHashtags(recognizedTags, text);
const intersectedOldHistory = oldHistory.filter(name => names.findIndex(newName => newName.toLowerCase() === name.toLowerCase()) === -1); const intersectedOldHistory = oldHistory.filter(name => names.findIndex(newName => newName.toLowerCase() === name.toLowerCase()) === -1);
@@ -1,24 +1,24 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { import {
importFetchedAccounts, importFetchedAccounts,
importFetchedStatuses, importFetchedStatuses,
importFetchedStatus, importFetchedStatus,
} from "./importer"; } from './importer';
export const CONVERSATIONS_MOUNT = "CONVERSATIONS_MOUNT"; export const CONVERSATIONS_MOUNT = 'CONVERSATIONS_MOUNT';
export const CONVERSATIONS_UNMOUNT = "CONVERSATIONS_UNMOUNT"; export const CONVERSATIONS_UNMOUNT = 'CONVERSATIONS_UNMOUNT';
export const CONVERSATIONS_FETCH_REQUEST = "CONVERSATIONS_FETCH_REQUEST"; export const CONVERSATIONS_FETCH_REQUEST = 'CONVERSATIONS_FETCH_REQUEST';
export const CONVERSATIONS_FETCH_SUCCESS = "CONVERSATIONS_FETCH_SUCCESS"; export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS';
export const CONVERSATIONS_FETCH_FAIL = "CONVERSATIONS_FETCH_FAIL"; export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL';
export const CONVERSATIONS_UPDATE = "CONVERSATIONS_UPDATE"; export const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE';
export const CONVERSATIONS_READ = "CONVERSATIONS_READ"; export const CONVERSATIONS_READ = 'CONVERSATIONS_READ';
export const CONVERSATIONS_DELETE_REQUEST = "CONVERSATIONS_DELETE_REQUEST"; export const CONVERSATIONS_DELETE_REQUEST = 'CONVERSATIONS_DELETE_REQUEST';
export const CONVERSATIONS_DELETE_SUCCESS = "CONVERSATIONS_DELETE_SUCCESS"; export const CONVERSATIONS_DELETE_SUCCESS = 'CONVERSATIONS_DELETE_SUCCESS';
export const CONVERSATIONS_DELETE_FAIL = "CONVERSATIONS_DELETE_FAIL"; export const CONVERSATIONS_DELETE_FAIL = 'CONVERSATIONS_DELETE_FAIL';
export const mountConversations = () => ({ export const mountConversations = () => ({
type: CONVERSATIONS_MOUNT, type: CONVERSATIONS_MOUNT,
@@ -43,14 +43,14 @@ export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
const params = { max_id: maxId }; const params = { max_id: maxId };
if (!maxId) { if (!maxId) {
params.since_id = getState().getIn(["conversations", "items", 0, "last_status"]); params.since_id = getState().getIn(['conversations', 'items', 0, 'last_status']);
} }
const isLoadingRecent = !!params.since_id; const isLoadingRecent = !!params.since_id;
api(getState).get("/api/v1/conversations", { params }) api(getState).get('/api/v1/conversations', { params })
.then(response => { .then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.reduce((aggr, item) => aggr.concat(item.accounts), []))); dispatch(importFetchedAccounts(response.data.reduce((aggr, item) => aggr.concat(item.accounts), [])));
dispatch(importFetchedStatuses(response.data.map(item => item.last_status).filter(x => !!x))); dispatch(importFetchedStatuses(response.data.map(item => item.last_status).filter(x => !!x)));
@@ -1,14 +1,14 @@
import api from "../api"; import api from '../api';
export const CUSTOM_EMOJIS_FETCH_REQUEST = "CUSTOM_EMOJIS_FETCH_REQUEST"; export const CUSTOM_EMOJIS_FETCH_REQUEST = 'CUSTOM_EMOJIS_FETCH_REQUEST';
export const CUSTOM_EMOJIS_FETCH_SUCCESS = "CUSTOM_EMOJIS_FETCH_SUCCESS"; export const CUSTOM_EMOJIS_FETCH_SUCCESS = 'CUSTOM_EMOJIS_FETCH_SUCCESS';
export const CUSTOM_EMOJIS_FETCH_FAIL = "CUSTOM_EMOJIS_FETCH_FAIL"; export const CUSTOM_EMOJIS_FETCH_FAIL = 'CUSTOM_EMOJIS_FETCH_FAIL';
export function fetchCustomEmojis() { export function fetchCustomEmojis() {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchCustomEmojisRequest()); dispatch(fetchCustomEmojisRequest());
api(getState).get("/api/v1/custom_emojis").then(response => { api(getState).get('/api/v1/custom_emojis').then(response => {
dispatch(fetchCustomEmojisSuccess(response.data)); dispatch(fetchCustomEmojisSuccess(response.data));
}).catch(error => { }).catch(error => {
dispatch(fetchCustomEmojisFail(error)); dispatch(fetchCustomEmojisFail(error));
@@ -1,20 +1,20 @@
import api from "../api"; import api from '../api';
import { fetchRelationships } from "./accounts"; import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from "./importer"; import { importFetchedAccounts } from './importer';
export const DIRECTORY_FETCH_REQUEST = "DIRECTORY_FETCH_REQUEST"; export const DIRECTORY_FETCH_REQUEST = 'DIRECTORY_FETCH_REQUEST';
export const DIRECTORY_FETCH_SUCCESS = "DIRECTORY_FETCH_SUCCESS"; export const DIRECTORY_FETCH_SUCCESS = 'DIRECTORY_FETCH_SUCCESS';
export const DIRECTORY_FETCH_FAIL = "DIRECTORY_FETCH_FAIL"; export const DIRECTORY_FETCH_FAIL = 'DIRECTORY_FETCH_FAIL';
export const DIRECTORY_EXPAND_REQUEST = "DIRECTORY_EXPAND_REQUEST"; export const DIRECTORY_EXPAND_REQUEST = 'DIRECTORY_EXPAND_REQUEST';
export const DIRECTORY_EXPAND_SUCCESS = "DIRECTORY_EXPAND_SUCCESS"; export const DIRECTORY_EXPAND_SUCCESS = 'DIRECTORY_EXPAND_SUCCESS';
export const DIRECTORY_EXPAND_FAIL = "DIRECTORY_EXPAND_FAIL"; export const DIRECTORY_EXPAND_FAIL = 'DIRECTORY_EXPAND_FAIL';
export const fetchDirectory = params => (dispatch, getState) => { export const fetchDirectory = params => (dispatch, getState) => {
dispatch(fetchDirectoryRequest()); dispatch(fetchDirectoryRequest());
api(getState).get("/api/v1/directory", { params: { ...params, limit: 20 } }).then(({ data }) => { api(getState).get('/api/v1/directory', { params: { ...params, limit: 20 } }).then(({ data }) => {
dispatch(importFetchedAccounts(data)); dispatch(importFetchedAccounts(data));
dispatch(fetchDirectorySuccess(data)); dispatch(fetchDirectorySuccess(data));
dispatch(fetchRelationships(data.map(x => x.id))); dispatch(fetchRelationships(data.map(x => x.id)));
@@ -38,9 +38,9 @@ export const fetchDirectoryFail = error => ({
export const expandDirectory = params => (dispatch, getState) => { export const expandDirectory = params => (dispatch, getState) => {
dispatch(expandDirectoryRequest()); dispatch(expandDirectoryRequest());
const loadedItems = getState().getIn(["user_lists", "directory", "items"]).size; const loadedItems = getState().getIn(['user_lists', 'directory', 'items']).size;
api(getState).get("/api/v1/directory", { params: { ...params, offset: loadedItems, limit: 20 } }).then(({ data }) => { api(getState).get('/api/v1/directory', { params: { ...params, offset: loadedItems, limit: 20 } }).then(({ data }) => {
dispatch(importFetchedAccounts(data)); dispatch(importFetchedAccounts(data));
dispatch(expandDirectorySuccess(data)); dispatch(expandDirectorySuccess(data));
dispatch(fetchRelationships(data.map(x => x.id))); dispatch(fetchRelationships(data.map(x => x.id)));
@@ -1,28 +1,28 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
export const DOMAIN_BLOCK_REQUEST = "DOMAIN_BLOCK_REQUEST"; export const DOMAIN_BLOCK_REQUEST = 'DOMAIN_BLOCK_REQUEST';
export const DOMAIN_BLOCK_SUCCESS = "DOMAIN_BLOCK_SUCCESS"; export const DOMAIN_BLOCK_SUCCESS = 'DOMAIN_BLOCK_SUCCESS';
export const DOMAIN_BLOCK_FAIL = "DOMAIN_BLOCK_FAIL"; export const DOMAIN_BLOCK_FAIL = 'DOMAIN_BLOCK_FAIL';
export const DOMAIN_UNBLOCK_REQUEST = "DOMAIN_UNBLOCK_REQUEST"; export const DOMAIN_UNBLOCK_REQUEST = 'DOMAIN_UNBLOCK_REQUEST';
export const DOMAIN_UNBLOCK_SUCCESS = "DOMAIN_UNBLOCK_SUCCESS"; export const DOMAIN_UNBLOCK_SUCCESS = 'DOMAIN_UNBLOCK_SUCCESS';
export const DOMAIN_UNBLOCK_FAIL = "DOMAIN_UNBLOCK_FAIL"; export const DOMAIN_UNBLOCK_FAIL = 'DOMAIN_UNBLOCK_FAIL';
export const DOMAIN_BLOCKS_FETCH_REQUEST = "DOMAIN_BLOCKS_FETCH_REQUEST"; export const DOMAIN_BLOCKS_FETCH_REQUEST = 'DOMAIN_BLOCKS_FETCH_REQUEST';
export const DOMAIN_BLOCKS_FETCH_SUCCESS = "DOMAIN_BLOCKS_FETCH_SUCCESS"; export const DOMAIN_BLOCKS_FETCH_SUCCESS = 'DOMAIN_BLOCKS_FETCH_SUCCESS';
export const DOMAIN_BLOCKS_FETCH_FAIL = "DOMAIN_BLOCKS_FETCH_FAIL"; export const DOMAIN_BLOCKS_FETCH_FAIL = 'DOMAIN_BLOCKS_FETCH_FAIL';
export const DOMAIN_BLOCKS_EXPAND_REQUEST = "DOMAIN_BLOCKS_EXPAND_REQUEST"; export const DOMAIN_BLOCKS_EXPAND_REQUEST = 'DOMAIN_BLOCKS_EXPAND_REQUEST';
export const DOMAIN_BLOCKS_EXPAND_SUCCESS = "DOMAIN_BLOCKS_EXPAND_SUCCESS"; export const DOMAIN_BLOCKS_EXPAND_SUCCESS = 'DOMAIN_BLOCKS_EXPAND_SUCCESS';
export const DOMAIN_BLOCKS_EXPAND_FAIL = "DOMAIN_BLOCKS_EXPAND_FAIL"; export const DOMAIN_BLOCKS_EXPAND_FAIL = 'DOMAIN_BLOCKS_EXPAND_FAIL';
export function blockDomain(domain) { export function blockDomain(domain) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(blockDomainRequest(domain)); dispatch(blockDomainRequest(domain));
api(getState).post("/api/v1/domain_blocks", { domain }).then(() => { api(getState).post('/api/v1/domain_blocks', { domain }).then(() => {
const at_domain = "@" + domain; const at_domain = '@' + domain;
const accounts = getState().get("accounts").filter(item => item.get("acct").endsWith(at_domain)).valueSeq().map(item => item.get("id")); const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
dispatch(blockDomainSuccess(domain, accounts)); dispatch(blockDomainSuccess(domain, accounts));
}).catch(err => { }).catch(err => {
@@ -58,9 +58,9 @@ export function unblockDomain(domain) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(unblockDomainRequest(domain)); dispatch(unblockDomainRequest(domain));
api(getState).delete("/api/v1/domain_blocks", { params: { domain } }).then(() => { api(getState).delete('/api/v1/domain_blocks', { params: { domain } }).then(() => {
const at_domain = "@" + domain; const at_domain = '@' + domain;
const accounts = getState().get("accounts").filter(item => item.get("acct").endsWith(at_domain)).valueSeq().map(item => item.get("id")); const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
dispatch(unblockDomainSuccess(domain, accounts)); dispatch(unblockDomainSuccess(domain, accounts));
}).catch(err => { }).catch(err => {
dispatch(unblockDomainFail(domain, err)); dispatch(unblockDomainFail(domain, err));
@@ -95,8 +95,8 @@ export function fetchDomainBlocks() {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchDomainBlocksRequest()); dispatch(fetchDomainBlocksRequest());
api(getState).get("/api/v1/domain_blocks").then(response => { api(getState).get('/api/v1/domain_blocks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(fetchDomainBlocksSuccess(response.data, next ? next.uri : null)); dispatch(fetchDomainBlocksSuccess(response.data, next ? next.uri : null));
}).catch(err => { }).catch(err => {
dispatch(fetchDomainBlocksFail(err)); dispatch(fetchDomainBlocksFail(err));
@@ -127,7 +127,7 @@ export function fetchDomainBlocksFail(error) {
export function expandDomainBlocks() { export function expandDomainBlocks() {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["domain_lists", "blocks", "next"]); const url = getState().getIn(['domain_lists', 'blocks', 'next']);
if (!url) { if (!url) {
return; return;
@@ -136,7 +136,7 @@ export function expandDomainBlocks() {
dispatch(expandDomainBlocksRequest()); dispatch(expandDomainBlocksRequest());
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(expandDomainBlocksSuccess(response.data, next ? next.uri : null)); dispatch(expandDomainBlocksSuccess(response.data, next ? next.uri : null));
}).catch(err => { }).catch(err => {
dispatch(expandDomainBlocksFail(err)); dispatch(expandDomainBlocksFail(err));
@@ -1,11 +1,11 @@
import { createAction } from "@reduxjs/toolkit"; import { createAction } from '@reduxjs/toolkit';
export const openDropdownMenu = createAction<{ export const openDropdownMenu = createAction<{
id: string, id: string;
keyboard: boolean, keyboard: boolean;
scrollKey: string, scrollKey: string;
}>("dropdownMenu/open"); }>('dropdownMenu/open');
export const closeDropdownMenu = createAction<{ id: string }>( export const closeDropdownMenu = createAction<{ id: string }>(
"dropdownMenu/close", 'dropdownMenu/close',
); );
@@ -1,6 +1,6 @@
import { saveSettings } from "./settings"; import { saveSettings } from './settings';
export const EMOJI_USE = "EMOJI_USE"; export const EMOJI_USE = 'EMOJI_USE';
export function useEmoji(emoji) { export function useEmoji(emoji) {
return dispatch => { return dispatch => {
@@ -1,25 +1,25 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { importFetchedStatuses } from "./importer"; import { importFetchedStatuses } from './importer';
export const FAVOURITED_STATUSES_FETCH_REQUEST = "FAVOURITED_STATUSES_FETCH_REQUEST"; export const FAVOURITED_STATUSES_FETCH_REQUEST = 'FAVOURITED_STATUSES_FETCH_REQUEST';
export const FAVOURITED_STATUSES_FETCH_SUCCESS = "FAVOURITED_STATUSES_FETCH_SUCCESS"; export const FAVOURITED_STATUSES_FETCH_SUCCESS = 'FAVOURITED_STATUSES_FETCH_SUCCESS';
export const FAVOURITED_STATUSES_FETCH_FAIL = "FAVOURITED_STATUSES_FETCH_FAIL"; export const FAVOURITED_STATUSES_FETCH_FAIL = 'FAVOURITED_STATUSES_FETCH_FAIL';
export const FAVOURITED_STATUSES_EXPAND_REQUEST = "FAVOURITED_STATUSES_EXPAND_REQUEST"; export const FAVOURITED_STATUSES_EXPAND_REQUEST = 'FAVOURITED_STATUSES_EXPAND_REQUEST';
export const FAVOURITED_STATUSES_EXPAND_SUCCESS = "FAVOURITED_STATUSES_EXPAND_SUCCESS"; export const FAVOURITED_STATUSES_EXPAND_SUCCESS = 'FAVOURITED_STATUSES_EXPAND_SUCCESS';
export const FAVOURITED_STATUSES_EXPAND_FAIL = "FAVOURITED_STATUSES_EXPAND_FAIL"; export const FAVOURITED_STATUSES_EXPAND_FAIL = 'FAVOURITED_STATUSES_EXPAND_FAIL';
export function fetchFavouritedStatuses() { export function fetchFavouritedStatuses() {
return (dispatch, getState) => { return (dispatch, getState) => {
if (getState().getIn(["status_lists", "favourites", "isLoading"])) { if (getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
return; return;
} }
dispatch(fetchFavouritedStatusesRequest()); dispatch(fetchFavouritedStatusesRequest());
api(getState).get("/api/v1/favourites").then(response => { api(getState).get('/api/v1/favourites').then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(fetchFavouritedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchFavouritedStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => { }).catch(error => {
@@ -54,16 +54,16 @@ export function fetchFavouritedStatusesFail(error) {
export function expandFavouritedStatuses() { export function expandFavouritedStatuses() {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["status_lists", "favourites", "next"], null); const url = getState().getIn(['status_lists', 'favourites', 'next'], null);
if (url === null || getState().getIn(["status_lists", "favourites", "isLoading"])) { if (url === null || getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
return; return;
} }
dispatch(expandFavouritedStatusesRequest()); dispatch(expandFavouritedStatusesRequest());
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(expandFavouritedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(expandFavouritedStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => { }).catch(error => {
@@ -1,11 +1,11 @@
import api from "../api"; import api from '../api';
export const FEATURED_TAGS_FETCH_REQUEST = "FEATURED_TAGS_FETCH_REQUEST"; export const FEATURED_TAGS_FETCH_REQUEST = 'FEATURED_TAGS_FETCH_REQUEST';
export const FEATURED_TAGS_FETCH_SUCCESS = "FEATURED_TAGS_FETCH_SUCCESS"; export const FEATURED_TAGS_FETCH_SUCCESS = 'FEATURED_TAGS_FETCH_SUCCESS';
export const FEATURED_TAGS_FETCH_FAIL = "FEATURED_TAGS_FETCH_FAIL"; export const FEATURED_TAGS_FETCH_FAIL = 'FEATURED_TAGS_FETCH_FAIL';
export const fetchFeaturedTags = (id) => (dispatch, getState) => { export const fetchFeaturedTags = (id) => (dispatch, getState) => {
if (getState().getIn(["user_lists", "featured_tags", id, "items"])) { if (getState().getIn(['user_lists', 'featured_tags', id, 'items'])) {
return; return;
} }
@@ -1,24 +1,24 @@
import api from "../api"; import api from '../api';
import { openModal } from "./modal"; import { openModal } from './modal';
export const FILTERS_FETCH_REQUEST = "FILTERS_FETCH_REQUEST"; export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST';
export const FILTERS_FETCH_SUCCESS = "FILTERS_FETCH_SUCCESS"; export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS';
export const FILTERS_FETCH_FAIL = "FILTERS_FETCH_FAIL"; export const FILTERS_FETCH_FAIL = 'FILTERS_FETCH_FAIL';
export const FILTERS_STATUS_CREATE_REQUEST = "FILTERS_STATUS_CREATE_REQUEST"; export const FILTERS_STATUS_CREATE_REQUEST = 'FILTERS_STATUS_CREATE_REQUEST';
export const FILTERS_STATUS_CREATE_SUCCESS = "FILTERS_STATUS_CREATE_SUCCESS"; export const FILTERS_STATUS_CREATE_SUCCESS = 'FILTERS_STATUS_CREATE_SUCCESS';
export const FILTERS_STATUS_CREATE_FAIL = "FILTERS_STATUS_CREATE_FAIL"; export const FILTERS_STATUS_CREATE_FAIL = 'FILTERS_STATUS_CREATE_FAIL';
export const FILTERS_CREATE_REQUEST = "FILTERS_CREATE_REQUEST"; export const FILTERS_CREATE_REQUEST = 'FILTERS_CREATE_REQUEST';
export const FILTERS_CREATE_SUCCESS = "FILTERS_CREATE_SUCCESS"; export const FILTERS_CREATE_SUCCESS = 'FILTERS_CREATE_SUCCESS';
export const FILTERS_CREATE_FAIL = "FILTERS_CREATE_FAIL"; export const FILTERS_CREATE_FAIL = 'FILTERS_CREATE_FAIL';
export const initAddFilter = (status, { contextType }) => dispatch => export const initAddFilter = (status, { contextType }) => dispatch =>
dispatch(openModal({ dispatch(openModal({
modalType: "FILTER", modalType: 'FILTER',
modalProps: { modalProps: {
statusId: status?.get("id"), statusId: status?.get('id'),
contextType: contextType, contextType: contextType,
}, },
})); }));
@@ -30,7 +30,7 @@ export const fetchFilters = () => (dispatch, getState) => {
}); });
api(getState) api(getState)
.get("/api/v2/filters") .get('/api/v2/filters')
.then(({ data }) => dispatch({ .then(({ data }) => dispatch({
type: FILTERS_FETCH_SUCCESS, type: FILTERS_FETCH_SUCCESS,
filters: data, filters: data,
@@ -49,14 +49,10 @@ export const createFilterStatus = (params, onSuccess, onFail) => (dispatch, getS
api(getState).post(`/api/v2/filters/${params.filter_id}/statuses`, params).then(response => { api(getState).post(`/api/v2/filters/${params.filter_id}/statuses`, params).then(response => {
dispatch(createFilterStatusSuccess(response.data)); dispatch(createFilterStatusSuccess(response.data));
if (onSuccess) { if (onSuccess) onSuccess();
onSuccess();
}
}).catch(error => { }).catch(error => {
dispatch(createFilterStatusFail(error)); dispatch(createFilterStatusFail(error));
if (onFail) { if (onFail) onFail();
onFail();
}
}); });
}; };
@@ -77,16 +73,12 @@ export const createFilterStatusFail = error => ({
export const createFilter = (params, onSuccess, onFail) => (dispatch, getState) => { export const createFilter = (params, onSuccess, onFail) => (dispatch, getState) => {
dispatch(createFilterRequest()); dispatch(createFilterRequest());
api(getState).post("/api/v2/filters", params).then(response => { api(getState).post('/api/v2/filters', params).then(response => {
dispatch(createFilterSuccess(response.data)); dispatch(createFilterSuccess(response.data));
if (onSuccess) { if (onSuccess) onSuccess(response.data);
onSuccess(response.data);
}
}).catch(error => { }).catch(error => {
dispatch(createFilterFail(error)); dispatch(createFilterFail(error));
if (onFail) { if (onFail) onFail();
onFail();
}
}); });
}; };
@@ -1,5 +1,5 @@
export const HEIGHT_CACHE_SET = "HEIGHT_CACHE_SET"; export const HEIGHT_CACHE_SET = 'HEIGHT_CACHE_SET';
export const HEIGHT_CACHE_CLEAR = "HEIGHT_CACHE_CLEAR"; export const HEIGHT_CACHE_CLEAR = 'HEIGHT_CACHE_CLEAR';
export function setHeight (key, id, height) { export function setHeight (key, id, height) {
return { return {
@@ -1,13 +1,13 @@
import api from "../api"; import api from '../api';
import { importFetchedAccounts } from "./importer"; import { importFetchedAccounts } from './importer';
export const HISTORY_FETCH_REQUEST = "HISTORY_FETCH_REQUEST"; export const HISTORY_FETCH_REQUEST = 'HISTORY_FETCH_REQUEST';
export const HISTORY_FETCH_SUCCESS = "HISTORY_FETCH_SUCCESS"; export const HISTORY_FETCH_SUCCESS = 'HISTORY_FETCH_SUCCESS';
export const HISTORY_FETCH_FAIL = "HISTORY_FETCH_FAIL"; export const HISTORY_FETCH_FAIL = 'HISTORY_FETCH_FAIL';
export const fetchHistory = statusId => (dispatch, getState) => { export const fetchHistory = statusId => (dispatch, getState) => {
const loading = getState().getIn(["history", statusId, "loading"]); const loading = getState().getIn(['history', statusId, 'loading']);
if (loading) { if (loading) {
return; return;
@@ -1,8 +1,8 @@
import api from "../api"; import api from '../api';
export const IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST = "IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST"; export const IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST = 'IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST';
export const IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS = "IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS"; export const IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS = 'IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS';
export const IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL = "IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL"; export const IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL = 'IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL';
export const fetchAccountIdentityProofs = accountId => (dispatch, getState) => { export const fetchAccountIdentityProofs = accountId => (dispatch, getState) => {
dispatch(fetchAccountIdentityProofsRequest(accountId)); dispatch(fetchAccountIdentityProofsRequest(accountId));
@@ -1,11 +1,11 @@
import { normalizeAccount, normalizeStatus, normalizePoll } from "./normalizer"; import { normalizeAccount, normalizeStatus, normalizePoll } from './normalizer';
export const ACCOUNT_IMPORT = "ACCOUNT_IMPORT"; export const ACCOUNT_IMPORT = 'ACCOUNT_IMPORT';
export const ACCOUNTS_IMPORT = "ACCOUNTS_IMPORT"; export const ACCOUNTS_IMPORT = 'ACCOUNTS_IMPORT';
export const STATUS_IMPORT = "STATUS_IMPORT"; export const STATUS_IMPORT = 'STATUS_IMPORT';
export const STATUSES_IMPORT = "STATUSES_IMPORT"; export const STATUSES_IMPORT = 'STATUSES_IMPORT';
export const POLLS_IMPORT = "POLLS_IMPORT"; export const POLLS_IMPORT = 'POLLS_IMPORT';
export const FILTERS_IMPORT = "FILTERS_IMPORT"; export const FILTERS_IMPORT = 'FILTERS_IMPORT';
function pushUnique(array, object) { function pushUnique(array, object) {
if (array.every(element => element.id !== object.id)) { if (array.every(element => element.id !== object.id)) {
@@ -69,7 +69,7 @@ export function importFetchedStatuses(statuses) {
const filters = []; const filters = [];
function processStatus(status) { function processStatus(status) {
pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(["statuses", status.id]), getState().get("local_settings"))); pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(['statuses', status.id]), getState().get('local_settings')));
pushUnique(accounts, status.account); pushUnique(accounts, status.account);
if (status.filtered) { if (status.filtered) {
@@ -81,7 +81,7 @@ export function importFetchedStatuses(statuses) {
} }
if (status.poll && status.poll.id) { if (status.poll && status.poll.id) {
pushUnique(polls, normalizePoll(status.poll, getState().getIn(["polls", status.poll.id]))); pushUnique(polls, normalizePoll(status.poll, getState().getIn(['polls', status.poll.id])));
} }
} }
@@ -96,6 +96,6 @@ export function importFetchedStatuses(statuses) {
export function importFetchedPoll(poll) { export function importFetchedPoll(poll) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(importPolls([normalizePoll(poll, getState().getIn(["polls", poll.id]))])); dispatch(importPolls([normalizePoll(poll, getState().getIn(['polls', poll.id]))]));
}; };
} }
@@ -1,8 +1,8 @@
import escapeTextContentForBrowser from "escape-html"; import escapeTextContentForBrowser from 'escape-html';
import emojify from "flavours/glitch/features/emoji/emoji"; import emojify from 'flavours/glitch/features/emoji/emoji';
import { autoHideCW } from "flavours/glitch/utils/content_warning"; import { autoHideCW } from 'flavours/glitch/utils/content_warning';
import { unescapeHTML } from "flavours/glitch/utils/html"; import { unescapeHTML } from 'flavours/glitch/utils/html';
const domParser = new DOMParser(); const domParser = new DOMParser();
@@ -12,9 +12,9 @@ const makeEmojiMap = emojis => emojis.reduce((obj, emoji) => {
}, {}); }, {});
export function searchTextFromRawStatus (status) { export function searchTextFromRawStatus (status) {
const spoilerText = status.spoiler_text || ""; const spoilerText = status.spoiler_text || '';
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join("\n\n").replace(/<br\s*\/?>/g, "\n").replace(/<\/p><p>/g, "\n\n"); const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
return domParser.parseFromString(searchContent, "text/html").documentElement.textContent; return domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
} }
export function normalizeAccount(account) { export function normalizeAccount(account) {
@@ -70,33 +70,33 @@ export function normalizeStatus(status, normalOldStatus, settings) {
// Only calculate these values when status first encountered and // Only calculate these values when status first encountered and
// when the underlying values change. Otherwise keep the ones // when the underlying values change. Otherwise keep the ones
// already in the reducer // already in the reducer
if (normalOldStatus && normalOldStatus.get("content") === normalStatus.content && normalOldStatus.get("spoiler_text") === normalStatus.spoiler_text) { if (normalOldStatus && normalOldStatus.get('content') === normalStatus.content && normalOldStatus.get('spoiler_text') === normalStatus.spoiler_text) {
normalStatus.search_index = normalOldStatus.get("search_index"); normalStatus.search_index = normalOldStatus.get('search_index');
normalStatus.contentHtml = normalOldStatus.get("contentHtml"); normalStatus.contentHtml = normalOldStatus.get('contentHtml');
normalStatus.spoilerHtml = normalOldStatus.get("spoilerHtml"); normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml');
normalStatus.hidden = normalOldStatus.get("hidden"); normalStatus.hidden = normalOldStatus.get('hidden');
if (normalOldStatus.get("translation")) { if (normalOldStatus.get('translation')) {
normalStatus.translation = normalOldStatus.get("translation"); normalStatus.translation = normalOldStatus.get('translation');
} }
} else { } else {
const spoilerText = normalStatus.spoiler_text || ""; const spoilerText = normalStatus.spoiler_text || '';
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join("\n\n").replace(/<br\s*\/?>/g, "\n").replace(/<\/p><p>/g, "\n\n"); const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
const emojiMap = makeEmojiMap(normalStatus.emojis); const emojiMap = makeEmojiMap(normalStatus.emojis);
normalStatus.search_index = domParser.parseFromString(searchContent, "text/html").documentElement.textContent; normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap); normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap); normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
normalStatus.hidden = (spoilerText.length > 0 || normalStatus.sensitive) && autoHideCW(settings, spoilerText); normalStatus.hidden = (spoilerText.length > 0 || normalStatus.sensitive) && autoHideCW(settings, spoilerText);
} }
if (normalOldStatus) { if (normalOldStatus) {
const list = normalOldStatus.get("media_attachments"); const list = normalOldStatus.get('media_attachments');
if (normalStatus.media_attachments && list) { if (normalStatus.media_attachments && list) {
normalStatus.media_attachments.forEach(item => { normalStatus.media_attachments.forEach(item => {
const oldItem = list.find(i => i.get("id") === item.id); const oldItem = list.find(i => i.get('id') === item.id);
if (oldItem && oldItem.get("description") === item.description) { if (oldItem && oldItem.get('description') === item.description) {
item.translation = oldItem.get("translation"); item.translation = oldItem.get('translation');
} }
}); });
} }
@@ -106,7 +106,7 @@ export function normalizeStatus(status, normalOldStatus, settings) {
} }
export function normalizeStatusTranslation(translation, status) { export function normalizeStatusTranslation(translation, status) {
const emojiMap = makeEmojiMap(status.get("emojis").toJS()); const emojiMap = makeEmojiMap(status.get('emojis').toJS());
const normalTranslation = { const normalTranslation = {
detected_source_language: translation.detected_source_language, detected_source_language: translation.detected_source_language,
@@ -131,8 +131,8 @@ export function normalizePoll(poll, normalOldPoll) {
titleHtml: emojify(escapeTextContentForBrowser(option.title), emojiMap), titleHtml: emojify(escapeTextContentForBrowser(option.title), emojiMap),
}; };
if (normalOldPoll && normalOldPoll.getIn(["options", index, "title"]) === option.title) { if (normalOldPoll && normalOldPoll.getIn(['options', index, 'title']) === option.title) {
normalOption.translation = normalOldPoll.getIn(["options", index, "translation"]); normalOption.translation = normalOldPoll.getIn(['options', index, 'translation']);
} }
return normalOption; return normalOption;
@@ -142,7 +142,7 @@ export function normalizePoll(poll, normalOldPoll) {
} }
export function normalizePollOptionTranslation(translation, poll) { export function normalizePollOptionTranslation(translation, poll) {
const emojiMap = makeEmojiMap(poll.get("emojis").toJS()); const emojiMap = makeEmojiMap(poll.get('emojis').toJS());
const normalTranslation = { const normalTranslation = {
...translation, ...translation,
@@ -1,61 +1,61 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { fetchRelationships } from "./accounts"; import { fetchRelationships } from './accounts';
import { importFetchedAccounts, importFetchedStatus } from "./importer"; import { importFetchedAccounts, importFetchedStatus } from './importer';
export const REBLOG_REQUEST = "REBLOG_REQUEST"; export const REBLOG_REQUEST = 'REBLOG_REQUEST';
export const REBLOG_SUCCESS = "REBLOG_SUCCESS"; export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
export const REBLOG_FAIL = "REBLOG_FAIL"; export const REBLOG_FAIL = 'REBLOG_FAIL';
export const REBLOGS_EXPAND_REQUEST = "REBLOGS_EXPAND_REQUEST"; export const REBLOGS_EXPAND_REQUEST = 'REBLOGS_EXPAND_REQUEST';
export const REBLOGS_EXPAND_SUCCESS = "REBLOGS_EXPAND_SUCCESS"; export const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS';
export const REBLOGS_EXPAND_FAIL = "REBLOGS_EXPAND_FAIL"; export const REBLOGS_EXPAND_FAIL = 'REBLOGS_EXPAND_FAIL';
export const FAVOURITE_REQUEST = "FAVOURITE_REQUEST"; export const FAVOURITE_REQUEST = 'FAVOURITE_REQUEST';
export const FAVOURITE_SUCCESS = "FAVOURITE_SUCCESS"; export const FAVOURITE_SUCCESS = 'FAVOURITE_SUCCESS';
export const FAVOURITE_FAIL = "FAVOURITE_FAIL"; export const FAVOURITE_FAIL = 'FAVOURITE_FAIL';
export const UNREBLOG_REQUEST = "UNREBLOG_REQUEST"; export const UNREBLOG_REQUEST = 'UNREBLOG_REQUEST';
export const UNREBLOG_SUCCESS = "UNREBLOG_SUCCESS"; export const UNREBLOG_SUCCESS = 'UNREBLOG_SUCCESS';
export const UNREBLOG_FAIL = "UNREBLOG_FAIL"; export const UNREBLOG_FAIL = 'UNREBLOG_FAIL';
export const UNFAVOURITE_REQUEST = "UNFAVOURITE_REQUEST"; export const UNFAVOURITE_REQUEST = 'UNFAVOURITE_REQUEST';
export const UNFAVOURITE_SUCCESS = "UNFAVOURITE_SUCCESS"; export const UNFAVOURITE_SUCCESS = 'UNFAVOURITE_SUCCESS';
export const UNFAVOURITE_FAIL = "UNFAVOURITE_FAIL"; export const UNFAVOURITE_FAIL = 'UNFAVOURITE_FAIL';
export const REBLOGS_FETCH_REQUEST = "REBLOGS_FETCH_REQUEST"; export const REBLOGS_FETCH_REQUEST = 'REBLOGS_FETCH_REQUEST';
export const REBLOGS_FETCH_SUCCESS = "REBLOGS_FETCH_SUCCESS"; export const REBLOGS_FETCH_SUCCESS = 'REBLOGS_FETCH_SUCCESS';
export const REBLOGS_FETCH_FAIL = "REBLOGS_FETCH_FAIL"; export const REBLOGS_FETCH_FAIL = 'REBLOGS_FETCH_FAIL';
export const FAVOURITES_FETCH_REQUEST = "FAVOURITES_FETCH_REQUEST"; export const FAVOURITES_FETCH_REQUEST = 'FAVOURITES_FETCH_REQUEST';
export const FAVOURITES_FETCH_SUCCESS = "FAVOURITES_FETCH_SUCCESS"; export const FAVOURITES_FETCH_SUCCESS = 'FAVOURITES_FETCH_SUCCESS';
export const FAVOURITES_FETCH_FAIL = "FAVOURITES_FETCH_FAIL"; export const FAVOURITES_FETCH_FAIL = 'FAVOURITES_FETCH_FAIL';
export const FAVOURITES_EXPAND_REQUEST = "FAVOURITES_EXPAND_REQUEST"; export const FAVOURITES_EXPAND_REQUEST = 'FAVOURITES_EXPAND_REQUEST';
export const FAVOURITES_EXPAND_SUCCESS = "FAVOURITES_EXPAND_SUCCESS"; export const FAVOURITES_EXPAND_SUCCESS = 'FAVOURITES_EXPAND_SUCCESS';
export const FAVOURITES_EXPAND_FAIL = "FAVOURITES_EXPAND_FAIL"; export const FAVOURITES_EXPAND_FAIL = 'FAVOURITES_EXPAND_FAIL';
export const PIN_REQUEST = "PIN_REQUEST"; export const PIN_REQUEST = 'PIN_REQUEST';
export const PIN_SUCCESS = "PIN_SUCCESS"; export const PIN_SUCCESS = 'PIN_SUCCESS';
export const PIN_FAIL = "PIN_FAIL"; export const PIN_FAIL = 'PIN_FAIL';
export const UNPIN_REQUEST = "UNPIN_REQUEST"; export const UNPIN_REQUEST = 'UNPIN_REQUEST';
export const UNPIN_SUCCESS = "UNPIN_SUCCESS"; export const UNPIN_SUCCESS = 'UNPIN_SUCCESS';
export const UNPIN_FAIL = "UNPIN_FAIL"; export const UNPIN_FAIL = 'UNPIN_FAIL';
export const BOOKMARK_REQUEST = "BOOKMARK_REQUEST"; export const BOOKMARK_REQUEST = 'BOOKMARK_REQUEST';
export const BOOKMARK_SUCCESS = "BOOKMARKED_SUCCESS"; export const BOOKMARK_SUCCESS = 'BOOKMARKED_SUCCESS';
export const BOOKMARK_FAIL = "BOOKMARKED_FAIL"; export const BOOKMARK_FAIL = 'BOOKMARKED_FAIL';
export const UNBOOKMARK_REQUEST = "UNBOOKMARKED_REQUEST"; export const UNBOOKMARK_REQUEST = 'UNBOOKMARKED_REQUEST';
export const UNBOOKMARK_SUCCESS = "UNBOOKMARKED_SUCCESS"; export const UNBOOKMARK_SUCCESS = 'UNBOOKMARKED_SUCCESS';
export const UNBOOKMARK_FAIL = "UNBOOKMARKED_FAIL"; export const UNBOOKMARK_FAIL = 'UNBOOKMARKED_FAIL';
export function reblog(status, visibility) { export function reblog(status, visibility) {
return function (dispatch, getState) { return function (dispatch, getState) {
dispatch(reblogRequest(status)); dispatch(reblogRequest(status));
api(getState).post(`/api/v1/statuses/${status.get("id")}/reblog`, { visibility }).then(function (response) { api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`, { visibility }).then(function (response) {
// The reblog API method returns a new status wrapped around the original. In this case we are only // The reblog API method returns a new status wrapped around the original. In this case we are only
// interested in how the original is modified, hence passing it skipping the wrapper // interested in how the original is modified, hence passing it skipping the wrapper
dispatch(importFetchedStatus(response.data.reblog)); dispatch(importFetchedStatus(response.data.reblog));
@@ -70,7 +70,7 @@ export function unreblog(status) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(unreblogRequest(status)); dispatch(unreblogRequest(status));
api(getState).post(`/api/v1/statuses/${status.get("id")}/unreblog`).then(response => { api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => {
dispatch(importFetchedStatus(response.data)); dispatch(importFetchedStatus(response.data));
dispatch(unreblogSuccess(status)); dispatch(unreblogSuccess(status));
}).catch(error => { }).catch(error => {
@@ -127,7 +127,7 @@ export function favourite(status) {
return function (dispatch, getState) { return function (dispatch, getState) {
dispatch(favouriteRequest(status)); dispatch(favouriteRequest(status));
api(getState).post(`/api/v1/statuses/${status.get("id")}/favourite`).then(function (response) { api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) {
dispatch(importFetchedStatus(response.data)); dispatch(importFetchedStatus(response.data));
dispatch(favouriteSuccess(status)); dispatch(favouriteSuccess(status));
}).catch(function (error) { }).catch(function (error) {
@@ -140,7 +140,7 @@ export function unfavourite(status) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(unfavouriteRequest(status)); dispatch(unfavouriteRequest(status));
api(getState).post(`/api/v1/statuses/${status.get("id")}/unfavourite`).then(response => { api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => {
dispatch(importFetchedStatus(response.data)); dispatch(importFetchedStatus(response.data));
dispatch(unfavouriteSuccess(status)); dispatch(unfavouriteSuccess(status));
}).catch(error => { }).catch(error => {
@@ -197,7 +197,7 @@ export function bookmark(status) {
return function (dispatch, getState) { return function (dispatch, getState) {
dispatch(bookmarkRequest(status)); dispatch(bookmarkRequest(status));
api(getState).post(`/api/v1/statuses/${status.get("id")}/bookmark`).then(function (response) { api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then(function (response) {
dispatch(importFetchedStatus(response.data)); dispatch(importFetchedStatus(response.data));
dispatch(bookmarkSuccess(status)); dispatch(bookmarkSuccess(status));
}).catch(function (error) { }).catch(function (error) {
@@ -210,7 +210,7 @@ export function unbookmark(status) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(unbookmarkRequest(status)); dispatch(unbookmarkRequest(status));
api(getState).post(`/api/v1/statuses/${status.get("id")}/unbookmark`).then(response => { api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then(response => {
dispatch(importFetchedStatus(response.data)); dispatch(importFetchedStatus(response.data));
dispatch(unbookmarkSuccess(status)); dispatch(unbookmarkSuccess(status));
}).catch(error => { }).catch(error => {
@@ -268,7 +268,7 @@ export function fetchReblogs(id) {
dispatch(fetchReblogsRequest(id)); dispatch(fetchReblogsRequest(id));
api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => { api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchReblogsSuccess(id, response.data, next ? next.uri : null)); dispatch(fetchReblogsSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -304,7 +304,7 @@ export function fetchReblogsFail(id, error) {
export function expandReblogs(id) { export function expandReblogs(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["user_lists", "reblogged_by", id, "next"]); const url = getState().getIn(['user_lists', 'reblogged_by', id, 'next']);
if (url === null) { if (url === null) {
return; return;
} }
@@ -312,7 +312,7 @@ export function expandReblogs(id) {
dispatch(expandReblogsRequest(id)); dispatch(expandReblogsRequest(id));
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(expandReblogsSuccess(id, response.data, next ? next.uri : null)); dispatch(expandReblogsSuccess(id, response.data, next ? next.uri : null));
@@ -350,7 +350,7 @@ export function fetchFavourites(id) {
dispatch(fetchFavouritesRequest(id)); dispatch(fetchFavouritesRequest(id));
api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => { api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchFavouritesSuccess(id, response.data, next ? next.uri : null)); dispatch(fetchFavouritesSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -386,7 +386,7 @@ export function fetchFavouritesFail(id, error) {
export function expandFavourites(id) { export function expandFavourites(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["user_lists", "favourited_by", id, "next"]); const url = getState().getIn(['user_lists', 'favourited_by', id, 'next']);
if (url === null) { if (url === null) {
return; return;
} }
@@ -394,7 +394,7 @@ export function expandFavourites(id) {
dispatch(expandFavouritesRequest(id)); dispatch(expandFavouritesRequest(id));
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(expandFavouritesSuccess(id, response.data, next ? next.uri : null)); dispatch(expandFavouritesSuccess(id, response.data, next ? next.uri : null));
@@ -431,7 +431,7 @@ export function pin(status) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(pinRequest(status)); dispatch(pinRequest(status));
api(getState).post(`/api/v1/statuses/${status.get("id")}/pin`).then(response => { api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then(response => {
dispatch(importFetchedStatus(response.data)); dispatch(importFetchedStatus(response.data));
dispatch(pinSuccess(status)); dispatch(pinSuccess(status));
}).catch(error => { }).catch(error => {
@@ -466,7 +466,7 @@ export function unpin (status) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(unpinRequest(status)); dispatch(unpinRequest(status));
api(getState).post(`/api/v1/statuses/${status.get("id")}/unpin`).then(response => { api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then(response => {
dispatch(importFetchedStatus(response.data)); dispatch(importFetchedStatus(response.data));
dispatch(unpinSuccess(status)); dispatch(unpinSuccess(status));
}).catch(error => { }).catch(error => {
@@ -1,6 +1,6 @@
import { saveSettings } from "./settings"; import { saveSettings } from './settings';
export const LANGUAGE_USE = "LANGUAGE_USE"; export const LANGUAGE_USE = 'LANGUAGE_USE';
export const useLanguage = language => dispatch => { export const useLanguage = language => dispatch => {
dispatch({ dispatch({
+51 -51
View File
@@ -1,57 +1,57 @@
import api from "../api"; import api from '../api';
import { showAlertForError } from "./alerts"; import { showAlertForError } from './alerts';
import { importFetchedAccounts } from "./importer"; import { importFetchedAccounts } from './importer';
export const LIST_FETCH_REQUEST = "LIST_FETCH_REQUEST"; export const LIST_FETCH_REQUEST = 'LIST_FETCH_REQUEST';
export const LIST_FETCH_SUCCESS = "LIST_FETCH_SUCCESS"; export const LIST_FETCH_SUCCESS = 'LIST_FETCH_SUCCESS';
export const LIST_FETCH_FAIL = "LIST_FETCH_FAIL"; export const LIST_FETCH_FAIL = 'LIST_FETCH_FAIL';
export const LISTS_FETCH_REQUEST = "LISTS_FETCH_REQUEST"; export const LISTS_FETCH_REQUEST = 'LISTS_FETCH_REQUEST';
export const LISTS_FETCH_SUCCESS = "LISTS_FETCH_SUCCESS"; export const LISTS_FETCH_SUCCESS = 'LISTS_FETCH_SUCCESS';
export const LISTS_FETCH_FAIL = "LISTS_FETCH_FAIL"; export const LISTS_FETCH_FAIL = 'LISTS_FETCH_FAIL';
export const LIST_EDITOR_TITLE_CHANGE = "LIST_EDITOR_TITLE_CHANGE"; export const LIST_EDITOR_TITLE_CHANGE = 'LIST_EDITOR_TITLE_CHANGE';
export const LIST_EDITOR_RESET = "LIST_EDITOR_RESET"; export const LIST_EDITOR_RESET = 'LIST_EDITOR_RESET';
export const LIST_EDITOR_SETUP = "LIST_EDITOR_SETUP"; export const LIST_EDITOR_SETUP = 'LIST_EDITOR_SETUP';
export const LIST_CREATE_REQUEST = "LIST_CREATE_REQUEST"; export const LIST_CREATE_REQUEST = 'LIST_CREATE_REQUEST';
export const LIST_CREATE_SUCCESS = "LIST_CREATE_SUCCESS"; export const LIST_CREATE_SUCCESS = 'LIST_CREATE_SUCCESS';
export const LIST_CREATE_FAIL = "LIST_CREATE_FAIL"; export const LIST_CREATE_FAIL = 'LIST_CREATE_FAIL';
export const LIST_UPDATE_REQUEST = "LIST_UPDATE_REQUEST"; export const LIST_UPDATE_REQUEST = 'LIST_UPDATE_REQUEST';
export const LIST_UPDATE_SUCCESS = "LIST_UPDATE_SUCCESS"; export const LIST_UPDATE_SUCCESS = 'LIST_UPDATE_SUCCESS';
export const LIST_UPDATE_FAIL = "LIST_UPDATE_FAIL"; export const LIST_UPDATE_FAIL = 'LIST_UPDATE_FAIL';
export const LIST_DELETE_REQUEST = "LIST_DELETE_REQUEST"; export const LIST_DELETE_REQUEST = 'LIST_DELETE_REQUEST';
export const LIST_DELETE_SUCCESS = "LIST_DELETE_SUCCESS"; export const LIST_DELETE_SUCCESS = 'LIST_DELETE_SUCCESS';
export const LIST_DELETE_FAIL = "LIST_DELETE_FAIL"; export const LIST_DELETE_FAIL = 'LIST_DELETE_FAIL';
export const LIST_ACCOUNTS_FETCH_REQUEST = "LIST_ACCOUNTS_FETCH_REQUEST"; export const LIST_ACCOUNTS_FETCH_REQUEST = 'LIST_ACCOUNTS_FETCH_REQUEST';
export const LIST_ACCOUNTS_FETCH_SUCCESS = "LIST_ACCOUNTS_FETCH_SUCCESS"; export const LIST_ACCOUNTS_FETCH_SUCCESS = 'LIST_ACCOUNTS_FETCH_SUCCESS';
export const LIST_ACCOUNTS_FETCH_FAIL = "LIST_ACCOUNTS_FETCH_FAIL"; export const LIST_ACCOUNTS_FETCH_FAIL = 'LIST_ACCOUNTS_FETCH_FAIL';
export const LIST_EDITOR_SUGGESTIONS_CHANGE = "LIST_EDITOR_SUGGESTIONS_CHANGE"; export const LIST_EDITOR_SUGGESTIONS_CHANGE = 'LIST_EDITOR_SUGGESTIONS_CHANGE';
export const LIST_EDITOR_SUGGESTIONS_READY = "LIST_EDITOR_SUGGESTIONS_READY"; export const LIST_EDITOR_SUGGESTIONS_READY = 'LIST_EDITOR_SUGGESTIONS_READY';
export const LIST_EDITOR_SUGGESTIONS_CLEAR = "LIST_EDITOR_SUGGESTIONS_CLEAR"; export const LIST_EDITOR_SUGGESTIONS_CLEAR = 'LIST_EDITOR_SUGGESTIONS_CLEAR';
export const LIST_EDITOR_ADD_REQUEST = "LIST_EDITOR_ADD_REQUEST"; export const LIST_EDITOR_ADD_REQUEST = 'LIST_EDITOR_ADD_REQUEST';
export const LIST_EDITOR_ADD_SUCCESS = "LIST_EDITOR_ADD_SUCCESS"; export const LIST_EDITOR_ADD_SUCCESS = 'LIST_EDITOR_ADD_SUCCESS';
export const LIST_EDITOR_ADD_FAIL = "LIST_EDITOR_ADD_FAIL"; export const LIST_EDITOR_ADD_FAIL = 'LIST_EDITOR_ADD_FAIL';
export const LIST_EDITOR_REMOVE_REQUEST = "LIST_EDITOR_REMOVE_REQUEST"; export const LIST_EDITOR_REMOVE_REQUEST = 'LIST_EDITOR_REMOVE_REQUEST';
export const LIST_EDITOR_REMOVE_SUCCESS = "LIST_EDITOR_REMOVE_SUCCESS"; export const LIST_EDITOR_REMOVE_SUCCESS = 'LIST_EDITOR_REMOVE_SUCCESS';
export const LIST_EDITOR_REMOVE_FAIL = "LIST_EDITOR_REMOVE_FAIL"; export const LIST_EDITOR_REMOVE_FAIL = 'LIST_EDITOR_REMOVE_FAIL';
export const LIST_ADDER_RESET = "LIST_ADDER_RESET"; export const LIST_ADDER_RESET = 'LIST_ADDER_RESET';
export const LIST_ADDER_SETUP = "LIST_ADDER_SETUP"; export const LIST_ADDER_SETUP = 'LIST_ADDER_SETUP';
export const LIST_ADDER_LISTS_FETCH_REQUEST = "LIST_ADDER_LISTS_FETCH_REQUEST"; export const LIST_ADDER_LISTS_FETCH_REQUEST = 'LIST_ADDER_LISTS_FETCH_REQUEST';
export const LIST_ADDER_LISTS_FETCH_SUCCESS = "LIST_ADDER_LISTS_FETCH_SUCCESS"; export const LIST_ADDER_LISTS_FETCH_SUCCESS = 'LIST_ADDER_LISTS_FETCH_SUCCESS';
export const LIST_ADDER_LISTS_FETCH_FAIL = "LIST_ADDER_LISTS_FETCH_FAIL"; export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL';
export const fetchList = id => (dispatch, getState) => { export const fetchList = id => (dispatch, getState) => {
if (getState().getIn(["lists", id])) { if (getState().getIn(['lists', id])) {
return; return;
} }
@@ -81,7 +81,7 @@ export const fetchListFail = (id, error) => ({
export const fetchLists = () => (dispatch, getState) => { export const fetchLists = () => (dispatch, getState) => {
dispatch(fetchListsRequest()); dispatch(fetchListsRequest());
api(getState).get("/api/v1/lists") api(getState).get('/api/v1/lists')
.then(({ data }) => dispatch(fetchListsSuccess(data))) .then(({ data }) => dispatch(fetchListsSuccess(data)))
.catch(err => dispatch(fetchListsFail(err))); .catch(err => dispatch(fetchListsFail(err)));
}; };
@@ -101,8 +101,8 @@ export const fetchListsFail = error => ({
}); });
export const submitListEditor = shouldReset => (dispatch, getState) => { export const submitListEditor = shouldReset => (dispatch, getState) => {
const listId = getState().getIn(["listEditor", "listId"]); const listId = getState().getIn(['listEditor', 'listId']);
const title = getState().getIn(["listEditor", "title"]); const title = getState().getIn(['listEditor', 'title']);
if (listId === null) { if (listId === null) {
dispatch(createList(title, shouldReset)); dispatch(createList(title, shouldReset));
@@ -114,7 +114,7 @@ export const submitListEditor = shouldReset => (dispatch, getState) => {
export const setupListEditor = listId => (dispatch, getState) => { export const setupListEditor = listId => (dispatch, getState) => {
dispatch({ dispatch({
type: LIST_EDITOR_SETUP, type: LIST_EDITOR_SETUP,
list: getState().getIn(["lists", listId]), list: getState().getIn(['lists', listId]),
}); });
dispatch(fetchListAccounts(listId)); dispatch(fetchListAccounts(listId));
@@ -128,7 +128,7 @@ export const changeListEditorTitle = value => ({
export const createList = (title, shouldReset) => (dispatch, getState) => { export const createList = (title, shouldReset) => (dispatch, getState) => {
dispatch(createListRequest()); dispatch(createListRequest());
api(getState).post("/api/v1/lists", { title }).then(({ data }) => { api(getState).post('/api/v1/lists', { title }).then(({ data }) => {
dispatch(createListSuccess(data)); dispatch(createListSuccess(data));
if (shouldReset) { if (shouldReset) {
@@ -154,7 +154,7 @@ export const createListFail = error => ({
export const updateList = (id, title, shouldReset, isExclusive, replies_policy) => (dispatch, getState) => { export const updateList = (id, title, shouldReset, isExclusive, replies_policy) => (dispatch, getState) => {
dispatch(updateListRequest(id)); dispatch(updateListRequest(id));
api(getState).put(`/api/v1/lists/${id}`, { title, replies_policy, exclusive: typeof isExclusive === "undefined" ? undefined : !!isExclusive }).then(({ data }) => { api(getState).put(`/api/v1/lists/${id}`, { title, replies_policy, exclusive: typeof isExclusive === 'undefined' ? undefined : !!isExclusive }).then(({ data }) => {
dispatch(updateListSuccess(data)); dispatch(updateListSuccess(data));
if (shouldReset) { if (shouldReset) {
@@ -242,7 +242,7 @@ export const fetchListSuggestions = q => (dispatch, getState) => {
following: true, following: true,
}; };
api(getState).get("/api/v1/accounts/search", { params }).then(({ data }) => { api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
dispatch(importFetchedAccounts(data)); dispatch(importFetchedAccounts(data));
dispatch(fetchListSuggestionsReady(q, data)); dispatch(fetchListSuggestionsReady(q, data));
}).catch(error => dispatch(showAlertForError(error))); }).catch(error => dispatch(showAlertForError(error)));
@@ -264,7 +264,7 @@ export const changeListSuggestions = value => ({
}); });
export const addToListEditor = accountId => (dispatch, getState) => { export const addToListEditor = accountId => (dispatch, getState) => {
dispatch(addToList(getState().getIn(["listEditor", "listId"]), accountId)); dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId));
}; };
export const addToList = (listId, accountId) => (dispatch, getState) => { export const addToList = (listId, accountId) => (dispatch, getState) => {
@@ -295,7 +295,7 @@ export const addToListFail = (listId, accountId, error) => ({
}); });
export const removeFromListEditor = accountId => (dispatch, getState) => { export const removeFromListEditor = accountId => (dispatch, getState) => {
dispatch(removeFromList(getState().getIn(["listEditor", "listId"]), accountId)); dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId));
}; };
export const removeFromList = (listId, accountId) => (dispatch, getState) => { export const removeFromList = (listId, accountId) => (dispatch, getState) => {
@@ -332,7 +332,7 @@ export const resetListAdder = () => ({
export const setupListAdder = accountId => (dispatch, getState) => { export const setupListAdder = accountId => (dispatch, getState) => {
dispatch({ dispatch({
type: LIST_ADDER_SETUP, type: LIST_ADDER_SETUP,
account: getState().getIn(["accounts", accountId]), account: getState().getIn(['accounts', accountId]),
}); });
dispatch(fetchLists()); dispatch(fetchLists());
dispatch(fetchAccountLists(accountId)); dispatch(fetchAccountLists(accountId));
@@ -364,10 +364,10 @@ export const fetchAccountListsFail = (id, err) => ({
}); });
export const addToListAdder = listId => (dispatch, getState) => { export const addToListAdder = listId => (dispatch, getState) => {
dispatch(addToList(listId, getState().getIn(["listAdder", "accountId"]))); dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId'])));
}; };
export const removeFromListAdder = listId => (dispatch, getState) => { export const removeFromListAdder = listId => (dispatch, getState) => {
dispatch(removeFromList(listId, getState().getIn(["listAdder", "accountId"]))); dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])));
}; };
@@ -1,26 +1,26 @@
import { disableSwiping } from "flavours/glitch/initial_state"; import { disableSwiping } from 'flavours/glitch/initial_state';
import { openModal } from "./modal"; import { openModal } from './modal';
export const LOCAL_SETTING_CHANGE = "LOCAL_SETTING_CHANGE"; export const LOCAL_SETTING_CHANGE = 'LOCAL_SETTING_CHANGE';
export const LOCAL_SETTING_DELETE = "LOCAL_SETTING_DELETE"; export const LOCAL_SETTING_DELETE = 'LOCAL_SETTING_DELETE';
export function checkDeprecatedLocalSettings() { export function checkDeprecatedLocalSettings() {
return (dispatch, getState) => { return (dispatch, getState) => {
const local_swipe_to_change_columns = getState().getIn(["local_settings", "swipe_to_change_columns"]); const local_swipe_to_change_columns = getState().getIn(['local_settings', 'swipe_to_change_columns']);
let changed_settings = []; let changed_settings = [];
if (local_swipe_to_change_columns !== null && local_swipe_to_change_columns !== undefined) { if (local_swipe_to_change_columns !== null && local_swipe_to_change_columns !== undefined) {
if (local_swipe_to_change_columns === !disableSwiping) { if (local_swipe_to_change_columns === !disableSwiping) {
dispatch(deleteLocalSetting(["swipe_to_change_columns"])); dispatch(deleteLocalSetting(['swipe_to_change_columns']));
} else { } else {
changed_settings.push("user_setting_disable_swiping"); changed_settings.push('user_setting_disable_swiping');
} }
} }
if (changed_settings.length > 0) { if (changed_settings.length > 0) {
dispatch(openModal({ dispatch(openModal({
modalType: "DEPRECATED_SETTINGS", modalType: 'DEPRECATED_SETTINGS',
modalProps: { modalProps: {
settings: changed_settings, settings: changed_settings,
onConfirm: () => dispatch(clearDeprecatedLocalSettings()), onConfirm: () => dispatch(clearDeprecatedLocalSettings()),
@@ -32,8 +32,8 @@ export function checkDeprecatedLocalSettings() {
export function clearDeprecatedLocalSettings() { export function clearDeprecatedLocalSettings() {
return (dispatch) => { return (dispatch) => {
dispatch(deleteLocalSetting(["content_warnings", "auto_unfold"])); dispatch(deleteLocalSetting(['content_warnings', 'auto_unfold']));
dispatch(deleteLocalSetting(["swipe_to_change_columns"])); dispatch(deleteLocalSetting(['swipe_to_change_columns']));
}; };
} }
@@ -66,7 +66,7 @@ export function deleteLocalSetting(key) {
// their *own* local settings. // their *own* local settings.
export function saveLocalSettings() { export function saveLocalSettings() {
return (_, getState) => { return (_, getState) => {
const localSettings = getState().get("local_settings").toJS(); const localSettings = getState().get('local_settings').toJS();
localStorage.setItem("mastodon-settings", JSON.stringify(localSettings)); localStorage.setItem('mastodon-settings', JSON.stringify(localSettings));
}; };
} }
@@ -1,33 +1,33 @@
import { List as ImmutableList } from "immutable"; import { List as ImmutableList } from 'immutable';
import { debounce } from "lodash"; import { debounce } from 'lodash';
import api from "../api"; import api from '../api';
import { compareId } from "../compare_id"; import { compareId } from '../compare_id';
export const MARKERS_FETCH_REQUEST = "MARKERS_FETCH_REQUEST"; export const MARKERS_FETCH_REQUEST = 'MARKERS_FETCH_REQUEST';
export const MARKERS_FETCH_SUCCESS = "MARKERS_FETCH_SUCCESS"; export const MARKERS_FETCH_SUCCESS = 'MARKERS_FETCH_SUCCESS';
export const MARKERS_FETCH_FAIL = "MARKERS_FETCH_FAIL"; export const MARKERS_FETCH_FAIL = 'MARKERS_FETCH_FAIL';
export const MARKERS_SUBMIT_SUCCESS = "MARKERS_SUBMIT_SUCCESS"; export const MARKERS_SUBMIT_SUCCESS = 'MARKERS_SUBMIT_SUCCESS';
export const synchronouslySubmitMarkers = () => (dispatch, getState) => { export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
const accessToken = getState().getIn(["meta", "access_token"], ""); const accessToken = getState().getIn(['meta', 'access_token'], '');
const params = _buildParams(getState()); const params = _buildParams(getState());
if (Object.keys(params).length === 0 || accessToken === "") { if (Object.keys(params).length === 0 || accessToken === '') {
return; return;
} }
// The Fetch API allows us to perform requests that will be carried out // The Fetch API allows us to perform requests that will be carried out
// after the page closes. But that only works if the `keepalive` attribute // after the page closes. But that only works if the `keepalive` attribute
// is supported. // is supported.
if (window.fetch && "keepalive" in new Request("")) { if (window.fetch && 'keepalive' in new Request('')) {
fetch("/api/v1/markers", { fetch('/api/v1/markers', {
keepalive: true, keepalive: true,
method: "POST", method: 'POST',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
"Authorization": `Bearer ${accessToken}`, 'Authorization': `Bearer ${accessToken}`,
}, },
body: JSON.stringify(params), body: JSON.stringify(params),
}); });
@@ -38,13 +38,13 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
// FormData for DoorKeeper to recognize the token. // FormData for DoorKeeper to recognize the token.
const formData = new FormData(); const formData = new FormData();
formData.append("bearer_token", accessToken); formData.append('bearer_token', accessToken);
for (const [id, value] of Object.entries(params)) { for (const [id, value] of Object.entries(params)) {
formData.append(`${id}[last_read_id]`, value.last_read_id); formData.append(`${id}[last_read_id]`, value.last_read_id);
} }
if (navigator.sendBeacon("/api/v1/markers", formData)) { if (navigator.sendBeacon('/api/v1/markers', formData)) {
return; return;
} }
} }
@@ -54,9 +54,9 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
try { try {
const client = new XMLHttpRequest(); const client = new XMLHttpRequest();
client.open("POST", "/api/v1/markers", false); client.open('POST', '/api/v1/markers', false);
client.setRequestHeader("Content-Type", "application/json"); client.setRequestHeader('Content-Type', 'application/json');
client.setRequestHeader("Authorization", `Bearer ${accessToken}`); client.setRequestHeader('Authorization', `Bearer ${accessToken}`);
client.send(JSON.stringify(params)); client.send(JSON.stringify(params));
} catch (e) { } catch (e) {
// Do not make the BeforeUnload handler error out // Do not make the BeforeUnload handler error out
@@ -66,16 +66,16 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
const _buildParams = (state) => { const _buildParams = (state) => {
const params = {}; const params = {};
const lastHomeId = state.getIn(["timelines", "home", "items"], ImmutableList()).find(item => item !== null); const lastHomeId = state.getIn(['timelines', 'home', 'items'], ImmutableList()).find(item => item !== null);
const lastNotificationId = state.getIn(["notifications", "lastReadId"]); const lastNotificationId = state.getIn(['notifications', 'lastReadId']);
if (lastHomeId && compareId(lastHomeId, state.getIn(["markers", "home"])) > 0) { if (lastHomeId && compareId(lastHomeId, state.getIn(['markers', 'home'])) > 0) {
params.home = { params.home = {
last_read_id: lastHomeId, last_read_id: lastHomeId,
}; };
} }
if (lastNotificationId && lastNotificationId !== "0" && compareId(lastNotificationId, state.getIn(["markers", "notifications"])) > 0) { if (lastNotificationId && lastNotificationId !== '0' && compareId(lastNotificationId, state.getIn(['markers', 'notifications'])) > 0) {
params.notifications = { params.notifications = {
last_read_id: lastNotificationId, last_read_id: lastNotificationId,
}; };
@@ -85,14 +85,14 @@ const _buildParams = (state) => {
}; };
const debouncedSubmitMarkers = debounce((dispatch, getState) => { const debouncedSubmitMarkers = debounce((dispatch, getState) => {
const accessToken = getState().getIn(["meta", "access_token"], ""); const accessToken = getState().getIn(['meta', 'access_token'], '');
const params = _buildParams(getState()); const params = _buildParams(getState());
if (Object.keys(params).length === 0 || accessToken === "") { if (Object.keys(params).length === 0 || accessToken === '') {
return; return;
} }
api(getState).post("/api/v1/markers", params).then(() => { api(getState).post('/api/v1/markers', params).then(() => {
dispatch(submitMarkersSuccess(params)); dispatch(submitMarkersSuccess(params));
}).catch(() => {}); }).catch(() => {});
}, 300000, { leading: true, trailing: true }); }, 300000, { leading: true, trailing: true });
@@ -116,11 +116,11 @@ export function submitMarkers(params = {}) {
} }
export const fetchMarkers = () => (dispatch, getState) => { export const fetchMarkers = () => (dispatch, getState) => {
const params = { timeline: ["notifications"] }; const params = { timeline: ['notifications'] };
dispatch(fetchMarkersRequest()); dispatch(fetchMarkersRequest());
api(getState).get("/api/v1/markers", { params }).then(response => { api(getState).get('/api/v1/markers', { params }).then(response => {
dispatch(fetchMarkersSuccess(response.data)); dispatch(fetchMarkersSuccess(response.data));
}).catch(error => { }).catch(error => {
dispatch(fetchMarkersFail(error)); dispatch(fetchMarkersFail(error));
@@ -1,19 +1,19 @@
import { createAction } from "@reduxjs/toolkit"; import { createAction } from '@reduxjs/toolkit';
import { type ModalProps } from "flavours/glitch/reducers/modal"; import type { ModalProps } from 'flavours/glitch/reducers/modal';
import { type MODAL_COMPONENTS } from "../features/ui/components/modal_root"; import type { MODAL_COMPONENTS } from '../features/ui/components/modal_root';
export type ModalType = keyof typeof MODAL_COMPONENTS; export type ModalType = keyof typeof MODAL_COMPONENTS;
interface OpenModalPayload { interface OpenModalPayload {
modalType: ModalType, modalType: ModalType;
modalProps: ModalProps, modalProps: ModalProps;
} }
export const openModal = createAction<OpenModalPayload>("MODAL_OPEN"); export const openModal = createAction<OpenModalPayload>('MODAL_OPEN');
interface CloseModalPayload { interface CloseModalPayload {
modalType: ModalType | undefined, modalType: ModalType | undefined;
ignoreFocus: boolean, ignoreFocus: boolean;
} }
export const closeModal = createAction<CloseModalPayload>("MODAL_CLOSE"); export const closeModal = createAction<CloseModalPayload>('MODAL_CLOSE');
+18 -18
View File
@@ -1,28 +1,28 @@
import { openModal } from "flavours/glitch/actions/modal"; import { openModal } from 'flavours/glitch/actions/modal';
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { fetchRelationships } from "./accounts"; import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from "./importer"; import { importFetchedAccounts } from './importer';
export const MUTES_FETCH_REQUEST = "MUTES_FETCH_REQUEST"; export const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST';
export const MUTES_FETCH_SUCCESS = "MUTES_FETCH_SUCCESS"; export const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS';
export const MUTES_FETCH_FAIL = "MUTES_FETCH_FAIL"; export const MUTES_FETCH_FAIL = 'MUTES_FETCH_FAIL';
export const MUTES_EXPAND_REQUEST = "MUTES_EXPAND_REQUEST"; export const MUTES_EXPAND_REQUEST = 'MUTES_EXPAND_REQUEST';
export const MUTES_EXPAND_SUCCESS = "MUTES_EXPAND_SUCCESS"; export const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS';
export const MUTES_EXPAND_FAIL = "MUTES_EXPAND_FAIL"; export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL';
export const MUTES_INIT_MODAL = "MUTES_INIT_MODAL"; export const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL';
export const MUTES_TOGGLE_HIDE_NOTIFICATIONS = "MUTES_TOGGLE_HIDE_NOTIFICATIONS"; export const MUTES_TOGGLE_HIDE_NOTIFICATIONS = 'MUTES_TOGGLE_HIDE_NOTIFICATIONS';
export const MUTES_CHANGE_DURATION = "MUTES_CHANGE_DURATION"; export const MUTES_CHANGE_DURATION = 'MUTES_CHANGE_DURATION';
export function fetchMutes() { export function fetchMutes() {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchMutesRequest()); dispatch(fetchMutesRequest());
api(getState).get("/api/v1/mutes").then(response => { api(getState).get('/api/v1/mutes').then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchMutesSuccess(response.data, next ? next.uri : null)); dispatch(fetchMutesSuccess(response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -53,7 +53,7 @@ export function fetchMutesFail(error) {
export function expandMutes() { export function expandMutes() {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["user_lists", "mutes", "next"]); const url = getState().getIn(['user_lists', 'mutes', 'next']);
if (url === null) { if (url === null) {
return; return;
@@ -62,7 +62,7 @@ export function expandMutes() {
dispatch(expandMutesRequest()); dispatch(expandMutesRequest());
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(expandMutesSuccess(response.data, next ? next.uri : null)); dispatch(expandMutesSuccess(response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id))); dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -98,7 +98,7 @@ export function initMuteModal(account) {
account, account,
}); });
dispatch(openModal({ modalType: "MUTE" })); dispatch(openModal({ modalType: 'MUTE' }));
}; };
} }
@@ -1,69 +1,69 @@
import { IntlMessageFormat } from "intl-messageformat"; import { IntlMessageFormat } from 'intl-messageformat';
import { defineMessages } from "react-intl"; import { defineMessages } from 'react-intl';
import { List as ImmutableList } from "immutable"; import { List as ImmutableList } from 'immutable';
import { compareId } from "flavours/glitch/compare_id"; import { compareId } from 'flavours/glitch/compare_id';
import { usePendingItems as preferPendingItems } from "flavours/glitch/initial_state"; import { usePendingItems as preferPendingItems } from 'flavours/glitch/initial_state';
import { unescapeHTML } from "flavours/glitch/utils/html"; import { unescapeHTML } from 'flavours/glitch/utils/html';
import { requestNotificationPermission } from "flavours/glitch/utils/notifications"; import { requestNotificationPermission } from 'flavours/glitch/utils/notifications';
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { fetchFollowRequests, fetchRelationships } from "./accounts"; import { fetchFollowRequests, fetchRelationships } from './accounts';
import { import {
importFetchedAccount, importFetchedAccount,
importFetchedAccounts, importFetchedAccounts,
importFetchedStatus, importFetchedStatus,
importFetchedStatuses, importFetchedStatuses,
} from "./importer"; } from './importer';
import { submitMarkers } from "./markers"; import { submitMarkers } from './markers';
import { register as registerPushNotifications } from "./push_notifications"; import { register as registerPushNotifications } from './push_notifications';
import { saveSettings } from "./settings"; import { saveSettings } from './settings';
export const NOTIFICATIONS_UPDATE = "NOTIFICATIONS_UPDATE"; export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
export const NOTIFICATIONS_UPDATE_NOOP = "NOTIFICATIONS_UPDATE_NOOP"; export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP';
// tracking the notif cleaning request // tracking the notif cleaning request
export const NOTIFICATIONS_DELETE_MARKED_REQUEST = "NOTIFICATIONS_DELETE_MARKED_REQUEST"; export const NOTIFICATIONS_DELETE_MARKED_REQUEST = 'NOTIFICATIONS_DELETE_MARKED_REQUEST';
export const NOTIFICATIONS_DELETE_MARKED_SUCCESS = "NOTIFICATIONS_DELETE_MARKED_SUCCESS"; export const NOTIFICATIONS_DELETE_MARKED_SUCCESS = 'NOTIFICATIONS_DELETE_MARKED_SUCCESS';
export const NOTIFICATIONS_DELETE_MARKED_FAIL = "NOTIFICATIONS_DELETE_MARKED_FAIL"; export const NOTIFICATIONS_DELETE_MARKED_FAIL = 'NOTIFICATIONS_DELETE_MARKED_FAIL';
export const NOTIFICATIONS_MARK_ALL_FOR_DELETE = "NOTIFICATIONS_MARK_ALL_FOR_DELETE"; export const NOTIFICATIONS_MARK_ALL_FOR_DELETE = 'NOTIFICATIONS_MARK_ALL_FOR_DELETE';
export const NOTIFICATIONS_ENTER_CLEARING_MODE = "NOTIFICATIONS_ENTER_CLEARING_MODE"; // arg: yes export const NOTIFICATIONS_ENTER_CLEARING_MODE = 'NOTIFICATIONS_ENTER_CLEARING_MODE'; // arg: yes
// Unmark notifications (when the cleaning mode is left) // Unmark notifications (when the cleaning mode is left)
export const NOTIFICATIONS_UNMARK_ALL_FOR_DELETE = "NOTIFICATIONS_UNMARK_ALL_FOR_DELETE"; export const NOTIFICATIONS_UNMARK_ALL_FOR_DELETE = 'NOTIFICATIONS_UNMARK_ALL_FOR_DELETE';
// Mark one for delete // Mark one for delete
export const NOTIFICATION_MARK_FOR_DELETE = "NOTIFICATION_MARK_FOR_DELETE"; export const NOTIFICATION_MARK_FOR_DELETE = 'NOTIFICATION_MARK_FOR_DELETE';
export const NOTIFICATIONS_EXPAND_REQUEST = "NOTIFICATIONS_EXPAND_REQUEST"; export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST';
export const NOTIFICATIONS_EXPAND_SUCCESS = "NOTIFICATIONS_EXPAND_SUCCESS"; export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS';
export const NOTIFICATIONS_EXPAND_FAIL = "NOTIFICATIONS_EXPAND_FAIL"; export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
export const NOTIFICATIONS_FILTER_SET = "NOTIFICATIONS_FILTER_SET"; export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET';
export const NOTIFICATIONS_CLEAR = "NOTIFICATIONS_CLEAR"; export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
export const NOTIFICATIONS_SCROLL_TOP = "NOTIFICATIONS_SCROLL_TOP"; export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
export const NOTIFICATIONS_LOAD_PENDING = "NOTIFICATIONS_LOAD_PENDING"; export const NOTIFICATIONS_LOAD_PENDING = 'NOTIFICATIONS_LOAD_PENDING';
export const NOTIFICATIONS_MOUNT = "NOTIFICATIONS_MOUNT"; export const NOTIFICATIONS_MOUNT = 'NOTIFICATIONS_MOUNT';
export const NOTIFICATIONS_UNMOUNT = "NOTIFICATIONS_UNMOUNT"; export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT';
export const NOTIFICATIONS_SET_VISIBILITY = "NOTIFICATIONS_SET_VISIBILITY"; export const NOTIFICATIONS_SET_VISIBILITY = 'NOTIFICATIONS_SET_VISIBILITY';
export const NOTIFICATIONS_MARK_AS_READ = "NOTIFICATIONS_MARK_AS_READ"; export const NOTIFICATIONS_MARK_AS_READ = 'NOTIFICATIONS_MARK_AS_READ';
export const NOTIFICATIONS_SET_BROWSER_SUPPORT = "NOTIFICATIONS_SET_BROWSER_SUPPORT"; export const NOTIFICATIONS_SET_BROWSER_SUPPORT = 'NOTIFICATIONS_SET_BROWSER_SUPPORT';
export const NOTIFICATIONS_SET_BROWSER_PERMISSION = "NOTIFICATIONS_SET_BROWSER_PERMISSION"; export const NOTIFICATIONS_SET_BROWSER_PERMISSION = 'NOTIFICATIONS_SET_BROWSER_PERMISSION';
defineMessages({ defineMessages({
mention: { id: "notification.mention", defaultMessage: "{name} mentioned you" }, mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
}); });
const fetchRelatedRelationships = (dispatch, notifications) => { const fetchRelatedRelationships = (dispatch, notifications) => {
const accountIds = notifications.filter(item => ["follow", "follow_request", "admin.sign_up"].indexOf(item.type) !== -1).map(item => item.account.id); const accountIds = notifications.filter(item => ['follow', 'follow_request', 'admin.sign_up'].indexOf(item.type) !== -1).map(item => item.account.id);
if (accountIds > 0) { if (accountIds > 0) {
dispatch(fetchRelationships(accountIds)); dispatch(fetchRelationships(accountIds));
@@ -76,24 +76,24 @@ export const loadPending = () => ({
export function updateNotifications(notification, intlMessages, intlLocale) { export function updateNotifications(notification, intlMessages, intlLocale) {
return (dispatch, getState) => { return (dispatch, getState) => {
const activeFilter = getState().getIn(["settings", "notifications", "quickFilter", "active"]); const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
const showInColumn = activeFilter === "all" ? getState().getIn(["settings", "notifications", "shows", notification.type], true) : activeFilter === notification.type; const showInColumn = activeFilter === 'all' ? getState().getIn(['settings', 'notifications', 'shows', notification.type], true) : activeFilter === notification.type;
const showAlert = getState().getIn(["settings", "notifications", "alerts", notification.type], true); const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true);
const playSound = getState().getIn(["settings", "notifications", "sounds", notification.type], true); const playSound = getState().getIn(['settings', 'notifications', 'sounds', notification.type], true);
let filtered = false; let filtered = false;
if (["mention", "status"].includes(notification.type) && notification.status.filtered) { if (['mention', 'status'].includes(notification.type) && notification.status.filtered) {
const filters = notification.status.filtered.filter(result => result.filter.context.includes("notifications")); const filters = notification.status.filtered.filter(result => result.filter.context.includes('notifications'));
if (filters.some(result => result.filter.filter_action === "hide")) { if (filters.some(result => result.filter.filter_action === 'hide')) {
return; return;
} }
filtered = filters.length > 0; filtered = filters.length > 0;
} }
if (["follow_request"].includes(notification.type)) { if (['follow_request'].includes(notification.type)) {
dispatch(fetchFollowRequests()); dispatch(fetchFollowRequests());
} }
@@ -114,24 +114,24 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
type: NOTIFICATIONS_UPDATE, type: NOTIFICATIONS_UPDATE,
notification, notification,
usePendingItems: preferPendingItems, usePendingItems: preferPendingItems,
meta: (playSound && !filtered) ? { sound: "boop" } : undefined, meta: (playSound && !filtered) ? { sound: 'boop' } : undefined,
}); });
fetchRelatedRelationships(dispatch, [notification]); fetchRelatedRelationships(dispatch, [notification]);
} else if (playSound && !filtered) { } else if (playSound && !filtered) {
dispatch({ dispatch({
type: NOTIFICATIONS_UPDATE_NOOP, type: NOTIFICATIONS_UPDATE_NOOP,
meta: { sound: "boop" }, meta: { sound: 'boop' },
}); });
} }
// Desktop notifications // Desktop notifications
if (typeof window.Notification !== "undefined" && showAlert && !filtered) { if (typeof window.Notification !== 'undefined' && showAlert && !filtered) {
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 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 : unescapeHTML(notification.status ? notification.status.content : '');
const notify = new Notification(title, { body, icon: notification.account.avatar, tag: notification.id }); const notify = new Notification(title, { body, icon: notification.account.avatar, tag: notification.id });
notify.addEventListener("click", () => { notify.addEventListener('click', () => {
window.focus(); window.focus();
notify.close(); notify.close();
}); });
@@ -139,21 +139,21 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
}; };
} }
const excludeTypesFromSettings = state => state.getIn(["settings", "notifications", "shows"]).filter(enabled => !enabled).keySeq().toJS(); const excludeTypesFromSettings = state => state.getIn(['settings', 'notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS();
const excludeTypesFromFilter = filter => { const excludeTypesFromFilter = filter => {
const allTypes = ImmutableList([ const allTypes = ImmutableList([
"follow", 'follow',
"follow_request", 'follow_request',
"favourite", 'favourite',
"reblog", 'reblog',
"mention", 'mention',
"poll", 'poll',
"status", 'status',
"update", 'update',
"admin.sign_up", 'admin.sign_up',
"admin.report", 'admin.report',
]); ]);
return allTypes.filterNot(item => item === filter).toJS(); return allTypes.filterNot(item => item === filter).toJS();
@@ -165,11 +165,11 @@ let expandNotificationsController = new AbortController();
export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) { export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
return (dispatch, getState) => { return (dispatch, getState) => {
const activeFilter = getState().getIn(["settings", "notifications", "quickFilter", "active"]); const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
const notifications = getState().get("notifications"); const notifications = getState().get('notifications');
const isLoadingMore = !!maxId; const isLoadingMore = !!maxId;
if (notifications.get("isLoading")) { if (notifications.get('isLoading')) {
if (forceLoad) { if (forceLoad) {
expandNotificationsController.abort(); expandNotificationsController.abort();
expandNotificationsController = new AbortController(); expandNotificationsController = new AbortController();
@@ -181,14 +181,14 @@ export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
const params = { const params = {
max_id: maxId, max_id: maxId,
exclude_types: activeFilter === "all" exclude_types: activeFilter === 'all'
? excludeTypesFromSettings(getState()) ? excludeTypesFromSettings(getState())
: excludeTypesFromFilter(activeFilter), : excludeTypesFromFilter(activeFilter),
}; };
if (!params.max_id && (notifications.get("items", ImmutableList()).size + notifications.get("pendingItems", ImmutableList()).size) > 0) { if (!params.max_id && (notifications.get('items', ImmutableList()).size + notifications.get('pendingItems', ImmutableList()).size) > 0) {
const a = notifications.getIn(["pendingItems", 0, "id"]); const a = notifications.getIn(['pendingItems', 0, 'id']);
const b = notifications.getIn(["items", 0, "id"]); const b = notifications.getIn(['items', 0, 'id']);
if (a && b && compareId(a, b) > 0) { if (a && b && compareId(a, b) > 0) {
params.since_id = a; params.since_id = a;
@@ -201,8 +201,8 @@ export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
dispatch(expandNotificationsRequest(isLoadingMore)); dispatch(expandNotificationsRequest(isLoadingMore));
api(getState).get("/api/v1/notifications", { params, signal: expandNotificationsController.signal }).then(response => { api(getState).get('/api/v1/notifications', { params, signal: expandNotificationsController.signal }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.map(item => item.account))); dispatch(importFetchedAccounts(response.data.map(item => item.account)));
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status))); dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
@@ -242,7 +242,7 @@ export function expandNotificationsFail(error, isLoadingMore) {
type: NOTIFICATIONS_EXPAND_FAIL, type: NOTIFICATIONS_EXPAND_FAIL,
error, error,
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
skipAlert: !isLoadingMore || error.name === "AbortError", skipAlert: !isLoadingMore || error.name === 'AbortError',
}; };
} }
@@ -252,7 +252,7 @@ export function clearNotifications() {
type: NOTIFICATIONS_CLEAR, type: NOTIFICATIONS_CLEAR,
}); });
api(getState).post("/api/v1/notifications/clear"); api(getState).post('/api/v1/notifications/clear');
}; };
} }
@@ -268,9 +268,9 @@ export function deleteMarkedNotifications() {
dispatch(deleteMarkedNotificationsRequest()); dispatch(deleteMarkedNotificationsRequest());
let ids = []; let ids = [];
getState().getIn(["notifications", "items"]).forEach((n) => { getState().getIn(['notifications', 'items']).forEach((n) => {
if (n.get("markedForDelete")) { if (n.get('markedForDelete')) {
ids.push(n.get("id")); ids.push(n.get('id'));
} }
}); });
@@ -278,7 +278,7 @@ export function deleteMarkedNotifications() {
return; return;
} }
api(getState).delete(`/api/v1/notifications/destroy_multiple?ids[]=${ids.join("&ids[]=")}`).then(() => { api(getState).delete(`/api/v1/notifications/destroy_multiple?ids[]=${ids.join('&ids[]=')}`).then(() => {
dispatch(deleteMarkedNotificationsSuccess()); dispatch(deleteMarkedNotificationsSuccess());
}).catch(error => { }).catch(error => {
console.error(error); console.error(error);
@@ -350,7 +350,7 @@ export function setFilter (filterType) {
return dispatch => { return dispatch => {
dispatch({ dispatch({
type: NOTIFICATIONS_FILTER_SET, type: NOTIFICATIONS_FILTER_SET,
path: ["notifications", "quickFilter", "active"], path: ['notifications', 'quickFilter', 'active'],
value: filterType, value: filterType,
}); });
dispatch(expandNotifications({ forceLoad: true })); dispatch(expandNotifications({ forceLoad: true }));
@@ -367,13 +367,13 @@ export function markNotificationsAsRead() {
// Browser support // Browser support
export function setupBrowserNotifications() { export function setupBrowserNotifications() {
return dispatch => { return dispatch => {
dispatch(setBrowserSupport("Notification" in window)); dispatch(setBrowserSupport('Notification' in window));
if ("Notification" in window) { if ('Notification' in window) {
dispatch(setBrowserPermission(Notification.permission)); dispatch(setBrowserPermission(Notification.permission));
} }
if ("Notification" in window && "permissions" in navigator) { if ('Notification' in window && 'permissions' in navigator) {
navigator.permissions.query({ name: "notifications" }).then((status) => { navigator.permissions.query({ name: 'notifications' }).then((status) => {
status.onchange = () => dispatch(setBrowserPermission(Notification.permission)); status.onchange = () => dispatch(setBrowserPermission(Notification.permission));
}).catch(console.warn); }).catch(console.warn);
} }
@@ -386,7 +386,7 @@ export function requestBrowserPermission(callback = noOp) {
dispatch(setBrowserPermission(permission)); dispatch(setBrowserPermission(permission));
callback(permission); callback(permission);
if (permission === "granted") { if (permission === 'granted') {
dispatch(registerPushNotifications()); dispatch(registerPushNotifications());
} }
}); });
@@ -1,15 +1,15 @@
import { openModal } from "./modal"; import { openModal } from './modal';
import { changeSetting, saveSettings } from "./settings"; import { changeSetting, saveSettings } from './settings';
export function showOnboardingOnce() { export function showOnboardingOnce() {
return (dispatch, getState) => { return (dispatch, getState) => {
const alreadySeen = getState().getIn(["settings", "onboarded"]); const alreadySeen = getState().getIn(['settings', 'onboarded']);
if (!alreadySeen) { if (!alreadySeen) {
dispatch(openModal({ dispatch(openModal({
modalType: "ONBOARDING", modalType: 'ONBOARDING',
})); }));
dispatch(changeSetting(["onboarded"], true)); dispatch(changeSetting(['onboarded'], true));
dispatch(saveSettings()); dispatch(saveSettings());
} }
}; };
@@ -1,7 +1,7 @@
// @ts-check // @ts-check
export const PICTURE_IN_PICTURE_DEPLOY = "PICTURE_IN_PICTURE_DEPLOY"; export const PICTURE_IN_PICTURE_DEPLOY = 'PICTURE_IN_PICTURE_DEPLOY';
export const PICTURE_IN_PICTURE_REMOVE = "PICTURE_IN_PICTURE_REMOVE"; export const PICTURE_IN_PICTURE_REMOVE = 'PICTURE_IN_PICTURE_REMOVE';
/** /**
* @typedef MediaProps * @typedef MediaProps
@@ -26,7 +26,7 @@ export const deployPictureInPicture = (statusId, accountId, playerType, props) =
// @ts-expect-error // @ts-expect-error
return (dispatch, getState) => { return (dispatch, getState) => {
// Do not open a player for a toot that does not exist // Do not open a player for a toot that does not exist
if (getState().hasIn(["statuses", statusId])) { if (getState().hasIn(['statuses', statusId])) {
dispatch({ dispatch({
type: PICTURE_IN_PICTURE_DEPLOY, type: PICTURE_IN_PICTURE_DEPLOY,
statusId, statusId,
@@ -1,13 +1,13 @@
import { me } from "flavours/glitch/initial_state"; import { me } from 'flavours/glitch/initial_state';
import api from "../api"; import api from '../api';
import { importFetchedStatuses } from "./importer"; import { importFetchedStatuses } from './importer';
export const PINNED_STATUSES_FETCH_REQUEST = "PINNED_STATUSES_FETCH_REQUEST"; export const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST';
export const PINNED_STATUSES_FETCH_SUCCESS = "PINNED_STATUSES_FETCH_SUCCESS"; export const PINNED_STATUSES_FETCH_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS';
export const PINNED_STATUSES_FETCH_FAIL = "PINNED_STATUSES_FETCH_FAIL"; export const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL';
export function fetchPinnedStatuses() { export function fetchPinnedStatuses() {
return (dispatch, getState) => { return (dispatch, getState) => {
@@ -1,14 +1,14 @@
import api from "../api"; import api from '../api';
import { importFetchedPoll } from "./importer"; import { importFetchedPoll } from './importer';
export const POLL_VOTE_REQUEST = "POLL_VOTE_REQUEST"; export const POLL_VOTE_REQUEST = 'POLL_VOTE_REQUEST';
export const POLL_VOTE_SUCCESS = "POLL_VOTE_SUCCESS"; export const POLL_VOTE_SUCCESS = 'POLL_VOTE_SUCCESS';
export const POLL_VOTE_FAIL = "POLL_VOTE_FAIL"; export const POLL_VOTE_FAIL = 'POLL_VOTE_FAIL';
export const POLL_FETCH_REQUEST = "POLL_FETCH_REQUEST"; export const POLL_FETCH_REQUEST = 'POLL_FETCH_REQUEST';
export const POLL_FETCH_SUCCESS = "POLL_FETCH_SUCCESS"; export const POLL_FETCH_SUCCESS = 'POLL_FETCH_SUCCESS';
export const POLL_FETCH_FAIL = "POLL_FETCH_FAIL"; export const POLL_FETCH_FAIL = 'POLL_FETCH_FAIL';
export const vote = (pollId, choices) => (dispatch, getState) => { export const vote = (pollId, choices) => (dispatch, getState) => {
dispatch(voteRequest()); dispatch(voteRequest());
@@ -1,5 +1,5 @@
import { saveSettings } from "./registerer"; import { saveSettings } from './registerer';
import { setAlerts } from "./setter"; import { setAlerts } from './setter';
export function changeAlerts(path, value) { export function changeAlerts(path, value) {
return dispatch => { return dispatch => {
@@ -13,5 +13,5 @@ export {
SET_BROWSER_SUPPORT, SET_BROWSER_SUPPORT,
SET_SUBSCRIPTION, SET_SUBSCRIPTION,
SET_ALERTS, SET_ALERTS,
} from "./setter"; } from './setter';
export { register } from "./registerer"; export { register } from './registerer';
@@ -1,14 +1,14 @@
import api from "../../api"; import api from '../../api';
import { pushNotificationsSetting } from "../../settings"; import { pushNotificationsSetting } from '../../settings';
import { setBrowserSupport, setSubscription, clearSubscription } from "./setter"; import { setBrowserSupport, setSubscription, clearSubscription } from './setter';
// Taken from https://www.npmjs.com/package/web-push // Taken from https://www.npmjs.com/package/web-push
const urlBase64ToUint8Array = (base64String) => { const urlBase64ToUint8Array = (base64String) => {
const padding = "=".repeat((4 - base64String.length % 4) % 4); const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding) const base64 = (base64String + padding)
.replace(/-/g, "+") .replace(/-/g, '+')
.replace(/_/g, "/"); .replace(/_/g, '/');
const rawData = window.atob(base64); const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length); const outputArray = new Uint8Array(rawData.length);
@@ -19,7 +19,7 @@ const urlBase64ToUint8Array = (base64String) => {
return outputArray; return outputArray;
}; };
const getApplicationServerKey = () => document.querySelector("[name=\"applicationServerKey\"]").getAttribute("content"); const getApplicationServerKey = () => document.querySelector('[name="applicationServerKey"]').getAttribute('content');
const getRegistration = () => navigator.serviceWorker.ready; const getRegistration = () => navigator.serviceWorker.ready;
@@ -46,20 +46,20 @@ const sendSubscriptionToBackend = (getState, subscription, me) => {
} }
} }
return api(getState).post("/api/web/push_subscriptions", params).then(response => response.data); return api(getState).post('/api/web/push_subscriptions', params).then(response => response.data);
}; };
// Last one checks for payload support: https://web-push-book.gauntface.com/chapter-06/01-non-standards-browsers/#no-payload // Last one checks for payload support: https://web-push-book.gauntface.com/chapter-06/01-non-standards-browsers/#no-payload
const supportsPushNotifications = ("serviceWorker" in navigator && "PushManager" in window && "getKey" in PushSubscription.prototype); const supportsPushNotifications = ('serviceWorker' in navigator && 'PushManager' in window && 'getKey' in PushSubscription.prototype);
export function register () { export function register () {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(setBrowserSupport(supportsPushNotifications)); dispatch(setBrowserSupport(supportsPushNotifications));
const me = getState().getIn(["meta", "me"]); const me = getState().getIn(['meta', 'me']);
if (supportsPushNotifications) { if (supportsPushNotifications) {
if (!getApplicationServerKey()) { if (!getApplicationServerKey()) {
console.error("The VAPID public key is not set. You will not be able to receive Web Push Notifications."); console.error('The VAPID public key is not set. You will not be able to receive Web Push Notifications.');
return; return;
} }
@@ -70,7 +70,7 @@ export function register () {
// We have a subscription, check if it is still valid // We have a subscription, check if it is still valid
const currentServerKey = (new Uint8Array(subscription.options.applicationServerKey)).toString(); const currentServerKey = (new Uint8Array(subscription.options.applicationServerKey)).toString();
const subscriptionServerKey = urlBase64ToUint8Array(getApplicationServerKey()).toString(); const subscriptionServerKey = urlBase64ToUint8Array(getApplicationServerKey()).toString();
const serverEndpoint = getState().getIn(["push_notifications", "subscription", "endpoint"]); const serverEndpoint = getState().getIn(['push_notifications', 'subscription', 'endpoint']);
// If the VAPID public key did not change and the endpoint corresponds // If the VAPID public key did not change and the endpoint corresponds
// to the endpoint saved in the backend, the subscription is valid // to the endpoint saved in the backend, the subscription is valid
@@ -98,10 +98,10 @@ export function register () {
} }
}) })
.catch(error => { .catch(error => {
if (error.code === 20 && error.name === "AbortError") { if (error.code === 20 && error.name === 'AbortError') {
console.warn("Your browser supports Web Push Notifications, but does not seem to implement the VAPID protocol."); console.warn('Your browser supports Web Push Notifications, but does not seem to implement the VAPID protocol.');
} else if (error.code === 5 && error.name === "InvalidCharacterError") { } else if (error.code === 5 && error.name === 'InvalidCharacterError') {
console.error("The VAPID public key seems to be invalid:", getApplicationServerKey()); console.error('The VAPID public key seems to be invalid:', getApplicationServerKey());
} }
// Clear alerts and hide UI settings // Clear alerts and hide UI settings
@@ -116,22 +116,22 @@ export function register () {
}) })
.catch(console.warn); .catch(console.warn);
} else { } else {
console.warn("Your browser does not support Web Push Notifications."); console.warn('Your browser does not support Web Push Notifications.');
} }
}; };
} }
export function saveSettings() { export function saveSettings() {
return (_, getState) => { return (_, getState) => {
const state = getState().get("push_notifications"); const state = getState().get('push_notifications');
const subscription = state.get("subscription"); const subscription = state.get('subscription');
const alerts = state.get("alerts"); const alerts = state.get('alerts');
const data = { alerts }; const data = { alerts };
api(getState).put(`/api/web/push_subscriptions/${subscription.get("id")}`, { api(getState).put(`/api/web/push_subscriptions/${subscription.get('id')}`, {
data, data,
}).then(() => { }).then(() => {
const me = getState().getIn(["meta", "me"]); const me = getState().getIn(['meta', 'me']);
if (me) { if (me) {
pushNotificationsSetting.set(me, data); pushNotificationsSetting.set(me, data);
} }
@@ -1,7 +1,7 @@
export const SET_BROWSER_SUPPORT = "PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT"; export const SET_BROWSER_SUPPORT = 'PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT';
export const SET_SUBSCRIPTION = "PUSH_NOTIFICATIONS_SET_SUBSCRIPTION"; export const SET_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_SET_SUBSCRIPTION';
export const CLEAR_SUBSCRIPTION = "PUSH_NOTIFICATIONS_CLEAR_SUBSCRIPTION"; export const CLEAR_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_CLEAR_SUBSCRIPTION';
export const SET_ALERTS = "PUSH_NOTIFICATIONS_SET_ALERTS"; export const SET_ALERTS = 'PUSH_NOTIFICATIONS_SET_ALERTS';
export function setBrowserSupport (value) { export function setBrowserSupport (value) {
return { return {
@@ -1,33 +1,29 @@
import api from "../api"; import api from '../api';
import { openModal } from "./modal"; import { openModal } from './modal';
export const REPORT_SUBMIT_REQUEST = "REPORT_SUBMIT_REQUEST"; export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST';
export const REPORT_SUBMIT_SUCCESS = "REPORT_SUBMIT_SUCCESS"; export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS';
export const REPORT_SUBMIT_FAIL = "REPORT_SUBMIT_FAIL"; export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL';
export const initReport = (account, status) => dispatch => export const initReport = (account, status) => dispatch =>
dispatch(openModal({ dispatch(openModal({
modalType: "REPORT", modalType: 'REPORT',
modalProps: { modalProps: {
accountId: account.get("id"), accountId: account.get('id'),
statusId: status?.get("id"), statusId: status?.get('id'),
}, },
})); }));
export const submitReport = (params, onSuccess, onFail) => (dispatch, getState) => { export const submitReport = (params, onSuccess, onFail) => (dispatch, getState) => {
dispatch(submitReportRequest()); dispatch(submitReportRequest());
api(getState).post("/api/v1/reports", params).then(response => { api(getState).post('/api/v1/reports', params).then(response => {
dispatch(submitReportSuccess(response.data)); dispatch(submitReportSuccess(response.data));
if (onSuccess) { if (onSuccess) onSuccess();
onSuccess();
}
}).catch(error => { }).catch(error => {
dispatch(submitReportFail(error)); dispatch(submitReportFail(error));
if (onFail) { if (onFail) onFail();
onFail();
}
}); });
}; };
@@ -1,25 +1,25 @@
import { fromJS } from "immutable"; import { fromJS } from 'immutable';
import { searchHistory } from "flavours/glitch/settings"; import { searchHistory } from 'flavours/glitch/settings';
import api from "../api"; import api from '../api';
import { fetchRelationships } from "./accounts"; import { fetchRelationships } from './accounts';
import { importFetchedAccounts, importFetchedStatuses } from "./importer"; import { importFetchedAccounts, importFetchedStatuses } from './importer';
export const SEARCH_CHANGE = "SEARCH_CHANGE"; export const SEARCH_CHANGE = 'SEARCH_CHANGE';
export const SEARCH_CLEAR = "SEARCH_CLEAR"; export const SEARCH_CLEAR = 'SEARCH_CLEAR';
export const SEARCH_SHOW = "SEARCH_SHOW"; export const SEARCH_SHOW = 'SEARCH_SHOW';
export const SEARCH_FETCH_REQUEST = "SEARCH_FETCH_REQUEST"; export const SEARCH_FETCH_REQUEST = 'SEARCH_FETCH_REQUEST';
export const SEARCH_FETCH_SUCCESS = "SEARCH_FETCH_SUCCESS"; export const SEARCH_FETCH_SUCCESS = 'SEARCH_FETCH_SUCCESS';
export const SEARCH_FETCH_FAIL = "SEARCH_FETCH_FAIL"; export const SEARCH_FETCH_FAIL = 'SEARCH_FETCH_FAIL';
export const SEARCH_EXPAND_REQUEST = "SEARCH_EXPAND_REQUEST"; export const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST';
export const SEARCH_EXPAND_SUCCESS = "SEARCH_EXPAND_SUCCESS"; export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS';
export const SEARCH_EXPAND_FAIL = "SEARCH_EXPAND_FAIL"; export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL';
export const SEARCH_HISTORY_UPDATE = "SEARCH_HISTORY_UPDATE"; export const SEARCH_HISTORY_UPDATE = 'SEARCH_HISTORY_UPDATE';
export function changeSearch(value) { export function changeSearch(value) {
return { return {
@@ -36,17 +36,17 @@ export function clearSearch() {
export function submitSearch(type) { export function submitSearch(type) {
return (dispatch, getState) => { return (dispatch, getState) => {
const value = getState().getIn(["search", "value"]); const value = getState().getIn(['search', 'value']);
const signedIn = !!getState().getIn(["meta", "me"]); const signedIn = !!getState().getIn(['meta', 'me']);
if (value.length === 0) { if (value.length === 0) {
dispatch(fetchSearchSuccess({ accounts: [], statuses: [], hashtags: [] }, "", type)); dispatch(fetchSearchSuccess({ accounts: [], statuses: [], hashtags: [] }, '', type));
return; return;
} }
dispatch(fetchSearchRequest(type)); dispatch(fetchSearchRequest(type));
api(getState).get("/api/v2/search", { api(getState).get('/api/v2/search', {
params: { params: {
q: value, q: value,
resolve: signedIn, resolve: signedIn,
@@ -94,12 +94,12 @@ export function fetchSearchFail(error) {
} }
export const expandSearch = type => (dispatch, getState) => { export const expandSearch = type => (dispatch, getState) => {
const value = getState().getIn(["search", "value"]); const value = getState().getIn(['search', 'value']);
const offset = getState().getIn(["search", "results", type]).size - 1; const offset = getState().getIn(['search', 'results', type]).size - 1;
dispatch(expandSearchRequest(type)); dispatch(expandSearchRequest(type));
api(getState).get("/api/v2/search", { api(getState).get('/api/v2/search', {
params: { params: {
q: value, q: value,
type, type,
@@ -144,8 +144,8 @@ export const showSearch = () => ({
}); });
export const openURL = routerHistory => (dispatch, getState) => { export const openURL = routerHistory => (dispatch, getState) => {
const value = getState().getIn(["search", "value"]); const value = getState().getIn(['search', 'value']);
const signedIn = !!getState().getIn(["meta", "me"]); const signedIn = !!getState().getIn(['meta', 'me']);
if (!signedIn) { if (!signedIn) {
return; return;
@@ -153,7 +153,7 @@ export const openURL = routerHistory => (dispatch, getState) => {
dispatch(fetchSearchRequest()); dispatch(fetchSearchRequest());
api(getState).get("/api/v2/search", { params: { q: value, resolve: true } }).then(response => { api(getState).get('/api/v2/search', { params: { q: value, resolve: true } }).then(response => {
if (response.data.accounts?.length > 0) { if (response.data.accounts?.length > 0) {
dispatch(importFetchedAccounts(response.data.accounts)); dispatch(importFetchedAccounts(response.data.accounts));
routerHistory.push(`/@${response.data.accounts[0].acct}`); routerHistory.push(`/@${response.data.accounts[0].acct}`);
@@ -169,8 +169,8 @@ export const openURL = routerHistory => (dispatch, getState) => {
}; };
export const clickSearchResult = (q, type) => (dispatch, getState) => { export const clickSearchResult = (q, type) => (dispatch, getState) => {
const previous = getState().getIn(["search", "recent"]); const previous = getState().getIn(['search', 'recent']);
const me = getState().getIn(["meta", "me"]); const me = getState().getIn(['meta', 'me']);
const current = previous.add(fromJS({ type, q })).takeLast(4); const current = previous.add(fromJS({ type, q })).takeLast(4);
searchHistory.set(me, current.toJS()); searchHistory.set(me, current.toJS());
@@ -178,9 +178,9 @@ export const clickSearchResult = (q, type) => (dispatch, getState) => {
}; };
export const forgetSearchResult = q => (dispatch, getState) => { export const forgetSearchResult = q => (dispatch, getState) => {
const previous = getState().getIn(["search", "recent"]); const previous = getState().getIn(['search', 'recent']);
const me = getState().getIn(["meta", "me"]); const me = getState().getIn(['meta', 'me']);
const current = previous.filterNot(result => result.get("q") === q); const current = previous.filterNot(result => result.get('q') === q);
searchHistory.set(me, current.toJS()); searchHistory.set(me, current.toJS());
dispatch(updateSearchHistory(current)); dispatch(updateSearchHistory(current));
@@ -192,7 +192,7 @@ export const updateSearchHistory = recent => ({
}); });
export const hydrateSearch = () => (dispatch, getState) => { export const hydrateSearch = () => (dispatch, getState) => {
const me = getState().getIn(["meta", "me"]); const me = getState().getIn(['meta', 'me']);
const history = searchHistory.get(me); const history = searchHistory.get(me);
if (history !== null) { if (history !== null) {
@@ -1,44 +1,37 @@
import api from "../api"; import api from '../api';
import { importFetchedAccount } from "./importer"; import { importFetchedAccount } from './importer';
export const SERVER_FETCH_REQUEST = "Server_FETCH_REQUEST"; export const SERVER_FETCH_REQUEST = 'Server_FETCH_REQUEST';
export const SERVER_FETCH_SUCCESS = "Server_FETCH_SUCCESS"; export const SERVER_FETCH_SUCCESS = 'Server_FETCH_SUCCESS';
export const SERVER_FETCH_FAIL = "Server_FETCH_FAIL"; export const SERVER_FETCH_FAIL = 'Server_FETCH_FAIL';
export const EXTENDED_DESCRIPTION_REQUEST = "EXTENDED_DESCRIPTION_REQUEST"; export const EXTENDED_DESCRIPTION_REQUEST = 'EXTENDED_DESCRIPTION_REQUEST';
export const EXTENDED_DESCRIPTION_SUCCESS = "EXTENDED_DESCRIPTION_SUCCESS"; export const EXTENDED_DESCRIPTION_SUCCESS = 'EXTENDED_DESCRIPTION_SUCCESS';
export const EXTENDED_DESCRIPTION_FAIL = "EXTENDED_DESCRIPTION_FAIL"; export const EXTENDED_DESCRIPTION_FAIL = 'EXTENDED_DESCRIPTION_FAIL';
export const SERVER_DOMAIN_BLOCKS_FETCH_REQUEST = "SERVER_DOMAIN_BLOCKS_FETCH_REQUEST"; export const SERVER_DOMAIN_BLOCKS_FETCH_REQUEST = 'SERVER_DOMAIN_BLOCKS_FETCH_REQUEST';
export const SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS = "SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS"; export const SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS = 'SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS';
export const SERVER_DOMAIN_BLOCKS_FETCH_FAIL = "SERVER_DOMAIN_BLOCKS_FETCH_FAIL"; export const SERVER_DOMAIN_BLOCKS_FETCH_FAIL = 'SERVER_DOMAIN_BLOCKS_FETCH_FAIL';
export const fetchServer = () => (dispatch, getState) => { export const fetchServer = () => (dispatch, getState) => {
if (getState().getIn(["server", "server", "isLoading"])) { if (getState().getIn(['server', 'server', 'isLoading'])) {
return; return;
} }
dispatch(fetchServerRequest()); dispatch(fetchServerRequest());
/* global data */
try { try {
api(getState) api(getState)
.get("/api/v2/instance").then({ data }).catch(error => { .get('/api/v2/instance').then({ data })
console.error(error); if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
}); dispatch(fetchServerSuccess(data));
if (data.contact.account) {
dispatch(importFetchedAccount(data.contact.account));
}
dispatch(fetchServerSuccess(data));
} catch (e) { } catch (e) {
api(getState) api(getState)
.get("/api/v1/instance").then(({ data }) => { .get('/api/v1/instance').then(({ data }) => {
if (data.contact_account) { if (data.contact_account) dispatch(importFetchedAccount(data.contact_account));
dispatch(importFetchedAccount(data.contact_account));
}
dispatch(fetchServerSuccess(data)); dispatch(fetchServerSuccess(data));
}).catch(err => dispatch(fetchServerFail(err))); }).catch(err => dispatch(fetchServerFail(err)));
} }
}; };
@@ -57,14 +50,14 @@ const fetchServerFail = error => ({
}); });
export const fetchDomainBlocks = () => (dispatch, getState) => { export const fetchDomainBlocks = () => (dispatch, getState) => {
if (getState().getIn(["server", "domainBlocks", "isLoading"])) { if (getState().getIn(['server', 'domainBlocks', 'isLoading'])) {
return; return;
} }
dispatch(fetchDomainBlocksRequest()); dispatch(fetchDomainBlocksRequest());
api(getState) api(getState)
.get("/api/v1/instance/domain_blocks") .get('/api/v1/instance/domain_blocks')
.then(({ data }) => dispatch(fetchDomainBlocksSuccess(true, data))) .then(({ data }) => dispatch(fetchDomainBlocksSuccess(true, data)))
.catch(err => { .catch(err => {
if (err.response.status === 404) { if (err.response.status === 404) {
@@ -1,7 +1,7 @@
import { debounce } from "lodash"; import { debounce } from 'lodash';
export const SETTING_CHANGE = "SETTING_CHANGE"; export const SETTING_CHANGE = 'SETTING_CHANGE';
export const SETTING_SAVE = "SETTING_SAVE"; export const SETTING_SAVE = 'SETTING_SAVE';
export function changeSetting(path, value) { export function changeSetting(path, value) {
return dispatch => { return dispatch => {
@@ -16,13 +16,13 @@ export function changeSetting(path, value) {
} }
const debouncedSave = debounce((dispatch, getState) => { const debouncedSave = debounce((dispatch, getState) => {
if (getState().getIn(["settings", "saved"])) { if (getState().getIn(['settings', 'saved'])) {
return; return;
} }
const data = getState().get("settings").filter((_, path) => path !== "saved").toJS(); const data = getState().get('settings').filter((_, path) => path !== 'saved').toJS();
localStorage.setItem("web_settings", JSON.stringify(data)); localStorage.setItem('web_settings', JSON.stringify(data));
dispatch({ type: SETTING_SAVE }); dispatch({ type: SETTING_SAVE });
}, 5000, { trailing: true }); }, 5000, { trailing: true });
@@ -1,43 +1,43 @@
import api from "../api"; import api from '../api';
import { ensureComposeIsVisible, setComposeToStatus } from "./compose"; import { ensureComposeIsVisible, setComposeToStatus } from './compose';
import { importFetchedStatus, importFetchedStatuses } from "./importer"; import { importFetchedStatus, importFetchedStatuses } from './importer';
import { deleteFromTimelines } from "./timelines"; import { deleteFromTimelines } from './timelines';
export const STATUS_FETCH_REQUEST = "STATUS_FETCH_REQUEST"; export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
export const STATUS_FETCH_SUCCESS = "STATUS_FETCH_SUCCESS"; export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
export const STATUS_FETCH_FAIL = "STATUS_FETCH_FAIL"; export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL';
export const STATUS_DELETE_REQUEST = "STATUS_DELETE_REQUEST"; export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST';
export const STATUS_DELETE_SUCCESS = "STATUS_DELETE_SUCCESS"; export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS';
export const STATUS_DELETE_FAIL = "STATUS_DELETE_FAIL"; export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL';
export const CONTEXT_FETCH_REQUEST = "CONTEXT_FETCH_REQUEST"; export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST';
export const CONTEXT_FETCH_SUCCESS = "CONTEXT_FETCH_SUCCESS"; export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS';
export const CONTEXT_FETCH_FAIL = "CONTEXT_FETCH_FAIL"; export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL';
export const STATUS_MUTE_REQUEST = "STATUS_MUTE_REQUEST"; export const STATUS_MUTE_REQUEST = 'STATUS_MUTE_REQUEST';
export const STATUS_MUTE_SUCCESS = "STATUS_MUTE_SUCCESS"; export const STATUS_MUTE_SUCCESS = 'STATUS_MUTE_SUCCESS';
export const STATUS_MUTE_FAIL = "STATUS_MUTE_FAIL"; export const STATUS_MUTE_FAIL = 'STATUS_MUTE_FAIL';
export const STATUS_UNMUTE_REQUEST = "STATUS_UNMUTE_REQUEST"; export const STATUS_UNMUTE_REQUEST = 'STATUS_UNMUTE_REQUEST';
export const STATUS_UNMUTE_SUCCESS = "STATUS_UNMUTE_SUCCESS"; export const STATUS_UNMUTE_SUCCESS = 'STATUS_UNMUTE_SUCCESS';
export const STATUS_UNMUTE_FAIL = "STATUS_UNMUTE_FAIL"; export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
export const STATUS_REVEAL = "STATUS_REVEAL"; export const STATUS_REVEAL = 'STATUS_REVEAL';
export const STATUS_HIDE = "STATUS_HIDE"; export const STATUS_HIDE = 'STATUS_HIDE';
export const STATUS_COLLAPSE = "STATUS_COLLAPSE"; export const STATUS_COLLAPSE = 'STATUS_COLLAPSE';
export const REDRAFT = "REDRAFT"; export const REDRAFT = 'REDRAFT';
export const STATUS_FETCH_SOURCE_REQUEST = "STATUS_FETCH_SOURCE_REQUEST"; export const STATUS_FETCH_SOURCE_REQUEST = 'STATUS_FETCH_SOURCE_REQUEST';
export const STATUS_FETCH_SOURCE_SUCCESS = "STATUS_FETCH_SOURCE_SUCCESS"; export const STATUS_FETCH_SOURCE_SUCCESS = 'STATUS_FETCH_SOURCE_SUCCESS';
export const STATUS_FETCH_SOURCE_FAIL = "STATUS_FETCH_SOURCE_FAIL"; export const STATUS_FETCH_SOURCE_FAIL = 'STATUS_FETCH_SOURCE_FAIL';
export const STATUS_TRANSLATE_REQUEST = "STATUS_TRANSLATE_REQUEST"; export const STATUS_TRANSLATE_REQUEST = 'STATUS_TRANSLATE_REQUEST';
export const STATUS_TRANSLATE_SUCCESS = "STATUS_TRANSLATE_SUCCESS"; export const STATUS_TRANSLATE_SUCCESS = 'STATUS_TRANSLATE_SUCCESS';
export const STATUS_TRANSLATE_FAIL = "STATUS_TRANSLATE_FAIL"; export const STATUS_TRANSLATE_FAIL = 'STATUS_TRANSLATE_FAIL';
export const STATUS_TRANSLATE_UNDO = "STATUS_TRANSLATE_UNDO"; export const STATUS_TRANSLATE_UNDO = 'STATUS_TRANSLATE_UNDO';
export function fetchStatusRequest(id, skipLoading) { export function fetchStatusRequest(id, skipLoading) {
return { return {
@@ -49,7 +49,7 @@ export function fetchStatusRequest(id, skipLoading) {
export function fetchStatus(id, forceFetch = false) { export function fetchStatus(id, forceFetch = false) {
return (dispatch, getState) => { return (dispatch, getState) => {
const skipLoading = !forceFetch && getState().getIn(["statuses", id], null) !== null; const skipLoading = !forceFetch && getState().getIn(['statuses', id], null) !== null;
dispatch(fetchContext(id)); dispatch(fetchContext(id));
@@ -95,10 +95,10 @@ export function redraft(status, raw_text, content_type) {
} }
export const editStatus = (id, routerHistory) => (dispatch, getState) => { export const editStatus = (id, routerHistory) => (dispatch, getState) => {
let status = getState().getIn(["statuses", id]); let status = getState().getIn(['statuses', id]);
if (status.get("poll")) { if (status.get('poll')) {
status = status.set("poll", getState().getIn(["polls", status.get("poll")])); status = status.set('poll', getState().getIn(['polls', status.get('poll')]));
} }
dispatch(fetchStatusSourceRequest()); dispatch(fetchStatusSourceRequest());
@@ -127,10 +127,10 @@ export const fetchStatusSourceFail = error => ({
export function deleteStatus(id, routerHistory, withRedraft = false) { export function deleteStatus(id, routerHistory, withRedraft = false) {
return (dispatch, getState) => { return (dispatch, getState) => {
let status = getState().getIn(["statuses", id]); let status = getState().getIn(['statuses', id]);
if (status.get("poll")) { if (status.get('poll')) {
status = status.set("poll", getState().getIn(["polls", status.get("poll")])); status = status.set('poll', getState().getIn(['polls', status.get('poll')]));
} }
dispatch(deleteStatusRequest(id)); dispatch(deleteStatusRequest(id));
+11 -11
View File
@@ -1,12 +1,12 @@
import { Iterable, fromJS } from "immutable"; import { Iterable, fromJS } from 'immutable';
import { hydrateCompose } from "./compose"; import { hydrateCompose } from './compose';
import { importFetchedAccounts } from "./importer"; import { importFetchedAccounts } from './importer';
import { hydrateSearch } from "./search"; import { hydrateSearch } from './search';
import { saveSettings } from "./settings"; import { saveSettings } from './settings';
export const STORE_HYDRATE = "STORE_HYDRATE"; export const STORE_HYDRATE = 'STORE_HYDRATE';
export const STORE_HYDRATE_LAZY = "STORE_HYDRATE_LAZY"; export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY';
const convertState = rawState => const convertState = rawState =>
fromJS(rawState, (k, v) => fromJS(rawState, (k, v) =>
@@ -15,12 +15,12 @@ const convertState = rawState =>
const applyMigrations = (state) => { const applyMigrations = (state) => {
return state.withMutations(state => { return state.withMutations(state => {
// Migrate glitch-soc local-only “Show unread marker” setting to Mastodon's setting // Migrate glitch-soc local-only “Show unread marker” setting to Mastodon's setting
if (state.getIn(["local_settings", "notifications", "show_unread"]) !== undefined) { if (state.getIn(['local_settings', 'notifications', 'show_unread']) !== undefined) {
// Only change if the Mastodon setting does not deviate from default // Only change if the Mastodon setting does not deviate from default
if (state.getIn(["settings", "notifications", "showUnread"]) !== false) { if (state.getIn(['settings', 'notifications', 'showUnread']) !== false) {
state.setIn(["settings", "notifications", "showUnread"], state.getIn(["local_settings", "notifications", "show_unread"])); state.setIn(['settings', 'notifications', 'showUnread'], state.getIn(['local_settings', 'notifications', 'show_unread']));
} }
state.removeIn(["local_settings", "notifications", "show_unread"]); state.removeIn(['local_settings', 'notifications', 'show_unread']);
} }
}); });
}; };
@@ -1,18 +1,18 @@
// @ts-check // @ts-check
import { getLocale } from "flavours/glitch/locales"; import { getLocale } from 'flavours/glitch/locales';
import { connectStream } from "../stream"; import { connectStream } from '../stream';
import { import {
fetchAnnouncements, fetchAnnouncements,
updateAnnouncements, updateAnnouncements,
updateReaction as updateAnnouncementsReaction, updateReaction as updateAnnouncementsReaction,
deleteAnnouncement, deleteAnnouncement,
} from "./announcements"; } from './announcements';
import { updateConversations } from "./conversations"; import { updateConversations } from './conversations';
import { updateNotifications, expandNotifications } from "./notifications"; import { updateNotifications, expandNotifications } from './notifications';
import { updateStatus } from "./statuses"; import { updateStatus } from './statuses';
import { import {
updateTimeline, updateTimeline,
deleteFromTimelines, deleteFromTimelines,
@@ -23,7 +23,7 @@ import {
fillPublicTimelineGaps, fillPublicTimelineGaps,
fillCommunityTimelineGaps, fillCommunityTimelineGaps,
fillListTimelineGaps, fillListTimelineGaps,
} from "./timelines"; } from './timelines';
/** /**
* @param {number} max * @param {number} max
@@ -46,7 +46,7 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
const { messages } = getLocale(); const { messages } = getLocale();
return connectStream(channelName, params, (dispatch, getState) => { return connectStream(channelName, params, (dispatch, getState) => {
const locale = getState().getIn(["meta", "locale"]); const locale = getState().getIn(['meta', 'locale']);
// @ts-expect-error // @ts-expect-error
let pollingId; let pollingId;
@@ -57,7 +57,7 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
const useFallback = fallback => { const useFallback = fallback => {
fallback(dispatch, () => { fallback(dispatch, () => {
// eslint-disable-next-line react-hooks/rules-of-hooks // eslint-disable-next-line react-hooks/rules-of-hooks -- this is not a react hook
pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000)); pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
}); });
}; };
@@ -88,36 +88,36 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
onReceive (data) { onReceive (data) {
switch(data.event) { switch(data.event) {
case "update": case 'update':
// @ts-expect-error // @ts-expect-error
dispatch(updateTimeline(timelineId, JSON.parse(data.payload), options.accept)); dispatch(updateTimeline(timelineId, JSON.parse(data.payload), options.accept));
break; break;
case "status.update": case 'status.update':
// @ts-expect-error // @ts-expect-error
dispatch(updateStatus(JSON.parse(data.payload))); dispatch(updateStatus(JSON.parse(data.payload)));
break; break;
case "delete": case 'delete':
dispatch(deleteFromTimelines(data.payload)); dispatch(deleteFromTimelines(data.payload));
break; break;
case "notification": case 'notification':
// @ts-expect-error // @ts-expect-error
dispatch(updateNotifications(JSON.parse(data.payload), messages, locale)); dispatch(updateNotifications(JSON.parse(data.payload), messages, locale));
break; break;
case "conversation": case 'conversation':
// @ts-expect-error // @ts-expect-error
dispatch(updateConversations(JSON.parse(data.payload))); dispatch(updateConversations(JSON.parse(data.payload)));
break; break;
case "announcement": case 'announcement':
// @ts-expect-error // @ts-expect-error
dispatch(updateAnnouncements(JSON.parse(data.payload))); dispatch(updateAnnouncements(JSON.parse(data.payload)));
break; break;
case "announcement.reaction": case 'announcement.reaction':
// @ts-expect-error // @ts-expect-error
dispatch(updateAnnouncementsReaction(JSON.parse(data.payload))); dispatch(updateAnnouncementsReaction(JSON.parse(data.payload)));
break; break;
case "announcement.delete": case 'announcement.delete':
dispatch(deleteAnnouncement(data.payload)); dispatch(deleteAnnouncement(data.payload));
break; break;
} }
}, },
}; };
@@ -129,7 +129,9 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
* @param {function(): void} done * @param {function(): void} done
*/ */
const refreshHomeTimelineAndNotification = (dispatch, done) => { const refreshHomeTimelineAndNotification = (dispatch, done) => {
// @ts-expect-error
dispatch(expandHomeTimeline({}, () => dispatch(expandHomeTimeline({}, () =>
// @ts-expect-error
dispatch(expandNotifications({}, () => dispatch(expandNotifications({}, () =>
dispatch(fetchAnnouncements(done)))))); dispatch(fetchAnnouncements(done))))));
}; };
@@ -139,7 +141,7 @@ const refreshHomeTimelineAndNotification = (dispatch, done) => {
*/ */
export const connectUserStream = () => export const connectUserStream = () =>
// @ts-expect-error // @ts-expect-error
connectTimelineStream("home", "user", {}, { fallback: refreshHomeTimelineAndNotification, fillGaps: fillHomeTimelineGaps }); connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification, fillGaps: fillHomeTimelineGaps });
/** /**
* @param {Object} options * @param {Object} options
@@ -147,7 +149,7 @@ export const connectUserStream = () =>
* @returns {function(): void} * @returns {function(): void}
*/ */
export const connectCommunityStream = ({ onlyMedia } = {}) => export const connectCommunityStream = ({ onlyMedia } = {}) =>
connectTimelineStream(`community${onlyMedia ? ":media" : ""}`, `public:local${onlyMedia ? ":media" : ""}`, {}, { fillGaps: () => (fillCommunityTimelineGaps({ onlyMedia })) }); connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => (fillCommunityTimelineGaps({ onlyMedia })) });
/** /**
* @param {Object} options * @param {Object} options
@@ -157,7 +159,7 @@ export const connectCommunityStream = ({ onlyMedia } = {}) =>
* @returns {function(): void} * @returns {function(): void}
*/ */
export const connectPublicStream = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}) => export const connectPublicStream = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}) =>
connectTimelineStream(`public${onlyRemote ? ":remote" : (allowLocalOnly ? ":allow_local_only" : "")}${onlyMedia ? ":media" : ""}`, `public${onlyRemote ? ":remote" : (allowLocalOnly ? ":allow_local_only" : "")}${onlyMedia ? ":media" : ""}`, {}, { fillGaps: () => fillPublicTimelineGaps({ onlyMedia, onlyRemote, allowLocalOnly }) }); connectTimelineStream(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => fillPublicTimelineGaps({ onlyMedia, onlyRemote, allowLocalOnly }) });
/** /**
* @param {string} columnId * @param {string} columnId
@@ -167,17 +169,17 @@ export const connectPublicStream = ({ onlyMedia, onlyRemote, allowLocalOnly } =
* @returns {function(): void} * @returns {function(): void}
*/ */
export const connectHashtagStream = (columnId, tagName, onlyLocal, accept) => export const connectHashtagStream = (columnId, tagName, onlyLocal, accept) =>
connectTimelineStream(`hashtag:${columnId}${onlyLocal ? ":local" : ""}`, `hashtag${onlyLocal ? ":local" : ""}`, { tag: tagName }, { accept }); connectTimelineStream(`hashtag:${columnId}${onlyLocal ? ':local' : ''}`, `hashtag${onlyLocal ? ':local' : ''}`, { tag: tagName }, { accept });
/** /**
* @returns {function(): void} * @returns {function(): void}
*/ */
export const connectDirectStream = () => export const connectDirectStream = () =>
connectTimelineStream("direct", "direct"); connectTimelineStream('direct', 'direct');
/** /**
* @param {string} listId * @param {string} listId
* @returns {function(): void} * @returns {function(): void}
*/ */
export const connectListStream = listId => export const connectListStream = listId =>
connectTimelineStream(`list:${listId}`, "list", { list: listId }, { fillGaps: () => fillListTimelineGaps(listId) }); connectTimelineStream(`list:${listId}`, 'list', { list: listId }, { fillGaps: () => fillListTimelineGaps(listId) });
@@ -1,19 +1,19 @@
import api from "../api"; import api from '../api';
import { fetchRelationships } from "./accounts"; import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from "./importer"; import { importFetchedAccounts } from './importer';
export const SUGGESTIONS_FETCH_REQUEST = "SUGGESTIONS_FETCH_REQUEST"; export const SUGGESTIONS_FETCH_REQUEST = 'SUGGESTIONS_FETCH_REQUEST';
export const SUGGESTIONS_FETCH_SUCCESS = "SUGGESTIONS_FETCH_SUCCESS"; export const SUGGESTIONS_FETCH_SUCCESS = 'SUGGESTIONS_FETCH_SUCCESS';
export const SUGGESTIONS_FETCH_FAIL = "SUGGESTIONS_FETCH_FAIL"; export const SUGGESTIONS_FETCH_FAIL = 'SUGGESTIONS_FETCH_FAIL';
export const SUGGESTIONS_DISMISS = "SUGGESTIONS_DISMISS"; export const SUGGESTIONS_DISMISS = 'SUGGESTIONS_DISMISS';
export function fetchSuggestions(withRelationships = false) { export function fetchSuggestions(withRelationships = false) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchSuggestionsRequest()); dispatch(fetchSuggestionsRequest());
api(getState).get("/api/v2/suggestions", { params: { limit: 20 } }).then(response => { api(getState).get('/api/v2/suggestions', { params: { limit: 20 } }).then(response => {
dispatch(importFetchedAccounts(response.data.map(x => x.account))); dispatch(importFetchedAccounts(response.data.map(x => x.account)));
dispatch(fetchSuggestionsSuccess(response.data)); dispatch(fetchSuggestionsSuccess(response.data));
@@ -57,7 +57,7 @@ export const dismissSuggestion = accountId => (dispatch, getState) => {
api(getState).delete(`/api/v1/suggestions/${accountId}`).then(() => { api(getState).delete(`/api/v1/suggestions/${accountId}`).then(() => {
dispatch(fetchSuggestionsRequest()); dispatch(fetchSuggestionsRequest());
api(getState).get("/api/v2/suggestions").then(response => { api(getState).get('/api/v2/suggestions').then(response => {
dispatch(importFetchedAccounts(response.data.map(x => x.account))); dispatch(importFetchedAccounts(response.data.map(x => x.account)));
dispatch(fetchSuggestionsSuccess(response.data)); dispatch(fetchSuggestionsSuccess(response.data));
}).catch(error => dispatch(fetchSuggestionsFail(error))); }).catch(error => dispatch(fetchSuggestionsFail(error)));
+20 -20
View File
@@ -1,24 +1,24 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
export const HASHTAG_FETCH_REQUEST = "HASHTAG_FETCH_REQUEST"; export const HASHTAG_FETCH_REQUEST = 'HASHTAG_FETCH_REQUEST';
export const HASHTAG_FETCH_SUCCESS = "HASHTAG_FETCH_SUCCESS"; export const HASHTAG_FETCH_SUCCESS = 'HASHTAG_FETCH_SUCCESS';
export const HASHTAG_FETCH_FAIL = "HASHTAG_FETCH_FAIL"; export const HASHTAG_FETCH_FAIL = 'HASHTAG_FETCH_FAIL';
export const FOLLOWED_HASHTAGS_FETCH_REQUEST = "FOLLOWED_HASHTAGS_FETCH_REQUEST"; export const FOLLOWED_HASHTAGS_FETCH_REQUEST = 'FOLLOWED_HASHTAGS_FETCH_REQUEST';
export const FOLLOWED_HASHTAGS_FETCH_SUCCESS = "FOLLOWED_HASHTAGS_FETCH_SUCCESS"; export const FOLLOWED_HASHTAGS_FETCH_SUCCESS = 'FOLLOWED_HASHTAGS_FETCH_SUCCESS';
export const FOLLOWED_HASHTAGS_FETCH_FAIL = "FOLLOWED_HASHTAGS_FETCH_FAIL"; export const FOLLOWED_HASHTAGS_FETCH_FAIL = 'FOLLOWED_HASHTAGS_FETCH_FAIL';
export const FOLLOWED_HASHTAGS_EXPAND_REQUEST = "FOLLOWED_HASHTAGS_EXPAND_REQUEST"; export const FOLLOWED_HASHTAGS_EXPAND_REQUEST = 'FOLLOWED_HASHTAGS_EXPAND_REQUEST';
export const FOLLOWED_HASHTAGS_EXPAND_SUCCESS = "FOLLOWED_HASHTAGS_EXPAND_SUCCESS"; export const FOLLOWED_HASHTAGS_EXPAND_SUCCESS = 'FOLLOWED_HASHTAGS_EXPAND_SUCCESS';
export const FOLLOWED_HASHTAGS_EXPAND_FAIL = "FOLLOWED_HASHTAGS_EXPAND_FAIL"; export const FOLLOWED_HASHTAGS_EXPAND_FAIL = 'FOLLOWED_HASHTAGS_EXPAND_FAIL';
export const HASHTAG_FOLLOW_REQUEST = "HASHTAG_FOLLOW_REQUEST"; export const HASHTAG_FOLLOW_REQUEST = 'HASHTAG_FOLLOW_REQUEST';
export const HASHTAG_FOLLOW_SUCCESS = "HASHTAG_FOLLOW_SUCCESS"; export const HASHTAG_FOLLOW_SUCCESS = 'HASHTAG_FOLLOW_SUCCESS';
export const HASHTAG_FOLLOW_FAIL = "HASHTAG_FOLLOW_FAIL"; export const HASHTAG_FOLLOW_FAIL = 'HASHTAG_FOLLOW_FAIL';
export const HASHTAG_UNFOLLOW_REQUEST = "HASHTAG_UNFOLLOW_REQUEST"; export const HASHTAG_UNFOLLOW_REQUEST = 'HASHTAG_UNFOLLOW_REQUEST';
export const HASHTAG_UNFOLLOW_SUCCESS = "HASHTAG_UNFOLLOW_SUCCESS"; export const HASHTAG_UNFOLLOW_SUCCESS = 'HASHTAG_UNFOLLOW_SUCCESS';
export const HASHTAG_UNFOLLOW_FAIL = "HASHTAG_UNFOLLOW_FAIL"; export const HASHTAG_UNFOLLOW_FAIL = 'HASHTAG_UNFOLLOW_FAIL';
export const fetchHashtag = name => (dispatch, getState) => { export const fetchHashtag = name => (dispatch, getState) => {
dispatch(fetchHashtagRequest()); dispatch(fetchHashtagRequest());
@@ -48,8 +48,8 @@ export const fetchHashtagFail = error => ({
export const fetchFollowedHashtags = () => (dispatch, getState) => { export const fetchFollowedHashtags = () => (dispatch, getState) => {
dispatch(fetchFollowedHashtagsRequest()); dispatch(fetchFollowedHashtagsRequest());
api(getState).get("/api/v1/followed_tags").then(response => { api(getState).get('/api/v1/followed_tags').then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(fetchFollowedHashtagsSuccess(response.data, next ? next.uri : null)); dispatch(fetchFollowedHashtagsSuccess(response.data, next ? next.uri : null));
}).catch(err => { }).catch(err => {
dispatch(fetchFollowedHashtagsFail(err)); dispatch(fetchFollowedHashtagsFail(err));
@@ -79,7 +79,7 @@ export function fetchFollowedHashtagsFail(error) {
export function expandFollowedHashtags() { export function expandFollowedHashtags() {
return (dispatch, getState) => { return (dispatch, getState) => {
const url = getState().getIn(["followed_tags", "next"]); const url = getState().getIn(['followed_tags', 'next']);
if (url === null) { if (url === null) {
return; return;
@@ -88,7 +88,7 @@ export function expandFollowedHashtags() {
dispatch(expandFollowedHashtagsRequest()); dispatch(expandFollowedHashtagsRequest());
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(expandFollowedHashtagsSuccess(response.data, next ? next.uri : null)); dispatch(expandFollowedHashtagsSuccess(response.data, next ? next.uri : null));
}).catch(error => { }).catch(error => {
dispatch(expandFollowedHashtagsFail(error)); dispatch(expandFollowedHashtagsFail(error));
@@ -1,27 +1,27 @@
import { Map as ImmutableMap, List as ImmutableList } from "immutable"; import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import api, { getLinks } from "flavours/glitch/api"; import api, { getLinks } from 'flavours/glitch/api';
import { compareId } from "flavours/glitch/compare_id"; import { compareId } from 'flavours/glitch/compare_id';
import { usePendingItems as preferPendingItems } from "flavours/glitch/initial_state"; import { usePendingItems as preferPendingItems } from 'flavours/glitch/initial_state';
import { toServerSideType } from "flavours/glitch/utils/filters"; import { toServerSideType } from 'flavours/glitch/utils/filters';
import { importFetchedStatus, importFetchedStatuses } from "./importer"; import { importFetchedStatus, importFetchedStatuses } from './importer';
import { submitMarkers } from "./markers"; import { submitMarkers } from './markers';
export const TIMELINE_UPDATE = "TIMELINE_UPDATE"; export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
export const TIMELINE_DELETE = "TIMELINE_DELETE"; export const TIMELINE_DELETE = 'TIMELINE_DELETE';
export const TIMELINE_CLEAR = "TIMELINE_CLEAR"; export const TIMELINE_CLEAR = 'TIMELINE_CLEAR';
export const TIMELINE_EXPAND_REQUEST = "TIMELINE_EXPAND_REQUEST"; export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST';
export const TIMELINE_EXPAND_SUCCESS = "TIMELINE_EXPAND_SUCCESS"; export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS';
export const TIMELINE_EXPAND_FAIL = "TIMELINE_EXPAND_FAIL"; export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL';
export const TIMELINE_SCROLL_TOP = "TIMELINE_SCROLL_TOP"; export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
export const TIMELINE_LOAD_PENDING = "TIMELINE_LOAD_PENDING"; export const TIMELINE_LOAD_PENDING = 'TIMELINE_LOAD_PENDING';
export const TIMELINE_DISCONNECT = "TIMELINE_DISCONNECT"; export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
export const TIMELINE_CONNECT = "TIMELINE_CONNECT"; export const TIMELINE_CONNECT = 'TIMELINE_CONNECT';
export const TIMELINE_MARK_AS_PARTIAL = "TIMELINE_MARK_AS_PARTIAL"; export const TIMELINE_MARK_AS_PARTIAL = 'TIMELINE_MARK_AS_PARTIAL';
export const loadPending = timeline => ({ export const loadPending = timeline => ({
type: TIMELINE_LOAD_PENDING, type: TIMELINE_LOAD_PENDING,
@@ -30,11 +30,11 @@ export const loadPending = timeline => ({
export function updateTimeline(timeline, status, accept) { export function updateTimeline(timeline, status, accept) {
return (dispatch, getState) => { return (dispatch, getState) => {
if (typeof accept === "function" && !accept(status)) { if (typeof accept === 'function' && !accept(status)) {
return; return;
} }
if (getState().getIn(["timelines", timeline, "isPartial"])) { if (getState().getIn(['timelines', timeline, 'isPartial'])) {
// Prevent new items from being added to a partial timeline, // Prevent new items from being added to a partial timeline,
// since it will be reloaded anyway // since it will be reloaded anyway
@@ -60,7 +60,7 @@ export function updateTimeline(timeline, status, accept) {
filtered, filtered,
}); });
if (timeline === "home") { if (timeline === 'home') {
dispatch(submitMarkers()); dispatch(submitMarkers());
} }
}; };
@@ -68,9 +68,9 @@ export function updateTimeline(timeline, status, accept) {
export function deleteFromTimelines(id) { export function deleteFromTimelines(id) {
return (dispatch, getState) => { return (dispatch, getState) => {
const accountId = getState().getIn(["statuses", id, "account"]); const accountId = getState().getIn(['statuses', id, 'account']);
const references = getState().get("statuses").filter(status => status.get("reblog") === id).map(status => status.get("id")); const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => status.get('id'));
const reblogOf = getState().getIn(["statuses", id, "reblog"], null); const reblogOf = getState().getIn(['statuses', id, 'reblog'], null);
dispatch({ dispatch({
type: TIMELINE_DELETE, type: TIMELINE_DELETE,
@@ -98,17 +98,17 @@ const parseTags = (tags = {}, mode) => {
export function expandTimeline(timelineId, path, params = {}, done = noOp) { export function expandTimeline(timelineId, path, params = {}, done = noOp) {
return (dispatch, getState) => { return (dispatch, getState) => {
const timeline = getState().getIn(["timelines", timelineId], ImmutableMap()); const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
const isLoadingMore = !!params.max_id; const isLoadingMore = !!params.max_id;
if (timeline.get("isLoading")) { if (timeline.get('isLoading')) {
done(); done();
return; return;
} }
if (!params.max_id && !params.pinned && (timeline.get("items", ImmutableList()).size + timeline.get("pendingItems", ImmutableList()).size) > 0) { if (!params.max_id && !params.pinned && (timeline.get('items', ImmutableList()).size + timeline.get('pendingItems', ImmutableList()).size) > 0) {
const a = timeline.getIn(["pendingItems", 0]); const a = timeline.getIn(['pendingItems', 0]);
const b = timeline.getIn(["items", 0]); const b = timeline.getIn(['items', 0]);
if (a && b && compareId(a, b) > 0) { if (a && b && compareId(a, b) > 0) {
params.since_id = a; params.since_id = a;
@@ -122,11 +122,11 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
dispatch(expandTimelineRequest(timelineId, isLoadingMore)); dispatch(expandTimelineRequest(timelineId, isLoadingMore));
api(getState).get(path, { params }).then(response => { api(getState).get(path, { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems)); dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems));
if (timelineId === "home") { if (timelineId === 'home') {
dispatch(submitMarkers()); dispatch(submitMarkers());
} }
}).catch(error => { }).catch(error => {
@@ -139,8 +139,8 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) { export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) {
return (dispatch, getState) => { return (dispatch, getState) => {
const timeline = getState().getIn(["timelines", timelineId], ImmutableMap()); const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
const items = timeline.get("items"); const items = timeline.get('items');
const nullIndexes = items.map((statusId, index) => statusId === null ? index : null); const nullIndexes = items.map((statusId, index) => statusId === null ? index : null);
const gaps = nullIndexes.map(index => index > 0 ? items.get(index - 1) : null); const gaps = nullIndexes.map(index => index > 0 ? items.get(index - 1) : null);
@@ -153,27 +153,27 @@ export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) {
}; };
} }
export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline("home", "/api/v1/timelines/home", { max_id: maxId }, done); export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => expandTimeline(`public${onlyRemote ? ":remote" : (allowLocalOnly ? ":allow_local_only" : "")}${onlyMedia ? ":media" : ""}`, "/api/v1/timelines/public", { remote: !!onlyRemote, allow_local_only: !!allowLocalOnly, max_id: maxId, only_media: !!onlyMedia }, done); export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => expandTimeline(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, allow_local_only: !!allowLocalOnly, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ":media" : ""}`, "/api/v1/timelines/public", { local: true, max_id: maxId, only_media: !!onlyMedia }, done); export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandDirectTimeline = ({ maxId } = {}, done = noOp) => expandTimeline("direct", "/api/v1/timelines/direct", { max_id: maxId }, done); export const expandDirectTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done);
export const expandAccountTimeline = (accountId, { maxId, withReplies, tagged } = {}) => expandTimeline(`account:${accountId}${withReplies ? ":with_replies" : ""}${tagged ? `:${tagged}` : ""}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, exclude_reblogs: withReplies, tagged, max_id: maxId }); export const expandAccountTimeline = (accountId, { maxId, withReplies, tagged } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}${tagged ? `:${tagged}` : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, exclude_reblogs: withReplies, tagged, max_id: maxId });
export const expandAccountFeaturedTimeline = (accountId, { tagged } = {}) => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, tagged }); export const expandAccountFeaturedTimeline = (accountId, { tagged } = {}) => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, tagged });
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 }); export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 });
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done); export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
export const expandHashtagTimeline = (hashtag, { maxId, tags, local } = {}, done = noOp) => { export const expandHashtagTimeline = (hashtag, { maxId, tags, local } = {}, done = noOp) => {
return expandTimeline(`hashtag:${hashtag}${local ? ":local" : ""}`, `/api/v1/timelines/tag/${hashtag}`, { return expandTimeline(`hashtag:${hashtag}${local ? ':local' : ''}`, `/api/v1/timelines/tag/${hashtag}`, {
max_id: maxId, max_id: maxId,
any: parseTags(tags, "any"), any: parseTags(tags, 'any'),
all: parseTags(tags, "all"), all: parseTags(tags, 'all'),
none: parseTags(tags, "none"), none: parseTags(tags, 'none'),
local: local, local: local,
}, done); }, done);
}; };
export const fillHomeTimelineGaps = (done = noOp) => fillTimelineGaps("home", "/api/v1/timelines/home", {}, done); export const fillHomeTimelineGaps = (done = noOp) => fillTimelineGaps('home', '/api/v1/timelines/home', {}, done);
export const fillPublicTimelineGaps = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => fillTimelineGaps(`public${onlyRemote ? ":remote" : (allowLocalOnly ? ":allow_local_only" : "")}${onlyMedia ? ":media" : ""}`, "/api/v1/timelines/public", { remote: !!onlyRemote, only_media: !!onlyMedia, allow_local_only: !!allowLocalOnly }, done); export const fillPublicTimelineGaps = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => fillTimelineGaps(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, only_media: !!onlyMedia, allow_local_only: !!allowLocalOnly }, done);
export const fillCommunityTimelineGaps = ({ onlyMedia } = {}, done = noOp) => fillTimelineGaps(`community${onlyMedia ? ":media" : ""}`, "/api/v1/timelines/public", { local: true, only_media: !!onlyMedia }, done); export const fillCommunityTimelineGaps = ({ onlyMedia } = {}, done = noOp) => fillTimelineGaps(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, only_media: !!onlyMedia }, done);
export const fillListTimelineGaps = (id, done = noOp) => fillTimelineGaps(`list:${id}`, `/api/v1/timelines/list/${id}`, {}, done); export const fillListTimelineGaps = (id, done = noOp) => fillTimelineGaps(`list:${id}`, `/api/v1/timelines/list/${id}`, {}, done);
export function expandTimelineRequest(timeline, isLoadingMore) { export function expandTimelineRequest(timeline, isLoadingMore) {
@@ -203,7 +203,7 @@ export function expandTimelineFail(timeline, error, isLoadingMore) {
timeline, timeline,
error, error,
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
skipNotFound: timeline.startsWith("account:"), skipNotFound: timeline.startsWith('account:'),
}; };
} }
@@ -1,28 +1,28 @@
import api, { getLinks } from "../api"; import api, { getLinks } from '../api';
import { importFetchedStatuses } from "./importer"; import { importFetchedStatuses } from './importer';
export const TRENDS_TAGS_FETCH_REQUEST = "TRENDS_TAGS_FETCH_REQUEST"; export const TRENDS_TAGS_FETCH_REQUEST = 'TRENDS_TAGS_FETCH_REQUEST';
export const TRENDS_TAGS_FETCH_SUCCESS = "TRENDS_TAGS_FETCH_SUCCESS"; export const TRENDS_TAGS_FETCH_SUCCESS = 'TRENDS_TAGS_FETCH_SUCCESS';
export const TRENDS_TAGS_FETCH_FAIL = "TRENDS_TAGS_FETCH_FAIL"; export const TRENDS_TAGS_FETCH_FAIL = 'TRENDS_TAGS_FETCH_FAIL';
export const TRENDS_LINKS_FETCH_REQUEST = "TRENDS_LINKS_FETCH_REQUEST"; export const TRENDS_LINKS_FETCH_REQUEST = 'TRENDS_LINKS_FETCH_REQUEST';
export const TRENDS_LINKS_FETCH_SUCCESS = "TRENDS_LINKS_FETCH_SUCCESS"; export const TRENDS_LINKS_FETCH_SUCCESS = 'TRENDS_LINKS_FETCH_SUCCESS';
export const TRENDS_LINKS_FETCH_FAIL = "TRENDS_LINKS_FETCH_FAIL"; export const TRENDS_LINKS_FETCH_FAIL = 'TRENDS_LINKS_FETCH_FAIL';
export const TRENDS_STATUSES_FETCH_REQUEST = "TRENDS_STATUSES_FETCH_REQUEST"; export const TRENDS_STATUSES_FETCH_REQUEST = 'TRENDS_STATUSES_FETCH_REQUEST';
export const TRENDS_STATUSES_FETCH_SUCCESS = "TRENDS_STATUSES_FETCH_SUCCESS"; export const TRENDS_STATUSES_FETCH_SUCCESS = 'TRENDS_STATUSES_FETCH_SUCCESS';
export const TRENDS_STATUSES_FETCH_FAIL = "TRENDS_STATUSES_FETCH_FAIL"; export const TRENDS_STATUSES_FETCH_FAIL = 'TRENDS_STATUSES_FETCH_FAIL';
export const TRENDS_STATUSES_EXPAND_REQUEST = "TRENDS_STATUSES_EXPAND_REQUEST"; export const TRENDS_STATUSES_EXPAND_REQUEST = 'TRENDS_STATUSES_EXPAND_REQUEST';
export const TRENDS_STATUSES_EXPAND_SUCCESS = "TRENDS_STATUSES_EXPAND_SUCCESS"; export const TRENDS_STATUSES_EXPAND_SUCCESS = 'TRENDS_STATUSES_EXPAND_SUCCESS';
export const TRENDS_STATUSES_EXPAND_FAIL = "TRENDS_STATUSES_EXPAND_FAIL"; export const TRENDS_STATUSES_EXPAND_FAIL = 'TRENDS_STATUSES_EXPAND_FAIL';
export const fetchTrendingHashtags = () => (dispatch, getState) => { export const fetchTrendingHashtags = () => (dispatch, getState) => {
dispatch(fetchTrendingHashtagsRequest()); dispatch(fetchTrendingHashtagsRequest());
api(getState) api(getState)
.get("/api/v1/trends/tags") .get('/api/v1/trends/tags')
.then(({ data }) => dispatch(fetchTrendingHashtagsSuccess(data))) .then(({ data }) => dispatch(fetchTrendingHashtagsSuccess(data)))
.catch(err => dispatch(fetchTrendingHashtagsFail(err))); .catch(err => dispatch(fetchTrendingHashtagsFail(err)));
}; };
@@ -49,7 +49,7 @@ export const fetchTrendingLinks = () => (dispatch, getState) => {
dispatch(fetchTrendingLinksRequest()); dispatch(fetchTrendingLinksRequest());
api(getState) api(getState)
.get("/api/v1/trends/links") .get('/api/v1/trends/links')
.then(({ data }) => dispatch(fetchTrendingLinksSuccess(data))) .then(({ data }) => dispatch(fetchTrendingLinksSuccess(data)))
.catch(err => dispatch(fetchTrendingLinksFail(err))); .catch(err => dispatch(fetchTrendingLinksFail(err)));
}; };
@@ -73,14 +73,14 @@ export const fetchTrendingLinksFail = error => ({
}); });
export const fetchTrendingStatuses = () => (dispatch, getState) => { export const fetchTrendingStatuses = () => (dispatch, getState) => {
if (getState().getIn(["status_lists", "trending", "isLoading"])) { if (getState().getIn(['status_lists', 'trending', 'isLoading'])) {
return; return;
} }
dispatch(fetchTrendingStatusesRequest()); dispatch(fetchTrendingStatusesRequest());
api(getState).get("/api/v1/trends/statuses").then(response => { api(getState).get('/api/v1/trends/statuses').then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(fetchTrendingStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchTrendingStatusesSuccess(response.data, next ? next.uri : null));
}).catch(err => dispatch(fetchTrendingStatusesFail(err))); }).catch(err => dispatch(fetchTrendingStatusesFail(err)));
@@ -107,16 +107,16 @@ export const fetchTrendingStatusesFail = error => ({
export const expandTrendingStatuses = () => (dispatch, getState) => { export const expandTrendingStatuses = () => (dispatch, getState) => {
const url = getState().getIn(["status_lists", "trending", "next"], null); const url = getState().getIn(['status_lists', 'trending', 'next'], null);
if (url === null || getState().getIn(["status_lists", "trending", "isLoading"])) { if (url === null || getState().getIn(['status_lists', 'trending', 'isLoading'])) {
return; return;
} }
dispatch(expandTrendingStatusesRequest()); dispatch(expandTrendingStatusesRequest());
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next"); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(expandTrendingStatusesSuccess(response.data, next ? next.uri : null)); dispatch(expandTrendingStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => { }).catch(error => {
+8 -8
View File
@@ -1,9 +1,9 @@
// @ts-check // @ts-check
import axios from "axios"; import axios from 'axios';
import LinkHeader from "http-link-header"; import LinkHeader from 'http-link-header';
import ready from "./ready"; import ready from './ready';
/** /**
* @param {import('axios').AxiosResponse} response * @param {import('axios').AxiosResponse} response
* @returns {LinkHeader} * @returns {LinkHeader}
@@ -26,10 +26,10 @@ const csrfHeader = {};
*/ */
const setCSRFHeader = () => { const setCSRFHeader = () => {
/** @type {HTMLMetaElement | null} */ /** @type {HTMLMetaElement | null} */
const csrfToken = document.querySelector("meta[name=csrf-token]"); const csrfToken = document.querySelector('meta[name=csrf-token]');
if (csrfToken) { if (csrfToken) {
csrfHeader["X-CSRF-Token"] = csrfToken.content; csrfHeader['X-CSRF-Token'] = csrfToken.content;
} }
}; };
@@ -40,14 +40,14 @@ ready(setCSRFHeader);
* @returns {import('axios').RawAxiosRequestHeaders} * @returns {import('axios').RawAxiosRequestHeaders}
*/ */
const authorizationHeaderFromState = getState => { const authorizationHeaderFromState = getState => {
const accessToken = getState && getState().getIn(["meta", "access_token"], ""); const accessToken = getState && getState().getIn(['meta', 'access_token'], '');
if (!accessToken) { if (!accessToken) {
return {}; return {};
} }
return { return {
"Authorization": `Bearer ${accessToken}`, 'Authorization': `Bearer ${accessToken}`,
}; };
}; };
@@ -56,7 +56,7 @@ const authorizationHeaderFromState = getState => {
* @returns {string} * @returns {string}
*/ */
const baseUrlFromState = getState => { const baseUrlFromState = getState => {
const baseUrl = getState && getState().getIn(["meta", "base_url"], ""); const baseUrl = getState && getState().getIn(['meta', 'base_url'], '');
return `${baseUrl}`; return `${baseUrl}`;
}; };
+83 -83
View File
@@ -1,87 +1,87 @@
const DIGIT_CHARACTERS = [ const DIGIT_CHARACTERS = [
"0", '0',
"1", '1',
"2", '2',
"3", '3',
"4", '4',
"5", '5',
"6", '6',
"7", '7',
"8", '8',
"9", '9',
"A", 'A',
"B", 'B',
"C", 'C',
"D", 'D',
"E", 'E',
"F", 'F',
"G", 'G',
"H", 'H',
"I", 'I',
"J", 'J',
"K", 'K',
"L", 'L',
"M", 'M',
"N", 'N',
"O", 'O',
"P", 'P',
"Q", 'Q',
"R", 'R',
"S", 'S',
"T", 'T',
"U", 'U',
"V", 'V',
"W", 'W',
"X", 'X',
"Y", 'Y',
"Z", 'Z',
"a", 'a',
"b", 'b',
"c", 'c',
"d", 'd',
"e", 'e',
"f", 'f',
"g", 'g',
"h", 'h',
"i", 'i',
"j", 'j',
"k", 'k',
"l", 'l',
"m", 'm',
"n", 'n',
"o", 'o',
"p", 'p',
"q", 'q',
"r", 'r',
"s", 's',
"t", 't',
"u", 'u',
"v", 'v',
"w", 'w',
"x", 'x',
"y", 'y',
"z", 'z',
"#", '#',
"$", '$',
"%", '%',
"*", '*',
"+", '+',
",", ',',
"-", '-',
".", '.',
":", ':',
";", ';',
"=", '=',
"?", '?',
"@", '@',
"[", '[',
"]", ']',
"^", '^',
"_", '_',
"{", '{',
"|", '|',
"}", '}',
"~", '~',
]; ];
export const decode83 = (str: string) => { export const decode83 = (str: string) => {
@@ -1,30 +1,30 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from "react-intl"; import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePropTypes from "react-immutable-proptypes"; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from "react-immutable-pure-component"; import ImmutablePureComponent from 'react-immutable-pure-component';
import { Skeleton } from "flavours/glitch/components/skeleton"; import { Skeleton } from 'flavours/glitch/components/skeleton';
import { me } from "flavours/glitch/initial_state"; import { me } from 'flavours/glitch/initial_state';
import { Avatar } from "./avatar"; import { Avatar } from './avatar';
import { DisplayName } from "./display_name"; import { DisplayName } from './display_name';
import { IconButton } from "./icon_button"; import { IconButton } from './icon_button';
import Permalink from "./permalink"; import Permalink from './permalink';
import { RelativeTimestamp } from "./relative_timestamp"; import { RelativeTimestamp } from './relative_timestamp';
const messages = defineMessages({ const messages = defineMessages({
follow: { id: "account.follow", defaultMessage: "Follow" }, follow: { id: 'account.follow', defaultMessage: 'Follow' },
unfollow: { id: "account.unfollow", defaultMessage: "Unfollow" }, unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
requested: { id: "account.requested", defaultMessage: "Awaiting approval. Click to cancel follow request" }, requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
unblock: { id: "account.unblock", defaultMessage: "Unblock @{name}" }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
unmute: { id: "account.unmute", defaultMessage: "Unmute @{name}" }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
mute_notifications: { id: "account.mute_notifications", defaultMessage: "Mute notifications from @{name}" }, mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' },
unmute_notifications: { id: "account.unmute_notifications", defaultMessage: "Unmute notifications from @{name}" }, unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' },
mute: { id: "account.mute", defaultMessage: "Mute @{name}" }, mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
block: { id: "account.block", defaultMessage: "Block @{name}" }, block: { id: 'account.block', defaultMessage: 'Block @{name}' },
}); });
class Account extends ImmutablePureComponent { class Account extends ImmutablePureComponent {
@@ -102,8 +102,8 @@ class Account extends ImmutablePureComponent {
if (hidden) { if (hidden) {
return ( return (
<> <>
{account.get("display_name")} {account.get('display_name')}
{account.get("username")} {account.get('username')}
</> </>
); );
} }
@@ -114,48 +114,48 @@ class Account extends ImmutablePureComponent {
if (actionIcon) { if (actionIcon) {
buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />; buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />;
} }
} else if (account.get("id") !== me && !small && account.get("relationship", null) !== null) { } else if (account.get('id') !== me && !small && account.get('relationship', null) !== null) {
const following = account.getIn(["relationship", "following"]); const following = account.getIn(['relationship', 'following']);
const requested = account.getIn(["relationship", "requested"]); const requested = account.getIn(['relationship', 'requested']);
const blocking = account.getIn(["relationship", "blocking"]); const blocking = account.getIn(['relationship', 'blocking']);
const muting = account.getIn(["relationship", "muting"]); const muting = account.getIn(['relationship', 'muting']);
if (requested) { if (requested) {
buttons = <IconButton disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />; buttons = <IconButton disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />;
} else if (blocking) { } else if (blocking) {
buttons = <IconButton active icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get("username") })} onClick={this.handleBlock} />; buttons = <IconButton active icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />;
} else if (muting) { } else if (muting) {
let hidingNotificationsButton; let hidingNotificationsButton;
if (account.getIn(["relationship", "muting_notifications"])) { if (account.getIn(['relationship', 'muting_notifications'])) {
hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get("username") })} onClick={this.handleUnmuteNotifications} />; hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get('username') })} onClick={this.handleUnmuteNotifications} />;
} else { } else {
hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get("username") })} onClick={this.handleMuteNotifications} />; hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get('username') })} onClick={this.handleMuteNotifications} />;
} }
buttons = ( buttons = (
<> <>
<IconButton active icon='volume-up' title={intl.formatMessage(messages.unmute, { name: account.get("username") })} onClick={this.handleMute} /> <IconButton active icon='volume-up' title={intl.formatMessage(messages.unmute, { name: account.get('username') })} onClick={this.handleMute} />
{hidingNotificationsButton} {hidingNotificationsButton}
</> </>
); );
} else if (defaultAction === "mute") { } else if (defaultAction === 'mute') {
buttons = <IconButton icon='volume-off' title={intl.formatMessage(messages.mute, { name: account.get("username") })} onClick={this.handleMute} />; buttons = <IconButton icon='volume-off' title={intl.formatMessage(messages.mute, { name: account.get('username') })} onClick={this.handleMute} />;
} else if (defaultAction === "block") { } else if (defaultAction === 'block') {
buttons = <IconButton icon='lock' title={intl.formatMessage(messages.block, { name: account.get("username") })} onClick={this.handleBlock} />; buttons = <IconButton icon='lock' title={intl.formatMessage(messages.block, { name: account.get('username') })} onClick={this.handleBlock} />;
} else if (!account.get("moved") || following) { } else if (!account.get('moved') || following) {
buttons = <IconButton icon={following ? "user-times" : "user-plus"} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />; buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />;
} }
} }
let mute_expires_at; let mute_expires_at;
if (account.get("mute_expires_at")) { if (account.get('mute_expires_at')) {
mute_expires_at = <div><RelativeTimestamp timestamp={account.get("mute_expires_at")} futureDate /></div>; mute_expires_at = <div><RelativeTimestamp timestamp={account.get('mute_expires_at')} futureDate /></div>;
} }
return small ? ( return small ? (
<Permalink <Permalink
className='account small' className='account small'
href={account.get("url")} href={account.get('url')}
to={`/@${account.get("acct")}`} to={`/@${account.get('acct')}`}
> >
<div className='account__avatar-wrapper'> <div className='account__avatar-wrapper'>
<Avatar <Avatar
@@ -171,7 +171,7 @@ class Account extends ImmutablePureComponent {
) : ( ) : (
<div className='account'> <div className='account'>
<div className='account__wrapper'> <div className='account__wrapper'>
<Permalink key={account.get("id")} className='account__display-name' title={account.get("acct")} href={account.get("url")} to={`/@${account.get("acct")}`}> <Permalink key={account.get('id')} className='account__display-name' title={account.get('acct')} href={account.get('url')} to={`/@${account.get('acct')}`}>
<div className='account__avatar-wrapper'><Avatar account={account} size={size} /></div> <div className='account__avatar-wrapper'><Avatar account={account} size={size} /></div>
{mute_expires_at} {mute_expires_at}
<DisplayName account={account} /> <DisplayName account={account} />
@@ -1,14 +1,14 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { FormattedNumber } from "react-intl"; import { FormattedNumber } from 'react-intl';
import classNames from "classnames"; import classNames from 'classnames';
import { Sparklines, SparklinesCurve } from "react-sparklines"; import { Sparklines, SparklinesCurve } from 'react-sparklines';
import api from "flavours/glitch/api"; import api from 'flavours/glitch/api';
import { Skeleton } from "flavours/glitch/components/skeleton"; import { Skeleton } from 'flavours/glitch/components/skeleton';
const percIncrease = (a, b) => { const percIncrease = (a, b) => {
let percent; let percent;
@@ -48,7 +48,7 @@ export default class Counter extends PureComponent {
componentDidMount () { componentDidMount () {
const { measure, start_at, end_at, params } = this.props; const { measure, start_at, end_at, params } = this.props;
api().post("/api/v1/admin/measures", { keys: [measure], start_at, end_at, [measure]: params }).then(res => { api().post('/api/v1/admin/measures', { keys: [measure], start_at, end_at, [measure]: params }).then(res => {
this.setState({ this.setState({
loading: false, loading: false,
data: res.data, data: res.data,
@@ -78,7 +78,7 @@ export default class Counter extends PureComponent {
content = ( content = (
<> <>
<span className='sparkline__value__total'>{measure.human_value || <FormattedNumber value={measure.total} />}</span> <span className='sparkline__value__total'>{measure.human_value || <FormattedNumber value={measure.total} />}</span>
{measure.previous_total && (<span className={classNames("sparkline__value__change", { positive: percentChange > 0, negative: percentChange < 0 })}>{percentChange > 0 && "+"}<FormattedNumber value={percentChange} style='percent' /></span>)} {measure.previous_total && (<span className={classNames('sparkline__value__change', { positive: percentChange > 0, negative: percentChange < 0 })}>{percentChange > 0 && '+'}<FormattedNumber value={percentChange} style='percent' /></span>)}
</> </>
); );
} }
@@ -1,11 +1,11 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { FormattedNumber } from "react-intl"; import { FormattedNumber } from 'react-intl';
import api from "flavours/glitch/api"; import api from 'flavours/glitch/api';
import { Skeleton } from "flavours/glitch/components/skeleton"; import { Skeleton } from 'flavours/glitch/components/skeleton';
import { roundTo10 } from "flavours/glitch/utils/numbers"; import { roundTo10 } from 'flavours/glitch/utils/numbers';
export default class Dimension extends PureComponent { export default class Dimension extends PureComponent {
@@ -26,7 +26,7 @@ export default class Dimension extends PureComponent {
componentDidMount () { componentDidMount () {
const { start_at, end_at, dimension, limit, params } = this.props; const { start_at, end_at, dimension, limit, params } = this.props;
api().post("/api/v1/admin/dimensions", { keys: [dimension], start_at, end_at, limit, [dimension]: params }).then(res => { api().post('/api/v1/admin/dimensions', { keys: [dimension], start_at, end_at, limit, [dimension]: params }).then(res => {
this.setState({ this.setState({
loading: false, loading: false,
data: res.data, data: res.data,
@@ -74,7 +74,7 @@ export default class Dimension extends PureComponent {
</td> </td>
<td className='dimension__item__value'> <td className='dimension__item__value'>
{typeof item.human_value !== "undefined" ? item.human_value : <FormattedNumber value={item.value} />} {typeof item.human_value !== 'undefined' ? item.human_value : <FormattedNumber value={item.value} />}
</td> </td>
</tr> </tr>
))} ))}
@@ -1,12 +1,12 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { FormattedNumber, FormattedMessage } from "react-intl"; import { FormattedNumber, FormattedMessage } from 'react-intl';
import classNames from "classnames"; import classNames from 'classnames';
import api from "flavours/glitch/api"; import api from 'flavours/glitch/api';
import { Skeleton } from "flavours/glitch/components/skeleton"; import { Skeleton } from 'flavours/glitch/components/skeleton';
export default class ImpactReport extends PureComponent { export default class ImpactReport extends PureComponent {
@@ -27,8 +27,8 @@ export default class ImpactReport extends PureComponent {
include_subdomains: true, include_subdomains: true,
}; };
api().post("/api/v1/admin/measures", { api().post('/api/v1/admin/measures', {
keys: ["instance_accounts", "instance_follows", "instance_followers"], keys: ['instance_accounts', 'instance_follows', 'instance_followers'],
start_at: null, start_at: null,
end_at: null, end_at: null,
instance_accounts: params, instance_accounts: params,
@@ -63,7 +63,7 @@ export default class ImpactReport extends PureComponent {
</td> </td>
</tr> </tr>
<tr className={classNames("dimension__item", { negative: !loading && data[1].total > 0 })}> <tr className={classNames('dimension__item', { negative: !loading && data[1].total > 0 })}>
<td className='dimension__item__key'> <td className='dimension__item__key'>
<FormattedMessage id='admin.impact_report.instance_follows' defaultMessage='Followers their users would lose' /> <FormattedMessage id='admin.impact_report.instance_follows' defaultMessage='Followers their users would lose' />
</td> </td>
@@ -73,7 +73,7 @@ export default class ImpactReport extends PureComponent {
</td> </td>
</tr> </tr>
<tr className={classNames("dimension__item", { negative: !loading && data[2].total > 0 })}> <tr className={classNames('dimension__item', { negative: !loading && data[2].total > 0 })}>
<td className='dimension__item__key'> <td className='dimension__item__key'>
<FormattedMessage id='admin.impact_report.instance_followers' defaultMessage='Followers our users would lose' /> <FormattedMessage id='admin.impact_report.instance_followers' defaultMessage='Followers our users would lose' />
</td> </td>
@@ -1,17 +1,17 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { injectIntl, defineMessages } from "react-intl"; import { injectIntl, defineMessages } from 'react-intl';
import classNames from "classnames"; import classNames from 'classnames';
import api from "flavours/glitch/api"; import api from 'flavours/glitch/api';
const messages = defineMessages({ const messages = defineMessages({
legal: { id: "report.categories.legal", defaultMessage: "Legal" }, legal: { id: 'report.categories.legal', defaultMessage: 'Legal' },
other: { id: "report.categories.other", defaultMessage: "Other" }, other: { id: 'report.categories.other', defaultMessage: 'Other' },
spam: { id: "report.categories.spam", defaultMessage: "Spam" }, spam: { id: 'report.categories.spam', defaultMessage: 'Spam' },
violation: { id: "report.categories.violation", defaultMessage: "Content violates one or more server rules" }, violation: { id: 'report.categories.violation', defaultMessage: 'Content violates one or more server rules' },
}); });
class Category extends PureComponent { class Category extends PureComponent {
@@ -37,11 +37,11 @@ class Category extends PureComponent {
const { id, text, disabled, selected, children } = this.props; const { id, text, disabled, selected, children } = this.props;
return ( return (
<div tabIndex={0} role='button' className={classNames("report-reason-selector__category", { selected, disabled })} onClick={this.handleClick}> <div tabIndex={0} role='button' className={classNames('report-reason-selector__category', { selected, disabled })} onClick={this.handleClick}>
{selected && <input type='hidden' name='report[category]' value={id} />} {selected && <input type='hidden' name='report[category]' value={id} />}
<div className='report-reason-selector__category__label'> <div className='report-reason-selector__category__label'>
<span className={classNames("poll__input", { active: selected, disabled })} /> <span className={classNames('poll__input', { active: selected, disabled })} />
{text} {text}
</div> </div>
@@ -78,8 +78,8 @@ class Rule extends PureComponent {
const { id, text, disabled, selected } = this.props; const { id, text, disabled, selected } = this.props;
return ( return (
<div tabIndex={0} role='button' className={classNames("report-reason-selector__rule", { selected, disabled })} onClick={this.handleClick}> <div tabIndex={0} role='button' className={classNames('report-reason-selector__rule', { selected, disabled })} onClick={this.handleClick}>
<span className={classNames("poll__input", { checkbox: true, active: selected, disabled })} /> <span className={classNames('poll__input', { checkbox: true, active: selected, disabled })} />
{selected && <input type='hidden' name='report[rule_ids][]' value={id} />} {selected && <input type='hidden' name='report[rule_ids][]' value={id} />}
{text} {text}
</div> </div>
@@ -105,7 +105,7 @@ class ReportReasonSelector extends PureComponent {
}; };
componentDidMount() { componentDidMount() {
api().get("/api/v1/instance").then(res => { api().get('/api/v1/instance').then(res => {
this.setState({ this.setState({
rules: res.data.rules, rules: res.data.rules,
}); });
@@ -150,10 +150,10 @@ class ReportReasonSelector extends PureComponent {
return ( return (
<div className='report-reason-selector'> <div className='report-reason-selector'>
<Category id='other' text={intl.formatMessage(messages.other)} selected={category === "other"} onSelect={this.handleSelect} disabled={disabled} /> <Category id='other' text={intl.formatMessage(messages.other)} selected={category === 'other'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='legal' text={intl.formatMessage(messages.legal)} selected={category === "legal"} onSelect={this.handleSelect} disabled={disabled} /> <Category id='legal' text={intl.formatMessage(messages.legal)} selected={category === 'legal'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === "spam"} onSelect={this.handleSelect} disabled={disabled} /> <Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === 'spam'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === "violation"} onSelect={this.handleSelect} disabled={disabled}> <Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === 'violation'} onSelect={this.handleSelect} disabled={disabled}>
{rules.map(rule => <Rule key={rule.id} id={rule.id} text={rule.text} selected={rule_ids.includes(rule.id)} onToggle={this.handleToggle} disabled={disabled} />)} {rules.map(rule => <Rule key={rule.id} id={rule.id} text={rule.text} selected={rule_ids.includes(rule.id)} onToggle={this.handleToggle} disabled={disabled} />)}
</Category> </Category>
</div> </div>
@@ -1,20 +1,20 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { FormattedMessage, FormattedNumber, FormattedDate } from "react-intl"; import { FormattedMessage, FormattedNumber, FormattedDate } from 'react-intl';
import classNames from "classnames"; import classNames from 'classnames';
import api from "flavours/glitch/api"; import api from 'flavours/glitch/api';
import { roundTo10 } from "flavours/glitch/utils/numbers"; import { roundTo10 } from 'flavours/glitch/utils/numbers';
const dateForCohort = cohort => { const dateForCohort = cohort => {
const timeZone = "UTC"; const timeZone = 'UTC';
switch(cohort.frequency) { switch(cohort.frequency) {
case "day": case 'day':
return <FormattedDate value={cohort.period} month='long' day='2-digit' timeZone={timeZone} />; return <FormattedDate value={cohort.period} month='long' day='2-digit' timeZone={timeZone} />;
default: default:
return <FormattedDate value={cohort.period} month='long' year='numeric' timeZone={timeZone} />; return <FormattedDate value={cohort.period} month='long' year='numeric' timeZone={timeZone} />;
} }
}; };
@@ -34,7 +34,7 @@ export default class Retention extends PureComponent {
componentDidMount () { componentDidMount () {
const { start_at, end_at, frequency } = this.props; const { start_at, end_at, frequency } = this.props;
api().post("/api/v1/admin/retention", { start_at, end_at, frequency }).then(res => { api().post('/api/v1/admin/retention', { start_at, end_at, frequency }).then(res => {
this.setState({ this.setState({
loading: false, loading: false,
data: res.data, data: res.data,
@@ -96,7 +96,7 @@ export default class Retention extends PureComponent {
return ( return (
<td key={retention.date}> <td key={retention.date}>
<div className={classNames("retention__table__box", "retention__table__average", `retention__table__box--${roundTo10(average * 100)}`)}> <div className={classNames('retention__table__box', 'retention__table__average', `retention__table__box--${roundTo10(average * 100)}`)}>
<FormattedNumber value={average} style='percent' /> <FormattedNumber value={average} style='percent' />
</div> </div>
</td> </td>
@@ -122,7 +122,7 @@ export default class Retention extends PureComponent {
{cohort.data.slice(1).map(retention => ( {cohort.data.slice(1).map(retention => (
<td key={retention.date}> <td key={retention.date}>
<div className={classNames("retention__table__box", `retention__table__box--${roundTo10(retention.rate * 100)}`)}> <div className={classNames('retention__table__box', `retention__table__box--${roundTo10(retention.rate * 100)}`)}>
<FormattedNumber value={retention.rate} style='percent' /> <FormattedNumber value={retention.rate} style='percent' />
</div> </div>
</td> </td>
@@ -134,13 +134,13 @@ export default class Retention extends PureComponent {
); );
} }
let title; let title = null;
switch(frequency) { switch(frequency) {
case "day": case 'day':
title = <FormattedMessage id='admin.dashboard.daily_retention' defaultMessage='User retention rate by day after sign-up' />; title = <FormattedMessage id='admin.dashboard.daily_retention' defaultMessage='User retention rate by day after sign-up' />;
break; break;
default: default:
title = <FormattedMessage id='admin.dashboard.monthly_retention' defaultMessage='User retention rate by month after sign-up' />; title = <FormattedMessage id='admin.dashboard.monthly_retention' defaultMessage='User retention rate by month after sign-up' />;
} }
return ( return (
@@ -1,12 +1,12 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from 'react-intl';
import classNames from "classnames"; import classNames from 'classnames';
import api from "flavours/glitch/api"; import api from 'flavours/glitch/api';
import Hashtag from "flavours/glitch/components/hashtag"; import Hashtag from 'flavours/glitch/components/hashtag';
export default class Trends extends PureComponent { export default class Trends extends PureComponent {
@@ -22,7 +22,7 @@ export default class Trends extends PureComponent {
componentDidMount () { componentDidMount () {
const { limit } = this.props; const { limit } = this.props;
api().get("/api/v1/admin/trends/tags", { params: { limit } }).then(res => { api().get('/api/v1/admin/trends/tags', { params: { limit } }).then(res => {
this.setState({ this.setState({
loading: false, loading: false,
data: res.data, data: res.data,
@@ -57,7 +57,7 @@ export default class Trends extends PureComponent {
people={hashtag.history[0].accounts * 1 + hashtag.history[1].accounts * 1} people={hashtag.history[0].accounts * 1 + hashtag.history[1].accounts * 1}
uses={hashtag.history[0].uses * 1 + hashtag.history[1].uses * 1} uses={hashtag.history[0].uses * 1 + hashtag.history[1].uses * 1}
history={hashtag.history.reverse().map(day => day.uses)} history={hashtag.history.reverse().map(day => day.uses)}
className={classNames(hashtag.requires_review && "trends__item--requires-review", !hashtag.trendable && !hashtag.requires_review && "trends__item--disabled")} className={classNames(hashtag.requires_review && 'trends__item--requires-review', !hashtag.trendable && !hashtag.requires_review && 'trends__item--disabled')}
/> />
))} ))}
</div> </div>
@@ -1,11 +1,11 @@
import { useCallback, useState } from "react"; import { useCallback, useState } from 'react';
import * as React from "react"; import * as React from 'react';
import { TransitionMotion, spring } from "react-motion"; import { TransitionMotion, spring } from 'react-motion';
import { reduceMotion } from "../initial_state"; import { reduceMotion } from '../initial_state';
import { ShortNumber } from "./short_number"; import { ShortNumber } from './short_number';
const obfuscatedCount = (count: number) => { const obfuscatedCount = (count: number) => {
if (count < 0) { if (count < 0) {
@@ -13,13 +13,13 @@ const obfuscatedCount = (count: number) => {
} else if (count <= 1) { } else if (count <= 1) {
return count; return count;
} else { } else {
return "1+"; return '1+';
} }
}; };
interface Props { interface Props {
value: number, value: number;
obfuscate?: boolean, obfuscate?: boolean;
} }
export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => { export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
const [previousValue, setPreviousValue] = useState(value); const [previousValue, setPreviousValue] = useState(value);
@@ -64,7 +64,7 @@ export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
<span <span
key={key} key={key}
style={{ style={{
position: direction * style.y > 0 ? "absolute" : "static", position: direction * style.y > 0 ? 'absolute' : 'static',
transform: `translateY(${style.y * 100}%)`, transform: `translateY(${style.y * 100}%)`,
}} }}
> >
@@ -1,15 +1,15 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from 'react-intl';
import classNames from "classnames"; import classNames from 'classnames';
import ImmutablePropTypes from "react-immutable-proptypes"; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from "react-immutable-pure-component"; import ImmutablePureComponent from 'react-immutable-pure-component';
import { Icon } from "flavours/glitch/components/icon"; import { Icon } from 'flavours/glitch/components/icon';
const filename = url => url.split("/").pop().split("#")[0].split("?")[0]; const filename = url => url.split('/').pop().split('#')[0].split('?')[0];
export default class AttachmentList extends ImmutablePureComponent { export default class AttachmentList extends ImmutablePureComponent {
@@ -22,7 +22,7 @@ export default class AttachmentList extends ImmutablePureComponent {
const { media, compact } = this.props; const { media, compact } = this.props;
return ( return (
<div className={classNames("attachment-list", { compact })}> <div className={classNames('attachment-list', { compact })}>
{!compact && ( {!compact && (
<div className='attachment-list__icon'> <div className='attachment-list__icon'>
<Icon id='link' /> <Icon id='link' />
@@ -31,13 +31,13 @@ export default class AttachmentList extends ImmutablePureComponent {
<ul className='attachment-list__list'> <ul className='attachment-list__list'>
{media.map(attachment => { {media.map(attachment => {
const displayUrl = attachment.get("remote_url") || attachment.get("url"); const displayUrl = attachment.get('remote_url') || attachment.get('url');
return ( return (
<li key={attachment.get("id")}> <li key={attachment.get('id')}>
<a href={displayUrl} target='_blank' rel='noopener noreferrer'> <a href={displayUrl} target='_blank' rel='noopener noreferrer'>
{compact && <Icon id='link' />} {compact && <Icon id='link' />}
{compact && " " } {compact && ' ' }
{displayUrl ? filename(displayUrl) : <FormattedMessage id='attachments_list.unprocessed' defaultMessage='(unprocessed)' />} {displayUrl ? filename(displayUrl) : <FormattedMessage id='attachments_list.unprocessed' defaultMessage='(unprocessed)' />}
</a> </a>
</li> </li>
@@ -1,8 +1,8 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import unicodeMapping from "flavours/glitch/features/emoji/emoji_unicode_mapping_light"; import unicodeMapping from 'flavours/glitch/features/emoji/emoji_unicode_mapping_light';
import { assetHost } from "flavours/glitch/utils/config"; import { assetHost } from 'flavours/glitch/utils/config';
export default class AutosuggestEmoji extends PureComponent { export default class AutosuggestEmoji extends PureComponent {
@@ -17,7 +17,7 @@ export default class AutosuggestEmoji extends PureComponent {
if (emoji.custom) { if (emoji.custom) {
url = emoji.imageUrl; url = emoji.imageUrl;
} else { } else {
const mapping = unicodeMapping[emoji.native] || unicodeMapping[emoji.native.replace(/\uFE0F$/, "")]; const mapping = unicodeMapping[emoji.native] || unicodeMapping[emoji.native.replace(/\uFE0F$/, '')];
if (!mapping) { if (!mapping) {
return null; return null;
@@ -1,19 +1,19 @@
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from 'react-intl';
import { ShortNumber } from "flavours/glitch/components/short_number"; import { ShortNumber } from 'flavours/glitch/components/short_number';
interface Props { interface Props {
tag: { tag: {
name: string, name: string;
url?: string, url?: string;
history?: { history?: {
uses: number, uses: number;
accounts: string, accounts: string;
day: string, day: string;
}[], }[];
following?: boolean, following?: boolean;
type: "hashtag", type: 'hashtag';
}, };
} }
export const AutosuggestHashtag: React.FC<Props> = ({ tag }) => { export const AutosuggestHashtag: React.FC<Props> = ({ tag }) => {
@@ -1,14 +1,14 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import classNames from "classnames"; import classNames from 'classnames';
import ImmutablePropTypes from "react-immutable-proptypes"; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from "react-immutable-pure-component"; import ImmutablePureComponent from 'react-immutable-pure-component';
import AutosuggestAccountContainer from "flavours/glitch/features/compose/containers/autosuggest_account_container"; import AutosuggestAccountContainer from 'flavours/glitch/features/compose/containers/autosuggest_account_container';
import AutosuggestEmoji from "./autosuggest_emoji"; import AutosuggestEmoji from './autosuggest_emoji';
import { AutosuggestHashtag } from "./autosuggest_hashtag"; import { AutosuggestHashtag } from './autosuggest_hashtag';
const textAtCursorMatchesToken = (str, caretPosition, searchTokens) => { const textAtCursorMatchesToken = (str, caretPosition, searchTokens) => {
let word; let word;
@@ -59,7 +59,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
static defaultProps = { static defaultProps = {
autoFocus: true, autoFocus: true,
searchTokens: ["@", ":", "#"], searchTokens: ['@', ':', '#'],
}; };
state = { state = {
@@ -100,39 +100,39 @@ export default class AutosuggestInput extends ImmutablePureComponent {
} }
switch(e.key) { switch(e.key) {
case "Escape": case 'Escape':
if (suggestions.size === 0 || suggestionsHidden) { if (suggestions.size === 0 || suggestionsHidden) {
document.querySelector(".ui").parentElement.focus(); document.querySelector('.ui').parentElement.focus();
} else { } else {
e.preventDefault(); e.preventDefault();
this.setState({ suggestionsHidden: true }); this.setState({ suggestionsHidden: true });
} }
break; break;
case "ArrowDown": case 'ArrowDown':
if (suggestions.size > 0 && !suggestionsHidden) { if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault(); e.preventDefault();
this.setState({ selectedSuggestion: Math.min(selectedSuggestion + 1, suggestions.size - 1) }); this.setState({ selectedSuggestion: Math.min(selectedSuggestion + 1, suggestions.size - 1) });
} }
break; break;
case "ArrowUp": case 'ArrowUp':
if (suggestions.size > 0 && !suggestionsHidden) { if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault(); e.preventDefault();
this.setState({ selectedSuggestion: Math.max(selectedSuggestion - 1, 0) }); this.setState({ selectedSuggestion: Math.max(selectedSuggestion - 1, 0) });
} }
break; break;
case "Enter": case 'Enter':
case "Tab": case 'Tab':
// Select suggestion // Select suggestion
if (this.state.lastToken !== null && suggestions.size > 0 && !suggestionsHidden) { if (this.state.lastToken !== null && suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestions.get(selectedSuggestion)); this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestions.get(selectedSuggestion));
} }
break; break;
} }
if (e.defaultPrevented || !this.props.onKeyDown) { if (e.defaultPrevented || !this.props.onKeyDown) {
@@ -151,7 +151,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
}; };
onSuggestionClick = (e) => { onSuggestionClick = (e) => {
const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute("data-index")); const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index'));
e.preventDefault(); e.preventDefault();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion);
this.input.focus(); this.input.focus();
@@ -171,19 +171,19 @@ export default class AutosuggestInput extends ImmutablePureComponent {
const { selectedSuggestion } = this.state; const { selectedSuggestion } = this.state;
let inner, key; let inner, key;
if (suggestion.type === "emoji") { if (suggestion.type === 'emoji') {
inner = <AutosuggestEmoji emoji={suggestion} />; inner = <AutosuggestEmoji emoji={suggestion} />;
key = suggestion.id; key = suggestion.id;
} else if (suggestion.type ==="hashtag") { } else if (suggestion.type ==='hashtag') {
inner = <AutosuggestHashtag tag={suggestion} />; inner = <AutosuggestHashtag tag={suggestion} />;
key = suggestion.name; key = suggestion.name;
} else if (suggestion.type === "account") { } else if (suggestion.type === 'account') {
inner = <AutosuggestAccountContainer id={suggestion.id} />; inner = <AutosuggestAccountContainer id={suggestion.id} />;
key = suggestion.id; key = suggestion.id;
} }
return ( return (
<div role='button' tabIndex={0} key={key} data-index={i} className={classNames("autosuggest-textarea__suggestions__item", { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}> <div role='button' tabIndex={0} key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
{inner} {inner}
</div> </div>
); );
@@ -196,7 +196,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
return ( return (
<div className='autosuggest-input'> <div className='autosuggest-input'>
<label> <label>
<span style={{ display: "none" }}>{placeholder}</span> <span style={{ display: 'none' }}>{placeholder}</span>
<input <input
type='text' type='text'
@@ -220,7 +220,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
/> />
</label> </label>
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? "" : "autosuggest-textarea__suggestions--visible"}`}> <div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
{suggestions.map(this.renderSuggestion)} {suggestions.map(this.renderSuggestion)}
</div> </div>
</div> </div>
@@ -1,16 +1,16 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import classNames from "classnames"; import classNames from 'classnames';
import ImmutablePropTypes from "react-immutable-proptypes"; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from "react-immutable-pure-component"; import ImmutablePureComponent from 'react-immutable-pure-component';
import Textarea from "react-textarea-autosize"; import Textarea from 'react-textarea-autosize';
import AutosuggestAccountContainer from "flavours/glitch/features/compose/containers/autosuggest_account_container"; import AutosuggestAccountContainer from 'flavours/glitch/features/compose/containers/autosuggest_account_container';
import AutosuggestEmoji from "./autosuggest_emoji"; import AutosuggestEmoji from './autosuggest_emoji';
import { AutosuggestHashtag } from "./autosuggest_hashtag"; import { AutosuggestHashtag } from './autosuggest_hashtag';
const textAtCursorMatchesToken = (str, caretPosition) => { const textAtCursorMatchesToken = (str, caretPosition) => {
let word; let word;
@@ -24,7 +24,7 @@ const textAtCursorMatchesToken = (str, caretPosition) => {
word = str.slice(left, right + caretPosition); word = str.slice(left, right + caretPosition);
} }
if (!word || word.trim().length < 3 || ["@", ":", "#"].indexOf(word[0]) === -1) { if (!word || word.trim().length < 3 || ['@', ':', '#'].indexOf(word[0]) === -1) {
return [null, null]; return [null, null];
} }
@@ -97,39 +97,39 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
} }
switch(e.key) { switch(e.key) {
case "Escape": case 'Escape':
if (suggestions.size === 0 || suggestionsHidden) { if (suggestions.size === 0 || suggestionsHidden) {
document.querySelector(".ui").parentElement.focus(); document.querySelector('.ui').parentElement.focus();
} else { } else {
e.preventDefault(); e.preventDefault();
this.setState({ suggestionsHidden: true }); this.setState({ suggestionsHidden: true });
} }
break; break;
case "ArrowDown": case 'ArrowDown':
if (suggestions.size > 0 && !suggestionsHidden) { if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault(); e.preventDefault();
this.setState({ selectedSuggestion: Math.min(selectedSuggestion + 1, suggestions.size - 1) }); this.setState({ selectedSuggestion: Math.min(selectedSuggestion + 1, suggestions.size - 1) });
} }
break; break;
case "ArrowUp": case 'ArrowUp':
if (suggestions.size > 0 && !suggestionsHidden) { if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault(); e.preventDefault();
this.setState({ selectedSuggestion: Math.max(selectedSuggestion - 1, 0) }); this.setState({ selectedSuggestion: Math.max(selectedSuggestion - 1, 0) });
} }
break; break;
case "Enter": case 'Enter':
case "Tab": case 'Tab':
// Select suggestion // Select suggestion
if (this.state.lastToken !== null && suggestions.size > 0 && !suggestionsHidden) { if (this.state.lastToken !== null && suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestions.get(selectedSuggestion)); this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestions.get(selectedSuggestion));
} }
break; break;
} }
if (e.defaultPrevented || !this.props.onKeyDown) { if (e.defaultPrevented || !this.props.onKeyDown) {
@@ -151,7 +151,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
}; };
onSuggestionClick = (e) => { onSuggestionClick = (e) => {
const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute("data-index")); const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index'));
e.preventDefault(); e.preventDefault();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion);
this.textarea.focus(); this.textarea.focus();
@@ -178,19 +178,19 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
const { selectedSuggestion } = this.state; const { selectedSuggestion } = this.state;
let inner, key; let inner, key;
if (suggestion.type === "emoji") { if (suggestion.type === 'emoji') {
inner = <AutosuggestEmoji emoji={suggestion} />; inner = <AutosuggestEmoji emoji={suggestion} />;
key = suggestion.id; key = suggestion.id;
} else if (suggestion.type === "hashtag") { } else if (suggestion.type === 'hashtag') {
inner = <AutosuggestHashtag tag={suggestion} />; inner = <AutosuggestHashtag tag={suggestion} />;
key = suggestion.name; key = suggestion.name;
} else if (suggestion.type === "account") { } else if (suggestion.type === 'account') {
inner = <AutosuggestAccountContainer id={suggestion.id} />; inner = <AutosuggestAccountContainer id={suggestion.id} />;
key = suggestion.id; key = suggestion.id;
} }
return ( return (
<div role='button' tabIndex={0} key={key} data-index={i} className={classNames("autosuggest-textarea__suggestions__item", { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}> <div role='button' tabIndex={0} key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
{inner} {inner}
</div> </div>
); );
@@ -204,7 +204,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
<div className='compose-form__autosuggest-wrapper' key='autosuggest-wrapper'> <div className='compose-form__autosuggest-wrapper' key='autosuggest-wrapper'>
<div className='autosuggest-textarea'> <div className='autosuggest-textarea'>
<label> <label>
<span style={{ display: "none" }}>{placeholder}</span> <span style={{ display: 'none' }}>{placeholder}</span>
<Textarea <Textarea
ref={this.setTextarea} ref={this.setTextarea}
@@ -229,7 +229,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
</div>, </div>,
<div className='autosuggest-textarea__suggestions-wrapper' key='suggestions-wrapper'> <div className='autosuggest-textarea__suggestions-wrapper' key='suggestions-wrapper'>
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? "" : "autosuggest-textarea__suggestions--visible"}`}> <div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
{suggestions.map(this.renderSuggestion)} {suggestions.map(this.renderSuggestion)}
</div> </div>
</div>, </div>,
@@ -1,17 +1,17 @@
import * as React from "react"; import * as React from 'react';
import classNames from "classnames"; import classNames from 'classnames';
import { useHovering } from "flavours/glitch/hooks/useHovering"; import { useHovering } from 'flavours/glitch/hooks/useHovering';
import { autoPlayGif } from "flavours/glitch/initial_state"; import { autoPlayGif } from 'flavours/glitch/initial_state';
import { type Account } from "flavours/glitch/types/resources"; import type { Account } from 'flavours/glitch/types/resources';
interface Props { interface Props {
account: Account | undefined, account: Account | undefined;
className?: string, className?: string;
size: number, size: number;
style?: React.CSSProperties, style?: React.CSSProperties;
inline?: boolean, inline?: boolean;
} }
export const Avatar: React.FC<Props> = ({ export const Avatar: React.FC<Props> = ({
@@ -33,23 +33,23 @@ export const Avatar: React.FC<Props> = ({
if (account) { if (account) {
style.backgroundImage = `url(${account.get( style.backgroundImage = `url(${account.get(
hovering ? "avatar" : "avatar_static", hovering ? 'avatar' : 'avatar_static',
)})`; )})`;
} }
return ( return (
<div <div
className={classNames( className={classNames(
"account__avatar", 'account__avatar',
{ "account__avatar-inline": inline }, { 'account__avatar-inline': inline },
className, className,
)} )}
onMouseEnter={handleMouseEnter} onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave} onMouseLeave={handleMouseLeave}
style={style} style={style}
data-avatar-of={account && `@${account.get("acct")}`} data-avatar-of={account && `@${account.get('acct')}`}
role='img' role='img'
aria-label={account?.get("acct")} aria-label={account?.get('acct')}
/> />
); );
}; };
@@ -1,9 +1,9 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import ImmutablePropTypes from "react-immutable-proptypes"; import ImmutablePropTypes from 'react-immutable-proptypes';
import { autoPlayGif } from "flavours/glitch/initial_state"; import { autoPlayGif } from 'flavours/glitch/initial_state';
export default class AvatarComposite extends PureComponent { export default class AvatarComposite extends PureComponent {
@@ -22,10 +22,10 @@ export default class AvatarComposite extends PureComponent {
let width = 50; let width = 50;
let height = 100; let height = 100;
let top = "auto"; let top = 'auto';
let left = "auto"; let left = 'auto';
let bottom = "auto"; let bottom = 'auto';
let right = "auto"; let right = 'auto';
if (size === 1) { if (size === 1) {
width = 100; width = 100;
@@ -37,35 +37,35 @@ export default class AvatarComposite extends PureComponent {
if (size === 2) { if (size === 2) {
if (index === 0) { if (index === 0) {
right = "1px"; right = '1px';
} else { } else {
left = "1px"; left = '1px';
} }
} else if (size === 3) { } else if (size === 3) {
if (index === 0) { if (index === 0) {
right = "1px"; right = '1px';
} else if (index > 0) { } else if (index > 0) {
left = "1px"; left = '1px';
} }
if (index === 1) { if (index === 1) {
bottom = "1px"; bottom = '1px';
} else if (index > 1) { } else if (index > 1) {
top = "1px"; top = '1px';
} }
} else if (size === 4) { } else if (size === 4) {
if (index === 0 || index === 2) { if (index === 0 || index === 2) {
right = "1px"; right = '1px';
} }
if (index === 1 || index === 3) { if (index === 1 || index === 3) {
left = "1px"; left = '1px';
} }
if (index < 2) { if (index < 2) {
bottom = "1px"; bottom = '1px';
} else { } else {
top = "1px"; top = '1px';
} }
} }
@@ -76,12 +76,12 @@ export default class AvatarComposite extends PureComponent {
bottom: bottom, bottom: bottom,
width: `${width}%`, width: `${width}%`,
height: `${height}%`, height: `${height}%`,
backgroundSize: "cover", backgroundSize: 'cover',
backgroundImage: `url(${account.get(animate ? "avatar" : "avatar_static")})`, backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
}; };
return ( return (
<div key={account.get("id")} style={style} data-avatar-of={`@${account.get("acct")}`} /> <div key={account.get('id')} style={style} data-avatar-of={`@${account.get('acct')}`} />
); );
} }
@@ -1,9 +1,9 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import ImmutablePropTypes from "react-immutable-proptypes"; import ImmutablePropTypes from 'react-immutable-proptypes';
import { autoPlayGif } from "flavours/glitch/initial_state"; import { autoPlayGif } from 'flavours/glitch/initial_state';
export default class AvatarOverlay extends PureComponent { export default class AvatarOverlay extends PureComponent {
@@ -21,17 +21,17 @@ export default class AvatarOverlay extends PureComponent {
const { account, friend, animate } = this.props; const { account, friend, animate } = this.props;
const baseStyle = { const baseStyle = {
backgroundImage: `url(${account.get(animate ? "avatar" : "avatar_static")})`, backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
}; };
const overlayStyle = { const overlayStyle = {
backgroundImage: `url(${friend.get(animate ? "avatar" : "avatar_static")})`, backgroundImage: `url(${friend.get(animate ? 'avatar' : 'avatar_static')})`,
}; };
return ( return (
<div className='account__avatar-overlay'> <div className='account__avatar-overlay'>
<div className='account__avatar-overlay-base' style={baseStyle} data-avatar-of={`@${account.get("acct")}`} /> <div className='account__avatar-overlay-base' style={baseStyle} data-avatar-of={`@${account.get('acct')}`} />
<div className='account__avatar-overlay-overlay' style={overlayStyle} data-avatar-of={`@${friend.get("acct")}`} /> <div className='account__avatar-overlay-overlay' style={overlayStyle} data-avatar-of={`@${friend.get('acct')}`} />
</div> </div>
); );
} }
@@ -1,14 +1,14 @@
import { useRef, useEffect } from "react"; import { useRef, useEffect } from 'react';
import * as React from "react"; import * as React from 'react';
import { decode } from "blurhash"; import { decode } from 'blurhash';
interface Props extends React.HTMLAttributes<HTMLCanvasElement> { interface Props extends React.HTMLAttributes<HTMLCanvasElement> {
hash: string, hash: string;
width?: number, width?: number;
height?: number, height?: number;
dummy?: boolean, // Whether dummy mode is enabled. If enabled, nothing is rendered and canvas left untouched dummy?: boolean; // Whether dummy mode is enabled. If enabled, nothing is rendered and canvas left untouched
children?: never, children?: never;
} }
const Blurhash: React.FC<Props> = ({ const Blurhash: React.FC<Props> = ({
hash, hash,
@@ -26,18 +26,16 @@ const Blurhash: React.FC<Props> = ({
// eslint-disable-next-line no-self-assign // eslint-disable-next-line no-self-assign
canvas.width = canvas.width; // resets canvas canvas.width = canvas.width; // resets canvas
if (dummy || !hash) { if (dummy || !hash) return;
return;
}
try { try {
const pixels = decode(hash, width, height); const pixels = decode(hash, width, height);
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext('2d');
const imageData = new ImageData(pixels, width, height); const imageData = new ImageData(pixels, width, height);
ctx?.putImageData(imageData, 0, 0); ctx?.putImageData(imageData, 0, 0);
} catch (err) { } catch (err) {
console.error("Blurhash decoding failure", { err, hash }); console.error('Blurhash decoding failure', { err, hash });
} }
}, [dummy, hash, width, height]); }, [dummy, hash, width, height]);
@@ -1,7 +1,7 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import classNames from "classnames"; import classNames from 'classnames';
export default class Button extends PureComponent { export default class Button extends PureComponent {
@@ -32,18 +32,16 @@ export default class Button extends PureComponent {
render () { render () {
let attrs = { let attrs = {
className: classNames("button", this.props.className, { className: classNames('button', this.props.className, {
"button-secondary": this.props.secondary, 'button-secondary': this.props.secondary,
"button--block": this.props.block, 'button--block': this.props.block,
}), }),
disabled: this.props.disabled, disabled: this.props.disabled,
onClick: this.handleClick, onClick: this.handleClick,
ref: this.setRef, ref: this.setRef,
}; };
if (this.props.title) { if (this.props.title) attrs.title = this.props.title;
attrs.title = this.props.title;
}
return ( return (
<button {...attrs}> <button {...attrs}>
@@ -1,6 +1,6 @@
interface Props { interface Props {
size: number, size: number;
strokeWidth: number, strokeWidth: number;
} }
export const CircularProgress: React.FC<Props> = ({ size, strokeWidth }) => { export const CircularProgress: React.FC<Props> = ({ size, strokeWidth }) => {
@@ -1,9 +1,9 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { supportsPassiveEvents } from "detect-passive-events"; import { supportsPassiveEvents } from 'detect-passive-events';
import { scrollTop } from "../scroll"; import { scrollTop } from '../scroll';
const listenerOptions = supportsPassiveEvents ? { passive: true } : false; const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
@@ -23,12 +23,12 @@ export default class Column extends PureComponent {
if (this.props.bindToDocument) { if (this.props.bindToDocument) {
scrollable = document.scrollingElement; scrollable = document.scrollingElement;
} else { } else {
scrollable = this.node.querySelector(".scrollable"); scrollable = this.node.querySelector('.scrollable');
// Some columns have nested `.scrollable` containers, with the outer one // Some columns have nested `.scrollable` containers, with the outer one
// being a wrapper while the actual scrollable content is deeper. // being a wrapper while the actual scrollable content is deeper.
if (scrollable.classList.contains("scrollable--flex")) { if (scrollable.classList.contains('scrollable--flex')) {
scrollable = scrollable?.querySelector(".scrollable") || scrollable; scrollable = scrollable?.querySelector('.scrollable') || scrollable;
} }
} }
@@ -40,7 +40,7 @@ export default class Column extends PureComponent {
} }
handleWheel = () => { handleWheel = () => {
if (typeof this._interruptScrollAnimation !== "function") { if (typeof this._interruptScrollAnimation !== 'function') {
return; return;
} }
@@ -53,17 +53,17 @@ export default class Column extends PureComponent {
componentDidMount () { componentDidMount () {
if (this.props.bindToDocument) { if (this.props.bindToDocument) {
document.addEventListener("wheel", this.handleWheel, listenerOptions); document.addEventListener('wheel', this.handleWheel, listenerOptions);
} else { } else {
this.node.addEventListener("wheel", this.handleWheel, listenerOptions); this.node.addEventListener('wheel', this.handleWheel, listenerOptions);
} }
} }
componentWillUnmount () { componentWillUnmount () {
if (this.props.bindToDocument) { if (this.props.bindToDocument) {
document.removeEventListener("wheel", this.handleWheel, listenerOptions); document.removeEventListener('wheel', this.handleWheel, listenerOptions);
} else { } else {
this.node.removeEventListener("wheel", this.handleWheel, listenerOptions); this.node.removeEventListener('wheel', this.handleWheel, listenerOptions);
} }
} }
@@ -71,7 +71,7 @@ export default class Column extends PureComponent {
const { children, extraClasses, name, label } = this.props; const { children, extraClasses, name, label } = this.props;
return ( return (
<div role='region' aria-label={label} data-column={name} className={`column ${extraClasses || ""}`} ref={this.setRef}> <div role='region' aria-label={label} data-column={name} className={`column ${extraClasses || ''}`} ref={this.setRef}>
{children} {children}
</div> </div>
); );
@@ -1,10 +1,10 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { createPortal } from "react-dom"; import { createPortal } from 'react-dom';
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from 'react-intl';
import { Icon } from "flavours/glitch/components/icon"; import { Icon } from 'flavours/glitch/components/icon';
export default class ColumnBackButton extends PureComponent { export default class ColumnBackButton extends PureComponent {
@@ -23,7 +23,7 @@ export default class ColumnBackButton extends PureComponent {
if (router.history.location?.state?.fromMastodon) { if (router.history.location?.state?.fromMastodon) {
router.history.goBack(); router.history.goBack();
} else { } else {
router.history.push("/"); router.history.push('/');
} }
}; };
@@ -43,7 +43,7 @@ export default class ColumnBackButton extends PureComponent {
// The portal container and the component may be rendered to the DOM in // The portal container and the component may be rendered to the DOM in
// the same React render pass, so the container might not be available at // the same React render pass, so the container might not be available at
// the time `render()` is called. // the time `render()` is called.
const container = document.getElementById("tabs-bar__portal"); const container = document.getElementById('tabs-bar__portal');
if (container === null) { if (container === null) {
// The container wasn't available, force a re-render so that the // The container wasn't available, force a re-render so that the
// component can eventually be inserted in the container and not scroll // component can eventually be inserted in the container and not scroll
@@ -1,9 +1,9 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from 'react-intl';
import { Icon } from "flavours/glitch/components/icon"; import { Icon } from 'flavours/glitch/components/icon';
export default class ColumnBackButtonSlim extends PureComponent { export default class ColumnBackButtonSlim extends PureComponent {
@@ -19,7 +19,7 @@ export default class ColumnBackButtonSlim extends PureComponent {
if (router.route.location.key) { if (router.route.location.key) {
router.history.goBack(); router.history.goBack();
} else { } else {
router.history.push("/"); router.history.push('/');
} }
}; };
@@ -1,18 +1,18 @@
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { createPortal } from "react-dom"; import { createPortal } from 'react-dom';
import { FormattedMessage, injectIntl, defineMessages } from "react-intl"; import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
import classNames from "classnames"; import classNames from 'classnames';
import { Icon } from "flavours/glitch/components/icon"; import { Icon } from 'flavours/glitch/components/icon';
const messages = defineMessages({ const messages = defineMessages({
show: { id: "column_header.show_settings", defaultMessage: "Show settings" }, show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
hide: { id: "column_header.hide_settings", defaultMessage: "Hide settings" }, hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
moveLeft: { id: "column_header.moveLeft_settings", defaultMessage: "Move column to the left" }, moveLeft: { id: 'column_header.moveLeft_settings', defaultMessage: 'Move column to the left' },
moveRight: { id: "column_header.moveRight_settings", defaultMessage: "Move column to the right" }, moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
}); });
class ColumnHeader extends PureComponent { class ColumnHeader extends PureComponent {
@@ -68,7 +68,7 @@ class ColumnHeader extends PureComponent {
if (router.history.location?.state?.fromMastodon) { if (router.history.location?.state?.fromMastodon) {
router.history.goBack(); router.history.goBack();
} else { } else {
router.history.push("/"); router.history.push('/');
} }
}; };
@@ -78,7 +78,7 @@ class ColumnHeader extends PureComponent {
handlePin = () => { handlePin = () => {
if (!this.props.pinned) { if (!this.props.pinned) {
this.context.router.history.replace("/"); this.context.router.history.replace('/');
} }
this.props.onPin(); this.props.onPin();
@@ -89,21 +89,21 @@ class ColumnHeader extends PureComponent {
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props; const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props;
const { collapsed, animating } = this.state; const { collapsed, animating } = this.state;
const wrapperClassName = classNames("column-header__wrapper", { const wrapperClassName = classNames('column-header__wrapper', {
"active": active, 'active': active,
}); });
const buttonClassName = classNames("column-header", { const buttonClassName = classNames('column-header', {
"active": active, 'active': active,
}); });
const collapsibleClassName = classNames("column-header__collapsible", { const collapsibleClassName = classNames('column-header__collapsible', {
"collapsed": collapsed, 'collapsed': collapsed,
"animating": animating, 'animating': animating,
}); });
const collapsibleButtonClassName = classNames("column-header__button", { const collapsibleButtonClassName = classNames('column-header__button', {
"active": !collapsed, 'active': !collapsed,
}); });
let extraContent, pinButton, moveButtons, backButton, collapseButton; let extraContent, pinButton, moveButtons, backButton, collapseButton;
@@ -200,7 +200,7 @@ class ColumnHeader extends PureComponent {
// The portal container and the component may be rendered to the DOM in // The portal container and the component may be rendered to the DOM in
// the same React render pass, so the container might not be available at // the same React render pass, so the container might not be available at
// the time `render()` is called. // the time `render()` is called.
const container = document.getElementById("tabs-bar__portal"); const container = document.getElementById('tabs-bar__portal');
if (container === null) { if (container === null) {
// The container wasn't available, force a re-render so that the // The container wasn't available, force a re-render so that the
// component can eventually be inserted in the container and not scroll // component can eventually be inserted in the container and not scroll
@@ -1,6 +1,6 @@
import React from "react"; import React from 'react';
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from 'react-intl';
export const StatusesCounter = ( export const StatusesCounter = (
displayNumber: React.ReactNode, displayNumber: React.ReactNode,
@@ -1,18 +1,18 @@
import { type PropsWithChildren } from "react"; import type { PropsWithChildren } from 'react';
import { useCallback, useState } from "react"; import { useCallback, useState } from 'react';
import { defineMessages, useIntl } from "react-intl"; import { defineMessages, useIntl } from 'react-intl';
import { bannerSettings } from "flavours/glitch/settings"; import { bannerSettings } from 'flavours/glitch/settings';
import { IconButton } from "./icon_button"; import { IconButton } from './icon_button';
const messages = defineMessages({ const messages = defineMessages({
dismiss: { id: "dismissable_banner.dismiss", defaultMessage: "Dismiss" }, dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' },
}); });
interface Props { interface Props {
id: string, id: string;
} }
export const DismissableBanner: React.FC<PropsWithChildren<Props>> = ({ export const DismissableBanner: React.FC<PropsWithChildren<Props>> = ({
@@ -1,20 +1,20 @@
import React from "react"; import React from 'react';
import classNames from "classnames"; import classNames from 'classnames';
import { type List } from "immutable"; import type { List } from 'immutable';
import { type Account } from "flavours/glitch/types/resources"; import type { Account } from 'flavours/glitch/types/resources';
import { autoPlayGif } from "../initial_state"; import { autoPlayGif } from '../initial_state';
import { Skeleton } from "./skeleton"; import { Skeleton } from './skeleton';
interface Props { interface Props {
account?: Account, account?: Account;
others?: List<Account>, others?: List<Account>;
localDomain?: string, localDomain?: string;
inline?: boolean, inline?: boolean;
} }
export class DisplayName extends React.PureComponent<Props> { export class DisplayName extends React.PureComponent<Props> {
@@ -26,13 +26,11 @@ export class DisplayName extends React.PureComponent<Props> {
} }
const emojis = const emojis =
currentTarget.querySelectorAll<HTMLImageElement>("img.custom-emoji"); currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
emojis.forEach((emoji) => { emojis.forEach((emoji) => {
const originalSrc = emoji.getAttribute("data-original"); const originalSrc = emoji.getAttribute('data-original');
if (originalSrc != null) { if (originalSrc != null) emoji.src = originalSrc;
emoji.src = originalSrc;
}
}); });
}; };
@@ -44,13 +42,11 @@ export class DisplayName extends React.PureComponent<Props> {
} }
const emojis = const emojis =
currentTarget.querySelectorAll<HTMLImageElement>("img.custom-emoji"); currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
emojis.forEach((emoji) => { emojis.forEach((emoji) => {
const staticSrc = emoji.getAttribute("data-static"); const staticSrc = emoji.getAttribute('data-static');
if (staticSrc != null) { if (staticSrc != null) emoji.src = staticSrc;
emoji.src = staticSrc;
}
}); });
}; };
@@ -71,22 +67,22 @@ export class DisplayName extends React.PureComponent<Props> {
displayName = others displayName = others
.take(2) .take(2)
.map((a) => ( .map((a) => (
<bdi key={a.get("id")}> <bdi key={a.get('id')}>
<strong <strong
className='display-name__html' className='display-name__html'
dangerouslySetInnerHTML={{ __html: a.get("display_name_html") }} dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }}
/> />
</bdi> </bdi>
)) ))
.reduce((prev, cur) => [prev, ", ", cur]); .reduce((prev, cur) => [prev, ', ', cur]);
if (others.size - 2 > 0) { if (others.size - 2 > 0) {
suffix = `+${others.size - 2}`; suffix = `+${others.size - 2}`;
} }
} else if (account) { } else if (account) {
let acct = account.get("acct"); let acct = account.get('acct');
if (!acct.includes("@") && localDomain) { if (!acct.includes('@') && localDomain) {
acct = `${acct}@${localDomain}`; acct = `${acct}@${localDomain}`;
} }
@@ -95,7 +91,7 @@ export class DisplayName extends React.PureComponent<Props> {
<strong <strong
className='display-name__html' className='display-name__html'
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: account.get("display_name_html"), __html: account.get('display_name_html'),
}} }}
/> />
</bdi> </bdi>
@@ -118,12 +114,12 @@ export class DisplayName extends React.PureComponent<Props> {
return ( return (
<span <span
className={classNames("display-name", { inline })} className={classNames('display-name', { inline })}
onMouseEnter={this.handleMouseEnter} onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave} onMouseLeave={this.handleMouseLeave}
> >
{displayName} {displayName}
{inline ? " " : null} {inline ? ' ' : null}
{suffix} {suffix}
</span> </span>
); );
@@ -1,20 +1,20 @@
import { useCallback } from "react"; import { useCallback } from 'react';
import * as React from "react"; import * as React from 'react';
import { defineMessages, useIntl } from "react-intl"; import { defineMessages, useIntl } from 'react-intl';
import { IconButton } from "./icon_button"; import { IconButton } from './icon_button';
const messages = defineMessages({ const messages = defineMessages({
unblockDomain: { unblockDomain: {
id: "account.unblock_domain", id: 'account.unblock_domain',
defaultMessage: "Unblock domain {domain}", defaultMessage: 'Unblock domain {domain}',
}, },
}); });
interface Props { interface Props {
domain: string, domain: string;
onUnblockDomain: (domain: string) => void, onUnblockDomain: (domain: string) => void;
} }
export const Domain: React.FC<Props> = ({ domain, onUnblockDomain }) => { export const Domain: React.FC<Props> = ({ domain, onUnblockDomain }) => {

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