[build] upgrade eslint to 9.37.0 (#88)

Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/88
Co-authored-by: Zoë Bijl <moiety@noreply.codeberg.org>
Co-committed-by: Zoë Bijl <moiety@noreply.codeberg.org>
This commit is contained in:
Zoë Bijl
2025-10-12 13:42:02 +02:00
committed by tobi
parent 75d7a62693
commit 1ff70886a1
975 changed files with 22196 additions and 21964 deletions

View File

@@ -1,13 +0,0 @@
/build/**
/coverage/**
/db/**
/lib/**
/log/**
/node_modules/**
/nonobox/**
/public/**
!/public/embed.js
/spec/**
/tmp/**
/vendor/**
!.eslintrc.js

View File

@@ -1,403 +0,0 @@
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',
mts: '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',
},
},
],
};

View File

@@ -1,4 +1,4 @@
module.exports = { module.exports = {
singleQuote: true, singleQuote: true,
jsxSingleQuote: true jsxSingleQuote: true,
} };

View File

@@ -4,10 +4,10 @@ FROM docker.io/superseriousbusiness/masto-fe-standalone-woodpecker-build:0.1.0 A
# Prepare the build directory, copy # Prepare the build directory, copy
# relevant source + config files over. # relevant source + config files over.
WORKDIR /build WORKDIR /build
COPY app /build/app COPY --chown=node:node app /build/app
COPY config /build/config COPY --chown=node:node config /build/config
COPY public /build/public COPY --chown=node:node public /build/public
COPY \ COPY --chown=node:node \
.browserslistrc \ .browserslistrc \
babel.config.js \ babel.config.js \
jsconfig.json \ jsconfig.json \
@@ -20,7 +20,7 @@ COPY \
RUN yarn && yarn build:production RUN yarn && yarn build:production
### RUNTIME IMAGE ### ### RUNTIME IMAGE ###
FROM nginx:1.28.0-alpine AS runtime FROM nginx:alpine AS runtime
# Copy bigger nested stuff. # 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

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 Rails 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 }) => { Rails.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 }) => { Rails.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', () => { Rails.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', () => { Rails.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', () => { Rails.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', () => { Rails.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 }) => { Rails.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)); Rails.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)); Rails.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,38 +173,44 @@ 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)); Rails.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) onDomainBlockSeverityChange(domainBlockSeverityInput); if (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) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts); if (enableBootstrapTimelineAccounts) {
onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts);
}
const registrationMode = document.getElementById('form_admin_settings_registrations_mode'); const registrationMode = document.getElementById("form_admin_settings_registrations_mode");
if (registrationMode) onChangeRegistrationMode(registrationMode); if (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);
} }
@@ -213,15 +219,15 @@ ready(() => {
} }
}); });
Rails.delegate(document, 'form', 'submit', ({ target }) => { Rails.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);
} }

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";

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);

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);
} }
}); });

View File

@@ -1,3 +1,3 @@
import '../styles/mailer.scss'; import "../styles/mailer.scss";
require.context('../icons'); require.context("../icons");

View File

@@ -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);
} }

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 Rails from "@rails/ujs";
Rails.delegate(document, '#edit_profile input[type=file]', 'change', ({ target }) => { Rails.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 }) => { Rails.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 }) => { Rails.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) {

View File

@@ -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();
}); });
} }

View File

@@ -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,

View File

@@ -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)));

View File

@@ -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;

View File

@@ -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;
} }
} }

View File

@@ -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");

View File

@@ -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" }));
}; };
} }

View File

@@ -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 => {

View File

@@ -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,
})); }));
}; };

View File

@@ -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 {

View File

@@ -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 => {

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,15 +316,17 @@ 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) break; if (media.size + i >= uploadLimit) {
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));
@@ -370,7 +372,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 }) => {
@@ -415,7 +417,7 @@ export function initMediaEditModal(id) {
}); });
dispatch(openModal({ dispatch(openModal({
modalType: 'FOCAL_POINT', modalType: "FOCAL_POINT",
modalProps: { id }, modalProps: { id },
})); }));
}; };
@@ -440,16 +442,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) } };
} }
@@ -543,7 +545,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: {
@@ -564,7 +566,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));
}; };
@@ -577,11 +579,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,
@@ -600,10 +602,10 @@ 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:
@@ -638,18 +640,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,
@@ -685,7 +687,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) {
@@ -697,8 +699,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);

View File

@@ -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)));

View File

@@ -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));

View File

@@ -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)));

View File

@@ -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));

View File

@@ -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",
); );

View File

@@ -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 => {

View File

@@ -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 => {

View File

@@ -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;
} }

View File

@@ -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,10 +49,14 @@ 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) onSuccess(); if (onSuccess) {
onSuccess();
}
}).catch(error => { }).catch(error => {
dispatch(createFilterStatusFail(error)); dispatch(createFilterStatusFail(error));
if (onFail) onFail(); if (onFail) {
onFail();
}
}); });
}; };
@@ -73,12 +77,16 @@ 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) onSuccess(response.data); if (onSuccess) {
onSuccess(response.data);
}
}).catch(error => { }).catch(error => {
dispatch(createFilterFail(error)); dispatch(createFilterFail(error));
if (onFail) onFail(); if (onFail) {
onFail();
}
}); });
}; };

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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));

View File

@@ -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]))]));
}; };
} }

View File

@@ -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,

View File

@@ -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 => {

View File

@@ -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({

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"])));
}; };

View File

@@ -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));
}; };
} }

View File

@@ -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));

View File

@@ -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");

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" }));
}; };
} }

View File

@@ -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());
} }
}); });

View File

@@ -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());
} }
}; };

View File

@@ -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,

View File

@@ -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) => {

View File

@@ -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());

View File

@@ -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";

View File

@@ -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);
} }

View File

@@ -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 {

View File

@@ -1,29 +1,33 @@
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) onSuccess(); if (onSuccess) {
onSuccess();
}
}).catch(error => { }).catch(error => {
dispatch(submitReportFail(error)); dispatch(submitReportFail(error));
if (onFail) onFail(); if (onFail) {
onFail();
}
}); });
}; };

View File

@@ -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) {

View File

@@ -1,21 +1,21 @@
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;
} }
@@ -24,15 +24,19 @@ export const fetchServer = () => (dispatch, getState) => {
/* global data */ /* global data */
try { try {
api(getState) api(getState)
.get('/api/v2/instance').then({ data }).catch(error => { .get("/api/v2/instance").then({ data }).catch(error => {
console.error(error); console.error(error);
}); });
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account)); if (data.contact.account) {
dispatch(importFetchedAccount(data.contact.account));
}
dispatch(fetchServerSuccess(data)); 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) dispatch(importFetchedAccount(data.contact_account)); if (data.contact_account) {
dispatch(importFetchedAccount(data.contact_account));
}
dispatch(fetchServerSuccess(data)); dispatch(fetchServerSuccess(data));
}).catch(err => dispatch(fetchServerFail(err))); }).catch(err => dispatch(fetchServerFail(err)));
} }
@@ -53,14 +57,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) {

View File

@@ -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 });

View File

@@ -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));

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"]);
} }
}); });
}; };

View File

@@ -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 -- this is not a react hook // eslint-disable-next-line react-hooks/rules-of-hooks
pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000)); pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
}); });
}; };
@@ -88,34 +88,34 @@ 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,9 +129,7 @@ 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))))));
}; };
@@ -141,7 +139,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
@@ -149,7 +147,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
@@ -159,7 +157,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
@@ -169,17 +167,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) });

View File

@@ -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)));

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));

View File

@@ -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:"),
}; };
} }

View File

@@ -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 => {

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}`;
}; };

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) => {

View File

@@ -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} />

View File

@@ -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>)}
</> </>
); );
} }

View File

@@ -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>
))} ))}

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,17 +1,17 @@
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,9 +134,9 @@ export default class Retention extends PureComponent {
); );
} }
let title = null; let title;
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:

View File

@@ -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>

View File

@@ -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}%)`,
}} }}
> >

View File

@@ -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>

View File

@@ -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;

View File

@@ -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 }) => {

View File

@@ -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,31 +100,31 @@ 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();
@@ -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>

View File

@@ -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,31 +97,31 @@ 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();
@@ -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>,

View File

@@ -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")}
/> />
); );
}; };

View File

@@ -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")}`} />
); );
} }

View File

@@ -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>
); );
} }

View File

@@ -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,16 +26,18 @@ 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) return; if (dummy || !hash) {
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]);

View File

@@ -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,16 +32,18 @@ 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) attrs.title = this.props.title; if (this.props.title) {
attrs.title = this.props.title;
}
return ( return (
<button {...attrs}> <button {...attrs}>

View File

@@ -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 }) => {

View File

@@ -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>
); );

View File

@@ -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

View File

@@ -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("/");
} }
}; };

View File

@@ -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

View File

@@ -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,

View File

@@ -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>> = ({

View File

@@ -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,11 +26,13 @@ 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) emoji.src = originalSrc; if (originalSrc != null) {
emoji.src = originalSrc;
}
}); });
}; };
@@ -42,11 +44,13 @@ 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) emoji.src = staticSrc; if (staticSrc != null) {
emoji.src = staticSrc;
}
}); });
}; };
@@ -67,22 +71,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}`;
} }
@@ -91,7 +95,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>
@@ -114,12 +118,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>
); );

View File

@@ -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 }) => {

View File

@@ -1,15 +1,15 @@
import PropTypes from 'prop-types'; import PropTypes from "prop-types";
import { PureComponent, cloneElement, Children } from 'react'; import { PureComponent, cloneElement, Children } from "react";
import classNames from 'classnames'; import classNames from "classnames";
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from "react-immutable-proptypes";
import { supportsPassiveEvents } from 'detect-passive-events'; import { supportsPassiveEvents } from "detect-passive-events";
import Overlay from 'react-overlays/Overlay'; import Overlay from "react-overlays/Overlay";
import { CircularProgress } from "./circular_progress"; import { CircularProgress } from "./circular_progress";
import { IconButton } from './icon_button'; import { IconButton } from "./icon_button";
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true; const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
let id = 0; let id = 0;
@@ -44,9 +44,9 @@ class DropdownMenu extends PureComponent {
}; };
componentDidMount () { componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, { capture: true }); document.addEventListener("click", this.handleDocumentClick, { capture: true });
document.addEventListener('keydown', this.handleKeyDown, { capture: true }); document.addEventListener("keydown", this.handleKeyDown, { capture: true });
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); document.addEventListener("touchend", this.handleDocumentClick, listenerOptions);
if (this.focusedItem && this.props.openedViaKeyboard) { if (this.focusedItem && this.props.openedViaKeyboard) {
this.focusedItem.focus({ preventScroll: true }); this.focusedItem.focus({ preventScroll: true });
@@ -54,9 +54,9 @@ class DropdownMenu extends PureComponent {
} }
componentWillUnmount () { componentWillUnmount () {
document.removeEventListener('click', this.handleDocumentClick, { capture: true }); document.removeEventListener("click", this.handleDocumentClick, { capture: true });
document.removeEventListener('keydown', this.handleKeyDown, { capture: true }); document.removeEventListener("keydown", this.handleKeyDown, { capture: true });
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); document.removeEventListener("touchend", this.handleDocumentClick, listenerOptions);
} }
setRef = c => { setRef = c => {
@@ -68,31 +68,31 @@ class DropdownMenu extends PureComponent {
}; };
handleKeyDown = e => { handleKeyDown = e => {
const items = Array.from(this.node.querySelectorAll('a, button')); const items = Array.from(this.node.querySelectorAll("a, button"));
const index = items.indexOf(document.activeElement); const index = items.indexOf(document.activeElement);
let element = null; let element = null;
switch(e.key) { switch(e.key) {
case 'ArrowDown': case "ArrowDown":
element = items[index+1] || items[0]; element = items[index+1] || items[0];
break; break;
case 'ArrowUp': case "ArrowUp":
element = items[index-1] || items[items.length-1]; element = items[index-1] || items[items.length-1];
break; break;
case 'Tab': case "Tab":
if (e.shiftKey) { if (e.shiftKey) {
element = items[index-1] || items[items.length-1]; element = items[index-1] || items[items.length-1];
} else { } else {
element = items[index+1] || items[0]; element = items[index+1] || items[0];
} }
break; break;
case 'Home': case "Home":
element = items[0]; element = items[0];
break; break;
case 'End': case "End":
element = items[items.length-1]; element = items[items.length-1];
break; break;
case 'Escape': case "Escape":
this.props.onClose(); this.props.onClose();
break; break;
} }
@@ -105,7 +105,7 @@ class DropdownMenu extends PureComponent {
}; };
handleItemKeyPress = e => { handleItemKeyPress = e => {
if (e.key === 'Enter' || e.key === ' ') { if (e.key === "Enter" || e.key === " ") {
this.handleClick(e); this.handleClick(e);
} }
}; };
@@ -120,10 +120,10 @@ class DropdownMenu extends PureComponent {
return <li key={`sep-${i}`} className='dropdown-menu__separator' />; return <li key={`sep-${i}`} className='dropdown-menu__separator' />;
} }
const { text, href = '#', target = '_blank', method, dangerous } = option; const { text, href = "#", target = "_blank", method, dangerous } = option;
return ( return (
<li className={classNames('dropdown-menu__item', { 'dropdown-menu__item--dangerous': dangerous })} key={`${text}-${i}`}> <li className={classNames("dropdown-menu__item", { "dropdown-menu__item--dangerous": dangerous })} key={`${text}-${i}`}>
<a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}> <a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
{text} {text}
</a> </a>
@@ -137,7 +137,7 @@ class DropdownMenu extends PureComponent {
let renderItem = this.props.renderItem || this.renderItem; let renderItem = this.props.renderItem || this.renderItem;
return ( return (
<div className={classNames('dropdown-menu__container', { 'dropdown-menu__container--loading': loading })} ref={this.setRef}> <div className={classNames("dropdown-menu__container", { "dropdown-menu__container--loading": loading })} ref={this.setRef}>
{loading && ( {loading && (
<CircularProgress size={30} strokeWidth={3.5} /> <CircularProgress size={30} strokeWidth={3.5} />
)} )}
@@ -149,7 +149,7 @@ class DropdownMenu extends PureComponent {
)} )}
{!loading && ( {!loading && (
<ul className={classNames('dropdown-menu__container__list', { 'dropdown-menu__container__list--scrollable': scrollable })}> <ul className={classNames("dropdown-menu__container__list", { "dropdown-menu__container__list--scrollable": scrollable })}>
{items.map((option, i) => renderItem(option, i, { onClick: this.handleClick, onKeyPress: this.handleItemKeyPress }))} {items.map((option, i) => renderItem(option, i, { onClick: this.handleClick, onKeyPress: this.handleItemKeyPress }))}
</ul> </ul>
)} )}
@@ -186,7 +186,7 @@ export default class Dropdown extends PureComponent {
}; };
static defaultProps = { static defaultProps = {
title: 'Menu', title: "Menu",
}; };
state = { state = {
@@ -197,7 +197,7 @@ export default class Dropdown extends PureComponent {
if (this.state.id === this.props.openDropdownId) { if (this.state.id === this.props.openDropdownId) {
this.handleClose(); this.handleClose();
} else { } else {
this.props.onOpen(this.state.id, this.handleItemClick, type !== 'click'); this.props.onOpen(this.state.id, this.handleItemClick, type !== "click");
} }
}; };
@@ -217,8 +217,8 @@ export default class Dropdown extends PureComponent {
handleButtonKeyDown = (e) => { handleButtonKeyDown = (e) => {
switch(e.key) { switch(e.key) {
case ' ': case " ":
case 'Enter': case "Enter":
this.handleMouseDown(); this.handleMouseDown();
break; break;
} }
@@ -226,8 +226,8 @@ export default class Dropdown extends PureComponent {
handleKeyPress = (e) => { handleKeyPress = (e) => {
switch(e.key) { switch(e.key) {
case ' ': case " ":
case 'Enter': case "Enter":
this.handleClick(e); this.handleClick(e);
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
@@ -237,15 +237,15 @@ export default class Dropdown extends PureComponent {
handleItemClick = e => { handleItemClick = e => {
const { onItemClick } = this.props; const { onItemClick } = this.props;
const i = Number(e.currentTarget.getAttribute('data-index')); const i = Number(e.currentTarget.getAttribute("data-index"));
const item = this.props.items[i]; const item = this.props.items[i];
this.handleClose(); this.handleClose();
if (typeof onItemClick === 'function') { if (typeof onItemClick === "function") {
e.preventDefault(); e.preventDefault();
onItemClick(item, i); onItemClick(item, i);
} else if (item && typeof item.action === 'function') { } else if (item && typeof item.action === "function") {
e.preventDefault(); e.preventDefault();
item.action(); item.action();
} else if (item && item.to) { } else if (item && item.to) {
@@ -314,7 +314,7 @@ export default class Dropdown extends PureComponent {
<span ref={this.setTargetRef}> <span ref={this.setTargetRef}>
{button} {button}
</span> </span>
<Overlay show={open} offset={[5, 5]} placement={'bottom'} flip target={this.findTarget} popperConfig={{ strategy: 'fixed' }}> <Overlay show={open} offset={[5, 5]} placement={"bottom"} flip target={this.findTarget} popperConfig={{ strategy: "fixed" }}>
{({ props, arrowProps, placement }) => ( {({ props, arrowProps, placement }) => (
<div {...props}> <div {...props}>
<div className={`dropdown-animation dropdown-menu ${placement}`}> <div className={`dropdown-animation dropdown-menu ${placement}`}>

View File

@@ -1,8 +1,8 @@
import { connect } from 'react-redux'; import { connect } from "react-redux";
import { openDropdownMenu, closeDropdownMenu } from 'flavours/glitch/actions/dropdown_menu'; import { openDropdownMenu, closeDropdownMenu } from "flavours/glitch/actions/dropdown_menu";
import { fetchHistory } from 'flavours/glitch/actions/history'; import { fetchHistory } from "flavours/glitch/actions/history";
import DropdownMenu from 'flavours/glitch/components/dropdown_menu'; import DropdownMenu from "flavours/glitch/components/dropdown_menu";
/** /**
* *
@@ -12,8 +12,8 @@ import DropdownMenu from 'flavours/glitch/components/dropdown_menu';
const mapStateToProps = (state, { statusId }) => ({ const mapStateToProps = (state, { statusId }) => ({
openDropdownId: state.dropdownMenu.openId, openDropdownId: state.dropdownMenu.openId,
openedViaKeyboard: state.dropdownMenu.keyboard, openedViaKeyboard: state.dropdownMenu.keyboard,
items: state.getIn(['history', statusId, 'items']), items: state.getIn(["history", statusId, "items"]),
loading: state.getIn(['history', statusId, 'loading']), loading: state.getIn(["history", statusId, "loading"]),
}); });
const mapDispatchToProps = (dispatch, { statusId }) => ({ const mapDispatchToProps = (dispatch, { statusId }) => ({

View File

@@ -1,22 +1,22 @@
import PropTypes from 'prop-types'; import PropTypes from "prop-types";
import { PureComponent } from 'react'; import { PureComponent } from "react";
import { FormattedMessage, injectIntl } from 'react-intl'; import { FormattedMessage, injectIntl } from "react-intl";
import { connect } from 'react-redux'; import { connect } from "react-redux";
import { openModal } from 'flavours/glitch/actions/modal'; import { openModal } from "flavours/glitch/actions/modal";
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from "flavours/glitch/components/icon";
import InlineAccount from 'flavours/glitch/components/inline_account'; import InlineAccount from "flavours/glitch/components/inline_account";
import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp'; import { RelativeTimestamp } from "flavours/glitch/components/relative_timestamp";
import DropdownMenu from './containers/dropdown_menu_container'; import DropdownMenu from "./containers/dropdown_menu_container";
const mapDispatchToProps = (dispatch, { statusId }) => ({ const mapDispatchToProps = (dispatch, { statusId }) => ({
onItemClick (index) { onItemClick (index) {
dispatch(openModal({ dispatch(openModal({
modalType: 'COMPARE_HISTORY', modalType: "COMPARE_HISTORY",
modalProps: { index, statusId }, modalProps: { index, statusId },
})); }));
}, },
@@ -44,17 +44,17 @@ class EditedTimestamp extends PureComponent {
}; };
renderItem = (item, index, { onClick, onKeyPress }) => { renderItem = (item, index, { onClick, onKeyPress }) => {
const formattedDate = <RelativeTimestamp timestamp={item.get('created_at')} short={false} />; const formattedDate = <RelativeTimestamp timestamp={item.get("created_at")} short={false} />;
const formattedName = <InlineAccount accountId={item.get('account')} />; const formattedName = <InlineAccount accountId={item.get("account")} />;
const label = item.get('original') ? ( const label = item.get("original") ? (
<FormattedMessage id='status.history.created' defaultMessage='{name} created {date}' values={{ name: formattedName, date: formattedDate }} /> <FormattedMessage id='status.history.created' defaultMessage='{name} created {date}' values={{ name: formattedName, date: formattedDate }} />
) : ( ) : (
<FormattedMessage id='status.history.edited' defaultMessage='{name} edited {date}' values={{ name: formattedName, date: formattedDate }} /> <FormattedMessage id='status.history.edited' defaultMessage='{name} edited {date}' values={{ name: formattedName, date: formattedDate }} />
); );
return ( return (
<li className='dropdown-menu__item edited-timestamp__history__item' key={item.get('created_at')}> <li className='dropdown-menu__item edited-timestamp__history__item' key={item.get("created_at")}>
<button data-index={index} onClick={onClick} onKeyPress={onKeyPress}>{label}</button> <button data-index={index} onClick={onClick} onKeyPress={onKeyPress}>{label}</button>
</li> </li>
); );
@@ -66,7 +66,7 @@ class EditedTimestamp extends PureComponent {
return ( return (
<DropdownMenu statusId={statusId} renderItem={this.renderItem} scrollable renderHeader={this.renderHeader} onItemClick={this.handleItemClick}> <DropdownMenu statusId={statusId} renderItem={this.renderItem} scrollable renderHeader={this.renderHeader} onItemClick={this.handleItemClick}>
<button className='dropdown-menu__text-button'> <button className='dropdown-menu__text-button'>
<FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(timestamp, { hourCycle: 'h23', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) }} /> <Icon id='caret-down' /> <FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(timestamp, { hourCycle: "h23", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit" }) }} /> <Icon id='caret-down' />
</button> </button>
</DropdownMenu> </DropdownMenu>
); );

View File

@@ -1,13 +1,13 @@
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 { Helmet } from 'react-helmet'; import { Helmet } from "react-helmet";
import StackTrace from 'stacktrace-js'; import StackTrace from "stacktrace-js";
import { version, source_url } from 'flavours/glitch/initial_state'; import { version, source_url } from "flavours/glitch/initial_state";
export default class ErrorBoundary extends PureComponent { export default class ErrorBoundary extends PureComponent {
@@ -34,7 +34,7 @@ export default class ErrorBoundary extends PureComponent {
StackTrace.fromError(error).then((stackframes) => { StackTrace.fromError(error).then((stackframes) => {
this.setState({ this.setState({
mappedStackTrace: stackframes.map((sf) => sf.toString()).join('\n'), mappedStackTrace: stackframes.map((sf) => sf.toString()).join("\n"),
}); });
}).catch(() => { }).catch(() => {
this.setState({ this.setState({
@@ -45,23 +45,23 @@ export default class ErrorBoundary extends PureComponent {
handleCopyStackTrace = () => { handleCopyStackTrace = () => {
const { errorMessage, stackTrace, mappedStackTrace } = this.state; const { errorMessage, stackTrace, mappedStackTrace } = this.state;
const textarea = document.createElement('textarea'); const textarea = document.createElement("textarea");
let contents = [errorMessage, stackTrace]; let contents = [errorMessage, stackTrace];
if (mappedStackTrace) { if (mappedStackTrace) {
contents.push(mappedStackTrace); contents.push(mappedStackTrace);
} }
textarea.textContent = contents.join('\n\n\n'); textarea.textContent = contents.join("\n\n\n");
textarea.style.position = 'fixed'; textarea.style.position = "fixed";
document.body.appendChild(textarea); document.body.appendChild(textarea);
try { try {
textarea.select(); textarea.select();
document.execCommand('copy'); document.execCommand("copy");
} catch (e) { } catch (e) {
console.error(e);
} finally { } finally {
document.body.removeChild(textarea); document.body.removeChild(textarea);
} }
@@ -77,7 +77,7 @@ export default class ErrorBoundary extends PureComponent {
return this.props.children; return this.props.children;
} }
const likelyBrowserAddonIssue = errorMessage && errorMessage.includes('NotFoundError'); const likelyBrowserAddonIssue = errorMessage && errorMessage.includes("NotFoundError");
return ( return (
<div className='error-boundary'> <div className='error-boundary'>
@@ -98,7 +98,7 @@ export default class ErrorBoundary extends PureComponent {
)} )}
</p> </p>
<p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p> <p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? "copied" : ""}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
</div> </div>
<Helmet> <Helmet>

View File

@@ -1,14 +1,14 @@
import { useCallback, useState } from 'react'; import { useCallback, useState } from "react";
import * as React from 'react'; import * as React from "react";
interface Props { interface Props {
src: string; src: string,
key: string; key: string,
alt?: string; alt?: string,
lang?: string; lang?: string,
width: number; width: number,
height: number; height: number,
onClick?: () => void; onClick?: () => void,
} }
export const GIFV: React.FC<Props> = ({ export const GIFV: React.FC<Props> = ({
@@ -37,7 +37,7 @@ export const GIFV: React.FC<Props> = ({
); );
return ( return (
<div className='gifv' style={{ position: 'relative' }}> <div className='gifv' style={{ position: "relative" }}>
{loading && ( {loading && (
<canvas <canvas
width={width} width={width}
@@ -64,7 +64,7 @@ export const GIFV: React.FC<Props> = ({
playsInline playsInline
onClick={handleClick} onClick={handleClick}
onLoadedData={handleLoadedData} onLoadedData={handleLoadedData}
style={{ position: loading ? 'absolute' : 'static', top: 0, left: 0 }} style={{ position: loading ? "absolute" : "static", top: 0, left: 0 }}
/> />
</div> </div>
); );

View File

@@ -1,19 +1,19 @@
// @ts-check // @ts-check
import PropTypes from 'prop-types'; import PropTypes from "prop-types";
import { Component } from 'react'; import { Component } from "react";
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 { Sparklines, SparklinesCurve } from 'react-sparklines'; import { Sparklines, SparklinesCurve } from "react-sparklines";
import { ShortNumber } from 'flavours/glitch/components/short_number'; import { ShortNumber } from "flavours/glitch/components/short_number";
import { Skeleton } from 'flavours/glitch/components/skeleton'; import { Skeleton } from "flavours/glitch/components/skeleton";
import Permalink from './permalink'; import Permalink from "./permalink";
class SilentErrorBoundary extends Component { class SilentErrorBoundary extends Component {
@@ -58,12 +58,12 @@ export const accountsCountRenderer = (displayNumber, pluralReady) => (
// @ts-expect-error // @ts-expect-error
export const ImmutableHashtag = ({ hashtag }) => ( export const ImmutableHashtag = ({ hashtag }) => (
<Hashtag <Hashtag
name={hashtag.get('name')} name={hashtag.get("name")}
href={hashtag.get('url')} href={hashtag.get("url")}
to={`/tags/${hashtag.get('name')}`} to={`/tags/${hashtag.get("name")}`}
people={hashtag.getIn(['history', 0, 'accounts']) * 1 + hashtag.getIn(['history', 1, 'accounts']) * 1} people={hashtag.getIn(["history", 0, "accounts"]) * 1 + hashtag.getIn(["history", 1, "accounts"]) * 1}
// @ts-expect-error // @ts-expect-error
history={hashtag.get('history')?.reverse().map((day) => day.get('uses')).toArray()} history={hashtag.get("history")?.reverse().map((day) => day.get("uses")).toArray()}
/> />
); );
@@ -73,7 +73,7 @@ ImmutableHashtag.propTypes = {
// @ts-expect-error // @ts-expect-error
const Hashtag = ({ name, href, to, people, uses, history, className, description, withGraph }) => ( const Hashtag = ({ name, href, to, people, uses, history, className, description, withGraph }) => (
<div className={classNames('trends__item', className)}> <div className={classNames("trends__item", className)}>
<div className='trends__item__name'> <div className='trends__item__name'>
<Permalink href={href} to={to}> <Permalink href={href} to={to}>
{name ? <>#<span>{name}</span></> : <Skeleton width={50} />} {name ? <>#<span>{name}</span></> : <Skeleton width={50} />}
@@ -82,21 +82,21 @@ const Hashtag = ({ name, href, to, people, uses, history, className, description
{description ? ( {description ? (
<span>{description}</span> <span>{description}</span>
) : ( ) : (
!isNaN(people) && (typeof people !== 'undefined' ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} />) !isNaN(people) && (typeof people !== "undefined" ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} />)
)} )}
</div> </div>
{typeof uses !== 'undefined' && ( {typeof uses !== "undefined" && (
<div className='trends__item__current'> <div className='trends__item__current'>
<ShortNumber value={uses} /> <ShortNumber value={uses} />
</div> </div>
)} )}
{withGraph && typeof history !== 'undefined' && ( {withGraph && typeof history !== "undefined" && (
<div className='trends__item__sparkline'> <div className='trends__item__sparkline'>
<SilentErrorBoundary> <SilentErrorBoundary>
<Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}> <Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}>
<SparklinesCurve style={{ fill: 'none' }} /> <SparklinesCurve style={{ fill: "none" }} />
</Sparklines> </Sparklines>
</SilentErrorBoundary> </SilentErrorBoundary>
</div> </div>

View File

@@ -1,12 +1,12 @@
import * as React from 'react'; import * as React from "react";
import classNames from 'classnames'; import classNames from "classnames";
interface Props extends React.HTMLAttributes<HTMLImageElement> { interface Props extends React.HTMLAttributes<HTMLImageElement> {
id: string; id: string,
className?: string; className?: string,
fixedWidth?: boolean; fixedWidth?: boolean,
children?: never; children?: never,
} }
export const Icon: React.FC<Props> = ({ export const Icon: React.FC<Props> = ({
@@ -16,7 +16,7 @@ export const Icon: React.FC<Props> = ({
...other ...other
}) => ( }) => (
<i <i
className={classNames('fa', `fa-${id}`, className, { 'fa-fw': fixedWidth })} className={classNames("fa", `fa-${id}`, className, { "fa-fw": fixedWidth })}
{...other} {...other}
/> />
); );

View File

@@ -1,37 +1,37 @@
import * as React from 'react'; import * as React from "react";
import classNames from 'classnames'; import classNames from "classnames";
import { AnimatedNumber } from './animated_number'; import { AnimatedNumber } from "./animated_number";
import { Icon } from './icon'; import { Icon } from "./icon";
interface Props { interface Props {
className?: string; className?: string,
title: string; title: string,
icon: string; icon: string,
onClick?: React.MouseEventHandler<HTMLButtonElement>; onClick?: React.MouseEventHandler<HTMLButtonElement>,
onMouseDown?: React.MouseEventHandler<HTMLButtonElement>; onMouseDown?: React.MouseEventHandler<HTMLButtonElement>,
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>; onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>,
onKeyPress?: React.KeyboardEventHandler<HTMLButtonElement>; onKeyPress?: React.KeyboardEventHandler<HTMLButtonElement>,
size: number; size: number,
active: boolean; active: boolean,
expanded?: boolean; expanded?: boolean,
style?: React.CSSProperties; style?: React.CSSProperties,
activeStyle?: React.CSSProperties; activeStyle?: React.CSSProperties,
disabled: boolean; disabled: boolean,
inverted?: boolean; inverted?: boolean,
animate: boolean; animate: boolean,
overlay: boolean; overlay: boolean,
tabIndex: number; tabIndex: number,
label?: string; label?: string,
counter?: number; counter?: number,
obfuscateCount?: boolean; obfuscateCount?: boolean,
href?: string; href?: string,
ariaHidden: boolean; ariaHidden: boolean,
} }
interface States { interface States {
activate: boolean; activate: boolean,
deactivate: boolean; deactivate: boolean,
} }
export class IconButton extends React.PureComponent<Props, States> { export class IconButton extends React.PureComponent<Props, States> {
static defaultProps = { static defaultProps = {
@@ -50,7 +50,9 @@ export class IconButton extends React.PureComponent<Props, States> {
}; };
UNSAFE_componentWillReceiveProps(nextProps: Props) { UNSAFE_componentWillReceiveProps(nextProps: Props) {
if (!nextProps.animate) return; if (!nextProps.animate) {
return;
}
if (this.props.active && !nextProps.active) { if (this.props.active && !nextProps.active) {
this.setState({ activate: false, deactivate: true }); this.setState({ activate: false, deactivate: true });
@@ -67,12 +69,6 @@ export class IconButton extends React.PureComponent<Props, States> {
} }
}; };
handleKeyPress: React.KeyboardEventHandler<HTMLButtonElement> = (e) => {
if (this.props.onKeyPress && !this.props.disabled) {
this.props.onKeyPress(e);
}
};
handleMouseDown: React.MouseEventHandler<HTMLButtonElement> = (e) => { handleMouseDown: React.MouseEventHandler<HTMLButtonElement> = (e) => {
if (!this.props.disabled && this.props.onMouseDown) { if (!this.props.disabled && this.props.onMouseDown) {
this.props.onMouseDown(e); this.props.onMouseDown(e);
@@ -87,7 +83,7 @@ export class IconButton extends React.PureComponent<Props, States> {
render() { render() {
// Hack required for some icons which have an overriden size // Hack required for some icons which have an overriden size
let containerSize = '1.28571429em'; let containerSize = "1.28571429em";
if (this.props.style?.fontSize) { if (this.props.style?.fontSize) {
containerSize = `${this.props.size * 1.28571429}px`; containerSize = `${this.props.size * 1.28571429}px`;
} }
@@ -102,7 +98,7 @@ export class IconButton extends React.PureComponent<Props, States> {
if (!this.props.label) { if (!this.props.label) {
style.width = containerSize; style.width = containerSize;
} else { } else {
style.textAlign = 'left'; style.textAlign = "left";
} }
const { const {
@@ -123,24 +119,24 @@ export class IconButton extends React.PureComponent<Props, States> {
const { activate, deactivate } = this.state; const { activate, deactivate } = this.state;
const classes = classNames(className, 'icon-button', { const classes = classNames(className, "icon-button", {
active, active,
disabled, disabled,
inverted, inverted,
activate, activate,
deactivate, deactivate,
overlayed: overlay, overlayed: overlay,
'icon-button--with-counter': typeof counter !== 'undefined', "icon-button--with-counter": typeof counter !== "undefined",
}); });
if (typeof counter !== 'undefined') { if (typeof counter !== "undefined") {
style.width = 'auto'; style.width = "auto";
} }
let contents = ( let contents = (
<> <>
<Icon id={icon} fixedWidth aria-hidden='true' />{' '} <Icon id={icon} fixedWidth aria-hidden='true' />{" "}
{typeof counter !== 'undefined' && ( {typeof counter !== "undefined" && (
<span className='icon-button__counter'> <span className='icon-button__counter'>
<AnimatedNumber value={counter} obfuscate={obfuscateCount} /> <AnimatedNumber value={counter} obfuscate={obfuscateCount} />
</span> </span>
@@ -168,7 +164,6 @@ export class IconButton extends React.PureComponent<Props, States> {
onClick={this.handleClick} onClick={this.handleClick}
onMouseDown={this.handleMouseDown} onMouseDown={this.handleMouseDown}
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
onKeyPress={this.handleKeyPress}
style={style} style={style}
tabIndex={tabIndex} tabIndex={tabIndex}
disabled={disabled} disabled={disabled}

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