diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..3de57a360
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,12 @@
+node_modules/
+dist/
+logs/
+.DS_Store
+.git/
+config/local.json
+pleroma-backend/
+test/e2e/reports/
+test/e2e-playwright/test-results/
+test/e2e-playwright/playwright-report/
+__screenshots__/
+
diff --git a/.gitignore b/.gitignore
index 01ffda9a8..c4a96ee1e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,8 +4,11 @@ dist/
npm-debug.log
test/unit/coverage
test/e2e/reports
+test/e2e-playwright/test-results
+test/e2e-playwright/playwright-report
selenium-debug.log
.idea/
+.gitlab-ci-local/
config/local.json
src/assets/emoji.json
logs/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 99c85dd36..06fbf45f9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,12 +34,23 @@ check-changelog:
- apk add git
- sh ./tools/check-changelog
-lint:
+lint-eslint:
stage: lint
script:
- yarn
- - yarn lint
- - yarn stylelint
+ - yarn ci-eslint
+
+lint-biome:
+ stage: lint
+ script:
+ - yarn
+ - yarn ci-biome
+
+lint-stylelint:
+ stage: lint
+ script:
+ - yarn
+ - yarn ci-stylelint
test:
stage: test
@@ -60,6 +71,135 @@ test:
- test/**/__screenshots__
when: on_failure
+e2e-pleroma:
+ stage: test
+ image: mcr.microsoft.com/playwright:v1.57.0-jammy
+ services:
+ - name: postgres:15-alpine
+ alias: db
+ - name: $PLEROMA_IMAGE
+ alias: pleroma
+ entrypoint: ["/bin/ash", "-c"]
+ command:
+ - |
+ set -eu
+
+ SEED_SENTINEL_PATH=/var/lib/pleroma/.e2e_seeded
+ CONFIG_OVERRIDE_PATH=/var/lib/pleroma/config.exs
+
+ echo '-- Waiting for database...'
+ while ! pg_isready -U ${DB_USER:-pleroma} -d postgres://${DB_HOST:-db}:${DB_PORT:-5432}/${DB_NAME:-pleroma} -t 1; do
+ sleep 1s
+ done
+
+ echo '-- Writing E2E config overrides...'
+ cat > $CONFIG_OVERRIDE_PATH </dev/null; then
+ kill -TERM $PLEROMA_PID
+ wait $PLEROMA_PID || true
+ fi
+ }
+
+ trap cleanup INT TERM
+
+ echo '-- Waiting for API...'
+ api_ok=false
+ for _i in $(seq 1 120); do
+ if wget -qO- http://127.0.0.1:4000/api/v1/instance >/dev/null 2>&1; then
+ api_ok=true
+ break
+ fi
+ sleep 1s
+ done
+
+ if [ $api_ok != true ]; then
+ echo 'Timed out waiting for Pleroma API to become available'
+ exit 1
+ fi
+
+ if [ ! -f $SEED_SENTINEL_PATH ]; then
+ if [ -n ${E2E_ADMIN_USERNAME:-} ] && [ -n ${E2E_ADMIN_PASSWORD:-} ] && [ -n ${E2E_ADMIN_EMAIL:-} ]; then
+ echo '-- Seeding admin user' $E2E_ADMIN_USERNAME '...'
+ if ! /opt/pleroma/bin/pleroma_ctl user new $E2E_ADMIN_USERNAME $E2E_ADMIN_EMAIL --admin --password $E2E_ADMIN_PASSWORD -y; then
+ echo '-- User already exists or creation failed, ensuring admin + confirmed...'
+ /opt/pleroma/bin/pleroma_ctl user set $E2E_ADMIN_USERNAME --admin --confirmed
+ fi
+ else
+ echo '-- Skipping admin seeding (missing E2E_ADMIN_* env)'
+ fi
+
+ touch $SEED_SENTINEL_PATH
+ fi
+
+ wait $PLEROMA_PID
+ tags:
+ - amd64
+ - himem
+ variables:
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
+ FF_NETWORK_PER_BUILD: "true"
+ PLEROMA_IMAGE: git.pleroma.social:5050/pleroma/pleroma:stable
+ POSTGRES_USER: pleroma
+ POSTGRES_PASSWORD: pleroma
+ POSTGRES_DB: pleroma
+ DB_USER: pleroma
+ DB_PASS: pleroma
+ DB_NAME: pleroma
+ DB_HOST: db
+ DB_PORT: 5432
+ DOMAIN: localhost
+ INSTANCE_NAME: Pleroma E2E
+ E2E_ADMIN_USERNAME: admin
+ E2E_ADMIN_PASSWORD: adminadmin
+ E2E_ADMIN_EMAIL: admin@example.com
+ ADMIN_EMAIL: $E2E_ADMIN_EMAIL
+ NOTIFY_EMAIL: $E2E_ADMIN_EMAIL
+ VITE_PROXY_TARGET: http://pleroma:4000
+ VITE_PROXY_ORIGIN: http://localhost:4000
+ E2E_BASE_URL: http://localhost:8080
+ script:
+ - npm install -g yarn@1.22.22
+ - yarn --frozen-lockfile
+ - |
+ echo "-- Waiting for Pleroma API..."
+ api_ok="false"
+ for _i in $(seq 1 120); do
+ if wget -qO- http://pleroma:4000/api/v1/instance >/dev/null 2>&1; then
+ api_ok="true"
+ break
+ fi
+ sleep 1s
+ done
+ if [ "$api_ok" != "true" ]; then
+ echo "Timed out waiting for Pleroma API to become available"
+ exit 1
+ fi
+ - yarn e2e:pw
+ artifacts:
+ when: on_failure
+ paths:
+ - test/e2e-playwright/test-results
+ - test/e2e-playwright/playwright-report
+
build:
stage: build
tags:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b3d38ea24..1eb5a9cb4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## 2.10.1
+### Fixed
+- fixed being unable to set actor type from profile page
+- fixed error when clicking mute menu itself (instead of submenu items)
+- fixed mute -> domain status submenu not working
+
+### Internal
+- Add playwright E2E-tests with an optional docker-based backend
+
## 2.10.0
### Changed
- Temporary changes modal now shows actual countdown instead of fixed timeout
diff --git a/biome.json b/biome.json
new file mode 100644
index 000000000..d64639d52
--- /dev/null
+++ b/biome.json
@@ -0,0 +1,145 @@
+{
+ "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
+ "vcs": {
+ "enabled": true,
+ "clientKind": "git",
+ "useIgnoreFile": true
+ },
+ "files": {
+ "includes": ["**", "!!**/dist", "!!tools/emojis.json"]
+ },
+ "formatter": {
+ "enabled": true,
+ "indentStyle": "space"
+ },
+ "linter": {
+ "enabled": true,
+ "domains": {
+ "vue": "recommended"
+ },
+ "rules": {
+ "recommended": false,
+ "complexity": {
+ "noAdjacentSpacesInRegex": "error",
+ "noExtraBooleanCast": "error",
+ "noUselessCatch": "error",
+ "noUselessEscapeInRegex": "error"
+ },
+ "correctness": {
+ "noConstAssign": "error",
+ "noConstantCondition": "error",
+ "noEmptyCharacterClassInRegex": "error",
+ "noEmptyPattern": "error",
+ "noGlobalObjectCalls": "error",
+ "noInvalidBuiltinInstantiation": "error",
+ "noInvalidConstructorSuper": "error",
+ "noNonoctalDecimalEscape": "error",
+ "noPrecisionLoss": "error",
+ "noSelfAssign": "error",
+ "noSetterReturn": "error",
+ "noSwitchDeclarations": "error",
+ "noUndeclaredVariables": "error",
+ "noUnreachable": "error",
+ "noUnreachableSuper": "error",
+ "noUnsafeFinally": "error",
+ "noUnsafeOptionalChaining": "error",
+ "noUnusedLabels": "error",
+ "noUnusedPrivateClassMembers": "error",
+ "noUnusedVariables": "error",
+ "useIsNan": "error",
+ "useValidForDirection": "error",
+ "useValidTypeof": "error",
+ "useYield": "error"
+ },
+ "suspicious": {
+ "noAsyncPromiseExecutor": "error",
+ "noCatchAssign": "error",
+ "noClassAssign": "error",
+ "noCompareNegZero": "error",
+ "noConstantBinaryExpressions": "error",
+ "noControlCharactersInRegex": "error",
+ "noDebugger": "error",
+ "noDuplicateCase": "error",
+ "noDuplicateClassMembers": "error",
+ "noDuplicateElseIf": "error",
+ "noDuplicateObjectKeys": "error",
+ "noDuplicateParameters": "error",
+ "noEmptyBlockStatements": "error",
+ "noFallthroughSwitchClause": "error",
+ "noFunctionAssign": "error",
+ "noGlobalAssign": "error",
+ "noImportAssign": "error",
+ "noIrregularWhitespace": "error",
+ "noMisleadingCharacterClass": "error",
+ "noPrototypeBuiltins": "error",
+ "noRedeclare": "error",
+ "noShadowRestrictedNames": "error",
+ "noSparseArray": "error",
+ "noUnsafeNegation": "error",
+ "noUselessRegexBackrefs": "error",
+ "noWith": "error",
+ "useGetterReturn": "error"
+ }
+ }
+ },
+ "javascript": {
+ "formatter": {
+ "quoteStyle": "single",
+ "semicolons": "asNeeded"
+ },
+ "globals": []
+ },
+ "overrides": [
+ {
+ "includes": ["**/*.spec.js", "test/fixtures/*.js"],
+ "javascript": {
+ "globals": [
+ "vi",
+ "describe",
+ "it",
+ "test",
+ "expect",
+ "before",
+ "beforeEach",
+ "after",
+ "afterEach"
+ ]
+ }
+ },
+ {
+ "includes": ["**/*.vue"],
+ "linter": {
+ "rules": {
+ "style": {
+ "useConst": "off",
+ "useImportType": "off"
+ },
+ "correctness": {
+ "noUnusedVariables": "off",
+ "noUnusedImports": "off"
+ }
+ }
+ }
+ }
+ ],
+ "assist": {
+ "enabled": true,
+ "actions": {
+ "source": {
+ "organizeImports": {
+ "level": "on",
+ "options": {
+ "groups": [
+ [":NODE:", ":PACKAGE:", "!src/**", "!@fortawesome/**"],
+ ":BLANK_LINE:",
+ [":PATH:", "src/**"],
+ ":BLANK_LINE:",
+ "@fortawesome/fontawesome-svg-core",
+ "@fortawesome/*"
+ ]
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/build/check-versions.mjs b/build/check-versions.mjs
index 73c1eeb15..8c5968a30 100644
--- a/build/check-versions.mjs
+++ b/build/check-versions.mjs
@@ -1,5 +1,5 @@
-import semver from 'semver'
import chalk from 'chalk'
+import semver from 'semver'
import packageConfig from '../package.json' with { type: 'json' }
@@ -7,8 +7,8 @@ var versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
- versionRequirement: packageConfig.engines.node
- }
+ versionRequirement: packageConfig.engines.node,
+ },
]
export default function () {
@@ -16,15 +16,22 @@ export default function () {
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
- warnings.push(mod.name + ': ' +
- chalk.red(mod.currentVersion) + ' should be ' +
- chalk.green(mod.versionRequirement)
+ warnings.push(
+ mod.name +
+ ': ' +
+ chalk.red(mod.currentVersion) +
+ ' should be ' +
+ chalk.green(mod.versionRequirement),
)
}
}
if (warnings.length) {
- console.warn(chalk.yellow('\nTo use this template, you must update following to modules:\n'))
+ console.warn(
+ chalk.yellow(
+ '\nTo use this template, you must update following to modules:\n',
+ ),
+ )
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.warn(' ' + warning)
diff --git a/build/commit_hash.js b/build/commit_hash.js
index c104af5d9..c60355804 100644
--- a/build/commit_hash.js
+++ b/build/commit_hash.js
@@ -1,8 +1,8 @@
import childProcess from 'child_process'
-export const getCommitHash = (() => {
- const subst = "$Format:%h$"
- if(!subst.match(/Format:/)) {
+export const getCommitHash = () => {
+ const subst = '$Format:%h$'
+ if (!subst.match(/Format:/)) {
return subst
} else {
try {
@@ -15,4 +15,4 @@ export const getCommitHash = (() => {
return 'UNKNOWN'
}
}
-})
+}
diff --git a/build/copy_plugin.js b/build/copy_plugin.js
index 694048a36..4f020f359 100644
--- a/build/copy_plugin.js
+++ b/build/copy_plugin.js
@@ -1,8 +1,8 @@
-import serveStatic from 'serve-static'
-import { resolve } from 'node:path'
import { cp } from 'node:fs/promises'
+import { resolve } from 'node:path'
+import serveStatic from 'serve-static'
-const getPrefix = s => {
+const getPrefix = (s) => {
const padEnd = s.endsWith('/') ? s : s + '/'
return padEnd.startsWith('/') ? padEnd : '/' + padEnd
}
@@ -13,28 +13,31 @@ const copyPlugin = ({ inUrl, inFs }) => {
let copyTarget
const handler = serveStatic(inFs)
- return [{
- name: 'copy-plugin-serve',
- apply: 'serve',
- configureServer (server) {
- server.middlewares.use(prefix, handler)
- }
- }, {
- name: 'copy-plugin-build',
- apply: 'build',
- configResolved (config) {
- copyTarget = resolve(config.root, config.build.outDir, subdir)
+ return [
+ {
+ name: 'copy-plugin-serve',
+ apply: 'serve',
+ configureServer(server) {
+ server.middlewares.use(prefix, handler)
+ },
},
- closeBundle: {
- order: 'post',
- sequential: true,
- async handler () {
- console.info(`Copying '${inFs}' to ${copyTarget}...`)
- await cp(inFs, copyTarget, { recursive: true })
- console.info('Done.')
- }
- }
- }]
+ {
+ name: 'copy-plugin-build',
+ apply: 'build',
+ configResolved(config) {
+ copyTarget = resolve(config.root, config.build.outDir, subdir)
+ },
+ closeBundle: {
+ order: 'post',
+ sequential: true,
+ async handler() {
+ console.info(`Copying '${inFs}' to ${copyTarget}...`)
+ await cp(inFs, copyTarget, { recursive: true })
+ console.info('Done.')
+ },
+ },
+ },
+ ]
}
export default copyPlugin
diff --git a/build/emojis_plugin.js b/build/emojis_plugin.js
index aed52066d..7979086dd 100644
--- a/build/emojis_plugin.js
+++ b/build/emojis_plugin.js
@@ -1,21 +1,23 @@
-import { resolve } from 'node:path'
import { access } from 'node:fs/promises'
-import { languages, langCodeToCldrName } from '../src/i18n/languages.js'
+import { resolve } from 'node:path'
+
+import { languages } from '../src/i18n/languages.js'
const annotationsImportPrefix = '@kazvmoe-infra/unicode-emoji-json/annotations/'
const specialAnnotationsLocale = {
- ja_easy: 'ja'
+ ja_easy: 'ja',
}
-const internalToAnnotationsLocale = (internal) => specialAnnotationsLocale[internal] || internal
+const internalToAnnotationsLocale = (internal) =>
+ specialAnnotationsLocale[internal] || internal
// This gets all the annotations that are accessible (whose language
// can be chosen in the settings). Data for other languages are
// discarded because there is no way for it to be fetched.
const getAllAccessibleAnnotations = async (projectRoot) => {
- const imports = (await Promise.all(
- languages
- .map(async lang => {
+ const imports = (
+ await Promise.all(
+ languages.map(async (lang) => {
const destLang = internalToAnnotationsLocale(lang)
const importModule = `${annotationsImportPrefix}${destLang}.json`
const importFile = resolve(projectRoot, 'node_modules', importModule)
@@ -23,11 +25,14 @@ const getAllAccessibleAnnotations = async (projectRoot) => {
await access(importFile)
return `'${lang}': () => import('${importModule}')`
} catch (e) {
+ console.error(e)
return
}
- })))
- .filter(k => k)
- .join(',\n')
+ }),
+ )
+ )
+ .filter((k) => k)
+ .join(',\n')
return `
export const annotationsLoader = {
@@ -43,21 +48,21 @@ const emojisPlugin = () => {
let projectRoot
return {
name: 'emojis-plugin',
- configResolved (conf) {
+ configResolved(conf) {
projectRoot = conf.root
},
- resolveId (id) {
+ resolveId(id) {
if (id === emojiAnnotationsId) {
return emojiAnnotationsIdResolved
}
return null
},
- async load (id) {
+ async load(id) {
if (id === emojiAnnotationsIdResolved) {
return await getAllAccessibleAnnotations(projectRoot)
}
return null
- }
+ },
}
}
diff --git a/build/msw_plugin.js b/build/msw_plugin.js
index f544348fc..c4e9098c5 100644
--- a/build/msw_plugin.js
+++ b/build/msw_plugin.js
@@ -1,5 +1,5 @@
-import { resolve } from 'node:path'
import { readFile } from 'node:fs/promises'
+import { resolve } from 'node:path'
const target = 'node_modules/msw/lib/mockServiceWorker.js'
@@ -8,10 +8,10 @@ const mswPlugin = () => {
return {
name: 'msw-plugin',
apply: 'serve',
- configResolved (conf) {
+ configResolved(conf) {
projectRoot = conf.root
},
- configureServer (server) {
+ configureServer(server) {
server.middlewares.use(async (req, res, next) => {
if (req.path === '/mockServiceWorker.js') {
const file = await readFile(resolve(projectRoot, target))
@@ -21,7 +21,7 @@ const mswPlugin = () => {
next()
}
})
- }
+ },
}
}
diff --git a/build/service_worker_messages.js b/build/service_worker_messages.js
index c078e8563..0948aa919 100644
--- a/build/service_worker_messages.js
+++ b/build/service_worker_messages.js
@@ -1,11 +1,12 @@
-import { languages, langCodeToJsonName } from '../src/i18n/languages.js'
import { readFile } from 'node:fs/promises'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
+import { langCodeToJsonName, languages } from '../src/i18n/languages.js'
+
const i18nDir = resolve(
dirname(dirname(fileURLToPath(import.meta.url))),
- 'src/i18n'
+ 'src/i18n',
)
export const i18nFiles = languages.reduce((acc, lang) => {
@@ -16,13 +17,15 @@ export const i18nFiles = languages.reduce((acc, lang) => {
}, {})
export const generateServiceWorkerMessages = async () => {
- const msgArray = await Promise.all(Object.entries(i18nFiles).map(async ([lang, file]) => {
- const fileContent = await readFile(file, 'utf-8')
- const msg = {
- notifications: JSON.parse(fileContent).notifications || {}
- }
- return [lang, msg]
- }))
+ const msgArray = await Promise.all(
+ Object.entries(i18nFiles).map(async ([lang, file]) => {
+ const fileContent = await readFile(file, 'utf-8')
+ const msg = {
+ notifications: JSON.parse(fileContent).notifications || {},
+ }
+ return [lang, msg]
+ }),
+ )
return msgArray.reduce((acc, [lang, msg]) => {
acc[lang] = msg
return acc
diff --git a/build/sw_plugin.js b/build/sw_plugin.js
index d970c5c09..03c5978d7 100644
--- a/build/sw_plugin.js
+++ b/build/sw_plugin.js
@@ -1,9 +1,13 @@
-import { fileURLToPath } from 'node:url'
-import { dirname, resolve } from 'node:path'
import { readFile } from 'node:fs/promises'
-import { build } from 'vite'
+import { dirname, resolve } from 'node:path'
+import { fileURLToPath } from 'node:url'
import * as esbuild from 'esbuild'
-import { generateServiceWorkerMessages, i18nFiles } from './service_worker_messages.js'
+import { build } from 'vite'
+
+import {
+ generateServiceWorkerMessages,
+ i18nFiles,
+} from './service_worker_messages.js'
const getSWMessagesAsText = async () => {
const messages = await generateServiceWorkerMessages()
@@ -14,14 +18,10 @@ const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)))
const swEnvName = 'virtual:pleroma-fe/service_worker_env'
const swEnvNameResolved = '\0' + swEnvName
const getDevSwEnv = () => `self.serviceWorkerOption = { assets: [] };`
-const getProdSwEnv = ({ assets }) => `self.serviceWorkerOption = { assets: ${JSON.stringify(assets)} };`
+const getProdSwEnv = ({ assets }) =>
+ `self.serviceWorkerOption = { assets: ${JSON.stringify(assets)} };`
-export const devSwPlugin = ({
- swSrc,
- swDest,
- transformSW,
- alias
-}) => {
+export const devSwPlugin = ({ swSrc, swDest, transformSW, alias }) => {
const swFullSrc = resolve(projectRoot, swSrc)
const esbuildAlias = {}
Object.entries(alias).forEach(([source, dest]) => {
@@ -31,9 +31,10 @@ export const devSwPlugin = ({
return {
name: 'dev-sw-plugin',
apply: 'serve',
- configResolved (conf) {
+ configResolved() {
+ /* no-op */
},
- resolveId (id) {
+ resolveId(id) {
const name = id.startsWith('/') ? id.slice(1) : id
if (name === swDest) {
return swFullSrc
@@ -42,7 +43,7 @@ export const devSwPlugin = ({
}
return null
},
- async load (id) {
+ async load(id) {
if (id === swFullSrc) {
return readFile(swFullSrc, 'utf-8')
} else if (id === swEnvNameResolved) {
@@ -55,7 +56,7 @@ export const devSwPlugin = ({
* during dev, and firefox does not support ESM as service worker
* https://bugzilla.mozilla.org/show_bug.cgi?id=1360870
*/
- async transform (code, id) {
+ async transform(code, id) {
if (id === swFullSrc && transformSW) {
const res = await esbuild.build({
entryPoints: [swSrc],
@@ -63,52 +64,54 @@ export const devSwPlugin = ({
write: false,
outfile: 'sw-pleroma.js',
alias: esbuildAlias,
- plugins: [{
- name: 'vite-like-root-resolve',
- setup (b) {
- b.onResolve(
- { filter: new RegExp(/^\//) },
- args => ({
- path: resolve(projectRoot, args.path.slice(1))
- })
- )
- }
- }, {
- name: 'sw-messages',
- setup (b) {
- b.onResolve(
- { filter: new RegExp('^' + swMessagesName + '$') },
- args => ({
- path: args.path,
- namespace: 'sw-messages'
+ plugins: [
+ {
+ name: 'vite-like-root-resolve',
+ setup(b) {
+ b.onResolve({ filter: new RegExp(/^\//) }, (args) => ({
+ path: resolve(projectRoot, args.path.slice(1)),
}))
- b.onLoad(
- { filter: /.*/, namespace: 'sw-messages' },
- async () => ({
- contents: await getSWMessagesAsText()
+ },
+ },
+ {
+ name: 'sw-messages',
+ setup(b) {
+ b.onResolve(
+ { filter: new RegExp('^' + swMessagesName + '$') },
+ (args) => ({
+ path: args.path,
+ namespace: 'sw-messages',
+ }),
+ )
+ b.onLoad(
+ { filter: /.*/, namespace: 'sw-messages' },
+ async () => ({
+ contents: await getSWMessagesAsText(),
+ }),
+ )
+ },
+ },
+ {
+ name: 'sw-env',
+ setup(b) {
+ b.onResolve(
+ { filter: new RegExp('^' + swEnvName + '$') },
+ (args) => ({
+ path: args.path,
+ namespace: 'sw-env',
+ }),
+ )
+ b.onLoad({ filter: /.*/, namespace: 'sw-env' }, () => ({
+ contents: getDevSwEnv(),
}))
- }
- }, {
- name: 'sw-env',
- setup (b) {
- b.onResolve(
- { filter: new RegExp('^' + swEnvName + '$') },
- args => ({
- path: args.path,
- namespace: 'sw-env'
- }))
- b.onLoad(
- { filter: /.*/, namespace: 'sw-env' },
- () => ({
- contents: getDevSwEnv()
- }))
- }
- }]
+ },
+ },
+ ],
})
const text = res.outputFiles[0].text
return text
}
- }
+ },
}
}
@@ -118,16 +121,13 @@ export const devSwPlugin = ({
// however, we must compile the service worker to iife because of browser support.
// Run another vite build just for the service worker targeting iife at
// the end of the build.
-export const buildSwPlugin = ({
- swSrc,
- swDest,
-}) => {
+export const buildSwPlugin = ({ swSrc, swDest }) => {
let config
return {
name: 'build-sw-plugin',
enforce: 'post',
apply: 'build',
- configResolved (resolvedConfig) {
+ configResolved(resolvedConfig) {
config = {
define: resolvedConfig.define,
resolve: resolvedConfig.resolve,
@@ -138,50 +138,50 @@ export const buildSwPlugin = ({
lib: {
entry: swSrc,
formats: ['iife'],
- name: 'sw_pleroma'
+ name: 'sw_pleroma',
},
emptyOutDir: false,
rollupOptions: {
output: {
- entryFileNames: swDest
- }
- }
+ entryFileNames: swDest,
+ },
+ },
},
- configFile: false
+ configFile: false,
}
},
generateBundle: {
order: 'post',
sequential: true,
- async handler (_, bundle) {
+ async handler(_, bundle) {
const assets = Object.keys(bundle)
- .filter(name => !/\.map$/.test(name))
- .map(name => '/' + name)
+ .filter((name) => !/\.map$/.test(name))
+ .map((name) => '/' + name)
config.plugins.push({
name: 'build-sw-env-plugin',
- resolveId (id) {
+ resolveId(id) {
if (id === swEnvName) {
return swEnvNameResolved
}
return null
},
- load (id) {
+ load(id) {
if (id === swEnvNameResolved) {
return getProdSwEnv({ assets })
}
return null
- }
+ },
})
- }
+ },
},
closeBundle: {
order: 'post',
sequential: true,
- async handler () {
+ async handler() {
console.info('Building service worker for production')
await build(config)
- }
- }
+ },
+ },
}
}
@@ -191,9 +191,9 @@ const swMessagesNameResolved = '\0' + swMessagesName
export const swMessagesPlugin = () => {
return {
name: 'sw-messages-plugin',
- resolveId (id) {
+ resolveId(id) {
if (id === swMessagesName) {
- Object.values(i18nFiles).forEach(f => {
+ Object.values(i18nFiles).forEach((f) => {
this.addWatchFile(f)
})
return swMessagesNameResolved
@@ -201,11 +201,11 @@ export const swMessagesPlugin = () => {
return null
}
},
- async load (id) {
+ async load(id) {
if (id === swMessagesNameResolved) {
return await getSWMessagesAsText()
}
return null
- }
+ },
}
}
diff --git a/build/update-emoji.js b/build/update-emoji.js
index 5d578ba61..4ff7e1de8 100644
--- a/build/update-emoji.js
+++ b/build/update-emoji.js
@@ -1,22 +1,21 @@
-
-import emojis from '@kazvmoe-infra/unicode-emoji-json/data-by-group.json' with { type: 'json' }
+import emojis from '@kazvmoe-infra/unicode-emoji-json/data-by-group.json' with {
+ type: 'json',
+}
import fs from 'fs'
-Object.keys(emojis)
- .map(k => {
- emojis[k].map(e => {
- delete e.unicode_version
- delete e.emoji_version
- delete e.skin_tone_support_unicode_version
- })
+Object.keys(emojis).map((k) => {
+ emojis[k].map((e) => {
+ delete e.unicode_version
+ delete e.emoji_version
+ delete e.skin_tone_support_unicode_version
})
+})
const res = {}
-Object.keys(emojis)
- .map(k => {
- const groupId = k.replace('&', 'and').replace(/ /g, '-').toLowerCase()
- res[groupId] = emojis[k]
- })
+Object.keys(emojis).map((k) => {
+ const groupId = k.replace('&', 'and').replace(/ /g, '-').toLowerCase()
+ res[groupId] = emojis[k]
+})
console.info('Updating emojis...')
fs.writeFileSync('src/assets/emoji.json', JSON.stringify(res))
diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml
new file mode 100644
index 000000000..75a4979a1
--- /dev/null
+++ b/docker-compose.e2e.yml
@@ -0,0 +1,57 @@
+services:
+ db:
+ image: postgres:15-alpine
+ environment:
+ POSTGRES_USER: pleroma
+ POSTGRES_PASSWORD: pleroma
+ POSTGRES_DB: pleroma
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U pleroma -d pleroma"]
+ interval: 2s
+ timeout: 2s
+ retries: 30
+
+ pleroma:
+ image: ${PLEROMA_IMAGE:-git.pleroma.social:5050/pleroma/pleroma:stable}
+ environment:
+ DB_USER: pleroma
+ DB_PASS: pleroma
+ DB_NAME: pleroma
+ DB_HOST: db
+ DB_PORT: 5432
+ DOMAIN: localhost
+ INSTANCE_NAME: Pleroma E2E
+ ADMIN_EMAIL: ${E2E_ADMIN_EMAIL:-admin@example.com}
+ NOTIFY_EMAIL: ${E2E_ADMIN_EMAIL:-admin@example.com}
+ E2E_ADMIN_USERNAME: ${E2E_ADMIN_USERNAME:-admin}
+ E2E_ADMIN_PASSWORD: ${E2E_ADMIN_PASSWORD:-adminadmin}
+ E2E_ADMIN_EMAIL: ${E2E_ADMIN_EMAIL:-admin@example.com}
+ depends_on:
+ db:
+ condition: service_healthy
+ volumes:
+ - ./docker/pleroma/entrypoint.e2e.sh:/opt/pleroma/entrypoint.e2e.sh:ro
+ entrypoint: ["/bin/ash", "/opt/pleroma/entrypoint.e2e.sh"]
+ healthcheck:
+ # NOTE: "localhost" may resolve to ::1 in some images (IPv6) while Pleroma only
+ # listens on IPv4 in this container. Use 127.0.0.1 to avoid false negatives.
+ test: ["CMD-SHELL", "test -f /var/lib/pleroma/.e2e_seeded && wget -qO- http://127.0.0.1:4000/api/v1/instance >/dev/null || exit 1"]
+ interval: 5s
+ timeout: 3s
+ retries: 60
+
+ e2e:
+ build:
+ context: .
+ dockerfile: docker/e2e/Dockerfile.e2e
+ depends_on:
+ pleroma:
+ condition: service_healthy
+ environment:
+ CI: "1"
+ VITE_PROXY_TARGET: http://pleroma:4000
+ VITE_PROXY_ORIGIN: http://localhost:4000
+ E2E_BASE_URL: http://localhost:8080
+ E2E_ADMIN_USERNAME: ${E2E_ADMIN_USERNAME:-admin}
+ E2E_ADMIN_PASSWORD: ${E2E_ADMIN_PASSWORD:-adminadmin}
+ command: ["yarn", "e2e:pw"]
diff --git a/docker/e2e/Dockerfile.e2e b/docker/e2e/Dockerfile.e2e
new file mode 100644
index 000000000..e84359ceb
--- /dev/null
+++ b/docker/e2e/Dockerfile.e2e
@@ -0,0 +1,16 @@
+FROM mcr.microsoft.com/playwright:v1.57.0-jammy
+
+WORKDIR /app
+
+ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
+
+RUN npm install -g yarn@1.22.22
+
+COPY package.json yarn.lock ./
+RUN yarn --frozen-lockfile
+
+COPY . .
+
+ENV CI=1
+
+CMD ["yarn", "e2e:pw"]
diff --git a/docker/pleroma/entrypoint.e2e.sh b/docker/pleroma/entrypoint.e2e.sh
new file mode 100644
index 000000000..96920eeae
--- /dev/null
+++ b/docker/pleroma/entrypoint.e2e.sh
@@ -0,0 +1,71 @@
+#!/bin/ash
+
+set -eu
+
+SEED_SENTINEL_PATH="/var/lib/pleroma/.e2e_seeded"
+CONFIG_OVERRIDE_PATH="/var/lib/pleroma/config.exs"
+
+echo "-- Waiting for database..."
+while ! pg_isready -U "${DB_USER:-pleroma}" -d "postgres://${DB_HOST:-db}:${DB_PORT:-5432}/${DB_NAME:-pleroma}" -t 1; do
+ sleep 1s
+done
+
+echo "-- Writing E2E config overrides..."
+cat > "$CONFIG_OVERRIDE_PATH" <<'EOF'
+import Config
+
+config :pleroma, Pleroma.Captcha,
+ enabled: false
+
+config :pleroma, :instance,
+ registrations_open: true,
+ account_activation_required: false,
+ approval_required: false
+EOF
+
+echo "-- Running migrations..."
+/opt/pleroma/bin/pleroma_ctl migrate
+
+echo "-- Starting!"
+/opt/pleroma/bin/pleroma start &
+PLEROMA_PID="$!"
+
+cleanup() {
+ if [ -n "${PLEROMA_PID:-}" ] && kill -0 "$PLEROMA_PID" 2>/dev/null; then
+ kill -TERM "$PLEROMA_PID"
+ wait "$PLEROMA_PID" || true
+ fi
+}
+
+trap cleanup INT TERM
+
+echo "-- Waiting for API..."
+api_ok="false"
+for _i in $(seq 1 120); do
+ if wget -qO- http://127.0.0.1:4000/api/v1/instance >/dev/null 2>&1; then
+ api_ok="true"
+ break
+ fi
+ sleep 1s
+done
+
+if [ "$api_ok" != "true" ]; then
+ echo "Timed out waiting for Pleroma API to become available"
+ exit 1
+fi
+
+if [ ! -f "$SEED_SENTINEL_PATH" ]; then
+ if [ -n "${E2E_ADMIN_USERNAME:-}" ] && [ -n "${E2E_ADMIN_PASSWORD:-}" ] && [ -n "${E2E_ADMIN_EMAIL:-}" ]; then
+ echo "-- Seeding admin user (${E2E_ADMIN_USERNAME})..."
+ if ! /opt/pleroma/bin/pleroma_ctl user new "$E2E_ADMIN_USERNAME" "$E2E_ADMIN_EMAIL" --admin --password "$E2E_ADMIN_PASSWORD" -y; then
+ echo "-- User already exists (or creation failed), ensuring admin + confirmed..."
+ /opt/pleroma/bin/pleroma_ctl user set "$E2E_ADMIN_USERNAME" --admin --confirmed
+ fi
+ else
+ echo "-- Skipping admin seeding (missing E2E_ADMIN_* env)"
+ fi
+
+ touch "$SEED_SENTINEL_PATH"
+fi
+
+wait "$PLEROMA_PID"
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 01bdb2038..417ff8cf3 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,37 +1,34 @@
-import vue from "eslint-plugin-vue";
-import js from "@eslint/js";
-import globals from "globals";
+import js from '@eslint/js'
+import { defineConfig, globalIgnores } from 'eslint/config'
+import vue from 'eslint-plugin-vue'
+import globals from 'globals'
-
-export default [
+export default defineConfig([
...vue.configs['flat/recommended'],
- js.configs.recommended,
+ globalIgnores(['**/*.js', 'build/', 'dist/', 'config/']),
{
- files: ["**/*.js", "**/*.mjs", "**/*.vue"],
- ignores: ["build/*.js", "config/*.js"],
-
+ files: ['src/**/*.vue'],
+ plugins: { js },
+ extends: ['js/recommended'],
languageOptions: {
ecmaVersion: 2024,
- sourceType: "module",
+ sourceType: 'module',
parserOptions: {
- parser: "@babel/eslint-parser",
+ parser: '@babel/eslint-parser',
},
globals: {
...globals.browser,
...globals.vitest,
...globals.chai,
...globals.commonjs,
- ...globals.serviceworker
- }
+ ...globals.serviceworker,
+ },
},
rules: {
- 'arrow-parens': 0,
- 'generator-star-spacing': 0,
- 'no-debugger': 0,
'vue/require-prop-types': 0,
'vue/multi-word-component-names': 0,
- }
- }
-]
+ },
+ },
+])
diff --git a/package.json b/package.json
index 21d75f0fb..bdd1acfbe 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "pleroma_fe",
- "version": "2.9.3",
+ "version": "2.10.1",
"description": "Pleroma frontend, the default frontend of Pleroma social network server",
"author": "Pleroma contributors ",
"private": false,
@@ -10,11 +10,14 @@
"unit": "node build/update-emoji.js && vitest --run",
"unit-ci": "node build/update-emoji.js && vitest --run --browser.headless",
"unit:watch": "node build/update-emoji.js && vitest",
- "e2e": "node test/e2e/runner.js",
+ "e2e:pw": "playwright test --config test/e2e-playwright/playwright.config.mjs",
+ "e2e": "sh ./tools/e2e/run.sh",
"test": "yarn run unit && yarn run e2e",
- "stylelint": "yarn exec stylelint '**/*.scss' '**/*.vue'",
- "lint": "eslint src test/unit/specs test/e2e/specs",
- "lint-fix": "eslint --fix src test/unit/specs test/e2e/specs"
+ "ci-biome": "yarn exec biome check",
+ "ci-eslint": "yarn exec eslint",
+ "ci-stylelint": "yarn exec stylelint '**/*.scss' '**/*.vue'",
+ "lint": "yarn ci-biome; yarn ci-eslint; yarn ci-stylelint",
+ "lint-fix": "yarn exec eslint --fix; yarn exec stylelint '**/*.scss' '**/*.vue' --fix; biome check --write"
},
"dependencies": {
"@babel/runtime": "7.28.4",
@@ -49,16 +52,17 @@
"uuid": "11.1.0",
"vue": "3.5.22",
"vue-i18n": "11",
- "vue-router": "4.5.1",
+ "vue-router": "4.6.4",
"vue-virtual-scroller": "^2.0.0-beta.7",
"vuex": "4.1.0"
},
"devDependencies": {
- "@babel/core": "7.28.4",
- "@babel/eslint-parser": "7.28.4",
- "@babel/plugin-transform-runtime": "7.28.3",
- "@babel/preset-env": "7.28.3",
+ "@babel/core": "7.28.5",
+ "@babel/eslint-parser": "7.28.5",
+ "@babel/plugin-transform-runtime": "7.28.5",
+ "@babel/preset-env": "7.28.5",
"@babel/register": "7.28.3",
+ "@biomejs/biome": "2.3.11",
"@ungap/event-target": "0.2.4",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
@@ -76,14 +80,13 @@
"connect-history-api-fallback": "2.0.0",
"cross-spawn": "7.0.6",
"custom-event-polyfill": "1.0.7",
- "eslint": "9.37.0",
- "vue-eslint-parser": "10.2.0",
+ "eslint": "9.39.2",
"eslint-config-standard": "17.1.0",
"eslint-formatter-friendly": "7.0.0",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-n": "17.23.1",
"eslint-plugin-promise": "7.2.1",
- "eslint-plugin-vue": "10.5.0",
+ "eslint-plugin-vue": "10.6.2",
"eventsource-polyfill": "0.9.6",
"express": "5.1.0",
"function-bind": "1.1.2",
@@ -92,7 +95,7 @@
"lodash": "4.17.21",
"msw": "2.10.5",
"nightwatch": "3.12.2",
- "playwright": "1.55.0",
+ "playwright": "1.57.0",
"postcss": "8.5.6",
"postcss-html": "^1.5.0",
"postcss-scss": "^4.0.6",
@@ -112,7 +115,8 @@
"vite": "^6.1.0",
"vite-plugin-eslint2": "^5.0.3",
"vite-plugin-stylelint": "^6.0.0",
- "vitest": "^3.0.7"
+ "vitest": "^3.0.7",
+ "vue-eslint-parser": "10.2.0"
},
"type": "module",
"engines": {
diff --git a/postcss.config.js b/postcss.config.js
index 95ebbf2a6..b7fc12838 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -1,7 +1,5 @@
import autoprefixer from 'autoprefixer'
export default {
- plugins: [
- autoprefixer
- ]
+ plugins: [autoprefixer],
}
diff --git a/public/static/palettes/index.json b/public/static/palettes/index.json
index 2cd110d1e..3c4e37e44 100644
--- a/public/static/palettes/index.json
+++ b/public/static/palettes/index.json
@@ -1,6 +1,26 @@
{
- "pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
- "pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
+ "pleroma-dark": [
+ "Pleroma Dark",
+ "#121a24",
+ "#182230",
+ "#b9b9ba",
+ "#d8a070",
+ "#d31014",
+ "#0fa00f",
+ "#0095ff",
+ "#ffa500"
+ ],
+ "pleroma-light": [
+ "Pleroma Light",
+ "#f2f4f6",
+ "#dbe0e8",
+ "#304055",
+ "#f86f0f",
+ "#d31014",
+ "#0fa00f",
+ "#0095ff",
+ "#ffa500"
+ ],
"classic-dark": {
"name": "Classic Dark",
"bg": "#161c20",
@@ -12,8 +32,28 @@
"cBlue": "#0095ff",
"cOrange": "#ffa500"
},
- "bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"],
- "pleroma-amoled": [ "Pleroma Dark AMOLED", "#000000", "#111111", "#b0b0b1", "#d8a070", "#aa0000", "#0fa00f", "#0095ff", "#d59500"],
+ "bird": [
+ "Bird",
+ "#f8fafd",
+ "#e6ecf0",
+ "#14171a",
+ "#0084b8",
+ "#e0245e",
+ "#17bf63",
+ "#1b95e0",
+ "#fab81e"
+ ],
+ "pleroma-amoled": [
+ "Pleroma Dark AMOLED",
+ "#000000",
+ "#111111",
+ "#b0b0b1",
+ "#d8a070",
+ "#aa0000",
+ "#0fa00f",
+ "#0095ff",
+ "#d59500"
+ ],
"tomorrow-night": {
"name": "Tomorrow Night",
"bg": "#1d1f21",
@@ -36,8 +76,28 @@
"cGreen": "#50FA7B",
"cOrange": "#FFB86C"
},
- "ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ],
- "monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ],
+ "ir-black": [
+ "Ir Black",
+ "#000000",
+ "#242422",
+ "#b5b3aa",
+ "#ff6c60",
+ "#FF6C60",
+ "#A8FF60",
+ "#96CBFE",
+ "#FFFFB6"
+ ],
+ "monokai": [
+ "Monokai",
+ "#272822",
+ "#383830",
+ "#f8f8f2",
+ "#f92672",
+ "#F92672",
+ "#a6e22e",
+ "#66d9ef",
+ "#f4bf75"
+ ],
"purple-stream": {
"name": "Purple stream",
"bg": "#17171A",
diff --git a/public/static/splash.css b/public/static/splash.css
index f56f33d07..caf57dacb 100644
--- a/public/static/splash.css
+++ b/public/static/splash.css
@@ -65,16 +65,17 @@ body {
z-index: 2;
grid-template-rows: repeat(8, 1fr);
grid-template-columns: repeat(5, 1fr);
- grid-template-areas: "P P . L L"
- "P P . L L"
- "P P . L L"
- "P P . L L"
- "P P . . ."
- "P P . . ."
- "P P . E E"
- "P P . E E";
+ grid-template-areas:
+ "P P . L L"
+ "P P . L L"
+ "P P . L L"
+ "P P . L L"
+ "P P . . ."
+ "P P . . ."
+ "P P . E E"
+ "P P . E E";
- --logoChunkSize: calc(2em * 0.5 * var(--scale))
+ --logoChunkSize: calc(2em * 0.5 * var(--scale));
}
.chunk {
@@ -84,7 +85,7 @@ body {
#chunk-P {
grid-area: P;
- border-top-left-radius: calc(var(--logoChunkSize) / 2);
+ border-top-left-radius: calc(var(--logoChunkSize) / 2);
}
#chunk-L {
diff --git a/renovate.json b/renovate.json
index 39a2b6e9a..4bd832f5f 100644
--- a/renovate.json
+++ b/renovate.json
@@ -1,6 +1,4 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
- "extends": [
- "config:base"
- ]
+ "extends": ["config:base"]
}
diff --git a/src/App.js b/src/App.js
index 0027d908a..33645c63d 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,34 +1,36 @@
-import UserPanel from './components/user_panel/user_panel.vue'
-import NavPanel from './components/nav_panel/nav_panel.vue'
-import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue'
-import FeaturesPanel from './components/features_panel/features_panel.vue'
-import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
-import ShoutPanel from './components/shout_panel/shout_panel.vue'
-import MediaModal from './components/media_modal/media_modal.vue'
-import SideDrawer from './components/side_drawer/side_drawer.vue'
-import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue'
-import MobileNav from './components/mobile_nav/mobile_nav.vue'
-import DesktopNav from './components/desktop_nav/desktop_nav.vue'
-import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
-import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue'
-import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
-import StatusHistoryModal from './components/status_history_modal/status_history_modal.vue'
-import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue'
-import { getOrCreateServiceWorker } from './services/sw/sw'
-import { windowWidth, windowHeight } from './services/window_utils/window_utils'
-import { mapGetters } from 'vuex'
-import { defineAsyncComponent } from 'vue'
-import { useShoutStore } from './stores/shout'
-import { useInterfaceStore } from './stores/interface'
-
import { throttle } from 'lodash'
+import { defineAsyncComponent } from 'vue'
+import { mapGetters } from 'vuex'
+
+import DesktopNav from './components/desktop_nav/desktop_nav.vue'
+import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue'
+import FeaturesPanel from './components/features_panel/features_panel.vue'
+import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue'
+import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue'
+import MediaModal from './components/media_modal/media_modal.vue'
+import MobileNav from './components/mobile_nav/mobile_nav.vue'
+import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue'
+import NavPanel from './components/nav_panel/nav_panel.vue'
+import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
+import ShoutPanel from './components/shout_panel/shout_panel.vue'
+import SideDrawer from './components/side_drawer/side_drawer.vue'
+import StatusHistoryModal from './components/status_history_modal/status_history_modal.vue'
+import UserPanel from './components/user_panel/user_panel.vue'
+import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
+import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
+import { getOrCreateServiceWorker } from './services/sw/sw'
+import { windowHeight, windowWidth } from './services/window_utils/window_utils'
+import { useInterfaceStore } from './stores/interface'
+import { useShoutStore } from './stores/shout'
export default {
name: 'app',
components: {
UserPanel,
NavPanel,
- Notifications: defineAsyncComponent(() => import('./components/notifications/notifications.vue')),
+ Notifications: defineAsyncComponent(
+ () => import('./components/notifications/notifications.vue'),
+ ),
InstanceSpecificPanel,
FeaturesPanel,
WhoToFollowPanel,
@@ -38,29 +40,33 @@ export default {
MobilePostStatusButton,
MobileNav,
DesktopNav,
- SettingsModal: defineAsyncComponent(() => import('./components/settings_modal/settings_modal.vue')),
- UpdateNotification: defineAsyncComponent(() => import('./components/update_notification/update_notification.vue')),
+ SettingsModal: defineAsyncComponent(
+ () => import('./components/settings_modal/settings_modal.vue'),
+ ),
+ UpdateNotification: defineAsyncComponent(
+ () => import('./components/update_notification/update_notification.vue'),
+ ),
UserReportingModal,
PostStatusModal,
EditStatusModal,
StatusHistoryModal,
- GlobalNoticeList
+ GlobalNoticeList,
},
data: () => ({
- mobileActivePanel: 'timeline'
+ mobileActivePanel: 'timeline',
}),
watch: {
- themeApplied () {
+ themeApplied() {
this.removeSplash()
},
- currentTheme () {
+ currentTheme() {
this.setThemeBodyClass()
},
- layoutType () {
+ layoutType() {
document.getElementById('modal').classList = ['-' + this.layoutType]
- }
+ },
},
- created () {
+ created() {
// Load the locale from the storage
const val = this.$store.getters.mergedConfig.interfaceLanguage
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
@@ -70,7 +76,7 @@ export default {
this.updateScrollState = throttle(this.scrollHandler, 200)
this.updateMobileState = throttle(this.resizeHandler, 200)
},
- mounted () {
+ mounted() {
window.addEventListener('resize', this.updateMobileState)
this.scrollParent.addEventListener('scroll', this.updateScrollState)
@@ -80,108 +86,145 @@ export default {
}
getOrCreateServiceWorker()
},
- unmounted () {
+ unmounted() {
window.removeEventListener('resize', this.updateMobileState)
this.scrollParent.removeEventListener('scroll', this.updateScrollState)
},
computed: {
- themeApplied () {
+ themeApplied() {
return useInterfaceStore().themeApplied
},
- currentTheme () {
+ currentTheme() {
if (useInterfaceStore().styleDataUsed) {
- const styleMeta = useInterfaceStore().styleDataUsed.find(x => x.component === '@meta')
+ const styleMeta = useInterfaceStore().styleDataUsed.find(
+ (x) => x.component === '@meta',
+ )
if (styleMeta !== undefined) {
- return styleMeta.directives.name.replaceAll(" ", "-").toLowerCase()
+ return styleMeta.directives.name.replaceAll(' ', '-').toLowerCase()
}
}
return 'stock'
},
- layoutModalClass () {
+ layoutModalClass() {
return '-' + this.layoutType
},
- classes () {
+ classes() {
return [
{
'-reverse': this.reverseLayout,
'-no-sticky-headers': this.noSticky,
- '-has-new-post-button': this.newPostButtonShown
+ '-has-new-post-button': this.newPostButtonShown,
},
- '-' + this.layoutType
+ '-' + this.layoutType,
]
},
- navClasses () {
+ navClasses() {
const { navbarColumnStretch } = this.$store.getters.mergedConfig
return [
'-' + this.layoutType,
- ...(navbarColumnStretch ? ['-column-stretch'] : [])
+ ...(navbarColumnStretch ? ['-column-stretch'] : []),
]
},
- currentUser () { return this.$store.state.users.currentUser },
- userBackground () { return this.currentUser.background_image },
- instanceBackground () {
+ currentUser() {
+ return this.$store.state.users.currentUser
+ },
+ userBackground() {
+ return this.currentUser.background_image
+ },
+ instanceBackground() {
return this.mergedConfig.hideInstanceWallpaper
? null
: this.$store.state.instance.background
},
- background () { return this.userBackground || this.instanceBackground },
- bgStyle () {
+ background() {
+ return this.userBackground || this.instanceBackground
+ },
+ bgStyle() {
if (this.background) {
return {
- '--body-background-image': `url(${this.background})`
+ '--body-background-image': `url(${this.background})`,
}
}
},
- shout () { return useShoutStore().joined },
- suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
- showInstanceSpecificPanel () {
- return this.$store.state.instance.showInstanceSpecificPanel &&
+ shout() {
+ return useShoutStore().joined
+ },
+ suggestionsEnabled() {
+ return this.$store.state.instance.suggestionsEnabled
+ },
+ showInstanceSpecificPanel() {
+ return (
+ this.$store.state.instance.showInstanceSpecificPanel &&
!this.$store.getters.mergedConfig.hideISP &&
this.$store.state.instance.instanceSpecificPanelContent
+ )
},
- isChats () {
+ isChats() {
return this.$route.name === 'chat' || this.$route.name === 'chats'
},
- isListEdit () {
+ isListEdit() {
return this.$route.name === 'lists-edit'
},
- newPostButtonShown () {
+ newPostButtonShown() {
if (this.isChats) return false
if (this.isListEdit) return false
- return this.$store.getters.mergedConfig.alwaysShowNewPostButton || this.layoutType === 'mobile'
+ return (
+ this.$store.getters.mergedConfig.alwaysShowNewPostButton ||
+ this.layoutType === 'mobile'
+ )
},
- showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
- editingAvailable () { return this.$store.state.instance.editingAvailable },
- shoutboxPosition () {
+ showFeaturesPanel() {
+ return this.$store.state.instance.showFeaturesPanel
+ },
+ editingAvailable() {
+ return this.$store.state.instance.editingAvailable
+ },
+ shoutboxPosition() {
return this.$store.getters.mergedConfig.alwaysShowNewPostButton || false
},
- hideShoutbox () {
+ hideShoutbox() {
return this.$store.getters.mergedConfig.hideShoutbox
},
- layoutType () { return useInterfaceStore().layoutType },
- privateMode () { return this.$store.state.instance.private },
- reverseLayout () {
- const { thirdColumnMode, sidebarRight: reverseSetting } = this.$store.getters.mergedConfig
+ layoutType() {
+ return useInterfaceStore().layoutType
+ },
+ privateMode() {
+ return this.$store.state.instance.private
+ },
+ reverseLayout() {
+ const { thirdColumnMode, sidebarRight: reverseSetting } =
+ this.$store.getters.mergedConfig
if (this.layoutType !== 'wide') {
return reverseSetting
} else {
- return thirdColumnMode === 'notifications' ? reverseSetting : !reverseSetting
+ return thirdColumnMode === 'notifications'
+ ? reverseSetting
+ : !reverseSetting
}
},
- noSticky () { return this.$store.getters.mergedConfig.disableStickyHeaders },
- showScrollbars () { return this.$store.getters.mergedConfig.showScrollbars },
- scrollParent () { return window; /* this.$refs.appContentRef */ },
- ...mapGetters(['mergedConfig'])
+ noSticky() {
+ return this.$store.getters.mergedConfig.disableStickyHeaders
+ },
+ showScrollbars() {
+ return this.$store.getters.mergedConfig.showScrollbars
+ },
+ scrollParent() {
+ return window /* this.$refs.appContentRef */
+ },
+ ...mapGetters(['mergedConfig']),
},
methods: {
- resizeHandler () {
+ resizeHandler() {
useInterfaceStore().setLayoutWidth(windowWidth())
useInterfaceStore().setLayoutHeight(windowHeight())
},
- scrollHandler () {
- const scrollPosition = this.scrollParent === window ? window.scrollY : this.scrollParent.scrollTop
+ scrollHandler() {
+ const scrollPosition =
+ this.scrollParent === window
+ ? window.scrollY
+ : this.scrollParent.scrollTop
if (scrollPosition != 0) {
this.$refs.appContentRef.classList.add(['-scrolled'])
@@ -189,10 +232,10 @@ export default {
this.$refs.appContentRef.classList.remove(['-scrolled'])
}
},
- setThemeBodyClass () {
+ setThemeBodyClass() {
const themeName = this.currentTheme
const classList = Array.from(document.body.classList)
- const oldTheme = classList.filter(c => c.startsWith('theme-'))
+ const oldTheme = classList.filter((c) => c.startsWith('theme-'))
if (themeName !== null && themeName !== '') {
const newTheme = `theme-${themeName.toLowerCase()}`
@@ -208,8 +251,10 @@ export default {
document.body.classList.remove(...oldTheme)
}
},
- removeSplash () {
- document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4))
+ removeSplash() {
+ document.querySelector('#status').textContent = this.$t(
+ 'splash.fun_' + Math.ceil(Math.random() * 4),
+ )
const splashscreenRoot = document.querySelector('#splash')
splashscreenRoot.addEventListener('transitionend', () => {
splashscreenRoot.remove()
@@ -219,6 +264,6 @@ export default {
}, 600)
splashscreenRoot.classList.add('hidden')
document.querySelector('#app').classList.remove('hidden')
- }
- }
+ },
+ },
}
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index ad994af6a..1a2be5bd7 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -1,30 +1,39 @@
/* global process */
+
+import vClickOutside from 'click-outside-vue3'
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
-import vClickOutside from 'click-outside-vue3'
import VueVirtualScroller from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
-import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
-import { config } from '@fortawesome/fontawesome-svg-core';
+import { config } from '@fortawesome/fontawesome-svg-core'
+import {
+ FontAwesomeIcon,
+ FontAwesomeLayers,
+} from '@fortawesome/vue-fontawesome'
+
config.autoAddCss = false
-import App from '../App.vue'
-import routes from './routes'
import VBodyScrollLock from 'src/directives/body_scroll_lock'
-
-import { windowWidth, windowHeight } from '../services/window_utils/window_utils'
-import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
-import { applyConfig } from '../services/style_setter/style_setter.js'
-import FaviconService from '../services/favicon_service/favicon_service.js'
-import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
-
-import { useOAuthStore } from 'src/stores/oauth'
-import { useI18nStore } from 'src/stores/i18n'
-import { useInterfaceStore } from 'src/stores/interface'
+import {
+ instanceDefaultConfig,
+ staticOrApiConfigDefault,
+} from 'src/modules/default_config_state.js'
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useAuthFlowStore } from 'src/stores/auth_flow'
-import { staticOrApiConfigDefault, instanceDefaultConfig } from 'src/modules/default_config_state.js'
+import { useI18nStore } from 'src/stores/i18n'
+import { useInterfaceStore } from 'src/stores/interface'
+import { useOAuthStore } from 'src/stores/oauth'
+import App from '../App.vue'
+import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
+import FaviconService from '../services/favicon_service/favicon_service.js'
+import { applyConfig } from '../services/style_setter/style_setter.js'
+import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
+import {
+ windowHeight,
+ windowWidth,
+} from '../services/window_utils/window_utils'
+import routes from './routes'
let staticInitialResults = null
@@ -33,7 +42,9 @@ const parsedInitialResults = () => {
return null
}
if (!staticInitialResults) {
- staticInitialResults = JSON.parse(document.getElementById('initial-results').textContent)
+ staticInitialResults = JSON.parse(
+ document.getElementById('initial-results').textContent,
+ )
}
return staticInitialResults
}
@@ -55,7 +66,7 @@ const preloadFetch = async (request) => {
return {
ok: true,
json: () => requestData,
- text: () => requestData
+ text: () => requestData,
}
}
@@ -67,17 +78,35 @@ const getInstanceConfig = async ({ store }) => {
const textlimit = data.max_toot_chars
const vapidPublicKey = data.pleroma.vapid_public_key
- store.dispatch('setInstanceOption', { name: 'pleromaExtensionsAvailable', value: data.pleroma })
- store.dispatch('setInstanceOption', { name: 'textlimit', value: textlimit })
- store.dispatch('setInstanceOption', { name: 'accountApprovalRequired', value: data.approval_required })
- store.dispatch('setInstanceOption', { name: 'birthdayRequired', value: !!data.pleroma?.metadata.birthday_required })
- store.dispatch('setInstanceOption', { name: 'birthdayMinAge', value: data.pleroma?.metadata.birthday_min_age || 0 })
+ store.dispatch('setInstanceOption', {
+ name: 'pleromaExtensionsAvailable',
+ value: data.pleroma,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'textlimit',
+ value: textlimit,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'accountApprovalRequired',
+ value: data.approval_required,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'birthdayRequired',
+ value: !!data.pleroma?.metadata.birthday_required,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'birthdayMinAge',
+ value: data.pleroma?.metadata.birthday_min_age || 0,
+ })
if (vapidPublicKey) {
- store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
+ store.dispatch('setInstanceOption', {
+ name: 'vapidPublicKey',
+ value: vapidPublicKey,
+ })
}
} else {
- throw (res)
+ throw res
}
} catch (error) {
console.error('Could not load instance config, potentially fatal')
@@ -94,10 +123,12 @@ const getBackendProvidedConfig = async () => {
const data = await res.json()
return data.pleroma_fe
} else {
- throw (res)
+ throw res
}
} catch (error) {
- console.error('Could not load backend-provided frontend config, potentially fatal')
+ console.error(
+ 'Could not load backend-provided frontend config, potentially fatal',
+ )
console.error(error)
}
}
@@ -108,7 +139,7 @@ const getStaticConfig = async () => {
if (res.ok) {
return res.json()
} else {
- throw (res)
+ throw res
}
} catch (error) {
console.warn('Failed to load static/config.json, continuing without it.')
@@ -149,7 +180,7 @@ const getTOS = async ({ store }) => {
const html = await res.text()
store.dispatch('setInstanceOption', { name: 'tos', value: html })
} else {
- throw (res)
+ throw res
}
} catch (e) {
console.warn("Can't load TOS\n", e)
@@ -161,9 +192,12 @@ const getInstancePanel = async ({ store }) => {
const res = await preloadFetch('/instance/panel.html')
if (res.ok) {
const html = await res.text()
- store.dispatch('setInstanceOption', { name: 'instanceSpecificPanelContent', value: html })
+ store.dispatch('setInstanceOption', {
+ name: 'instanceSpecificPanelContent',
+ value: html,
+ })
} else {
- throw (res)
+ throw res
}
} catch (e) {
console.warn("Can't load instance panel\n", e)
@@ -175,25 +209,27 @@ const getStickers = async ({ store }) => {
const res = await window.fetch('/static/stickers.json')
if (res.ok) {
const values = await res.json()
- const stickers = (await Promise.all(
- Object.entries(values).map(async ([name, path]) => {
- const resPack = await window.fetch(path + 'pack.json')
- let meta = {}
- if (resPack.ok) {
- meta = await resPack.json()
- }
- return {
- pack: name,
- path,
- meta
- }
- })
- )).sort((a, b) => {
+ const stickers = (
+ await Promise.all(
+ Object.entries(values).map(async ([name, path]) => {
+ const resPack = await window.fetch(path + 'pack.json')
+ let meta = {}
+ if (resPack.ok) {
+ meta = await resPack.json()
+ }
+ return {
+ pack: name,
+ path,
+ meta,
+ }
+ }),
+ )
+ ).sort((a, b) => {
return a.meta.title.localeCompare(b.meta.title)
})
store.dispatch('setInstanceOption', { name: 'stickers', value: stickers })
} else {
- throw (res)
+ throw res
}
} catch (e) {
console.warn("Can't load stickers\n", e)
@@ -203,13 +239,19 @@ const getStickers = async ({ store }) => {
const getAppSecret = async ({ store }) => {
const oauth = useOAuthStore()
if (oauth.userToken) {
- store.commit('setBackendInteractor', backendInteractorService(oauth.getToken))
+ store.commit(
+ 'setBackendInteractor',
+ backendInteractorService(oauth.getToken),
+ )
}
}
const resolveStaffAccounts = ({ store, accounts }) => {
- const nicknames = accounts.map(uri => uri.split('/').pop())
- store.dispatch('setInstanceOption', { name: 'staffAccounts', value: nicknames })
+ const nicknames = accounts.map((uri) => uri.split('/').pop())
+ store.dispatch('setInstanceOption', {
+ name: 'staffAccounts',
+ value: nicknames,
+ })
}
const getNodeInfo = async ({ store }) => {
@@ -220,77 +262,167 @@ const getNodeInfo = async ({ store }) => {
const data = await res.json()
const metadata = data.metadata
const features = metadata.features
- store.dispatch('setInstanceOption', { name: 'name', value: metadata.nodeName })
- store.dispatch('setInstanceOption', { name: 'registrationOpen', value: data.openRegistrations })
- store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: features.includes('media_proxy') })
- store.dispatch('setInstanceOption', { name: 'safeDM', value: features.includes('safe_dm_mentions') })
- store.dispatch('setInstanceOption', { name: 'shoutAvailable', value: features.includes('chat') })
- store.dispatch('setInstanceOption', { name: 'pleromaChatMessagesAvailable', value: features.includes('pleroma_chat_messages') })
+ store.dispatch('setInstanceOption', {
+ name: 'name',
+ value: metadata.nodeName,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'registrationOpen',
+ value: data.openRegistrations,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'mediaProxyAvailable',
+ value: features.includes('media_proxy'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'safeDM',
+ value: features.includes('safe_dm_mentions'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'shoutAvailable',
+ value: features.includes('chat'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'pleromaChatMessagesAvailable',
+ value: features.includes('pleroma_chat_messages'),
+ })
store.dispatch('setInstanceOption', {
name: 'pleromaCustomEmojiReactionsAvailable',
value:
features.includes('pleroma_custom_emoji_reactions') ||
- features.includes('custom_emoji_reactions')
+ features.includes('custom_emoji_reactions'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'pleromaBookmarkFoldersAvailable',
+ value: features.includes('pleroma:bookmark_folders'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'gopherAvailable',
+ value: features.includes('gopher'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'pollsAvailable',
+ value: features.includes('polls'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'editingAvailable',
+ value: features.includes('editing'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'pollLimits',
+ value: metadata.pollLimits,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'mailerEnabled',
+ value: metadata.mailerEnabled,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'quotingAvailable',
+ value: features.includes('quote_posting'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'groupActorAvailable',
+ value: features.includes('pleroma:group_actors'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'blockExpiration',
+ value: features.includes('pleroma:block_expiration'),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'localBubbleInstances',
+ value: metadata.localBubbleInstances ?? [],
})
- store.dispatch('setInstanceOption', { name: 'pleromaBookmarkFoldersAvailable', value: features.includes('pleroma:bookmark_folders') })
- store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') })
- store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') })
- store.dispatch('setInstanceOption', { name: 'editingAvailable', value: features.includes('editing') })
- store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
- store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
- store.dispatch('setInstanceOption', { name: 'quotingAvailable', value: features.includes('quote_posting') })
- store.dispatch('setInstanceOption', { name: 'groupActorAvailable', value: features.includes('pleroma:group_actors') })
- store.dispatch('setInstanceOption', { name: 'blockExpiration', value: features.includes('pleroma:block_expiration') })
- store.dispatch('setInstanceOption', { name: 'localBubbleInstances', value: metadata.localBubbleInstances ?? [] })
const uploadLimits = metadata.uploadLimits
- store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadLimits.general) })
- store.dispatch('setInstanceOption', { name: 'avatarlimit', value: parseInt(uploadLimits.avatar) })
- store.dispatch('setInstanceOption', { name: 'backgroundlimit', value: parseInt(uploadLimits.background) })
- store.dispatch('setInstanceOption', { name: 'bannerlimit', value: parseInt(uploadLimits.banner) })
- store.dispatch('setInstanceOption', { name: 'fieldsLimits', value: metadata.fieldsLimits })
+ store.dispatch('setInstanceOption', {
+ name: 'uploadlimit',
+ value: parseInt(uploadLimits.general),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'avatarlimit',
+ value: parseInt(uploadLimits.avatar),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'backgroundlimit',
+ value: parseInt(uploadLimits.background),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'bannerlimit',
+ value: parseInt(uploadLimits.banner),
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'fieldsLimits',
+ value: metadata.fieldsLimits,
+ })
- store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames })
- store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats })
+ store.dispatch('setInstanceOption', {
+ name: 'restrictedNicknames',
+ value: metadata.restrictedNicknames,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'postFormats',
+ value: metadata.postFormats,
+ })
const suggestions = metadata.suggestions
- store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: suggestions.enabled })
- store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: suggestions.web })
+ store.dispatch('setInstanceOption', {
+ name: 'suggestionsEnabled',
+ value: suggestions.enabled,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'suggestionsWeb',
+ value: suggestions.web,
+ })
const software = data.software
- store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
- store.dispatch('setInstanceOption', { name: 'backendRepository', value: software.repository })
+ store.dispatch('setInstanceOption', {
+ name: 'backendVersion',
+ value: software.version,
+ })
+ store.dispatch('setInstanceOption', {
+ name: 'backendRepository',
+ value: software.repository,
+ })
const priv = metadata.private
store.dispatch('setInstanceOption', { name: 'private', value: priv })
const frontendVersion = window.___pleromafe_commit_hash
- store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
+ store.dispatch('setInstanceOption', {
+ name: 'frontendVersion',
+ value: frontendVersion,
+ })
const federation = metadata.federation
store.dispatch('setInstanceOption', {
name: 'tagPolicyAvailable',
- value: typeof federation.mrf_policies === 'undefined'
- ? false
- : metadata.federation.mrf_policies.includes('TagPolicy')
+ value:
+ typeof federation.mrf_policies === 'undefined'
+ ? false
+ : metadata.federation.mrf_policies.includes('TagPolicy'),
})
- store.dispatch('setInstanceOption', { name: 'federationPolicy', value: federation })
+ store.dispatch('setInstanceOption', {
+ name: 'federationPolicy',
+ value: federation,
+ })
store.dispatch('setInstanceOption', {
name: 'federating',
- value: typeof federation.enabled === 'undefined'
- ? true
- : federation.enabled
+ value:
+ typeof federation.enabled === 'undefined' ? true : federation.enabled,
})
const accountActivationRequired = metadata.accountActivationRequired
- store.dispatch('setInstanceOption', { name: 'accountActivationRequired', value: accountActivationRequired })
+ store.dispatch('setInstanceOption', {
+ name: 'accountActivationRequired',
+ value: accountActivationRequired,
+ })
const accounts = metadata.staffAccounts
resolveStaffAccounts({ store, accounts })
} else {
- throw (res)
+ throw res
}
} catch (e) {
console.warn('Could not load nodeinfo')
@@ -300,7 +432,10 @@ const getNodeInfo = async ({ store }) => {
const setConfig = async ({ store }) => {
// apiConfig, staticConfig
- const configInfos = await Promise.all([getBackendProvidedConfig({ store }), getStaticConfig()])
+ const configInfos = await Promise.all([
+ getBackendProvidedConfig({ store }),
+ getStaticConfig(),
+ ])
const apiConfig = configInfos[0]
const staticConfig = configInfos[1]
@@ -331,29 +466,37 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
if (process.env.NODE_ENV === 'development') {
// do some checks to avoid common errors
if (!Object.keys(allStores).length) {
- throw new Error('No stores are available. Check the code in src/boot/after_store.js')
+ throw new Error(
+ 'No stores are available. Check the code in src/boot/after_store.js',
+ )
}
}
await Promise.all(
- Object.entries(allStores)
- .map(async ([name, mod]) => {
- const isStoreName = name => name.startsWith('use')
- if (process.env.NODE_ENV === 'development') {
- if (Object.keys(mod).filter(isStoreName).length !== 1) {
- throw new Error('Each store file must export exactly one store as a named export. Check your code in src/stores/')
- }
+ Object.entries(allStores).map(async ([name, mod]) => {
+ const isStoreName = (name) => name.startsWith('use')
+ if (process.env.NODE_ENV === 'development') {
+ if (Object.keys(mod).filter(isStoreName).length !== 1) {
+ throw new Error(
+ 'Each store file must export exactly one store as a named export. Check your code in src/stores/',
+ )
}
- const storeFuncName = Object.keys(mod).find(isStoreName)
- if (storeFuncName && typeof mod[storeFuncName] === 'function') {
- const p = mod[storeFuncName]().$persistLoaded
- if (!(p instanceof Promise)) {
- throw new Error(`${name} store's $persistLoaded is not a Promise. The persist plugin is not applied.`)
- }
- await p
- } else {
- throw new Error(`Store module ${name} does not export a 'use...' function`)
+ }
+ const storeFuncName = Object.keys(mod).find(isStoreName)
+ if (storeFuncName && typeof mod[storeFuncName] === 'function') {
+ const p = mod[storeFuncName]().$persistLoaded
+ if (!(p instanceof Promise)) {
+ throw new Error(
+ `${name} store's $persistLoaded is not a Promise. The persist plugin is not applied.`,
+ )
}
- }))
+ await p
+ } else {
+ throw new Error(
+ `Store module ${name} does not export a 'use...' function`,
+ )
+ }
+ }),
+ )
}
try {
@@ -364,7 +507,10 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
}
if (storageError) {
- useInterfaceStore().pushGlobalNotice({ messageKey: 'errors.storage_unavailable', level: 'error' })
+ useInterfaceStore().pushGlobalNotice({
+ messageKey: 'errors.storage_unavailable',
+ level: 'error',
+ })
}
useInterfaceStore().setLayoutWidth(windowWidth())
@@ -376,12 +522,19 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
window.addEventListener('focus', () => updateFocus())
const overrides = window.___pleromafe_dev_overrides || {}
- const server = (typeof overrides.target !== 'undefined') ? overrides.target : window.location.origin
+ const server =
+ typeof overrides.target !== 'undefined'
+ ? overrides.target
+ : window.location.origin
store.dispatch('setInstanceOption', { name: 'server', value: server })
await setConfig({ store })
try {
- await useInterfaceStore().applyTheme().catch((e) => { console.error('Error setting theme', e) })
+ await useInterfaceStore()
+ .applyTheme()
+ .catch((e) => {
+ console.error('Error setting theme', e)
+ })
} catch (e) {
window.splashError(e)
return Promise.reject(e)
@@ -395,8 +548,8 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
checkOAuthToken({ store }),
getInstancePanel({ store }),
getNodeInfo({ store }),
- getInstanceConfig({ store })
- ]).catch(e => Promise.reject(e))
+ getInstanceConfig({ store }),
+ ]).catch((e) => Promise.reject(e))
// Start fetching things that don't need to block the UI
store.dispatch('fetchMutes')
@@ -409,11 +562,11 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
history: createWebHistory(),
routes: routes(store),
scrollBehavior: (to, _from, savedPosition) => {
- if (to.matched.some(m => m.meta.dontScroll)) {
+ if (to.matched.some((m) => m.meta.dontScroll)) {
return false
}
return savedPosition || { left: 0, top: 0 }
- }
+ },
})
useI18nStore().setI18n(i18n)
diff --git a/src/boot/routes.js b/src/boot/routes.js
index 02abf8ce6..3296755a1 100644
--- a/src/boot/routes.js
+++ b/src/boot/routes.js
@@ -1,35 +1,36 @@
-import PublicTimeline from 'components/public_timeline/public_timeline.vue'
-import BubbleTimeline from 'components/bubble_timeline/bubble_timeline.vue'
-import PublicAndExternalTimeline from 'components/public_and_external_timeline/public_and_external_timeline.vue'
-import FriendsTimeline from 'components/friends_timeline/friends_timeline.vue'
-import TagTimeline from 'components/tag_timeline/tag_timeline.vue'
-import BookmarkTimeline from 'components/bookmark_timeline/bookmark_timeline.vue'
-import ConversationPage from 'components/conversation-page/conversation-page.vue'
-import Interactions from 'components/interactions/interactions.vue'
-import DMs from 'components/dm_timeline/dm_timeline.vue'
-import ChatList from 'components/chat_list/chat_list.vue'
-import Chat from 'components/chat/chat.vue'
-import UserProfile from 'components/user_profile/user_profile.vue'
-import Search from 'components/search/search.vue'
-import Registration from 'components/registration/registration.vue'
-import PasswordReset from 'components/password_reset/password_reset.vue'
-import FollowRequests from 'components/follow_requests/follow_requests.vue'
-import OAuthCallback from 'components/oauth_callback/oauth_callback.vue'
-import Notifications from 'components/notifications/notifications.vue'
-import AuthForm from 'components/auth_form/auth_form.js'
-import ShoutPanel from 'components/shout_panel/shout_panel.vue'
-import WhoToFollow from 'components/who_to_follow/who_to_follow.vue'
import About from 'components/about/about.vue'
-import RemoteUserResolver from 'components/remote_user_resolver/remote_user_resolver.vue'
-import Lists from 'components/lists/lists.vue'
-import ListsTimeline from 'components/lists_timeline/lists_timeline.vue'
-import ListsEdit from 'components/lists_edit/lists_edit.vue'
-import NavPanel from 'src/components/nav_panel/nav_panel.vue'
import AnnouncementsPage from 'components/announcements_page/announcements_page.vue'
-import QuotesTimeline from '../components/quotes_timeline/quotes_timeline.vue'
+import AuthForm from 'components/auth_form/auth_form.js'
+import BookmarkTimeline from 'components/bookmark_timeline/bookmark_timeline.vue'
+import BubbleTimeline from 'components/bubble_timeline/bubble_timeline.vue'
+import Chat from 'components/chat/chat.vue'
+import ChatList from 'components/chat_list/chat_list.vue'
+import ConversationPage from 'components/conversation-page/conversation-page.vue'
+import DMs from 'components/dm_timeline/dm_timeline.vue'
import Drafts from 'components/drafts/drafts.vue'
-import BookmarkFolders from '../components/bookmark_folders/bookmark_folders.vue'
+import FollowRequests from 'components/follow_requests/follow_requests.vue'
+import FriendsTimeline from 'components/friends_timeline/friends_timeline.vue'
+import Interactions from 'components/interactions/interactions.vue'
+import Lists from 'components/lists/lists.vue'
+import ListsEdit from 'components/lists_edit/lists_edit.vue'
+import ListsTimeline from 'components/lists_timeline/lists_timeline.vue'
+import Notifications from 'components/notifications/notifications.vue'
+import OAuthCallback from 'components/oauth_callback/oauth_callback.vue'
+import PasswordReset from 'components/password_reset/password_reset.vue'
+import PublicAndExternalTimeline from 'components/public_and_external_timeline/public_and_external_timeline.vue'
+import PublicTimeline from 'components/public_timeline/public_timeline.vue'
+import Registration from 'components/registration/registration.vue'
+import RemoteUserResolver from 'components/remote_user_resolver/remote_user_resolver.vue'
+import Search from 'components/search/search.vue'
+import ShoutPanel from 'components/shout_panel/shout_panel.vue'
+import TagTimeline from 'components/tag_timeline/tag_timeline.vue'
+import UserProfile from 'components/user_profile/user_profile.vue'
+import WhoToFollow from 'components/who_to_follow/who_to_follow.vue'
+
+import NavPanel from 'src/components/nav_panel/nav_panel.vue'
import BookmarkFolderEdit from '../components/bookmark_folder_edit/bookmark_folder_edit.vue'
+import BookmarkFolders from '../components/bookmark_folders/bookmark_folders.vue'
+import QuotesTimeline from '../components/quotes_timeline/quotes_timeline.vue'
export default (store) => {
const validateAuthenticatedRoute = (to, from, next) => {
@@ -45,46 +46,124 @@ export default (store) => {
name: 'root',
path: '/',
redirect: () => {
- return (store.state.users.currentUser
- ? store.state.instance.redirectRootLogin
- : store.state.instance.redirectRootNoLogin) || '/main/all'
- }
+ return (
+ (store.state.users.currentUser
+ ? store.state.instance.redirectRootLogin
+ : store.state.instance.redirectRootNoLogin) || '/main/all'
+ )
+ },
+ },
+ {
+ name: 'public-external-timeline',
+ path: '/main/all',
+ component: PublicAndExternalTimeline,
+ },
+ {
+ name: 'public-timeline',
+ path: '/main/public',
+ component: PublicTimeline,
+ },
+ {
+ name: 'friends',
+ path: '/main/friends',
+ component: FriendsTimeline,
+ beforeEnter: validateAuthenticatedRoute,
},
- { name: 'public-external-timeline', path: '/main/all', component: PublicAndExternalTimeline },
- { name: 'public-timeline', path: '/main/public', component: PublicTimeline },
- { name: 'friends', path: '/main/friends', component: FriendsTimeline, beforeEnter: validateAuthenticatedRoute },
{ name: 'tag-timeline', path: '/tag/:tag', component: TagTimeline },
{ name: 'bookmarks', path: '/bookmarks', component: BookmarkTimeline },
{ name: 'bubble', path: '/bubble', component: BubbleTimeline },
- { name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
+ {
+ name: 'conversation',
+ path: '/notice/:id',
+ component: ConversationPage,
+ meta: { dontScroll: true },
+ },
{ name: 'quotes', path: '/notice/:id/quotes', component: QuotesTimeline },
{
name: 'remote-user-profile-acct',
path: '/remote-users/:_(@)?:username([^/@]+)@:hostname([^/@]+)',
component: RemoteUserResolver,
- beforeEnter: validateAuthenticatedRoute
+ beforeEnter: validateAuthenticatedRoute,
},
{
name: 'remote-user-profile',
path: '/remote-users/:hostname/:username',
component: RemoteUserResolver,
- beforeEnter: validateAuthenticatedRoute
+ beforeEnter: validateAuthenticatedRoute,
+ },
+ {
+ name: 'external-user-profile',
+ path: '/users/$:id',
+ component: UserProfile,
+ },
+ {
+ name: 'interactions',
+ path: '/users/:username/interactions',
+ component: Interactions,
+ beforeEnter: validateAuthenticatedRoute,
+ },
+ {
+ name: 'dms',
+ path: '/users/:username/dms',
+ component: DMs,
+ beforeEnter: validateAuthenticatedRoute,
},
- { name: 'external-user-profile', path: '/users/$:id', component: UserProfile },
- { name: 'interactions', path: '/users/:username/interactions', component: Interactions, beforeEnter: validateAuthenticatedRoute },
- { name: 'dms', path: '/users/:username/dms', component: DMs, beforeEnter: validateAuthenticatedRoute },
{ name: 'registration', path: '/registration', component: Registration },
- { name: 'password-reset', path: '/password-reset', component: PasswordReset, props: true },
- { name: 'registration-token', path: '/registration/:token', component: Registration },
- { name: 'friend-requests', path: '/friend-requests', component: FollowRequests, beforeEnter: validateAuthenticatedRoute },
- { name: 'notifications', path: '/:username/notifications', component: Notifications, props: () => ({ disableTeleport: true }), beforeEnter: validateAuthenticatedRoute },
+ {
+ name: 'password-reset',
+ path: '/password-reset',
+ component: PasswordReset,
+ props: true,
+ },
+ {
+ name: 'registration-token',
+ path: '/registration/:token',
+ component: Registration,
+ },
+ {
+ name: 'friend-requests',
+ path: '/friend-requests',
+ component: FollowRequests,
+ beforeEnter: validateAuthenticatedRoute,
+ },
+ {
+ name: 'notifications',
+ path: '/:username/notifications',
+ component: Notifications,
+ props: () => ({ disableTeleport: true }),
+ beforeEnter: validateAuthenticatedRoute,
+ },
{ name: 'login', path: '/login', component: AuthForm },
- { name: 'shout-panel', path: '/shout-panel', component: ShoutPanel, props: () => ({ floating: false }) },
- { name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) },
- { name: 'search', path: '/search', component: Search, props: (route) => ({ query: route.query.query }) },
- { name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow, beforeEnter: validateAuthenticatedRoute },
+ {
+ name: 'shout-panel',
+ path: '/shout-panel',
+ component: ShoutPanel,
+ props: () => ({ floating: false }),
+ },
+ {
+ name: 'oauth-callback',
+ path: '/oauth-callback',
+ component: OAuthCallback,
+ props: (route) => ({ code: route.query.code }),
+ },
+ {
+ name: 'search',
+ path: '/search',
+ component: Search,
+ props: (route) => ({ query: route.query.query }),
+ },
+ {
+ name: 'who-to-follow',
+ path: '/who-to-follow',
+ component: WhoToFollow,
+ beforeEnter: validateAuthenticatedRoute,
+ },
{ name: 'about', path: '/about', component: About },
- { name: 'announcements', path: '/announcements', component: AnnouncementsPage },
+ {
+ name: 'announcements',
+ path: '/announcements',
+ component: AnnouncementsPage,
+ },
{ name: 'drafts', path: '/drafts', component: Drafts },
{ name: 'user-profile', path: '/users/:name', component: UserProfile },
{ name: 'legacy-user-profile', path: '/:name', component: UserProfile },
@@ -92,17 +171,51 @@ export default (store) => {
{ name: 'lists-timeline', path: '/lists/:id', component: ListsTimeline },
{ name: 'lists-edit', path: '/lists/:id/edit', component: ListsEdit },
{ name: 'lists-new', path: '/lists/new', component: ListsEdit },
- { name: 'edit-navigation', path: '/nav-edit', component: NavPanel, props: () => ({ forceExpand: true, forceEditMode: true }), beforeEnter: validateAuthenticatedRoute },
- { name: 'bookmark-folders', path: '/bookmark_folders', component: BookmarkFolders },
- { name: 'bookmark-folder-new', path: '/bookmarks/new-folder', component: BookmarkFolderEdit },
- { name: 'bookmark-folder', path: '/bookmarks/:id', component: BookmarkTimeline },
- { name: 'bookmark-folder-edit', path: '/bookmarks/:id/edit', component: BookmarkFolderEdit }
+ {
+ name: 'edit-navigation',
+ path: '/nav-edit',
+ component: NavPanel,
+ props: () => ({ forceExpand: true, forceEditMode: true }),
+ beforeEnter: validateAuthenticatedRoute,
+ },
+ {
+ name: 'bookmark-folders',
+ path: '/bookmark_folders',
+ component: BookmarkFolders,
+ },
+ {
+ name: 'bookmark-folder-new',
+ path: '/bookmarks/new-folder',
+ component: BookmarkFolderEdit,
+ },
+ {
+ name: 'bookmark-folder',
+ path: '/bookmarks/:id',
+ component: BookmarkTimeline,
+ },
+ {
+ name: 'bookmark-folder-edit',
+ path: '/bookmarks/:id/edit',
+ component: BookmarkFolderEdit,
+ },
]
if (store.state.instance.pleromaChatMessagesAvailable) {
routes = routes.concat([
- { name: 'chat', path: '/users/:username/chats/:recipient_id', component: Chat, meta: { dontScroll: false }, beforeEnter: validateAuthenticatedRoute },
- { name: 'chats', path: '/users/:username/chats', component: ChatList, meta: { dontScroll: false }, beforeEnter: validateAuthenticatedRoute }
+ {
+ name: 'chat',
+ path: '/users/:username/chats/:recipient_id',
+ component: Chat,
+ meta: { dontScroll: false },
+ beforeEnter: validateAuthenticatedRoute,
+ },
+ {
+ name: 'chats',
+ path: '/users/:username/chats',
+ component: ChatList,
+ meta: { dontScroll: false },
+ beforeEnter: validateAuthenticatedRoute,
+ },
])
}
diff --git a/src/components/about/about.js b/src/components/about/about.js
index 1df258450..d091dfd0a 100644
--- a/src/components/about/about.js
+++ b/src/components/about/about.js
@@ -1,8 +1,8 @@
-import InstanceSpecificPanel from '../instance_specific_panel/instance_specific_panel.vue'
import FeaturesPanel from '../features_panel/features_panel.vue'
-import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue'
-import StaffPanel from '../staff_panel/staff_panel.vue'
+import InstanceSpecificPanel from '../instance_specific_panel/instance_specific_panel.vue'
import MRFTransparencyPanel from '../mrf_transparency_panel/mrf_transparency_panel.vue'
+import StaffPanel from '../staff_panel/staff_panel.vue'
+import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue'
const About = {
components: {
@@ -10,16 +10,20 @@ const About = {
FeaturesPanel,
TermsOfServicePanel,
StaffPanel,
- MRFTransparencyPanel
+ MRFTransparencyPanel,
},
computed: {
- showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
- showInstanceSpecificPanel () {
- return this.$store.state.instance.showInstanceSpecificPanel &&
+ showFeaturesPanel() {
+ return this.$store.state.instance.showFeaturesPanel
+ },
+ showInstanceSpecificPanel() {
+ return (
+ this.$store.state.instance.showInstanceSpecificPanel &&
!this.$store.getters.mergedConfig.hideISP &&
this.$store.state.instance.instanceSpecificPanelContent
- }
- }
+ )
+ },
+ },
}
export default About
diff --git a/src/components/account_actions/account_actions.js b/src/components/account_actions/account_actions.js
index 2ac74ea76..ee94dc544 100644
--- a/src/components/account_actions/account_actions.js
+++ b/src/components/account_actions/account_actions.js
@@ -1,27 +1,23 @@
import { mapState } from 'vuex'
-import ProgressButton from '../progress_button/progress_button.vue'
-import Popover from '../popover/popover.vue'
-import UserListMenu from 'src/components/user_list_menu/user_list_menu.vue'
-import ConfirmModal from '../confirm_modal/confirm_modal.vue'
-import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faEllipsisV
-} from '@fortawesome/free-solid-svg-icons'
-import { useReportsStore } from 'src/stores/reports'
-library.add(
- faEllipsisV
-)
+import UserListMenu from 'src/components/user_list_menu/user_list_menu.vue'
+import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
+import { useReportsStore } from 'src/stores/reports'
+import ConfirmModal from '../confirm_modal/confirm_modal.vue'
+import Popover from '../popover/popover.vue'
+import ProgressButton from '../progress_button/progress_button.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faEllipsisV } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faEllipsisV)
const AccountActions = {
- props: [
- 'user', 'relationship'
- ],
- data () {
+ props: ['user', 'relationship'],
+ data() {
return {
showingConfirmBlock: false,
- showingConfirmRemoveFollower: false
+ showingConfirmRemoveFollower: false,
}
},
components: {
@@ -29,25 +25,25 @@ const AccountActions = {
Popover,
UserListMenu,
ConfirmModal,
- UserTimedFilterModal
+ UserTimedFilterModal,
},
methods: {
- showConfirmRemoveUserFromFollowers () {
+ showConfirmRemoveUserFromFollowers() {
this.showingConfirmRemoveFollower = true
},
- hideConfirmRemoveUserFromFollowers () {
+ hideConfirmRemoveUserFromFollowers() {
this.showingConfirmRemoveFollower = false
},
- hideConfirmBlock () {
+ hideConfirmBlock() {
this.showingConfirmBlock = false
},
- showRepeats () {
+ showRepeats() {
this.$store.dispatch('showReblogs', this.user.id)
},
- hideRepeats () {
+ hideRepeats() {
this.$store.dispatch('hideReblogs', this.user.id)
},
- blockUser () {
+ blockUser() {
if (this.$refs.timedBlockDialog) {
this.$refs.timedBlockDialog.optionallyPrompt()
} else {
@@ -58,46 +54,50 @@ const AccountActions = {
}
}
},
- doBlockUser () {
+ doBlockUser() {
this.$store.dispatch('blockUser', { id: this.user.id })
this.hideConfirmBlock()
},
- unblockUser () {
+ unblockUser() {
this.$store.dispatch('unblockUser', this.user.id)
},
- removeUserFromFollowers () {
+ removeUserFromFollowers() {
if (!this.shouldConfirmRemoveUserFromFollowers) {
this.doRemoveUserFromFollowers()
} else {
this.showConfirmRemoveUserFromFollowers()
}
},
- doRemoveUserFromFollowers () {
+ doRemoveUserFromFollowers() {
this.$store.dispatch('removeUserFromFollowers', this.user.id)
this.hideConfirmRemoveUserFromFollowers()
},
- reportUser () {
+ reportUser() {
useReportsStore().openUserReportingModal({ userId: this.user.id })
},
- openChat () {
+ openChat() {
this.$router.push({
name: 'chat',
- params: { username: this.$store.state.users.currentUser.screen_name, recipient_id: this.user.id }
+ params: {
+ username: this.$store.state.users.currentUser.screen_name,
+ recipient_id: this.user.id,
+ },
})
- }
+ },
},
computed: {
- shouldConfirmBlock () {
+ shouldConfirmBlock() {
return this.$store.getters.mergedConfig.modalOnBlock
},
- shouldConfirmRemoveUserFromFollowers () {
+ shouldConfirmRemoveUserFromFollowers() {
return this.$store.getters.mergedConfig.modalOnRemoveUserFromFollowers
},
...mapState({
- blockExpirationSupported: state => state.instance.blockExpiration,
- pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
- })
- }
+ blockExpirationSupported: (state) => state.instance.blockExpiration,
+ pleromaChatMessagesAvailable: (state) =>
+ state.instance.pleromaChatMessagesAvailable,
+ }),
+ },
}
export default AccountActions
diff --git a/src/components/alert.style.js b/src/components/alert.style.js
index 868514764..8a6f842ed 100644
--- a/src/components/alert.style.js
+++ b/src/components/alert.style.js
@@ -1,57 +1,51 @@
export default {
name: 'Alert',
selector: '.alert',
- validInnerComponents: [
- 'Text',
- 'Icon',
- 'Link',
- 'Border',
- 'ButtonUnstyled'
- ],
+ validInnerComponents: ['Text', 'Icon', 'Link', 'Border', 'ButtonUnstyled'],
variants: {
normal: '.neutral',
error: '.error',
warning: '.warning',
- success: '.success'
+ success: '.success',
},
editor: {
border: 1,
- aspect: '3 / 1'
+ aspect: '3 / 1',
},
defaultRules: [
{
directives: {
background: '--text',
opacity: 0.5,
- blur: '9px'
- }
+ blur: '9px',
+ },
},
{
parent: {
- component: 'Alert'
+ component: 'Alert',
},
component: 'Border',
directives: {
- textColor: '--parent'
- }
+ textColor: '--parent',
+ },
},
{
variant: 'error',
directives: {
- background: '--cRed'
- }
+ background: '--cRed',
+ },
},
{
variant: 'warning',
directives: {
- background: '--cOrange'
- }
+ background: '--cOrange',
+ },
},
{
variant: 'success',
directives: {
- background: '--cGreen'
- }
- }
- ]
+ background: '--cGreen',
+ },
+ },
+ ],
}
diff --git a/src/components/announcement/announcement.js b/src/components/announcement/announcement.js
index d1b8257d8..906b84ce2 100644
--- a/src/components/announcement/announcement.js
+++ b/src/components/announcement/announcement.js
@@ -1,109 +1,129 @@
import { mapState } from 'vuex'
+
+import { useAnnouncementsStore } from 'src/stores/announcements'
+import localeService from '../../services/locale/locale.service.js'
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
import RichContent from '../rich_content/rich_content.jsx'
-import localeService from '../../services/locale/locale.service.js'
-import { useAnnouncementsStore } from 'src/stores/announcements'
const Announcement = {
components: {
AnnouncementEditor,
- RichContent
+ RichContent,
},
- data () {
+ data() {
return {
editing: false,
editedAnnouncement: {
content: '',
startsAt: undefined,
endsAt: undefined,
- allDay: undefined
+ allDay: undefined,
},
- editError: ''
+ editError: '',
}
},
props: {
- announcement: Object
+ announcement: Object,
},
computed: {
...mapState({
- currentUser: state => state.users.currentUser
+ currentUser: (state) => state.users.currentUser,
}),
- canEditAnnouncement () {
- return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
+ canEditAnnouncement() {
+ return (
+ this.currentUser &&
+ this.currentUser.privileges.includes(
+ 'announcements_manage_announcements',
+ )
+ )
},
- content () {
+ content() {
return this.announcement.content
},
- isRead () {
+ isRead() {
return this.announcement.read
},
- publishedAt () {
+ publishedAt() {
const time = this.announcement.published_at
if (!time) {
return
}
- return this.formatTimeOrDate(time, localeService.internalToBrowserLocale(this.$i18n.locale))
+ return this.formatTimeOrDate(
+ time,
+ localeService.internalToBrowserLocale(this.$i18n.locale),
+ )
},
- startsAt () {
+ startsAt() {
const time = this.announcement.starts_at
if (!time) {
return
}
- return this.formatTimeOrDate(time, localeService.internalToBrowserLocale(this.$i18n.locale))
+ return this.formatTimeOrDate(
+ time,
+ localeService.internalToBrowserLocale(this.$i18n.locale),
+ )
},
- endsAt () {
+ endsAt() {
const time = this.announcement.ends_at
if (!time) {
return
}
- return this.formatTimeOrDate(time, localeService.internalToBrowserLocale(this.$i18n.locale))
+ return this.formatTimeOrDate(
+ time,
+ localeService.internalToBrowserLocale(this.$i18n.locale),
+ )
},
- inactive () {
+ inactive() {
return this.announcement.inactive
- }
+ },
},
methods: {
- markAsRead () {
+ markAsRead() {
if (!this.isRead) {
- return useAnnouncementsStore().markAnnouncementAsRead(this.announcement.id)
+ return useAnnouncementsStore().markAnnouncementAsRead(
+ this.announcement.id,
+ )
}
},
- deleteAnnouncement () {
+ deleteAnnouncement() {
return useAnnouncementsStore().deleteAnnouncement(this.announcement.id)
},
- formatTimeOrDate (time, locale) {
+ formatTimeOrDate(time, locale) {
const d = new Date(time)
- return this.announcement.all_day ? d.toLocaleDateString(locale) : d.toLocaleString(locale)
+ return this.announcement.all_day
+ ? d.toLocaleDateString(locale)
+ : d.toLocaleString(locale)
},
- enterEditMode () {
+ enterEditMode() {
this.editedAnnouncement.content = this.announcement.pleroma.raw_content
this.editedAnnouncement.startsAt = this.announcement.starts_at
this.editedAnnouncement.endsAt = this.announcement.ends_at
this.editedAnnouncement.allDay = this.announcement.all_day
this.editing = true
},
- submitEdit () {
- useAnnouncementsStore().editAnnouncement({
- id: this.announcement.id,
- ...this.editedAnnouncement
- })
+ submitEdit() {
+ useAnnouncementsStore()
+ .editAnnouncement({
+ id: this.announcement.id,
+ ...this.editedAnnouncement,
+ })
.then(() => {
this.editing = false
})
- .catch(error => {
+ .catch((error) => {
this.editError = error.error
})
},
- cancelEdit () {
+ cancelEdit() {
this.editing = false
},
- clearError () {
+ clearError() {
this.editError = undefined
- }
- }
+ },
+ },
}
export default Announcement
diff --git a/src/components/announcement_editor/announcement_editor.js b/src/components/announcement_editor/announcement_editor.js
index 79a03afe1..6d22ac1fd 100644
--- a/src/components/announcement_editor/announcement_editor.js
+++ b/src/components/announcement_editor/announcement_editor.js
@@ -2,12 +2,12 @@ import Checkbox from '../checkbox/checkbox.vue'
const AnnouncementEditor = {
components: {
- Checkbox
+ Checkbox,
},
props: {
announcement: Object,
- disabled: Boolean
- }
+ disabled: Boolean,
+ },
}
export default AnnouncementEditor
diff --git a/src/components/announcements_page/announcements_page.js b/src/components/announcements_page/announcements_page.js
index 9ce0b45f5..0c4383d2e 100644
--- a/src/components/announcements_page/announcements_page.js
+++ b/src/components/announcements_page/announcements_page.js
@@ -1,59 +1,66 @@
import { mapState } from 'vuex'
+
+import { useAnnouncementsStore } from 'src/stores/announcements'
import Announcement from '../announcement/announcement.vue'
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
-import { useAnnouncementsStore } from 'src/stores/announcements'
const AnnouncementsPage = {
components: {
Announcement,
- AnnouncementEditor
+ AnnouncementEditor,
},
- data () {
+ data() {
return {
newAnnouncement: {
content: '',
startsAt: undefined,
endsAt: undefined,
- allDay: false
+ allDay: false,
},
posting: false,
- error: undefined
+ error: undefined,
}
},
- mounted () {
+ mounted() {
useAnnouncementsStore().fetchAnnouncements()
},
computed: {
...mapState({
- currentUser: state => state.users.currentUser
+ currentUser: (state) => state.users.currentUser,
}),
- announcements () {
+ announcements() {
return useAnnouncementsStore().announcements
},
- canPostAnnouncement () {
- return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
- }
+ canPostAnnouncement() {
+ return (
+ this.currentUser &&
+ this.currentUser.privileges.includes(
+ 'announcements_manage_announcements',
+ )
+ )
+ },
},
methods: {
- postAnnouncement () {
+ postAnnouncement() {
this.posting = true
- useAnnouncementsStore().postAnnouncement(this.newAnnouncement)
+ useAnnouncementsStore()
+ .postAnnouncement(this.newAnnouncement)
.then(() => {
this.newAnnouncement.content = ''
this.startsAt = undefined
this.endsAt = undefined
})
- .catch(error => {
+ .catch((error) => {
this.error = error.error
})
.finally(() => {
this.posting = false
})
},
- clearError () {
+ clearError() {
this.error = undefined
- }
- }
+ },
+ },
}
export default AnnouncementsPage
diff --git a/src/components/async_component_error/async_component_error.vue b/src/components/async_component_error/async_component_error.vue
index 2ff8974c1..baf430950 100644
--- a/src/components/async_component_error/async_component_error.vue
+++ b/src/components/async_component_error/async_component_error.vue
@@ -21,10 +21,10 @@
export default {
emits: ['resetAsyncComponent'],
methods: {
- retry () {
+ retry() {
this.$emit('resetAsyncComponent')
- }
- }
+ },
+ },
}
diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js
index 21d793930..31fceba60 100644
--- a/src/components/attachment/attachment.js
+++ b/src/components/attachment/attachment.js
@@ -1,24 +1,26 @@
-import StillImage from '../still-image/still-image.vue'
-import Flash from '../flash/flash.vue'
-import VideoAttachment from '../video_attachment/video_attachment.vue'
+import { mapGetters } from 'vuex'
+
+import { useMediaViewerStore } from 'src/stores/media_viewer'
import nsfwImage from '../../assets/nsfw.png'
import fileTypeService from '../../services/file_type/file_type.service.js'
-import { mapGetters } from 'vuex'
+import Flash from '../flash/flash.vue'
+import StillImage from '../still-image/still-image.vue'
+import VideoAttachment from '../video_attachment/video_attachment.vue'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
+ faAlignRight,
faFile,
- faMusic,
faImage,
- faVideo,
- faPlayCircle,
- faTimes,
- faStop,
- faSearchPlus,
- faTrashAlt,
+ faMusic,
faPencilAlt,
- faAlignRight
+ faPlayCircle,
+ faSearchPlus,
+ faStop,
+ faTimes,
+ faTrashAlt,
+ faVideo,
} from '@fortawesome/free-solid-svg-icons'
-import { useMediaViewerStore } from 'src/stores/media_viewer'
library.add(
faFile,
@@ -31,7 +33,7 @@ library.add(
faSearchPlus,
faTrashAlt,
faPencilAlt,
- faAlignRight
+ faAlignRight,
)
const Attachment = {
@@ -46,72 +48,74 @@ const Attachment = {
'remove',
'shiftUp',
'shiftDn',
- 'edit'
+ 'edit',
],
- data () {
+ data() {
return {
localDescription: this.description || this.attachment.description,
nsfwImage: this.$store.state.instance.nsfwCensorImage || nsfwImage,
hideNsfwLocal: this.$store.getters.mergedConfig.hideNsfw,
preloadImage: this.$store.getters.mergedConfig.preloadImage,
loading: false,
- img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img'),
+ img:
+ fileTypeService.fileType(this.attachment.mimetype) === 'image' &&
+ document.createElement('img'),
modalOpen: false,
showHidden: false,
flashLoaded: false,
- showDescription: false
+ showDescription: false,
}
},
components: {
Flash,
StillImage,
- VideoAttachment
+ VideoAttachment,
},
computed: {
- classNames () {
+ classNames() {
return [
{
'-loading': this.loading,
'-nsfw-placeholder': this.hidden,
'-editable': this.edit !== undefined,
- '-compact': this.compact
+ '-compact': this.compact,
},
'-type-' + this.type,
this.size && '-size-' + this.size,
- `-${this.useContainFit ? 'contain' : 'cover'}-fit`
+ `-${this.useContainFit ? 'contain' : 'cover'}-fit`,
]
},
- usePlaceholder () {
+ usePlaceholder() {
return this.size === 'hide'
},
- useContainFit () {
+ useContainFit() {
return this.$store.getters.mergedConfig.useContainFit
},
- placeholderName () {
+ placeholderName() {
if (this.attachment.description === '' || !this.attachment.description) {
return this.type.toUpperCase()
}
return this.attachment.description
},
- placeholderIconClass () {
+ placeholderIconClass() {
if (this.type === 'image') return 'image'
if (this.type === 'video') return 'video'
if (this.type === 'audio') return 'music'
return 'file'
},
- referrerpolicy () {
+ referrerpolicy() {
return this.$store.state.instance.mediaProxyAvailable ? '' : 'no-referrer'
},
- type () {
+ type() {
return fileTypeService.fileType(this.attachment.mimetype)
},
- hidden () {
+ hidden() {
return this.nsfw && this.hideNsfwLocal && !this.showHidden
},
- isEmpty () {
- return (this.type === 'html' && !this.attachment.oembed)
+ isEmpty() {
+ return this.type === 'html' && !this.attachment.oembed
},
- useModal () {
+ useModal() {
let modalTypes = []
switch (this.size) {
case 'hide':
@@ -126,26 +130,26 @@ const Attachment = {
}
return modalTypes.includes(this.type)
},
- videoTag () {
+ videoTag() {
return this.useModal ? 'button' : 'span'
},
- ...mapGetters(['mergedConfig'])
+ ...mapGetters(['mergedConfig']),
},
watch: {
- 'attachment.description' (newVal) {
+ 'attachment.description'(newVal) {
this.localDescription = newVal
},
- localDescription (newVal) {
+ localDescription(newVal) {
this.onEdit(newVal)
- }
+ },
},
methods: {
- linkClicked ({ target }) {
+ linkClicked({ target }) {
if (target.tagName === 'A') {
window.open(target.href, '_blank')
}
},
- openModal () {
+ openModal() {
if (this.useModal) {
this.$emit('setMedia')
useMediaViewerStore().setCurrentMedia(this.attachment)
@@ -153,34 +157,35 @@ const Attachment = {
window.open(this.attachment.url)
}
},
- openModalForce () {
+ openModalForce() {
this.$emit('setMedia')
useMediaViewerStore().setCurrentMedia(this.attachment)
},
- onEdit (event) {
+ onEdit(event) {
this.edit && this.edit(this.attachment, event)
},
- onRemove () {
+ onRemove() {
this.remove && this.remove(this.attachment)
},
- onShiftUp () {
+ onShiftUp() {
this.shiftUp && this.shiftUp(this.attachment)
},
- onShiftDn () {
+ onShiftDn() {
this.shiftDn && this.shiftDn(this.attachment)
},
- stopFlash () {
+ stopFlash() {
this.$refs.flash.closePlayer()
},
- setFlashLoaded (event) {
+ setFlashLoaded(event) {
this.flashLoaded = event
},
- toggleDescription () {
+ toggleDescription() {
this.showDescription = !this.showDescription
},
- toggleHidden (event) {
+ toggleHidden(event) {
if (
- (this.mergedConfig.useOneClickNsfw && !this.showHidden) &&
+ this.mergedConfig.useOneClickNsfw &&
+ !this.showHidden &&
(this.type !== 'video' || this.mergedConfig.playVideosInModal)
) {
this.openModal(event)
@@ -201,12 +206,12 @@ const Attachment = {
this.showHidden = !this.showHidden
}
},
- onImageLoad (image) {
+ onImageLoad(image) {
const width = image.naturalWidth
const height = image.naturalHeight
this.$emit('naturalSizeLoad', { id: this.attachment.id, width, height })
- }
- }
+ },
+ },
}
export default Attachment
diff --git a/src/components/auth_form/auth_form.js b/src/components/auth_form/auth_form.js
index 243cbf574..ce88aa6f9 100644
--- a/src/components/auth_form/auth_form.js
+++ b/src/components/auth_form/auth_form.js
@@ -1,28 +1,33 @@
+import { mapState } from 'pinia'
import { h, resolveComponent } from 'vue'
+
+import { useAuthFlowStore } from 'src/stores/auth_flow'
import LoginForm from '../login_form/login_form.vue'
import MFARecoveryForm from '../mfa_form/recovery_form.vue'
import MFATOTPForm from '../mfa_form/totp_form.vue'
-import { mapState } from 'pinia'
-import { useAuthFlowStore } from 'src/stores/auth_flow'
const AuthForm = {
name: 'AuthForm',
- render () {
+ render() {
return h(resolveComponent(this.authForm))
},
computed: {
- authForm () {
- if (this.requiredTOTP) { return 'MFATOTPForm' }
- if (this.requiredRecovery) { return 'MFARecoveryForm' }
+ authForm() {
+ if (this.requiredTOTP) {
+ return 'MFATOTPForm'
+ }
+ if (this.requiredRecovery) {
+ return 'MFARecoveryForm'
+ }
return 'LoginForm'
},
- ...mapState(useAuthFlowStore, ['requiredTOTP', 'requiredRecovery'])
+ ...mapState(useAuthFlowStore, ['requiredTOTP', 'requiredRecovery']),
},
components: {
MFARecoveryForm,
MFATOTPForm,
- LoginForm
- }
+ LoginForm,
+ },
}
export default AuthForm
diff --git a/src/components/autosuggest/autosuggest.js b/src/components/autosuggest/autosuggest.js
index f58f17bb6..37b7706db 100644
--- a/src/components/autosuggest/autosuggest.js
+++ b/src/components/autosuggest/autosuggest.js
@@ -2,51 +2,55 @@ const debounceMilliseconds = 500
export default {
props: {
- query: { // function to query results and return a promise
+ query: {
+ // function to query results and return a promise
type: Function,
- required: true
+ required: true,
},
- filter: { // function to filter results in real time
- type: Function
+ filter: {
+ // function to filter results in real time
+ type: Function,
},
placeholder: {
type: String,
- default: 'Search...'
- }
+ default: 'Search...',
+ },
},
- data () {
+ data() {
return {
term: '',
timeout: null,
results: [],
- resultsVisible: false
+ resultsVisible: false,
}
},
computed: {
- filtered () {
+ filtered() {
return this.filter ? this.filter(this.results) : this.results
- }
+ },
},
watch: {
- term (val) {
+ term(val) {
this.fetchResults(val)
- }
+ },
},
methods: {
- fetchResults (term) {
+ fetchResults(term) {
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
this.results = []
if (term) {
- this.query(term).then((results) => { this.results = results })
+ this.query(term).then((results) => {
+ this.results = results
+ })
}
}, debounceMilliseconds)
},
- onInputClick () {
+ onInputClick() {
this.resultsVisible = true
},
- onClickOutside () {
+ onClickOutside() {
this.resultsVisible = false
- }
- }
+ },
+ },
}
diff --git a/src/components/avatar_list/avatar_list.js b/src/components/avatar_list/avatar_list.js
index 9b6301b22..aad157686 100644
--- a/src/components/avatar_list/avatar_list.js
+++ b/src/components/avatar_list/avatar_list.js
@@ -1,21 +1,25 @@
-import UserAvatar from '../user_avatar/user_avatar.vue'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
+import UserAvatar from '../user_avatar/user_avatar.vue'
const AvatarList = {
props: ['users'],
computed: {
- slicedUsers () {
+ slicedUsers() {
return this.users ? this.users.slice(0, 15) : []
- }
+ },
},
components: {
- UserAvatar
+ UserAvatar,
},
methods: {
- userProfileLink (user) {
- return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
- }
- }
+ userProfileLink(user) {
+ return generateProfileLink(
+ user.id,
+ user.screen_name,
+ this.$store.state.instance.restrictedNicknames,
+ )
+ },
+ },
}
export default AvatarList
diff --git a/src/components/badge.style.js b/src/components/badge.style.js
index 0697cac6c..ab28429cc 100644
--- a/src/components/badge.style.js
+++ b/src/components/badge.style.js
@@ -1,30 +1,27 @@
export default {
name: 'Badge',
selector: '.badge',
- validInnerComponents: [
- 'Text',
- 'Icon'
- ],
+ validInnerComponents: ['Text', 'Icon'],
variants: {
- notification: '.-notification'
+ notification: '.-notification',
},
defaultRules: [
{
component: 'Root',
directives: {
- '--badgeNotification': 'color | --cRed'
- }
+ '--badgeNotification': 'color | --cRed',
+ },
},
{
directives: {
- background: '--cGreen'
- }
+ background: '--cGreen',
+ },
},
{
variant: 'notification',
directives: {
- background: '--cRed'
- }
- }
- ]
+ background: '--cRed',
+ },
+ },
+ ],
}
diff --git a/src/components/basic_user_card/basic_user_card.js b/src/components/basic_user_card/basic_user_card.js
index 31de2d75f..cc4cbce44 100644
--- a/src/components/basic_user_card/basic_user_card.js
+++ b/src/components/basic_user_card/basic_user_card.js
@@ -1,24 +1,26 @@
-import UserPopover from '../user_popover/user_popover.vue'
-import UserAvatar from '../user_avatar/user_avatar.vue'
-import UserLink from '../user_link/user_link.vue'
import RichContent from 'src/components/rich_content/rich_content.jsx'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
+import UserAvatar from '../user_avatar/user_avatar.vue'
+import UserLink from '../user_link/user_link.vue'
+import UserPopover from '../user_popover/user_popover.vue'
const BasicUserCard = {
- props: [
- 'user'
- ],
+ props: ['user'],
components: {
UserPopover,
UserAvatar,
RichContent,
- UserLink
+ UserLink,
},
methods: {
- userProfileLink (user) {
- return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
- }
- }
+ userProfileLink(user) {
+ return generateProfileLink(
+ user.id,
+ user.screen_name,
+ this.$store.state.instance.restrictedNicknames,
+ )
+ },
+ },
}
export default BasicUserCard
diff --git a/src/components/block_card/block_card.js b/src/components/block_card/block_card.js
index 9a618db3f..7301bf0c7 100644
--- a/src/components/block_card/block_card.js
+++ b/src/components/block_card/block_card.js
@@ -5,42 +5,44 @@ import BasicUserCard from '../basic_user_card/basic_user_card.vue'
const BlockCard = {
props: ['userId'],
computed: {
- user () {
+ user() {
return this.$store.getters.findUser(this.userId)
},
- relationship () {
+ relationship() {
return this.$store.getters.relationship(this.userId)
},
- blocked () {
+ blocked() {
return this.relationship.blocking
},
- blockExpiryAvailable () {
- return this.user.block_expires_at !== undefined
+ blockExpiryAvailable() {
+ return Object.hasOwn(this.user, 'block_expires_at')
},
- blockExpiry () {
- return this.user.block_expires_at == null
+ blockExpiry() {
+ return this.user.block_expires_at === false
? this.$t('user_card.block_expires_forever')
- : this.$t('user_card.block_expires_at', [new Date(this.user.mute_expires_at).toLocaleString()])
+ : this.$t('user_card.block_expires_at', [
+ new Date(this.user.mute_expires_at).toLocaleString(),
+ ])
},
...mapState({
- blockExpirationSupported: state => state.instance.blockExpiration,
- })
+ blockExpirationSupported: (state) => state.instance.blockExpiration,
+ }),
},
components: {
- BasicUserCard
+ BasicUserCard,
},
methods: {
- unblockUser () {
+ unblockUser() {
this.$store.dispatch('unblockUser', this.user.id)
},
- blockUser () {
+ blockUser() {
if (this.blockExpirationSupported) {
this.$refs.timedBlockDialog.optionallyPrompt()
} else {
this.$store.dispatch('blockUser', { id: this.user.id })
}
- }
- }
+ },
+ },
}
export default BlockCard
diff --git a/src/components/bookmark_folder_card/bookmark_folder_card.js b/src/components/bookmark_folder_card/bookmark_folder_card.js
index bf274d9d7..37b3f2e5e 100644
--- a/src/components/bookmark_folder_card/bookmark_folder_card.js
+++ b/src/components/bookmark_folder_card/bookmark_folder_card.js
@@ -1,22 +1,15 @@
import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faEllipsisH
-} from '@fortawesome/free-solid-svg-icons'
+import { faEllipsisH } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faEllipsisH
-)
+library.add(faEllipsisH)
const BookmarkFolderCard = {
- props: [
- 'folder',
- 'allBookmarks'
- ],
+ props: ['folder', 'allBookmarks'],
computed: {
- firstLetter () {
+ firstLetter() {
return this.folder ? this.folder.name[0] : null
- }
- }
+ },
+ },
}
export default BookmarkFolderCard
diff --git a/src/components/bookmark_folder_edit/bookmark_folder_edit.js b/src/components/bookmark_folder_edit/bookmark_folder_edit.js
index bb96585bf..a658a0f40 100644
--- a/src/components/bookmark_folder_edit/bookmark_folder_edit.js
+++ b/src/components/bookmark_folder_edit/bookmark_folder_edit.js
@@ -1,10 +1,10 @@
-import EmojiPicker from '../emoji_picker/emoji_picker.vue'
-import apiService from '../../services/api/api.service'
-import { useInterfaceStore } from 'src/stores/interface'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
+import { useInterfaceStore } from 'src/stores/interface'
+import apiService from '../../services/api/api.service'
+import EmojiPicker from '../emoji_picker/emoji_picker.vue'
const BookmarkFolderEdit = {
- data () {
+ data() {
return {
name: '',
nameDraft: '',
@@ -13,54 +13,59 @@ const BookmarkFolderEdit = {
emojiDraft: '',
emojiUrlDraft: null,
emojiPickerExpanded: false,
- reallyDelete: false
+ reallyDelete: false,
}
},
components: {
- EmojiPicker
+ EmojiPicker,
},
- created () {
+ created() {
if (!this.id) return
const credentials = this.$store.state.users.currentUser.credentials
- apiService.fetchBookmarkFolders({ credentials })
- .then((folders) => {
- const folder = folders.find(folder => folder.id === this.id)
- if (!folder) return
+ apiService.fetchBookmarkFolders({ credentials }).then((folders) => {
+ const folder = folders.find((folder) => folder.id === this.id)
+ if (!folder) return
- this.nameDraft = this.name = folder.name
- this.emojiDraft = this.emoji = folder.emoji
- this.emojiUrlDraft = this.emojiUrl = folder.emoji_url
- })
+ this.nameDraft = this.name = folder.name
+ this.emojiDraft = this.emoji = folder.emoji
+ this.emojiUrlDraft = this.emojiUrl = folder.emoji_url
+ })
},
computed: {
- id () {
+ id() {
return this.$route.params.id
- }
+ },
},
methods: {
- selectEmoji (event) {
+ selectEmoji(event) {
this.emojiDraft = event.insertion
this.emojiUrlDraft = event.insertionUrl
},
- showEmojiPicker () {
+ showEmojiPicker() {
if (!this.emojiPickerExpanded) {
this.$refs.picker.showPicker()
}
},
- onShowPicker () {
+ onShowPicker() {
this.emojiPickerExpanded = true
},
- onClosePicker () {
+ onClosePicker() {
this.emojiPickerExpanded = false
},
- updateFolder () {
- useBookmarkFoldersStore().updateBookmarkFolder({ folderId: this.id, name: this.nameDraft, emoji: this.emojiDraft })
+ updateFolder() {
+ useBookmarkFoldersStore()
+ .updateBookmarkFolder({
+ folderId: this.id,
+ name: this.nameDraft,
+ emoji: this.emojiDraft,
+ })
.then(() => {
this.$router.push({ name: 'bookmark-folders' })
})
},
- createFolder () {
- useBookmarkFoldersStore().createBookmarkFolder({ name: this.nameDraft, emoji: this.emojiDraft })
+ createFolder() {
+ useBookmarkFoldersStore()
+ .createBookmarkFolder({ name: this.nameDraft, emoji: this.emojiDraft })
.then(() => {
this.$router.push({ name: 'bookmark-folders' })
})
@@ -68,15 +73,15 @@ const BookmarkFolderEdit = {
useInterfaceStore().pushGlobalNotice({
messageKey: 'bookmark_folders.error',
messageArgs: [e.message],
- level: 'error'
+ level: 'error',
})
})
},
- deleteFolder () {
+ deleteFolder() {
useBookmarkFoldersStore().deleteBookmarkFolder({ folderId: this.id })
this.$router.push({ name: 'bookmark-folders' })
- }
- }
+ },
+ },
}
export default BookmarkFolderEdit
diff --git a/src/components/bookmark_folders/bookmark_folders.js b/src/components/bookmark_folders/bookmark_folders.js
index 096f3769d..8e09abb31 100644
--- a/src/components/bookmark_folders/bookmark_folders.js
+++ b/src/components/bookmark_folders/bookmark_folders.js
@@ -1,28 +1,28 @@
-import BookmarkFolderCard from '../bookmark_folder_card/bookmark_folder_card.vue'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
+import BookmarkFolderCard from '../bookmark_folder_card/bookmark_folder_card.vue'
const BookmarkFolders = {
- data () {
+ data() {
return {
- isNew: false
+ isNew: false,
}
},
components: {
- BookmarkFolderCard
+ BookmarkFolderCard,
},
computed: {
- bookmarkFolders () {
+ bookmarkFolders() {
return useBookmarkFoldersStore().allFolders
- }
+ },
},
methods: {
- cancelNewFolder () {
+ cancelNewFolder() {
this.isNew = false
},
- newFolder () {
+ newFolder() {
this.isNew = true
- }
- }
+ },
+ },
}
export default BookmarkFolders
diff --git a/src/components/bookmark_folders_menu/bookmark_folders_menu_content.js b/src/components/bookmark_folders_menu/bookmark_folders_menu_content.js
index dc46b91b3..e84b3bc85 100644
--- a/src/components/bookmark_folders_menu/bookmark_folders_menu_content.js
+++ b/src/components/bookmark_folders_menu/bookmark_folders_menu_content.js
@@ -1,20 +1,19 @@
import { mapState } from 'pinia'
-import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
+
import { getBookmarkFolderEntries } from 'src/components/navigation/filter.js'
+import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
export const BookmarkFoldersMenuContent = {
- props: [
- 'showPin'
- ],
+ props: ['showPin'],
components: {
- NavigationEntry
+ NavigationEntry,
},
computed: {
...mapState(useBookmarkFoldersStore, {
- folders: getBookmarkFolderEntries
- })
- }
+ folders: getBookmarkFolderEntries,
+ }),
+ },
}
export default BookmarkFoldersMenuContent
diff --git a/src/components/bookmark_timeline/bookmark_timeline.js b/src/components/bookmark_timeline/bookmark_timeline.js
index 9571d630f..a241b6ac7 100644
--- a/src/components/bookmark_timeline/bookmark_timeline.js
+++ b/src/components/bookmark_timeline/bookmark_timeline.js
@@ -1,32 +1,38 @@
import Timeline from '../timeline/timeline.vue'
const Bookmarks = {
- created () {
+ created() {
this.$store.commit('clearTimeline', { timeline: 'bookmarks' })
- this.$store.dispatch('startFetchingTimeline', { timeline: 'bookmarks', bookmarkFolderId: this.folderId || null })
+ this.$store.dispatch('startFetchingTimeline', {
+ timeline: 'bookmarks',
+ bookmarkFolderId: this.folderId || null,
+ })
},
components: {
- Timeline
+ Timeline,
},
computed: {
- folderId () {
+ folderId() {
return this.$route.params.id
},
- timeline () {
+ timeline() {
return this.$store.state.statuses.timelines.bookmarks
- }
+ },
},
watch: {
- folderId () {
+ folderId() {
this.$store.commit('clearTimeline', { timeline: 'bookmarks' })
this.$store.dispatch('stopFetchingTimeline', 'bookmarks')
- this.$store.dispatch('startFetchingTimeline', { timeline: 'bookmarks', bookmarkFolderId: this.folderId || null })
- }
+ this.$store.dispatch('startFetchingTimeline', {
+ timeline: 'bookmarks',
+ bookmarkFolderId: this.folderId || null,
+ })
+ },
},
- unmounted () {
+ unmounted() {
this.$store.commit('clearTimeline', { timeline: 'bookmarks' })
this.$store.dispatch('stopFetchingTimeline', 'bookmarks')
- }
+ },
}
export default Bookmarks
diff --git a/src/components/border.style.js b/src/components/border.style.js
index 7f2c30163..e7cc31c57 100644
--- a/src/components/border.style.js
+++ b/src/components/border.style.js
@@ -6,8 +6,8 @@ export default {
{
directives: {
textColor: '$mod(--parent 10)',
- textAuto: 'no-auto'
- }
- }
- ]
+ textAuto: 'no-auto',
+ },
+ },
+ ],
}
diff --git a/src/components/bubble_timeline/bubble_timeline.js b/src/components/bubble_timeline/bubble_timeline.js
index 6f73dd2b8..d3835e0e8 100644
--- a/src/components/bubble_timeline/bubble_timeline.js
+++ b/src/components/bubble_timeline/bubble_timeline.js
@@ -1,18 +1,20 @@
import Timeline from '../timeline/timeline.vue'
+
const BubbleTimeline = {
components: {
- Timeline
+ Timeline,
},
computed: {
- timeline () { return this.$store.state.statuses.timelines.bubble }
+ timeline() {
+ return this.$store.state.statuses.timelines.bubble
+ },
},
- created () {
+ created() {
this.$store.dispatch('startFetchingTimeline', { timeline: 'bubble' })
},
- unmounted () {
+ unmounted() {
this.$store.dispatch('stopFetchingTimeline', 'bubble')
- }
-
+ },
}
export default BubbleTimeline
diff --git a/src/components/button.style.js b/src/components/button.style.js
index 5cffefd91..3fb308b89 100644
--- a/src/components/button.style.js
+++ b/src/components/button.style.js
@@ -12,25 +12,22 @@ export default {
focused: ':focus-within',
pressed: ':active',
hover: ':is(:hover, :focus-visible):not(:disabled)',
- disabled: ':disabled'
+ disabled: ':disabled',
},
// Variants are mutually exclusive, each component implicitly has "normal" variant, and all other variants inherit from it.
variants: {
// Variants save on computation time since adding new variant just adds one more "set".
// normal: '', // you can override normal variant, it will be appenended to the main class
danger: '.-danger',
- transparent: '.-transparent'
+ transparent: '.-transparent',
// Overall the compuation difficulty is N*((1/6)M^3+M) where M is number of distinct states and N is number of variants.
// This (currently) is further multipled by number of places where component can exist.
},
editor: {
- aspect: '2 / 1'
+ aspect: '2 / 1',
},
// This lists all other components that can possibly exist within one. Recursion is currently not supported (and probably won't be supported ever).
- validInnerComponents: [
- 'Text',
- 'Icon'
- ],
+ validInnerComponents: ['Text', 'Icon'],
// Default rules, used as "default theme", essentially.
defaultRules: [
{
@@ -39,9 +36,11 @@ export default {
'--buttonDefaultHoverGlow': 'shadow | 0 0 1 2 --text / 0.4',
'--buttonDefaultFocusGlow': 'shadow | 0 0 1 2 --link / 0.5',
'--buttonDefaultShadow': 'shadow | 0 0 2 #000000',
- '--buttonDefaultBevel': 'shadow | $borderSide(#FFFFFF top 0.2 1), $borderSide(#000000 bottom 0.2 1)',
- '--buttonPressedBevel': 'shadow | inset 0 0 4 #000000, $borderSide(#FFFFFF bottom 0.2 1), $borderSide(#000000 top 0.2 1)'
- }
+ '--buttonDefaultBevel':
+ 'shadow | $borderSide(#FFFFFF top 0.2 1), $borderSide(#000000 bottom 0.2 1)',
+ '--buttonPressedBevel':
+ 'shadow | inset 0 0 4 #000000, $borderSide(#FFFFFF bottom 0.2 1), $borderSide(#000000 top 0.2 1)',
+ },
},
{
// component: 'Button', // no need to specify components every time unless you're specifying how other component should look
@@ -49,128 +48,128 @@ export default {
directives: {
background: '--fg',
shadow: ['--buttonDefaultShadow', '--buttonDefaultBevel'],
- roundness: 3
- }
+ roundness: 3,
+ },
},
{
variant: 'danger',
directives: {
- background: '--cRed'
- }
+ background: '--cRed',
+ },
},
{
variant: 'transparent',
directives: {
- opacity: 0.5
- }
+ opacity: 0.5,
+ },
},
{
component: 'Text',
parent: {
component: 'Button',
- variant: 'transparent'
+ variant: 'transparent',
},
directives: {
- textColor: '--text'
- }
+ textColor: '--text',
+ },
},
{
component: 'Icon',
parent: {
component: 'Button',
- variant: 'transparent'
+ variant: 'transparent',
},
directives: {
- textColor: '--text'
- }
+ textColor: '--text',
+ },
},
{
state: ['hover'],
directives: {
- shadow: ['--buttonDefaultHoverGlow', '--buttonDefaultBevel']
- }
+ shadow: ['--buttonDefaultHoverGlow', '--buttonDefaultBevel'],
+ },
},
{
state: ['focused'],
directives: {
- shadow: ['--buttonDefaultFocusGlow', '--buttonDefaultBevel']
- }
+ shadow: ['--buttonDefaultFocusGlow', '--buttonDefaultBevel'],
+ },
},
{
state: ['pressed'],
directives: {
- shadow: ['--buttonDefaultShadow', '--buttonPressedBevel']
- }
+ shadow: ['--buttonDefaultShadow', '--buttonPressedBevel'],
+ },
},
{
state: ['pressed', 'hover'],
directives: {
- shadow: ['--buttonPressedBevel', '--buttonDefaultHoverGlow']
- }
+ shadow: ['--buttonPressedBevel', '--buttonDefaultHoverGlow'],
+ },
},
{
state: ['toggled'],
directives: {
background: '--accent,-24.2',
- shadow: ['--buttonDefaultShadow', '--buttonPressedBevel']
- }
+ shadow: ['--buttonDefaultShadow', '--buttonPressedBevel'],
+ },
},
{
state: ['toggled', 'hover'],
directives: {
background: '--accent,-24.2',
- shadow: ['--buttonDefaultHoverGlow', '--buttonPressedBevel']
- }
+ shadow: ['--buttonDefaultHoverGlow', '--buttonPressedBevel'],
+ },
},
{
state: ['toggled', 'focused'],
directives: {
background: '--accent,-24.2',
- shadow: ['--buttonDefaultHoverGlow', '--buttonPressedBevel']
- }
+ shadow: ['--buttonDefaultHoverGlow', '--buttonPressedBevel'],
+ },
},
{
state: ['toggled', 'hover', 'focused'],
directives: {
background: '--accent,-24.2',
- shadow: ['--buttonDefaultHoverGlow', '--buttonPressedBevel']
- }
+ shadow: ['--buttonDefaultHoverGlow', '--buttonPressedBevel'],
+ },
},
{
state: ['toggled', 'disabled'],
directives: {
background: '$blend(--accent 0.25 --parent)',
- shadow: ['--buttonPressedBevel']
- }
+ shadow: ['--buttonPressedBevel'],
+ },
},
{
state: ['disabled'],
directives: {
background: '$blend(--inheritedBackground 0.25 --parent)',
- shadow: ['--buttonDefaultBevel']
- }
+ shadow: ['--buttonDefaultBevel'],
+ },
},
{
component: 'Text',
parent: {
component: 'Button',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
+ textOpacityMode: 'blend',
+ },
},
{
component: 'Icon',
parent: {
component: 'Button',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
- }
- ]
+ textOpacityMode: 'blend',
+ },
+ },
+ ],
}
diff --git a/src/components/button_unstyled.style.js b/src/components/button_unstyled.style.js
index 9e1a2ca90..c35fb8f69 100644
--- a/src/components/button_unstyled.style.js
+++ b/src/components/button_unstyled.style.js
@@ -7,91 +7,86 @@ export default {
toggled: '.toggled',
disabled: ':disabled',
hover: ':is(:hover, :focus-visible):not(:disabled)',
- focused: ':focus-within:not(:is(:focus-visible))'
+ focused: ':focus-within:not(:is(:focus-visible))',
},
- validInnerComponents: [
- 'Text',
- 'Link',
- 'Icon',
- 'Badge'
- ],
+ validInnerComponents: ['Text', 'Link', 'Icon', 'Badge'],
defaultRules: [
{
directives: {
- shadow: []
- }
+ shadow: [],
+ },
},
{
component: 'Icon',
parent: {
component: 'ButtonUnstyled',
- state: ['hover']
+ state: ['hover'],
},
directives: {
- textColor: '--parent--text'
- }
+ textColor: '--parent--text',
+ },
},
{
component: 'Icon',
parent: {
component: 'ButtonUnstyled',
- state: ['toggled']
+ state: ['toggled'],
},
directives: {
- textColor: '--parent--text'
- }
+ textColor: '--parent--text',
+ },
},
{
component: 'Icon',
parent: {
component: 'ButtonUnstyled',
- state: ['toggled', 'hover']
+ state: ['toggled', 'hover'],
},
directives: {
- textColor: '--parent--text'
- }
+ textColor: '--parent--text',
+ },
},
{
component: 'Icon',
parent: {
component: 'ButtonUnstyled',
- state: ['toggled', 'focused']
+ state: ['toggled', 'focused'],
},
directives: {
- textColor: '--parent--text'
- }
+ textColor: '--parent--text',
+ },
},
{
component: 'Icon',
parent: {
component: 'ButtonUnstyled',
- state: ['toggled', 'focused', 'hover']
+ state: ['toggled', 'focused', 'hover'],
},
directives: {
- textColor: '--parent--text'
- }
+ textColor: '--parent--text',
+ },
},
{
component: 'Text',
parent: {
component: 'ButtonUnstyled',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
+ textOpacityMode: 'blend',
+ },
},
{
component: 'Icon',
parent: {
component: 'ButtonUnstyled',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
- }
- ]
+ textOpacityMode: 'blend',
+ },
+ },
+ ],
}
diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js
index 56f389e60..6dd69ada4 100644
--- a/src/components/chat/chat.js
+++ b/src/components/chat/chat.js
@@ -1,25 +1,26 @@
import _ from 'lodash'
-import { WSConnectionStatus } from '../../services/api/api.service.js'
-import { mapGetters, mapState } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
-import ChatMessage from '../chat_message/chat_message.vue'
-import PostStatusForm from '../post_status_form/post_status_form.vue'
-import ChatTitle from '../chat_title/chat_title.vue'
-import chatService from '../../services/chat_service/chat_service.js'
-import { promiseInterval } from '../../services/promise_interval/promise_interval.js'
-import { getScrollPosition, getNewTopPosition, isBottomedOut, isScrollable } from './chat_layout_utils.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faChevronDown,
- faChevronLeft
-} from '@fortawesome/free-solid-svg-icons'
-import { buildFakeMessage } from '../../services/chat_utils/chat_utils.js'
-import { useInterfaceStore } from 'src/stores/interface.js'
+import { mapGetters, mapState } from 'vuex'
-library.add(
- faChevronDown,
- faChevronLeft
-)
+import { useInterfaceStore } from 'src/stores/interface.js'
+import { WSConnectionStatus } from '../../services/api/api.service.js'
+import chatService from '../../services/chat_service/chat_service.js'
+import { buildFakeMessage } from '../../services/chat_utils/chat_utils.js'
+import { promiseInterval } from '../../services/promise_interval/promise_interval.js'
+import ChatMessage from '../chat_message/chat_message.vue'
+import ChatTitle from '../chat_title/chat_title.vue'
+import PostStatusForm from '../post_status_form/post_status_form.vue'
+import {
+ getNewTopPosition,
+ getScrollPosition,
+ isBottomedOut,
+ isScrollable,
+} from './chat_layout_utils.js'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faChevronDown, faChevronLeft } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faChevronDown, faChevronLeft)
const BOTTOMED_OUT_OFFSET = 10
const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 10
@@ -31,78 +32,95 @@ const Chat = {
components: {
ChatMessage,
ChatTitle,
- PostStatusForm
+ PostStatusForm,
},
- data () {
+ data() {
return {
jumpToBottomButtonVisible: false,
hoveredMessageChainId: undefined,
lastScrollPosition: {},
scrollableContainerHeight: '100%',
errorLoadingChat: false,
- messageRetriers: {}
+ messageRetriers: {},
}
},
- created () {
+ created() {
this.startFetching()
window.addEventListener('resize', this.handleResize)
},
- mounted () {
+ mounted() {
window.addEventListener('scroll', this.handleScroll)
if (typeof document.hidden !== 'undefined') {
- document.addEventListener('visibilitychange', this.handleVisibilityChange, false)
+ document.addEventListener(
+ 'visibilitychange',
+ this.handleVisibilityChange,
+ false,
+ )
}
this.$nextTick(() => {
this.handleResize()
})
},
- unmounted () {
+ unmounted() {
window.removeEventListener('scroll', this.handleScroll)
window.removeEventListener('resize', this.handleResize)
- if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false)
+ if (typeof document.hidden !== 'undefined')
+ document.removeEventListener(
+ 'visibilitychange',
+ this.handleVisibilityChange,
+ false,
+ )
this.$store.dispatch('clearCurrentChat')
},
computed: {
- recipient () {
+ recipient() {
return this.currentChat && this.currentChat.account
},
- recipientId () {
+ recipientId() {
return this.$route.params.recipient_id
},
- formPlaceholder () {
+ formPlaceholder() {
if (this.recipient) {
- return this.$t('chats.message_user', { nickname: this.recipient.screen_name_ui })
+ return this.$t('chats.message_user', {
+ nickname: this.recipient.screen_name_ui,
+ })
} else {
return ''
}
},
- chatViewItems () {
+ chatViewItems() {
return chatService.getView(this.currentChatMessageService)
},
- newMessageCount () {
- return this.currentChatMessageService && this.currentChatMessageService.newMessageCount
+ newMessageCount() {
+ return (
+ this.currentChatMessageService &&
+ this.currentChatMessageService.newMessageCount
+ )
},
- streamingEnabled () {
- return this.mergedConfig.useStreamingApi && this.mastoUserSocketStatus === WSConnectionStatus.JOINED
+ streamingEnabled() {
+ return (
+ this.mergedConfig.useStreamingApi &&
+ this.mastoUserSocketStatus === WSConnectionStatus.JOINED
+ )
},
...mapGetters([
'currentChat',
'currentChatMessageService',
'findOpenedChatByRecipientId',
- 'mergedConfig'
+ 'mergedConfig',
]),
...mapPiniaState(useInterfaceStore, {
- mobileLayout: store => store.layoutType === 'mobile'
+ mobileLayout: (store) => store.layoutType === 'mobile',
}),
...mapState({
- backendInteractor: state => state.api.backendInteractor,
- mastoUserSocketStatus: state => state.api.mastoUserSocketStatus,
- currentUser: state => state.users.currentUser
- })
+ backendInteractor: (state) => state.api.backendInteractor,
+ mastoUserSocketStatus: (state) => state.api.mastoUserSocketStatus,
+ currentUser: (state) => state.users.currentUser,
+ }),
},
watch: {
- chatViewItems () {
+ chatViewItems() {
// We don't want to scroll to the bottom on a new message when the user is viewing older messages.
// Therefore we need to know whether the scroll position was at the bottom before the DOM update.
const bottomedOutBeforeUpdate = this.bottomedOut(BOTTOMED_OUT_OFFSET)
@@ -115,23 +133,23 @@ const Chat = {
$route: function () {
this.startFetching()
},
- mastoUserSocketStatus (newValue) {
+ mastoUserSocketStatus(newValue) {
if (newValue === WSConnectionStatus.JOINED) {
this.fetchChat({ isFirstFetch: true })
}
- }
+ },
},
methods: {
// Used to animate the avatar near the first message of the message chain when any message belonging to the chain is hovered
- onMessageHover ({ isHovered, messageChainId }) {
+ onMessageHover({ isHovered, messageChainId }) {
this.hoveredMessageChainId = isHovered ? messageChainId : undefined
},
- onFilesDropped () {
+ onFilesDropped() {
this.$nextTick(() => {
this.handleResize()
})
},
- handleVisibilityChange () {
+ handleVisibilityChange() {
this.$nextTick(() => {
if (!document.hidden && this.bottomedOut(BOTTOMED_OUT_OFFSET)) {
this.scrollDown({ forceRead: true })
@@ -139,7 +157,7 @@ const Chat = {
})
},
// "Sticks" scroll to bottom instead of top, helps with OSK resizing the viewport
- handleResize (opts = {}) {
+ handleResize(opts = {}) {
const { delayed = false } = opts
if (delayed) {
@@ -160,40 +178,56 @@ const Chat = {
this.lastScrollPosition = getScrollPosition()
})
},
- scrollDown (options = {}) {
+ scrollDown(options = {}) {
const { behavior = 'auto', forceRead = false } = options
this.$nextTick(() => {
- window.scrollTo({ top: document.documentElement.scrollHeight, behavior })
+ window.scrollTo({
+ top: document.documentElement.scrollHeight,
+ behavior,
+ })
})
if (forceRead) {
this.readChat()
}
},
- readChat () {
- if (!(this.currentChatMessageService && this.currentChatMessageService.maxId)) { return }
- if (document.hidden) { return }
+ readChat() {
+ if (
+ !(
+ this.currentChatMessageService && this.currentChatMessageService.maxId
+ )
+ ) {
+ return
+ }
+ if (document.hidden) {
+ return
+ }
const lastReadId = this.currentChatMessageService.maxId
this.$store.dispatch('readChat', {
id: this.currentChat.id,
- lastReadId
+ lastReadId,
})
},
- bottomedOut (offset) {
+ bottomedOut(offset) {
return isBottomedOut(offset)
},
- reachedTop () {
+ reachedTop() {
return window.scrollY <= 0
},
- cullOlderCheck () {
+ cullOlderCheck() {
window.setTimeout(() => {
if (this.bottomedOut(JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET)) {
- this.$store.dispatch('cullOlderMessages', this.currentChatMessageService.chatId)
+ this.$store.dispatch(
+ 'cullOlderMessages',
+ this.currentChatMessageService.chatId,
+ )
}
}, 5000)
},
handleScroll: _.throttle(function () {
this.lastScrollPosition = getScrollPosition()
- if (!this.currentChat) { return }
+ if (!this.currentChat) {
+ return
+ }
if (this.reachedTop()) {
this.fetchChat({ maxId: this.currentChatMessageService.minId })
@@ -213,22 +247,27 @@ const Chat = {
this.jumpToBottomButtonVisible = true
}
}, 200),
- handleScrollUp (positionBeforeLoading) {
+ handleScrollUp(positionBeforeLoading) {
const positionAfterLoading = getScrollPosition()
window.scrollTo({
- top: getNewTopPosition(positionBeforeLoading, positionAfterLoading)
+ top: getNewTopPosition(positionBeforeLoading, positionAfterLoading),
})
},
- fetchChat ({ isFirstFetch = false, fetchLatest = false, maxId }) {
+ fetchChat({ isFirstFetch = false, fetchLatest = false, maxId }) {
const chatMessageService = this.currentChatMessageService
- if (!chatMessageService) { return }
- if (fetchLatest && this.streamingEnabled) { return }
+ if (!chatMessageService) {
+ return
+ }
+ if (fetchLatest && this.streamingEnabled) {
+ return
+ }
const chatId = chatMessageService.chatId
const fetchOlderMessages = !!maxId
const sinceId = fetchLatest && chatMessageService.maxId
- return this.backendInteractor.chatMessages({ id: chatId, maxId, sinceId })
+ return this.backendInteractor
+ .chatMessages({ id: chatId, maxId, sinceId })
.then((messages) => {
// Clear the current chat in case we're recovering from a ws connection loss.
if (isFirstFetch) {
@@ -236,28 +275,34 @@ const Chat = {
}
const positionBeforeUpdate = getScrollPosition()
- this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => {
- this.$nextTick(() => {
- if (fetchOlderMessages) {
- this.handleScrollUp(positionBeforeUpdate)
- }
+ this.$store
+ .dispatch('addChatMessages', { chatId, messages })
+ .then(() => {
+ this.$nextTick(() => {
+ if (fetchOlderMessages) {
+ this.handleScrollUp(positionBeforeUpdate)
+ }
- // In vertical screens, the first batch of fetched messages may not always take the
- // full height of the scrollable container.
- // If this is the case, we want to fetch the messages until the scrollable container
- // is fully populated so that the user has the ability to scroll up and load the history.
- if (!isScrollable() && messages.length > 0) {
- this.fetchChat({ maxId: this.currentChatMessageService.minId })
- }
+ // In vertical screens, the first batch of fetched messages may not always take the
+ // full height of the scrollable container.
+ // If this is the case, we want to fetch the messages until the scrollable container
+ // is fully populated so that the user has the ability to scroll up and load the history.
+ if (!isScrollable() && messages.length > 0) {
+ this.fetchChat({
+ maxId: this.currentChatMessageService.minId,
+ })
+ }
+ })
})
- })
})
},
- async startFetching () {
+ async startFetching() {
let chat = this.findOpenedChatByRecipientId(this.recipientId)
if (!chat) {
try {
- chat = await this.backendInteractor.getOrCreateChat({ accountId: this.recipientId })
+ chat = await this.backendInteractor.getOrCreateChat({
+ accountId: this.recipientId,
+ })
} catch (e) {
console.error('Error creating or getting a chat', e)
this.errorLoadingChat = true
@@ -271,13 +316,14 @@ const Chat = {
this.doStartFetching()
}
},
- doStartFetching () {
+ doStartFetching() {
this.$store.dispatch('startFetchingCurrentChat', {
- fetcher: () => promiseInterval(() => this.fetchChat({ fetchLatest: true }), 5000)
+ fetcher: () =>
+ promiseInterval(() => this.fetchChat({ fetchLatest: true }), 5000),
})
this.fetchChat({ isFirstFetch: true })
},
- handleAttachmentPosting () {
+ handleAttachmentPosting() {
this.$nextTick(() => {
this.handleResize()
// When the posting form size changes because of a media attachment, we need an extra resize
@@ -285,11 +331,11 @@ const Chat = {
this.scrollDown({ forceRead: true })
})
},
- sendMessage ({ status, media, idempotencyKey }) {
+ sendMessage({ status, media, idempotencyKey }) {
const params = {
id: this.currentChat.id,
content: status,
- idempotencyKey
+ idempotencyKey,
}
if (media[0]) {
@@ -301,52 +347,72 @@ const Chat = {
chatId: this.currentChat.id,
content: status,
userId: this.currentUser.id,
- idempotencyKey
+ idempotencyKey,
})
- this.$store.dispatch('addChatMessages', {
- chatId: this.currentChat.id,
- messages: [fakeMessage]
- }).then(() => {
- this.handleAttachmentPosting()
- })
+ this.$store
+ .dispatch('addChatMessages', {
+ chatId: this.currentChat.id,
+ messages: [fakeMessage],
+ })
+ .then(() => {
+ this.handleAttachmentPosting()
+ })
- return this.doSendMessage({ params, fakeMessage, retriesLeft: MAX_RETRIES })
+ return this.doSendMessage({
+ params,
+ fakeMessage,
+ retriesLeft: MAX_RETRIES,
+ })
},
- doSendMessage ({ params, fakeMessage, retriesLeft = MAX_RETRIES }) {
+ doSendMessage({ params, fakeMessage, retriesLeft = MAX_RETRIES }) {
if (retriesLeft <= 0) return
- this.backendInteractor.sendChatMessage(params)
- .then(data => {
+ this.backendInteractor
+ .sendChatMessage(params)
+ .then((data) => {
this.$store.dispatch('addChatMessages', {
chatId: this.currentChat.id,
updateMaxId: false,
- messages: [{ ...data, fakeId: fakeMessage.id }]
+ messages: [{ ...data, fakeId: fakeMessage.id }],
})
return data
})
- .catch(error => {
+ .catch((error) => {
console.error('Error sending message', error)
this.$store.dispatch('handleMessageError', {
chatId: this.currentChat.id,
fakeId: fakeMessage.id,
- isRetry: retriesLeft !== MAX_RETRIES
+ isRetry: retriesLeft !== MAX_RETRIES,
})
- if ((error.statusCode >= 500 && error.statusCode < 600) || error.message === 'Failed to fetch') {
- this.messageRetriers[fakeMessage.id] = setTimeout(() => {
- this.doSendMessage({ params, fakeMessage, retriesLeft: retriesLeft - 1 })
- }, 1000 * (2 ** (MAX_RETRIES - retriesLeft)))
+ if (
+ (error.statusCode >= 500 && error.statusCode < 600) ||
+ error.message === 'Failed to fetch'
+ ) {
+ this.messageRetriers[fakeMessage.id] = setTimeout(
+ () => {
+ this.doSendMessage({
+ params,
+ fakeMessage,
+ retriesLeft: retriesLeft - 1,
+ })
+ },
+ 1000 * 2 ** (MAX_RETRIES - retriesLeft),
+ )
}
return {}
})
return Promise.resolve(fakeMessage)
},
- goBack () {
- this.$router.push({ name: 'chats', params: { username: this.currentUser.screen_name } })
- }
- }
+ goBack() {
+ this.$router.push({
+ name: 'chats',
+ params: { username: this.currentUser.screen_name },
+ })
+ },
+ },
}
export default Chat
diff --git a/src/components/chat/chat.style.js b/src/components/chat/chat.style.js
index 9ae2b7d71..55cf657c2 100644
--- a/src/components/chat/chat.style.js
+++ b/src/components/chat/chat.style.js
@@ -1,19 +1,13 @@
export default {
name: 'Chat',
selector: '.chat-message-list',
- validInnerComponents: [
- 'Text',
- 'Link',
- 'Icon',
- 'Avatar',
- 'ChatMessage'
- ],
+ validInnerComponents: ['Text', 'Link', 'Icon', 'Avatar', 'ChatMessage'],
defaultRules: [
{
directives: {
background: '--bg',
- blur: '5px'
- }
- }
- ]
+ blur: '5px',
+ },
+ },
+ ],
}
diff --git a/src/components/chat/chat_layout_utils.js b/src/components/chat/chat_layout_utils.js
index c187892d9..10d0a5e45 100644
--- a/src/components/chat/chat_layout_utils.js
+++ b/src/components/chat/chat_layout_utils.js
@@ -3,14 +3,17 @@ export const getScrollPosition = () => {
return {
scrollTop: window.scrollY,
scrollHeight: document.documentElement.scrollHeight,
- offsetHeight: window.innerHeight
+ offsetHeight: window.innerHeight,
}
}
// A helper function that is used to keep the scroll position fixed as the new elements are added to the top
// Takes two scroll positions, before and after the update.
export const getNewTopPosition = (previousPosition, newPosition) => {
- return previousPosition.scrollTop + (newPosition.scrollHeight - previousPosition.scrollHeight)
+ return (
+ previousPosition.scrollTop +
+ (newPosition.scrollHeight - previousPosition.scrollHeight)
+ )
}
export const isBottomedOut = (offset = 0) => {
diff --git a/src/components/chat_list/chat_list.js b/src/components/chat_list/chat_list.js
index 95708d1dd..4c3194ae1 100644
--- a/src/components/chat_list/chat_list.js
+++ b/src/components/chat_list/chat_list.js
@@ -1,4 +1,5 @@
-import { mapState, mapGetters } from 'vuex'
+import { mapGetters, mapState } from 'vuex'
+
import ChatListItem from '../chat_list_item/chat_list_item.vue'
import ChatNew from '../chat_new/chat_new.vue'
import List from '../list/list.vue'
@@ -7,31 +8,31 @@ const ChatList = {
components: {
ChatListItem,
List,
- ChatNew
+ ChatNew,
},
computed: {
...mapState({
- currentUser: state => state.users.currentUser
+ currentUser: (state) => state.users.currentUser,
}),
- ...mapGetters(['sortedChatList'])
+ ...mapGetters(['sortedChatList']),
},
- data () {
+ data() {
return {
- isNew: false
+ isNew: false,
}
},
- created () {
+ created() {
this.$store.dispatch('fetchChats', { latest: true })
},
methods: {
- cancelNewChat () {
+ cancelNewChat() {
this.isNew = false
this.$store.dispatch('fetchChats', { latest: true })
},
- newChat () {
+ newChat() {
this.isNew = true
- }
- }
+ },
+ },
}
export default ChatList
diff --git a/src/components/chat_list_item/chat_list_item.js b/src/components/chat_list_item/chat_list_item.js
index 8f8c491f5..0923a8568 100644
--- a/src/components/chat_list_item/chat_list_item.js
+++ b/src/components/chat_list_item/chat_list_item.js
@@ -1,31 +1,34 @@
import { mapState } from 'vuex'
-import StatusBody from '../status_content/status_content.vue'
+
import fileType from 'src/services/file_type/file_type.service'
-import UserAvatar from '../user_avatar/user_avatar.vue'
import AvatarList from '../avatar_list/avatar_list.vue'
-import Timeago from '../timeago/timeago.vue'
import ChatTitle from '../chat_title/chat_title.vue'
+import StatusBody from '../status_content/status_content.vue'
+import Timeago from '../timeago/timeago.vue'
+import UserAvatar from '../user_avatar/user_avatar.vue'
const ChatListItem = {
name: 'ChatListItem',
- props: [
- 'chat'
- ],
+ props: ['chat'],
components: {
UserAvatar,
AvatarList,
Timeago,
ChatTitle,
- StatusBody
+ StatusBody,
},
computed: {
...mapState({
- currentUser: state => state.users.currentUser
+ currentUser: (state) => state.users.currentUser,
}),
- attachmentInfo () {
- if (this.chat.lastMessage.attachments.length === 0) { return }
+ attachmentInfo() {
+ if (this.chat.lastMessage.attachments.length === 0) {
+ return
+ }
- const types = this.chat.lastMessage.attachments.map(file => fileType.fileType(file.mimetype))
+ const types = this.chat.lastMessage.attachments.map((file) =>
+ fileType.fileType(file.mimetype),
+ )
if (types.includes('video')) {
return this.$t('file_type.video')
} else if (types.includes('audio')) {
@@ -36,34 +39,36 @@ const ChatListItem = {
return this.$t('file_type.file')
}
},
- messageForStatusContent () {
+ messageForStatusContent() {
const message = this.chat.lastMessage
const messageEmojis = message ? message.emojis : []
const isYou = message && message.account_id === this.currentUser.id
- const content = message ? (this.attachmentInfo || message.content) : ''
- const messagePreview = isYou ? `${this.$t('chats.you')} ${content}` : content
+ const content = message ? this.attachmentInfo || message.content : ''
+ const messagePreview = isYou
+ ? `${this.$t('chats.you')} ${content}`
+ : content
return {
summary: '',
emojis: messageEmojis,
raw_html: messagePreview,
text: messagePreview,
- attachments: []
+ attachments: [],
}
- }
+ },
},
methods: {
- openChat () {
+ openChat() {
if (this.chat.id) {
this.$router.push({
name: 'chat',
params: {
username: this.currentUser.screen_name,
- recipient_id: this.chat.account.id
- }
+ recipient_id: this.chat.account.id,
+ },
})
}
- }
- }
+ },
+ },
}
export default ChatListItem
diff --git a/src/components/chat_message/chat_message.js b/src/components/chat_message/chat_message.js
index 837f6d214..f3cc495c2 100644
--- a/src/components/chat_message/chat_message.js
+++ b/src/components/chat_message/chat_message.js
@@ -1,24 +1,20 @@
-import { mapState, mapGetters } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
-import Popover from '../popover/popover.vue'
+import { defineAsyncComponent } from 'vue'
+import { mapGetters, mapState } from 'vuex'
+
+import { useInterfaceStore } from 'src/stores/interface'
import Attachment from '../attachment/attachment.vue'
-import UserAvatar from '../user_avatar/user_avatar.vue'
+import ChatMessageDate from '../chat_message_date/chat_message_date.vue'
import Gallery from '../gallery/gallery.vue'
import LinkPreview from '../link-preview/link-preview.vue'
+import Popover from '../popover/popover.vue'
import StatusContent from '../status_content/status_content.vue'
-import ChatMessageDate from '../chat_message_date/chat_message_date.vue'
-import { defineAsyncComponent } from 'vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faTimes,
- faEllipsisH
-} from '@fortawesome/free-solid-svg-icons'
-import { useInterfaceStore } from 'src/stores/interface'
+import UserAvatar from '../user_avatar/user_avatar.vue'
-library.add(
- faTimes,
- faEllipsisH
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faEllipsisH, faTimes } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faTimes, faEllipsisH)
const ChatMessage = {
name: 'ChatMessage',
@@ -27,7 +23,7 @@ const ChatMessage = {
'edited',
'noHeading',
'chatViewItem',
- 'hoveredMessageChain'
+ 'hoveredMessageChain',
],
emits: ['hover'],
components: {
@@ -38,73 +34,82 @@ const ChatMessage = {
Gallery,
LinkPreview,
ChatMessageDate,
- UserPopover: defineAsyncComponent(() => import('../user_popover/user_popover.vue'))
+ UserPopover: defineAsyncComponent(
+ () => import('../user_popover/user_popover.vue'),
+ ),
},
computed: {
// Returns HH:MM (hours and minutes) in local time.
- createdAt () {
+ createdAt() {
const time = this.chatViewItem.data.created_at
- return time.toLocaleTimeString('en', { hour: '2-digit', minute: '2-digit', hour12: false })
+ return time.toLocaleTimeString('en', {
+ hour: '2-digit',
+ minute: '2-digit',
+ hour12: false,
+ })
},
- isCurrentUser () {
+ isCurrentUser() {
return this.message.account_id === this.currentUser.id
},
- message () {
+ message() {
return this.chatViewItem.data
},
- isMessage () {
+ isMessage() {
return this.chatViewItem.type === 'message'
},
- messageForStatusContent () {
+ messageForStatusContent() {
return {
summary: '',
emojis: this.message.emojis,
raw_html: this.message.content || '',
text: this.message.content || '',
- attachments: this.message.attachments
+ attachments: this.message.attachments,
}
},
- hasAttachment () {
+ hasAttachment() {
return this.message.attachments.length > 0
},
...mapPiniaState(useInterfaceStore, {
- betterShadow: store => store.browserSupport.cssFilter
+ betterShadow: (store) => store.browserSupport.cssFilter,
}),
...mapState({
- currentUser: state => state.users.currentUser,
- restrictedNicknames: state => state.instance.restrictedNicknames
+ currentUser: (state) => state.users.currentUser,
+ restrictedNicknames: (state) => state.instance.restrictedNicknames,
}),
- popoverMarginStyle () {
+ popoverMarginStyle() {
if (this.isCurrentUser) {
return {}
} else {
return { left: 50 }
}
},
- ...mapGetters(['mergedConfig', 'findUser'])
+ ...mapGetters(['mergedConfig', 'findUser']),
},
- data () {
+ data() {
return {
hovered: false,
- menuOpened: false
+ menuOpened: false,
}
},
methods: {
- onHover (bool) {
- this.$emit('hover', { isHovered: bool, messageChainId: this.chatViewItem.messageChainId })
+ onHover(bool) {
+ this.$emit('hover', {
+ isHovered: bool,
+ messageChainId: this.chatViewItem.messageChainId,
+ })
},
- async deleteMessage () {
+ async deleteMessage() {
const confirmed = window.confirm(this.$t('chats.delete_confirm'))
if (confirmed) {
await this.$store.dispatch('deleteChatMessage', {
messageId: this.chatViewItem.data.id,
- chatId: this.chatViewItem.data.chat_id
+ chatId: this.chatViewItem.data.chat_id,
})
}
this.hovered = false
this.menuOpened = false
- }
- }
+ },
+ },
}
export default ChatMessage
diff --git a/src/components/chat_message/chat_message.style.js b/src/components/chat_message/chat_message.style.js
index 76b565823..f7632bc6f 100644
--- a/src/components/chat_message/chat_message.style.js
+++ b/src/components/chat_message/chat_message.style.js
@@ -2,26 +2,21 @@ export default {
name: 'ChatMessage',
selector: '.chat-message',
variants: {
- outgoing: '.outgoing'
+ outgoing: '.outgoing',
},
- validInnerComponents: [
- 'Text',
- 'Icon',
- 'Border',
- 'PollGraph'
- ],
+ validInnerComponents: ['Text', 'Icon', 'Border', 'PollGraph'],
defaultRules: [
{
directives: {
background: '--bg, 2',
- backgroundNoCssColor: 'yes'
- }
+ backgroundNoCssColor: 'yes',
+ },
},
{
variant: 'outgoing',
directives: {
- background: '--bg, 5'
- }
- }
- ]
+ background: '--bg, 5',
+ },
+ },
+ ],
}
diff --git a/src/components/chat_message_date/chat_message_date.vue b/src/components/chat_message_date/chat_message_date.vue
index 98349b753..f0cadb6e7 100644
--- a/src/components/chat_message_date/chat_message_date.vue
+++ b/src/components/chat_message_date/chat_message_date.vue
@@ -11,16 +11,19 @@ export default {
name: 'Timeago',
props: ['date'],
computed: {
- displayDate () {
+ displayDate() {
const today = new Date()
today.setHours(0, 0, 0, 0)
if (this.date.getTime() === today.getTime()) {
return this.$t('display_date.today')
} else {
- return this.date.toLocaleDateString(localeService.internalToBrowserLocale(this.$i18n.locale), { day: 'numeric', month: 'long' })
+ return this.date.toLocaleDateString(
+ localeService.internalToBrowserLocale(this.$i18n.locale),
+ { day: 'numeric', month: 'long' },
+ )
}
- }
- }
+ },
+ },
}
diff --git a/src/components/chat_new/chat_new.js b/src/components/chat_new/chat_new.js
index 71585995a..50e0f7a8f 100644
--- a/src/components/chat_new/chat_new.js
+++ b/src/components/chat_new/chat_new.js
@@ -1,39 +1,35 @@
-import { mapState, mapGetters } from 'vuex'
+import { mapGetters, mapState } from 'vuex'
+
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faSearch,
- faChevronLeft
-} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faSearch,
- faChevronLeft
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faChevronLeft, faSearch } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faSearch, faChevronLeft)
const chatNew = {
components: {
BasicUserCard,
- UserAvatar
+ UserAvatar,
},
- data () {
+ data() {
return {
suggestions: [],
userIds: [],
loading: false,
- query: ''
+ query: '',
}
},
- async created () {
+ async created() {
const { chats } = await this.backendInteractor.chats()
- chats.forEach(chat => this.suggestions.push(chat.account))
+ chats.forEach((chat) => this.suggestions.push(chat.account))
},
computed: {
- users () {
- return this.userIds.map(userId => this.findUser(userId))
+ users() {
+ return this.userIds.map((userId) => this.findUser(userId))
},
- availableUsers () {
+ availableUsers() {
if (this.query.length !== 0) {
return this.users
} else {
@@ -41,29 +37,29 @@ const chatNew = {
}
},
...mapState({
- currentUser: state => state.users.currentUser,
- backendInteractor: state => state.api.backendInteractor
+ currentUser: (state) => state.users.currentUser,
+ backendInteractor: (state) => state.api.backendInteractor,
}),
- ...mapGetters(['findUser'])
+ ...mapGetters(['findUser']),
},
methods: {
- goBack () {
+ goBack() {
this.$emit('cancel')
},
- goToChat (user) {
+ goToChat(user) {
this.$router.push({ name: 'chat', params: { recipient_id: user.id } })
},
- onInput () {
+ onInput() {
this.search(this.query)
},
- addUser (user) {
+ addUser(user) {
this.selectedUserIds.push(user.id)
this.query = ''
},
- removeUser (userId) {
- this.selectedUserIds = this.selectedUserIds.filter(id => id !== userId)
+ removeUser(userId) {
+ this.selectedUserIds = this.selectedUserIds.filter((id) => id !== userId)
},
- search (query) {
+ search(query) {
if (!query) {
this.loading = false
return
@@ -71,13 +67,14 @@ const chatNew = {
this.loading = true
this.userIds = []
- this.$store.dispatch('search', { q: query, resolve: true, type: 'accounts' })
- .then(data => {
+ this.$store
+ .dispatch('search', { q: query, resolve: true, type: 'accounts' })
+ .then((data) => {
this.loading = false
- this.userIds = data.accounts.map(a => a.id)
+ this.userIds = data.accounts.map((a) => a.id)
})
- }
- }
+ },
+ },
}
export default chatNew
diff --git a/src/components/chat_title/chat_title.js b/src/components/chat_title/chat_title.js
index b87211265..3447f5163 100644
--- a/src/components/chat_title/chat_title.js
+++ b/src/components/chat_title/chat_title.js
@@ -1,23 +1,24 @@
-import UserAvatar from '../user_avatar/user_avatar.vue'
-import RichContent from 'src/components/rich_content/rich_content.jsx'
import { defineAsyncComponent } from 'vue'
+import RichContent from 'src/components/rich_content/rich_content.jsx'
+import UserAvatar from '../user_avatar/user_avatar.vue'
+
export default {
name: 'ChatTitle',
components: {
UserAvatar,
RichContent,
- UserPopover: defineAsyncComponent(() => import('../user_popover/user_popover.vue'))
+ UserPopover: defineAsyncComponent(
+ () => import('../user_popover/user_popover.vue'),
+ ),
},
- props: [
- 'user', 'withAvatar'
- ],
+ props: ['user', 'withAvatar'],
computed: {
- title () {
+ title() {
return this.user ? this.user.screen_name_ui : ''
},
- htmlTitle () {
+ htmlTitle() {
return this.user ? this.user.name_html : ''
- }
- }
+ },
+ },
}
diff --git a/src/components/checkbox/checkbox.vue b/src/components/checkbox/checkbox.vue
index 1e0f5ad05..cbe3dd80f 100644
--- a/src/components/checkbox/checkbox.vue
+++ b/src/components/checkbox/checkbox.vue
@@ -36,30 +36,25 @@
diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue
index 58aee575c..a6fc2047b 100644
--- a/src/components/color_input/color_input.vue
+++ b/src/components/color_input/color_input.vue
@@ -64,95 +64,95 @@
diff --git a/src/components/component_preview/component_preview.js b/src/components/component_preview/component_preview.js
index 9f830cd72..70696f56b 100644
--- a/src/components/component_preview/component_preview.js
+++ b/src/components/component_preview/component_preview.js
@@ -1,13 +1,15 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import ColorInput from 'src/components/color_input/color_input.vue'
-
import genRandomSeed from 'src/services/random_seed/random_seed.service.js'
-import { createStyleSheet, adoptStyleSheets } from 'src/services/style_setter/style_setter.js'
+import {
+ adoptStyleSheets,
+ createStyleSheet,
+} from 'src/services/style_setter/style_setter.js'
export default {
components: {
Checkbox,
- ColorInput
+ ColorInput,
},
props: [
'shadow',
@@ -17,41 +19,41 @@ export default {
'previewCss',
'disabled',
'invalid',
- 'noColorControl'
+ 'noColorControl',
],
emits: ['update:shadow'],
- data () {
+ data() {
return {
colorOverride: undefined,
lightGrid: false,
zoom: 100,
- randomSeed: genRandomSeed()
+ randomSeed: genRandomSeed(),
}
},
- mounted () {
+ mounted() {
this.update()
},
computed: {
- hideControls () {
+ hideControls() {
return typeof this.shadow === 'string'
- }
+ },
},
watch: {
- previewCss () {
+ previewCss() {
this.update()
},
- previewStyle () {
+ previewStyle() {
this.update()
},
- zoom () {
+ zoom() {
this.update()
- }
+ },
},
methods: {
- updateProperty (axis, value) {
+ updateProperty(axis, value) {
this.$emit('update:shadow', { axis, value: Number(value) })
},
- update () {
+ update() {
const sheet = createStyleSheet('style-component-preview', 90)
sheet.clear()
@@ -60,23 +62,25 @@ export default {
if (this.colorOverride) result.push(`--background: ${this.colorOverride}`)
const styleRule = [
- '#component-preview-', this.randomSeed, ' {\n',
+ '#component-preview-',
+ this.randomSeed,
+ ' {\n',
'.preview-block {\n',
`zoom: ${this.zoom / 100};`,
this.previewStyle,
'\n}',
- '\n}'
+ '\n}',
].join('')
sheet.addRule(styleRule)
- sheet.addRule([
- '#component-preview-', this.randomSeed, ' {\n',
- ...result,
- '\n}'
- ].join(''))
+ sheet.addRule(
+ ['#component-preview-', this.randomSeed, ' {\n', ...result, '\n}'].join(
+ '',
+ ),
+ )
sheet.ready = true
adoptStyleSheets()
- }
- }
+ },
+ },
}
diff --git a/src/components/confirm_modal/confirm_modal.js b/src/components/confirm_modal/confirm_modal.js
index 3e2bc2cb7..cd83194be 100644
--- a/src/components/confirm_modal/confirm_modal.js
+++ b/src/components/confirm_modal/confirm_modal.js
@@ -9,30 +9,29 @@ import DialogModal from '../dialog_modal/dialog_modal.vue'
*/
const ConfirmModal = {
components: {
- DialogModal
+ DialogModal,
},
props: {
title: {
- type: String
+ type: String,
},
cancelText: {
- type: String
+ type: String,
},
confirmText: {
- type: String
- }
+ type: String,
+ },
},
emits: ['cancelled', 'accepted'],
- computed: {
- },
+ computed: {},
methods: {
- onCancel () {
+ onCancel() {
this.$emit('cancelled')
},
- onAccept () {
+ onAccept() {
this.$emit('accepted')
- }
- }
+ },
+ },
}
export default ConfirmModal
diff --git a/src/components/confirm_modal/mute_confirm.js b/src/components/confirm_modal/mute_confirm.js
index a279dc716..c486ad7e4 100644
--- a/src/components/confirm_modal/mute_confirm.js
+++ b/src/components/confirm_modal/mute_confirm.js
@@ -1,70 +1,73 @@
import { mapGetters } from 'vuex'
-import ConfirmModal from './confirm_modal.vue'
import Select from 'src/components/select/select.vue'
+import ConfirmModal from './confirm_modal.vue'
export default {
props: ['type', 'user', 'status'],
emits: ['hide', 'show', 'muted'],
data: () => ({
- showing: false
+ showing: false,
}),
components: {
ConfirmModal,
- Select
+ Select,
},
computed: {
- domain () {
+ domain() {
return this.user.fqn.split('@')[1]
},
- keypath () {
+ keypath() {
if (this.type === 'domain') {
- return 'status.mute_domain_confirm'
+ return 'user_card.mute_domain_confirm'
} else if (this.type === 'conversation') {
- return 'status.mute_conversation_confirm'
+ return 'user_card.mute_conversation_confirm'
}
},
- conversationIsMuted () {
+ conversationIsMuted() {
return this.status.conversation_muted
},
- domainIsMuted () {
- return new Set(this.$store.state.users.currentUser.domainMutes).has(this.domain)
+ domainIsMuted() {
+ return new Set(this.$store.state.users.currentUser.domainMutes).has(
+ this.domain,
+ )
},
- shouldConfirm () {
+ shouldConfirm() {
switch (this.type) {
case 'domain': {
return this.mergedConfig.modalOnMuteDomain
}
- default: { // conversation
+ default: {
+ // conversation
return this.mergedConfig.modalOnMuteConversation
}
}
},
- ...mapGetters(['mergedConfig'])
+ ...mapGetters(['mergedConfig']),
},
methods: {
- optionallyPrompt () {
+ optionallyPrompt() {
if (this.shouldConfirm) {
this.show()
} else {
this.doMute()
}
},
- show () {
+ show() {
this.showing = true
this.$emit('show')
},
- hide () {
+ hide() {
this.showing = false
this.$emit('hide')
},
- doMute () {
+ doMute() {
switch (this.type) {
case 'domain': {
if (!this.domainIsMuted) {
- this.$store.dispatch('muteDomain', { id: this.domain })
+ this.$store.dispatch('muteDomain', this.domain)
} else {
- this.$store.dispatch('unmuteDomain', { id: this.domain })
+ this.$store.dispatch('unmuteDomain', this.domain)
}
break
}
@@ -79,6 +82,6 @@ export default {
}
this.$emit('muted')
this.hide()
- }
- }
+ },
+ },
}
diff --git a/src/components/contrast_ratio/contrast_ratio.vue b/src/components/contrast_ratio/contrast_ratio.vue
index 93799e4c2..1f8b62809 100644
--- a/src/components/contrast_ratio/contrast_ratio.vue
+++ b/src/components/contrast_ratio/contrast_ratio.vue
@@ -63,54 +63,68 @@ import { library } from '@fortawesome/fontawesome-svg-core'
import {
faAdjust,
faExclamationTriangle,
- faThumbsUp
+ faThumbsUp,
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faAdjust,
- faExclamationTriangle,
- faThumbsUp
-)
+library.add(faAdjust, faExclamationTriangle, faThumbsUp)
export default {
components: {
- Tooltip
+ Tooltip,
},
props: {
large: {
required: false,
type: Boolean,
- default: false
+ default: false,
},
// TODO: Make theme switcher compute theme initially so that contrast
// component won't be called without contrast data
contrast: {
required: false,
type: Object,
- default: () => ({})
+ default: () => ({
+ /* no-op */
+ }),
},
showRatio: {
required: false,
type: Boolean,
- default: false
- }
+ default: false,
+ },
},
computed: {
- hint () {
- const levelVal = this.contrast.aaa ? 'aaa' : (this.contrast.aa ? 'aa' : 'bad')
+ hint() {
+ const levelVal = this.contrast.aaa
+ ? 'aaa'
+ : this.contrast.aa
+ ? 'aa'
+ : 'bad'
const level = this.$t(`settings.style.common.contrast.level.${levelVal}`)
const context = this.$t('settings.style.common.contrast.context.text')
const ratio = this.contrast.text
- return this.$t('settings.style.common.contrast.hint', { level, context, ratio })
+ return this.$t('settings.style.common.contrast.hint', {
+ level,
+ context,
+ ratio,
+ })
},
- hint_18pt () {
- const levelVal = this.contrast.laaa ? 'aaa' : (this.contrast.laa ? 'aa' : 'bad')
+ hint_18pt() {
+ const levelVal = this.contrast.laaa
+ ? 'aaa'
+ : this.contrast.laa
+ ? 'aa'
+ : 'bad'
const level = this.$t(`settings.style.common.contrast.level.${levelVal}`)
const context = this.$t('settings.style.common.contrast.context.18pt')
const ratio = this.contrast.text
- return this.$t('settings.style.common.contrast.hint', { level, context, ratio })
- }
- }
+ return this.$t('settings.style.common.contrast.hint', {
+ level,
+ context,
+ ratio,
+ })
+ },
+ },
}
diff --git a/src/components/conversation-page/conversation-page.js b/src/components/conversation-page/conversation-page.js
index 8f996be12..d4705303e 100644
--- a/src/components/conversation-page/conversation-page.js
+++ b/src/components/conversation-page/conversation-page.js
@@ -2,13 +2,13 @@ import Conversation from '../conversation/conversation.vue'
const conversationPage = {
components: {
- Conversation
+ Conversation,
},
computed: {
- statusId () {
+ statusId() {
return this.$route.params.id
- }
- }
+ },
+ },
}
export default conversationPage
diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 491a8543f..3caf4add7 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -1,25 +1,22 @@
-import { reduce, filter, findIndex, clone, get } from 'lodash'
-import Status from '../status/status.vue'
-import ThreadTree from '../thread_tree/thread_tree.vue'
-import { WSConnectionStatus } from '../../services/api/api.service.js'
-import { mapGetters, mapState } from 'vuex'
+import { clone, filter, findIndex, get, reduce } from 'lodash'
import { mapState as mapPiniaState } from 'pinia'
+import { mapGetters, mapState } from 'vuex'
+
+import { useInterfaceStore } from 'src/stores/interface'
+import { WSConnectionStatus } from '../../services/api/api.service.js'
import QuickFilterSettings from '../quick_filter_settings/quick_filter_settings.vue'
import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue'
-import { useInterfaceStore } from 'src/stores/interface'
+import Status from '../status/status.vue'
+import ThreadTree from '../thread_tree/thread_tree.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faAngleDoubleDown,
faAngleDoubleLeft,
- faChevronLeft
+ faChevronLeft,
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faAngleDoubleDown,
- faAngleDoubleLeft,
- faChevronLeft
-)
+library.add(faAngleDoubleDown, faAngleDoubleLeft, faChevronLeft)
const sortById = (a, b) => {
const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id
@@ -43,23 +40,25 @@ const sortAndFilterConversation = (conversation, statusoid) => {
if (statusoid.type === 'retweet') {
conversation = filter(
conversation,
- (status) => (status.type === 'retweet' || status.id !== statusoid.retweeted_status.id)
+ (status) =>
+ status.type === 'retweet' ||
+ status.id !== statusoid.retweeted_status.id,
)
} else {
conversation = filter(conversation, (status) => status.type !== 'retweet')
}
- return conversation.filter(_ => _).sort(sortById)
+ return conversation.filter((_) => _).sort(sortById)
}
const conversation = {
- data () {
+ data() {
return {
highlight: null,
expanded: false,
threadDisplayStatusObject: {}, // id => 'showing' | 'hidden'
statusContentPropertiesObject: {},
inlineDivePosition: null,
- loadStatusError: null
+ loadStatusError: null,
}
},
props: [
@@ -69,76 +68,80 @@ const conversation = {
'pinnedStatusIdsObject',
'inProfile',
'profileUserId',
- 'virtualHidden'
+ 'virtualHidden',
],
- created () {
+ created() {
if (this.isPage) {
this.fetchConversation()
}
},
computed: {
- maxDepthToShowByDefault () {
+ maxDepthToShowByDefault() {
// maxDepthInThread = max number of depths that is *visible*
// since our depth starts with 0 and "showing" means "showing children"
// there is a -2 here
const maxDepth = this.$store.getters.mergedConfig.maxDepthInThread - 2
return maxDepth >= 1 ? maxDepth : 1
},
- streamingEnabled () {
- return this.mergedConfig.useStreamingApi && this.mastoUserSocketStatus === WSConnectionStatus.JOINED
+ streamingEnabled() {
+ return (
+ this.mergedConfig.useStreamingApi &&
+ this.mastoUserSocketStatus === WSConnectionStatus.JOINED
+ )
},
- displayStyle () {
+ displayStyle() {
return this.$store.getters.mergedConfig.conversationDisplay
},
- isTreeView () {
+ isTreeView() {
return !this.isLinearView
},
- treeViewIsSimple () {
+ treeViewIsSimple() {
return !this.$store.getters.mergedConfig.conversationTreeAdvanced
},
- isLinearView () {
+ isLinearView() {
return this.displayStyle === 'linear'
},
- shouldFadeAncestors () {
+ shouldFadeAncestors() {
return this.$store.getters.mergedConfig.conversationTreeFadeAncestors
},
- otherRepliesButtonPosition () {
+ otherRepliesButtonPosition() {
return this.$store.getters.mergedConfig.conversationOtherRepliesButton
},
- showOtherRepliesButtonBelowStatus () {
+ showOtherRepliesButtonBelowStatus() {
return this.otherRepliesButtonPosition === 'below'
},
- showOtherRepliesButtonInsideStatus () {
+ showOtherRepliesButtonInsideStatus() {
return this.otherRepliesButtonPosition === 'inside'
},
- suspendable () {
+ suspendable() {
if (this.isTreeView) {
- return Object.entries(this.statusContentProperties)
- .every(([, prop]) => !prop.replying && prop.mediaPlaying.length === 0)
+ return Object.entries(this.statusContentProperties).every(
+ ([, prop]) => !prop.replying && prop.mediaPlaying.length === 0,
+ )
}
if (this.$refs.statusComponent && this.$refs.statusComponent[0]) {
- return this.$refs.statusComponent.every(s => s.suspendable)
+ return this.$refs.statusComponent.every((s) => s.suspendable)
} else {
return true
}
},
- hideStatus () {
+ hideStatus() {
return this.virtualHidden && this.suspendable
},
- status () {
+ status() {
return this.$store.state.statuses.allStatusesObject[this.statusId]
},
- originalStatusId () {
+ originalStatusId() {
if (this.status.retweeted_status) {
return this.status.retweeted_status.id
} else {
return this.statusId
}
},
- conversationId () {
+ conversationId() {
return this.getConversationId(this.statusId)
},
- conversation () {
+ conversation() {
if (!this.status) {
return []
}
@@ -147,7 +150,9 @@ const conversation = {
return [this.status]
}
- const conversation = clone(this.$store.state.statuses.conversationsObject[this.conversationId])
+ const conversation = clone(
+ this.$store.state.statuses.conversationsObject[this.conversationId],
+ )
const statusIndex = findIndex(conversation, { id: this.originalStatusId })
if (statusIndex !== -1) {
conversation[statusIndex] = this.status
@@ -155,144 +160,188 @@ const conversation = {
return sortAndFilterConversation(conversation, this.status)
},
- statusMap () {
+ statusMap() {
return this.conversation.reduce((res, s) => {
res[s.id] = s
return res
}, {})
},
- threadTree () {
- const reverseLookupTable = this.conversation.reduce((table, status, index) => {
- table[status.id] = index
- return table
- }, {})
+ threadTree() {
+ const reverseLookupTable = this.conversation.reduce(
+ (table, status, index) => {
+ table[status.id] = index
+ return table
+ },
+ {},
+ )
- const threads = this.conversation.reduce((a, cur) => {
- const id = cur.id
- a.forest[id] = this.getReplies(id)
- .map(s => s.id)
+ const threads = this.conversation.reduce(
+ (a, cur) => {
+ const id = cur.id
+ a.forest[id] = this.getReplies(id).map((s) => s.id)
- return a
- }, {
- forest: {}
- })
+ return a
+ },
+ {
+ forest: {},
+ },
+ )
- const walk = (forest, topLevel, depth = 0, processed = {}) => topLevel.map(id => {
- if (processed[id]) {
- return []
- }
+ const walk = (forest, topLevel, depth = 0, processed = {}) =>
+ topLevel
+ .map((id) => {
+ if (processed[id]) {
+ return []
+ }
- processed[id] = true
- return [{
- status: this.conversation[reverseLookupTable[id]],
- id,
- depth
- }, walk(forest, forest[id], depth + 1, processed)].reduce((a, b) => a.concat(b), [])
- }).reduce((a, b) => a.concat(b), [])
+ processed[id] = true
+ return [
+ {
+ status: this.conversation[reverseLookupTable[id]],
+ id,
+ depth,
+ },
+ walk(forest, forest[id], depth + 1, processed),
+ ].reduce((a, b) => a.concat(b), [])
+ })
+ .reduce((a, b) => a.concat(b), [])
- const linearized = walk(threads.forest, this.topLevel.map(k => k.id))
+ const linearized = walk(
+ threads.forest,
+ this.topLevel.map((k) => k.id),
+ )
return linearized
},
- replyIds () {
- return this.conversation.map(k => k.id)
+ replyIds() {
+ return this.conversation
+ .map((k) => k.id)
.reduce((res, id) => {
- res[id] = (this.replies[id] || []).map(k => k.id)
+ res[id] = (this.replies[id] || []).map((k) => k.id)
return res
}, {})
},
- totalReplyCount () {
+ totalReplyCount() {
const sizes = {}
const subTreeSizeFor = (id) => {
if (sizes[id]) {
return sizes[id]
}
- sizes[id] = 1 + this.replyIds[id].map(cid => subTreeSizeFor(cid)).reduce((a, b) => a + b, 0)
+ sizes[id] =
+ 1 +
+ this.replyIds[id]
+ .map((cid) => subTreeSizeFor(cid))
+ .reduce((a, b) => a + b, 0)
return sizes[id]
}
- this.conversation.map(k => k.id).map(subTreeSizeFor)
+ this.conversation.map((k) => k.id).map(subTreeSizeFor)
return Object.keys(sizes).reduce((res, id) => {
res[id] = sizes[id] - 1 // exclude itself
return res
}, {})
},
- totalReplyDepth () {
+ totalReplyDepth() {
const depths = {}
const subTreeDepthFor = (id) => {
if (depths[id]) {
return depths[id]
}
- depths[id] = 1 + this.replyIds[id].map(cid => subTreeDepthFor(cid)).reduce((a, b) => a > b ? a : b, 0)
+ depths[id] =
+ 1 +
+ this.replyIds[id]
+ .map((cid) => subTreeDepthFor(cid))
+ .reduce((a, b) => (a > b ? a : b), 0)
return depths[id]
}
- this.conversation.map(k => k.id).map(subTreeDepthFor)
+ this.conversation.map((k) => k.id).map(subTreeDepthFor)
return Object.keys(depths).reduce((res, id) => {
res[id] = depths[id] - 1 // exclude itself
return res
}, {})
},
- depths () {
+ depths() {
return this.threadTree.reduce((a, k) => {
a[k.id] = k.depth
return a
}, {})
},
- topLevel () {
- const topLevel = this.conversation.reduce((tl, cur) =>
- tl.filter(k => this.getReplies(cur.id).map(v => v.id).indexOf(k.id) === -1), this.conversation)
+ topLevel() {
+ const topLevel = this.conversation.reduce(
+ (tl, cur) =>
+ tl.filter(
+ (k) =>
+ this.getReplies(cur.id)
+ .map((v) => v.id)
+ .indexOf(k.id) === -1,
+ ),
+ this.conversation,
+ )
return topLevel
},
- otherTopLevelCount () {
+ otherTopLevelCount() {
return this.topLevel.length - 1
},
- showingTopLevel () {
+ showingTopLevel() {
if (this.canDive && this.diveRoot) {
return [this.statusMap[this.diveRoot]]
}
return this.topLevel
},
- diveRoot () {
+ diveRoot() {
const statusId = this.inlineDivePosition || this.statusId
const isTopLevel = !this.parentOf(statusId)
return isTopLevel ? null : statusId
},
- diveDepth () {
+ diveDepth() {
return this.canDive && this.diveRoot ? this.depths[this.diveRoot] : 0
},
- diveMode () {
+ diveMode() {
return this.canDive && !!this.diveRoot
},
- shouldShowAllConversationButton () {
+ shouldShowAllConversationButton() {
// The "show all conversation" button tells the user that there exist
// other toplevel statuses, so do not show it if there is only a single root
- return this.isTreeView && this.isExpanded && this.diveMode && this.topLevel.length > 1
+ return (
+ this.isTreeView &&
+ this.isExpanded &&
+ this.diveMode &&
+ this.topLevel.length > 1
+ )
},
- shouldShowAncestors () {
- return this.isTreeView && this.isExpanded && this.ancestorsOf(this.diveRoot).length
+ shouldShowAncestors() {
+ return (
+ this.isTreeView &&
+ this.isExpanded &&
+ this.ancestorsOf(this.diveRoot).length
+ )
},
- replies () {
+ replies() {
let i = 1
- return reduce(this.conversation, (result, { id, in_reply_to_status_id: irid }) => {
- if (irid) {
- result[irid] = result[irid] || []
- result[irid].push({
- name: `#${i}`,
- id
- })
- }
- i++
- return result
- }, {})
+ return reduce(
+ this.conversation,
+ (result, { id, in_reply_to_status_id: irid }) => {
+ if (irid) {
+ result[irid] = result[irid] || []
+ result[irid].push({
+ name: `#${i}`,
+ id,
+ })
+ }
+ i++
+ return result
+ },
+ {},
+ )
},
- isExpanded () {
+ isExpanded() {
return !!(this.expanded || this.isPage)
},
- hiddenStyle () {
+ hiddenStyle() {
const height = (this.status && this.status.virtualHeight) || '120px'
return this.virtualHidden ? { height } : {}
},
- threadDisplayStatus () {
+ threadDisplayStatus() {
return this.conversation.reduce((a, k) => {
const id = k.id
const depth = this.depths[id]
@@ -300,7 +349,7 @@ const conversation = {
if (this.threadDisplayStatusObject[id]) {
return this.threadDisplayStatusObject[id]
}
- if ((depth - this.diveDepth) <= this.maxDepthToShowByDefault) {
+ if (depth - this.diveDepth <= this.maxDepthToShowByDefault) {
return 'showing'
} else {
return 'hidden'
@@ -311,7 +360,7 @@ const conversation = {
return a
}, {})
},
- statusContentProperties () {
+ statusContentProperties() {
return this.conversation.reduce((a, k) => {
const id = k.id
const props = (() => {
@@ -320,13 +369,13 @@ const conversation = {
expandingSubject: false,
showingLongSubject: false,
isReplying: false,
- mediaPlaying: []
+ mediaPlaying: [],
}
if (this.statusContentPropertiesObject[id]) {
return {
...def,
- ...this.statusContentPropertiesObject[id]
+ ...this.statusContentPropertiesObject[id],
}
}
return def
@@ -336,54 +385,59 @@ const conversation = {
return a
}, {})
},
- canDive () {
+ canDive() {
return this.isTreeView && this.isExpanded
},
- maybeHighlight () {
+ maybeHighlight() {
return this.isExpanded ? this.highlight : null
},
...mapGetters(['mergedConfig']),
...mapState({
- mastoUserSocketStatus: state => state.api.mastoUserSocketStatus
+ mastoUserSocketStatus: (state) => state.api.mastoUserSocketStatus,
}),
...mapPiniaState(useInterfaceStore, {
- mobileLayout: store => store.layoutType === 'mobile'
- })
+ mobileLayout: (store) => store.layoutType === 'mobile',
+ }),
},
components: {
Status,
ThreadTree,
QuickFilterSettings,
- QuickViewSettings
+ QuickViewSettings,
},
watch: {
- statusId (newVal, oldVal) {
+ statusId(newVal, oldVal) {
const newConversationId = this.getConversationId(newVal)
const oldConversationId = this.getConversationId(oldVal)
- if (newConversationId && oldConversationId && newConversationId === oldConversationId) {
+ if (
+ newConversationId &&
+ oldConversationId &&
+ newConversationId === oldConversationId
+ ) {
this.setHighlight(this.originalStatusId)
} else {
this.fetchConversation()
}
},
- expanded (value) {
+ expanded(value) {
if (value) {
this.fetchConversation()
} else {
this.resetDisplayState()
}
},
- virtualHidden () {
- this.$store.dispatch(
- 'setVirtualHeight',
- { statusId: this.statusId, height: `${this.$el.clientHeight}px` }
- )
- }
+ virtualHidden() {
+ this.$store.dispatch('setVirtualHeight', {
+ statusId: this.statusId,
+ height: `${this.$el.clientHeight}px`,
+ })
+ },
},
methods: {
- fetchConversation () {
+ fetchConversation() {
if (this.status) {
- this.$store.state.api.backendInteractor.fetchConversation({ id: this.statusId })
+ this.$store.state.api.backendInteractor
+ .fetchConversation({ id: this.statusId })
.then(({ ancestors, descendants }) => {
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
this.$store.dispatch('addNewStatuses', { statuses: descendants })
@@ -391,7 +445,8 @@ const conversation = {
})
} else {
this.loadStatusError = null
- this.$store.state.api.backendInteractor.fetchStatus({ id: this.statusId })
+ this.$store.state.api.backendInteractor
+ .fetchStatus({ id: this.statusId })
.then((status) => {
this.$store.dispatch('addNewStatuses', { statuses: [status] })
this.fetchConversation()
@@ -401,16 +456,16 @@ const conversation = {
})
}
},
- isFocused (id) {
- return (this.isExpanded) && id === this.highlight
+ isFocused(id) {
+ return this.isExpanded && id === this.highlight
},
- getReplies (id) {
+ getReplies(id) {
return this.replies[id] || []
},
- getHighlight () {
+ getHighlight() {
return this.isExpanded ? this.highlight : null
},
- setHighlight (id) {
+ setHighlight(id) {
if (!id) return
this.highlight = id
@@ -421,44 +476,54 @@ const conversation = {
this.$store.dispatch('fetchFavsAndRepeats', id)
this.$store.dispatch('fetchEmojiReactionsBy', id)
},
- toggleExpanded () {
+ toggleExpanded() {
this.expanded = !this.expanded
},
- getConversationId (statusId) {
+ getConversationId(statusId) {
const status = this.$store.state.statuses.allStatusesObject[statusId]
- return get(status, 'retweeted_status.statusnet_conversation_id', get(status, 'statusnet_conversation_id'))
+ return get(
+ status,
+ 'retweeted_status.statusnet_conversation_id',
+ get(status, 'statusnet_conversation_id'),
+ )
},
- setThreadDisplay (id, nextStatus) {
+ setThreadDisplay(id, nextStatus) {
this.threadDisplayStatusObject = {
...this.threadDisplayStatusObject,
- [id]: nextStatus
+ [id]: nextStatus,
}
},
- toggleThreadDisplay (id) {
+ toggleThreadDisplay(id) {
const curStatus = this.threadDisplayStatus[id]
const nextStatus = curStatus === 'showing' ? 'hidden' : 'showing'
this.setThreadDisplay(id, nextStatus)
},
- setThreadDisplayRecursively (id, nextStatus) {
+ setThreadDisplayRecursively(id, nextStatus) {
this.setThreadDisplay(id, nextStatus)
- this.getReplies(id).map(k => k.id).map(id => this.setThreadDisplayRecursively(id, nextStatus))
+ this.getReplies(id)
+ .map((k) => k.id)
+ .map((id) => this.setThreadDisplayRecursively(id, nextStatus))
},
- showThreadRecursively (id) {
+ showThreadRecursively(id) {
this.setThreadDisplayRecursively(id, 'showing')
},
- setStatusContentProperty (id, name, value) {
+ setStatusContentProperty(id, name, value) {
this.statusContentPropertiesObject = {
...this.statusContentPropertiesObject,
[id]: {
...this.statusContentPropertiesObject[id],
- [name]: value
- }
+ [name]: value,
+ },
}
},
- toggleStatusContentProperty (id, name) {
- this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name])
+ toggleStatusContentProperty(id, name) {
+ this.setStatusContentProperty(
+ id,
+ name,
+ !this.statusContentProperties[id][name],
+ )
},
- leastVisibleAncestor (id) {
+ leastVisibleAncestor(id) {
let cur = id
let parent = this.parentOf(cur)
while (cur) {
@@ -472,18 +537,20 @@ const conversation = {
// nothing found, fall back to toplevel
return this.topLevel[0] ? this.topLevel[0].id : undefined
},
- diveIntoStatus (id) {
+ diveIntoStatus(id) {
this.tryScrollTo(id)
},
- diveToTopLevel () {
- this.tryScrollTo(this.topLevelAncestorOrSelfId(this.diveRoot) || this.topLevel[0].id)
+ diveToTopLevel() {
+ this.tryScrollTo(
+ this.topLevelAncestorOrSelfId(this.diveRoot) || this.topLevel[0].id,
+ )
},
// only used when we are not on a page
- undive () {
+ undive() {
this.inlineDivePosition = null
this.setHighlight(this.statusId)
},
- tryScrollTo (id) {
+ tryScrollTo(id) {
if (!id) {
return
}
@@ -512,13 +579,13 @@ const conversation = {
this.setHighlight(id)
})
},
- goToCurrent () {
+ goToCurrent() {
this.tryScrollTo(this.diveRoot || this.topLevel[0].id)
},
- statusById (id) {
+ statusById(id) {
return this.statusMap[id]
},
- parentOf (id) {
+ parentOf(id) {
const status = this.statusById(id)
if (!status) {
return undefined
@@ -529,11 +596,11 @@ const conversation = {
}
return parentId
},
- parentOrSelf (id) {
+ parentOrSelf(id) {
return this.parentOf(id) || id
},
// Ancestors of some status, from top to bottom
- ancestorsOf (id) {
+ ancestorsOf(id) {
const ancestors = []
let cur = this.parentOf(id)
while (cur) {
@@ -542,7 +609,7 @@ const conversation = {
}
return ancestors
},
- topLevelAncestorOrSelfId (id) {
+ topLevelAncestorOrSelfId(id) {
let cur = id
let parent = this.parentOf(id)
while (parent) {
@@ -551,11 +618,11 @@ const conversation = {
}
return cur
},
- resetDisplayState () {
+ resetDisplayState() {
this.undive()
this.threadDisplayStatusObject = {}
- }
- }
+ },
+ },
}
export default conversation
diff --git a/src/components/desktop_nav/desktop_nav.js b/src/components/desktop_nav/desktop_nav.js
index 98d408a7e..8ab54b3df 100644
--- a/src/components/desktop_nav/desktop_nav.js
+++ b/src/components/desktop_nav/desktop_nav.js
@@ -1,20 +1,22 @@
import SearchBar from 'components/search_bar/search_bar.vue'
+
+import { useInterfaceStore } from 'src/stores/interface'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
+ faBell,
+ faBullhorn,
+ faCog,
+ faComments,
+ faHome,
+ faInfoCircle,
+ faSearch,
faSignInAlt,
faSignOutAlt,
- faHome,
- faComments,
- faBell,
- faUserPlus,
- faBullhorn,
- faSearch,
faTachometerAlt,
- faCog,
- faInfoCircle
+ faUserPlus,
} from '@fortawesome/free-solid-svg-icons'
-import { useInterfaceStore } from 'src/stores/interface'
library.add(
faSignInAlt,
@@ -27,91 +29,109 @@ library.add(
faSearch,
faTachometerAlt,
faCog,
- faInfoCircle
+ faInfoCircle,
)
export default {
components: {
SearchBar,
- ConfirmModal
+ ConfirmModal,
},
data: () => ({
searchBarHidden: true,
- supportsMask: window.CSS && window.CSS.supports && (
- window.CSS.supports('mask-size', 'contain') ||
+ supportsMask:
+ window.CSS &&
+ window.CSS.supports &&
+ (window.CSS.supports('mask-size', 'contain') ||
window.CSS.supports('-webkit-mask-size', 'contain') ||
window.CSS.supports('-moz-mask-size', 'contain') ||
window.CSS.supports('-ms-mask-size', 'contain') ||
- window.CSS.supports('-o-mask-size', 'contain')
- ),
- showingConfirmLogout: false
+ window.CSS.supports('-o-mask-size', 'contain')),
+ showingConfirmLogout: false,
}),
computed: {
- enableMask () { return this.supportsMask && this.$store.state.instance.logoMask },
- logoStyle () {
+ enableMask() {
+ return this.supportsMask && this.$store.state.instance.logoMask
+ },
+ logoStyle() {
return {
- visibility: this.enableMask ? 'hidden' : 'visible'
+ visibility: this.enableMask ? 'hidden' : 'visible',
}
},
- logoMaskStyle () {
+ logoMaskStyle() {
return this.enableMask
? {
- 'mask-image': `url(${this.$store.state.instance.logo})`
+ 'mask-image': `url(${this.$store.state.instance.logo})`,
}
: {
- 'background-color': this.enableMask ? '' : 'transparent'
+ 'background-color': this.enableMask ? '' : 'transparent',
}
},
- logoBgStyle () {
- return Object.assign({
- margin: `${this.$store.state.instance.logoMargin} 0`,
- opacity: this.searchBarHidden ? 1 : 0
- }, this.enableMask
- ? {}
- : {
- 'background-color': this.enableMask ? '' : 'transparent'
- })
+ logoBgStyle() {
+ return Object.assign(
+ {
+ margin: `${this.$store.state.instance.logoMargin} 0`,
+ opacity: this.searchBarHidden ? 1 : 0,
+ },
+ this.enableMask
+ ? {}
+ : {
+ 'background-color': this.enableMask ? '' : 'transparent',
+ },
+ )
},
- logo () { return this.$store.state.instance.logo },
- sitename () { return this.$store.state.instance.name },
- hideSitename () { return this.$store.state.instance.hideSitename },
- logoLeft () { return this.$store.state.instance.logoLeft },
- currentUser () { return this.$store.state.users.currentUser },
- privateMode () { return this.$store.state.instance.private },
- shouldConfirmLogout () {
+ logo() {
+ return this.$store.state.instance.logo
+ },
+ sitename() {
+ return this.$store.state.instance.name
+ },
+ hideSitename() {
+ return this.$store.state.instance.hideSitename
+ },
+ logoLeft() {
+ return this.$store.state.instance.logoLeft
+ },
+ currentUser() {
+ return this.$store.state.users.currentUser
+ },
+ privateMode() {
+ return this.$store.state.instance.private
+ },
+ shouldConfirmLogout() {
return this.$store.getters.mergedConfig.modalOnLogout
- }
+ },
},
methods: {
- scrollToTop () {
+ scrollToTop() {
window.scrollTo(0, 0)
},
- showConfirmLogout () {
+ showConfirmLogout() {
this.showingConfirmLogout = true
},
- hideConfirmLogout () {
+ hideConfirmLogout() {
this.showingConfirmLogout = false
},
- logout () {
+ logout() {
if (!this.shouldConfirmLogout) {
this.doLogout()
} else {
this.showConfirmLogout()
}
},
- doLogout () {
+ doLogout() {
this.$router.replace('/main/public')
this.$store.dispatch('logout')
this.hideConfirmLogout()
},
- onSearchBarToggled (hidden) {
+ onSearchBarToggled(hidden) {
this.searchBarHidden = hidden
},
- openSettingsModal () {
+ openSettingsModal() {
useInterfaceStore().openSettingsModal('user')
},
- openAdminModal () {
+ openAdminModal() {
useInterfaceStore().openSettingsModal('admin')
- }
- }
+ },
+ },
}
diff --git a/src/components/dialog_modal/dialog_modal.js b/src/components/dialog_modal/dialog_modal.js
index b39851fe7..8070d3429 100644
--- a/src/components/dialog_modal/dialog_modal.js
+++ b/src/components/dialog_modal/dialog_modal.js
@@ -2,18 +2,20 @@ const DialogModal = {
props: {
darkOverlay: {
default: true,
- type: Boolean
+ type: Boolean,
},
onCancel: {
- default: () => {},
- type: Function
- }
+ default: () => {
+ /* no-op */
+ },
+ type: Function,
+ },
},
computed: {
- mobileCenter () {
+ mobileCenter() {
return this.$store.getters.mergedConfig.modalMobileCenter
- }
- }
+ },
+ },
}
export default DialogModal
diff --git a/src/components/dm_timeline/dm_timeline.js b/src/components/dm_timeline/dm_timeline.js
index 8b5393a98..c977efe30 100644
--- a/src/components/dm_timeline/dm_timeline.js
+++ b/src/components/dm_timeline/dm_timeline.js
@@ -2,13 +2,13 @@ import Timeline from '../timeline/timeline.vue'
const DMs = {
computed: {
- timeline () {
+ timeline() {
return this.$store.state.statuses.timelines.dms
- }
+ },
},
components: {
- Timeline
- }
+ Timeline,
+ },
}
export default DMs
diff --git a/src/components/domain_mute_card/domain_mute_card.js b/src/components/domain_mute_card/domain_mute_card.js
index f234dcb0f..71da2684c 100644
--- a/src/components/domain_mute_card/domain_mute_card.js
+++ b/src/components/domain_mute_card/domain_mute_card.js
@@ -3,24 +3,24 @@ import ProgressButton from '../progress_button/progress_button.vue'
const DomainMuteCard = {
props: ['domain'],
components: {
- ProgressButton
+ ProgressButton,
},
computed: {
- user () {
+ user() {
return this.$store.state.users.currentUser
},
- muted () {
+ muted() {
return this.user.domainMutes.includes(this.domain)
- }
+ },
},
methods: {
- unmuteDomain () {
+ unmuteDomain() {
return this.$store.dispatch('unmuteDomain', this.domain)
},
- muteDomain () {
+ muteDomain() {
return this.$store.dispatch('muteDomain', this.domain)
- }
- }
+ },
+ },
}
export default DomainMuteCard
diff --git a/src/components/draft/draft.js b/src/components/draft/draft.js
index 55ee11a15..971a75b10 100644
--- a/src/components/draft/draft.js
+++ b/src/components/draft/draft.js
@@ -1,18 +1,15 @@
-import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
-import EditStatusForm from 'src/components/edit_status_form/edit_status_form.vue'
-import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
-import StatusContent from 'src/components/status_content/status_content.vue'
-import Gallery from 'src/components/gallery/gallery.vue'
import { cloneDeep } from 'lodash'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faPollH
-} from '@fortawesome/free-solid-svg-icons'
+import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
+import EditStatusForm from 'src/components/edit_status_form/edit_status_form.vue'
+import Gallery from 'src/components/gallery/gallery.vue'
+import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
+import StatusContent from 'src/components/status_content/status_content.vue'
-library.add(
- faPollH
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faPollH } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faPollH)
const Draft = {
components: {
@@ -20,23 +17,23 @@ const Draft = {
EditStatusForm,
ConfirmModal,
StatusContent,
- Gallery
+ Gallery,
},
props: {
draft: {
type: Object,
- required: true
- }
+ required: true,
+ },
},
- data () {
+ data() {
return {
referenceDraft: cloneDeep(this.draft),
editing: false,
- showingConfirmDialog: false
+ showingConfirmDialog: false,
}
},
computed: {
- relAttrs () {
+ relAttrs() {
if (this.draft.type === 'edit') {
return { statusId: this.draft.refId }
} else if (this.draft.type === 'reply') {
@@ -45,24 +42,24 @@ const Draft = {
return {}
}
},
- safeToSave () {
- return this.draft.status ||
- this.draft.files?.length ||
- this.draft.hasPoll
+ safeToSave() {
+ return this.draft.status || this.draft.files?.length || this.draft.hasPoll
},
- postStatusFormProps () {
+ postStatusFormProps() {
return {
draftId: this.draft.id,
- ...this.relAttrs
+ ...this.relAttrs,
}
},
- refStatus () {
- return this.draft.refId ? this.$store.state.statuses.allStatusesObject[this.draft.refId] : undefined
+ refStatus() {
+ return this.draft.refId
+ ? this.$store.state.statuses.allStatusesObject[this.draft.refId]
+ : undefined
},
- localCollapseSubjectDefault () {
+ localCollapseSubjectDefault() {
return this.$store.getters.mergedConfig.collapseMessageWithSubject
},
- nsfwClickthrough () {
+ nsfwClickthrough() {
if (!this.draft.nsfw) {
return false
}
@@ -70,35 +67,34 @@ const Draft = {
return false
}
return true
- }
+ },
},
watch: {
- editing (newVal) {
+ editing(newVal) {
if (newVal) return
if (this.safeToSave) {
this.$store.dispatch('addOrSaveDraft', { draft: this.draft })
} else {
this.$store.dispatch('addOrSaveDraft', { draft: this.referenceDraft })
}
- }
+ },
},
methods: {
- toggleEditing () {
+ toggleEditing() {
this.editing = !this.editing
},
- abandon () {
+ abandon() {
this.showingConfirmDialog = true
},
- doAbandon () {
- this.$store.dispatch('abandonDraft', { id: this.draft.id })
- .then(() => {
- this.hideConfirmDialog()
- })
+ doAbandon() {
+ this.$store.dispatch('abandonDraft', { id: this.draft.id }).then(() => {
+ this.hideConfirmDialog()
+ })
},
- hideConfirmDialog () {
+ hideConfirmDialog() {
this.showingConfirmDialog = false
- }
- }
+ },
+ },
}
export default Draft
diff --git a/src/components/draft_closer/draft_closer.js b/src/components/draft_closer/draft_closer.js
index e50ea05ab..d724ab4ac 100644
--- a/src/components/draft_closer/draft_closer.js
+++ b/src/components/draft_closer/draft_closer.js
@@ -1,32 +1,29 @@
import DialogModal from 'src/components/dialog_modal/dialog_modal.vue'
const DraftCloser = {
- data () {
+ data() {
return {
- showing: false
+ showing: false,
}
},
components: {
- DialogModal
+ DialogModal,
},
- emits: [
- 'save',
- 'discard'
- ],
+ emits: ['save', 'discard'],
computed: {
- action () {
+ action() {
if (this.$store.getters.mergedConfig.autoSaveDraft) {
return 'save'
} else {
return this.$store.getters.mergedConfig.unsavedPostAction
}
},
- shouldConfirm () {
+ shouldConfirm() {
return this.action === 'confirm'
- }
+ },
},
methods: {
- requestClose () {
+ requestClose() {
if (this.shouldConfirm) {
this.showing = true
} else if (this.action === 'save') {
@@ -35,18 +32,18 @@ const DraftCloser = {
this.discard()
}
},
- save () {
+ save() {
this.$emit('save')
this.showing = false
},
- discard () {
+ discard() {
this.$emit('discard')
this.showing = false
},
- cancel () {
+ cancel() {
this.showing = false
- }
- }
+ },
+ },
}
export default DraftCloser
diff --git a/src/components/drafts/drafts.js b/src/components/drafts/drafts.js
index 201417f66..8acde3c17 100644
--- a/src/components/drafts/drafts.js
+++ b/src/components/drafts/drafts.js
@@ -4,13 +4,13 @@ import List from 'src/components/list/list.vue'
const Drafts = {
components: {
Draft,
- List
+ List,
},
computed: {
- drafts () {
+ drafts() {
return this.$store.getters.draftsArray
- }
- }
+ },
+ },
}
export default Drafts
diff --git a/src/components/edit_status_form/edit_status_form.js b/src/components/edit_status_form/edit_status_form.js
index 323763370..b8df92794 100644
--- a/src/components/edit_status_form/edit_status_form.js
+++ b/src/components/edit_status_form/edit_status_form.js
@@ -1,21 +1,21 @@
-import PostStatusForm from '../post_status_form/post_status_form.vue'
import statusPosterService from '../../services/status_poster/status_poster.service.js'
+import PostStatusForm from '../post_status_form/post_status_form.vue'
const EditStatusForm = {
components: {
- PostStatusForm
+ PostStatusForm,
},
props: {
params: {
type: Object,
- required: true
- }
+ required: true,
+ },
},
methods: {
- requestClose () {
+ requestClose() {
this.$refs.postStatusForm.requestClose()
},
- doEditStatus ({ status, spoilerText, sensitive, media, contentType, poll }) {
+ doEditStatus({ status, spoilerText, sensitive, media, contentType, poll }) {
const params = {
store: this.$store,
statusId: this.params.statusId,
@@ -24,21 +24,22 @@ const EditStatusForm = {
sensitive,
poll,
media,
- contentType
+ contentType,
}
- return statusPosterService.editStatus(params)
+ return statusPosterService
+ .editStatus(params)
.then((data) => {
return data
})
.catch((err) => {
console.error('Error editing status', err)
return {
- error: err.message
+ error: err.message,
}
})
- }
- }
+ },
+ },
}
export default EditStatusForm
diff --git a/src/components/edit_status_modal/edit_status_modal.js b/src/components/edit_status_modal/edit_status_modal.js
index 4c10c21a0..8a16e4234 100644
--- a/src/components/edit_status_modal/edit_status_modal.js
+++ b/src/components/edit_status_modal/edit_status_modal.js
@@ -1,34 +1,35 @@
+import get from 'lodash/get'
+
+import { useEditStatusStore } from 'src/stores/editStatus'
import EditStatusForm from '../edit_status_form/edit_status_form.vue'
import Modal from '../modal/modal.vue'
-import get from 'lodash/get'
-import { useEditStatusStore } from 'src/stores/editStatus'
const EditStatusModal = {
components: {
EditStatusForm,
- Modal
+ Modal,
},
- data () {
+ data() {
return {
- resettingForm: false
+ resettingForm: false,
}
},
computed: {
- isLoggedIn () {
+ isLoggedIn() {
return !!this.$store.state.users.currentUser
},
- modalActivated () {
+ modalActivated() {
return useEditStatusStore().modalActivated
},
- isFormVisible () {
+ isFormVisible() {
return this.isLoggedIn && !this.resettingForm && this.modalActivated
},
- params () {
+ params() {
return useEditStatusStore().params || {}
- }
+ },
},
watch: {
- params (newVal, oldVal) {
+ params(newVal, oldVal) {
if (get(newVal, 'statusId') !== get(oldVal, 'statusId')) {
this.resettingForm = true
this.$nextTick(() => {
@@ -36,20 +37,22 @@ const EditStatusModal = {
})
}
},
- isFormVisible (val) {
+ isFormVisible(val) {
if (val) {
- this.$nextTick(() => this.$el && this.$el.querySelector('textarea').focus())
+ this.$nextTick(
+ () => this.$el && this.$el.querySelector('textarea').focus(),
+ )
}
- }
+ },
},
methods: {
- closeModal () {
+ closeModal() {
this.$refs.editStatusForm.requestClose()
},
- doCloseModal () {
+ doCloseModal() {
useEditStatusStore().closeEditStatusModal()
- }
- }
+ },
+ },
}
export default EditStatusModal
diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js
index f6ba6e245..24794640e 100644
--- a/src/components/emoji_input/emoji_input.js
+++ b/src/components/emoji_input/emoji_input.js
@@ -1,20 +1,18 @@
-import Completion from '../../services/completion/completion.js'
-import genRandomSeed from '../../services/random_seed/random_seed.service.js'
-import EmojiPicker from '../emoji_picker/emoji_picker.vue'
+import { take } from 'lodash'
+
import Popover from 'src/components/popover/popover.vue'
import ScreenReaderNotice from 'src/components/screen_reader_notice/screen_reader_notice.vue'
-import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
-import { take } from 'lodash'
-import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
import { ensureFinalFallback } from '../../i18n/languages.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faSmileBeam
-} from '@fortawesome/free-regular-svg-icons'
+import Completion from '../../services/completion/completion.js'
+import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
+import genRandomSeed from '../../services/random_seed/random_seed.service.js'
+import EmojiPicker from '../emoji_picker/emoji_picker.vue'
+import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
-library.add(
- faSmileBeam
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faSmileBeam } from '@fortawesome/free-regular-svg-icons'
+
+library.add(faSmileBeam)
/**
* EmojiInput - augmented inputs for emoji and autocomplete support in inputs
@@ -60,14 +58,14 @@ const EmojiInput = {
* For commonly used suggestors (emoji, users, both) use suggestor.js
*/
required: true,
- type: Function
+ type: Function,
},
modelValue: {
/**
* Used for v-model
*/
required: true,
- type: String
+ type: String,
},
enableEmojiPicker: {
/**
@@ -75,7 +73,7 @@ const EmojiInput = {
*/
required: false,
type: Boolean,
- default: false
+ default: false,
},
hideEmojiButton: {
/**
@@ -84,7 +82,7 @@ const EmojiInput = {
*/
required: false,
type: Boolean,
- default: false
+ default: false,
},
enableStickerPicker: {
/**
@@ -92,7 +90,7 @@ const EmojiInput = {
*/
required: false,
type: Boolean,
- default: false
+ default: false,
},
placement: {
/**
@@ -101,15 +99,15 @@ const EmojiInput = {
*/
required: false,
type: String, // 'auto', 'top', 'bottom'
- default: 'auto'
+ default: 'auto',
},
newlineOnCtrlEnter: {
required: false,
type: Boolean,
- default: false
- }
+ default: false,
+ },
},
- data () {
+ data() {
return {
randomSeed: genRandomSeed(),
input: undefined,
@@ -122,58 +120,65 @@ const EmojiInput = {
disableClickOutside: false,
suggestions: [],
overlayStyle: {},
- pickerShown: false
+ pickerShown: false,
}
},
components: {
Popover,
EmojiPicker,
UnicodeDomainIndicator,
- ScreenReaderNotice
+ ScreenReaderNotice,
},
computed: {
- padEmoji () {
+ padEmoji() {
return this.$store.getters.mergedConfig.padEmoji
},
- defaultCandidateIndex () {
+ defaultCandidateIndex() {
return this.$store.getters.mergedConfig.autocompleteSelect ? 0 : -1
},
- preText () {
+ preText() {
return this.modelValue.slice(0, this.caret)
},
- postText () {
+ postText() {
return this.modelValue.slice(this.caret)
},
- showSuggestions () {
- return this.focused &&
+ showSuggestions() {
+ return (
+ this.focused &&
this.suggestions &&
this.suggestions.length > 0 &&
!this.pickerShown &&
!this.temporarilyHideSuggestions
+ )
},
- textAtCaret () {
+ textAtCaret() {
return this.wordAtCaret?.word
},
- wordAtCaret () {
+ wordAtCaret() {
if (this.modelValue && this.caret) {
- const word = Completion.wordAtPosition(this.modelValue, this.caret - 1) || {}
+ const word =
+ Completion.wordAtPosition(this.modelValue, this.caret - 1) || {}
return word
}
},
- languages () {
- return ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage)
+ languages() {
+ return ensureFinalFallback(
+ this.$store.getters.mergedConfig.interfaceLanguage,
+ )
},
- maybeLocalizedEmojiNamesAndKeywords () {
- return emoji => {
+ maybeLocalizedEmojiNamesAndKeywords() {
+ return (emoji) => {
const names = [emoji.displayText]
const keywords = []
if (emoji.displayTextI18n) {
- names.push(this.$t(emoji.displayTextI18n.key, emoji.displayTextI18n.args))
+ names.push(
+ this.$t(emoji.displayTextI18n.key, emoji.displayTextI18n.args),
+ )
}
if (emoji.annotations) {
- this.languages.forEach(lang => {
+ this.languages.forEach((lang) => {
names.push(emoji.annotations[lang]?.name)
keywords.push(...(emoji.annotations[lang]?.keywords || []))
@@ -181,13 +186,13 @@ const EmojiInput = {
}
return {
- names: names.filter(k => k),
- keywords: keywords.filter(k => k)
+ names: names.filter((k) => k),
+ keywords: keywords.filter((k) => k),
}
}
},
- maybeLocalizedEmojiName () {
- return emoji => {
+ maybeLocalizedEmojiName() {
+ return (emoji) => {
if (!emoji.annotations) {
return emoji.displayText
}
@@ -205,16 +210,18 @@ const EmojiInput = {
return emoji.displayText
}
},
- suggestionListId () {
+ suggestionListId() {
return `suggestions-${this.randomSeed}`
},
- suggestionItemId () {
+ suggestionItemId() {
return (index) => `suggestion-item-${index}-${this.randomSeed}`
- }
+ },
},
- mounted () {
+ mounted() {
const { root, hiddenOverlayCaret, suggestorPopover } = this.$refs
- const input = root.querySelector('.emoji-input > input') || root.querySelector('.emoji-input > textarea')
+ const input =
+ root.querySelector('.emoji-input > input') ||
+ root.querySelector('.emoji-input > textarea')
if (!input) return
this.input = input
this.caretEl = hiddenOverlayCaret
@@ -243,7 +250,7 @@ const EmojiInput = {
input.addEventListener('input', this.onInput)
input.addEventListener('scroll', this.onInputScroll)
},
- unmounted () {
+ unmounted() {
const { input } = this
if (input) {
input.removeEventListener('blur', this.onBlur)
@@ -273,36 +280,40 @@ const EmojiInput = {
this.suggestions = []
return
}
- const matchedSuggestions = await this.suggest(newWord, this.maybeLocalizedEmojiNamesAndKeywords)
+ const matchedSuggestions = await this.suggest(
+ newWord,
+ this.maybeLocalizedEmojiNamesAndKeywords,
+ )
// Async: cancel if textAtCaret has changed during wait
if (this.textAtCaret !== newWord || matchedSuggestions.length <= 0) {
this.suggestions = []
return
}
- this.suggestions = take(matchedSuggestions, 5)
- .map(({ imageUrl, ...rest }) => ({
+ this.suggestions = take(matchedSuggestions, 5).map(
+ ({ imageUrl, ...rest }) => ({
...rest,
- img: imageUrl || ''
- }))
+ img: imageUrl || '',
+ }),
+ )
this.highlighted = this.defaultCandidateIndex
this.$refs.screenReaderNotice.announce(
this.$t(
'tool_tip.autocomplete_available',
{ number: this.suggestions.length },
- this.suggestions.length
- )
+ this.suggestions.length,
+ ),
)
- }
+ },
},
methods: {
- onInputScroll (e) {
+ onInputScroll(e) {
this.$refs.hiddenOverlay.scrollTo({
top: this.input.scrollTop,
- left: this.input.scrollLeft
+ left: this.input.scrollLeft,
})
this.setCaret(e)
},
- triggerShowPicker () {
+ triggerShowPicker() {
this.$nextTick(() => {
this.$refs.picker.showPicker()
this.scrollIntoView()
@@ -315,7 +326,7 @@ const EmojiInput = {
this.disableClickOutside = false
}, 0)
},
- togglePicker () {
+ togglePicker() {
this.input.focus()
if (!this.pickerShown) {
this.scrollIntoView()
@@ -325,12 +336,16 @@ const EmojiInput = {
this.$refs.picker.hidePicker()
}
},
- replace (replacement) {
- const newValue = Completion.replaceWord(this.modelValue, this.wordAtCaret, replacement)
+ replace(replacement) {
+ const newValue = Completion.replaceWord(
+ this.modelValue,
+ this.wordAtCaret,
+ replacement,
+ )
this.$emit('update:modelValue', newValue)
this.caret = 0
},
- insert ({ insertion, keepOpen, surroundingSpace = true }) {
+ insert({ insertion, keepOpen, surroundingSpace = true }) {
const before = this.modelValue.substring(0, this.caret) || ''
const after = this.modelValue.substring(this.caret) || ''
@@ -349,18 +364,24 @@ const EmojiInput = {
* them, masto seem to be rendering :emoji::emoji: correctly now so why not
*/
const isSpaceRegex = /\s/
- const spaceBefore = (surroundingSpace && !isSpaceRegex.exec(before.slice(-1)) && before.length && this.padEmoji > 0) ? ' ' : ''
- const spaceAfter = (surroundingSpace && !isSpaceRegex.exec(after[0]) && this.padEmoji) ? ' ' : ''
+ const spaceBefore =
+ surroundingSpace &&
+ !isSpaceRegex.exec(before.slice(-1)) &&
+ before.length &&
+ this.padEmoji > 0
+ ? ' '
+ : ''
+ const spaceAfter =
+ surroundingSpace && !isSpaceRegex.exec(after[0]) && this.padEmoji
+ ? ' '
+ : ''
- const newValue = [
- before,
- spaceBefore,
- insertion,
- spaceAfter,
- after
- ].join('')
+ const newValue = [before, spaceBefore, insertion, spaceAfter, after].join(
+ '',
+ )
this.$emit('update:modelValue', newValue)
- const position = this.caret + (insertion + spaceAfter + spaceBefore).length
+ const position =
+ this.caret + (insertion + spaceAfter + spaceBefore).length
if (!keepOpen) {
this.input.focus()
}
@@ -372,13 +393,20 @@ const EmojiInput = {
this.caret = position
})
},
- replaceText (e, suggestion) {
+ replaceText(e, suggestion) {
const len = this.suggestions.length || 0
- if (this.textAtCaret.length === 1) { return }
+ if (this.textAtCaret.length === 1) {
+ return
+ }
if (len > 0 || suggestion) {
- const chosenSuggestion = suggestion || this.suggestions[this.highlighted]
+ const chosenSuggestion =
+ suggestion || this.suggestions[this.highlighted]
const replacement = chosenSuggestion.replacement
- const newValue = Completion.replaceWord(this.modelValue, this.wordAtCaret, replacement)
+ const newValue = Completion.replaceWord(
+ this.modelValue,
+ this.wordAtCaret,
+ replacement,
+ )
this.$emit('update:modelValue', newValue)
this.highlighted = 0
const position = this.wordAtCaret.start + replacement.length
@@ -393,7 +421,7 @@ const EmojiInput = {
e.preventDefault()
}
},
- cycleBackward (e) {
+ cycleBackward(e) {
const len = this.suggestions.length || 0
this.highlighted -= 1
@@ -406,7 +434,7 @@ const EmojiInput = {
e.preventDefault()
}
},
- cycleForward (e) {
+ cycleForward(e) {
const len = this.suggestions.length || 0
this.highlighted += 1
@@ -418,26 +446,28 @@ const EmojiInput = {
e.preventDefault()
}
},
- scrollIntoView () {
+ scrollIntoView() {
const rootRef = this.$refs.picker.$el
/* Scroller is either `window` (replies in TL), sidebar (main post form,
* replies in notifs) or mobile post form. Note that getting and setting
* scroll is different for `Window` and `Element`s
*/
- const scrollerRef = this.$el.closest('.sidebar-scroller') ||
- this.$el.closest('.post-form-modal-view') ||
- window
- const currentScroll = scrollerRef === window
- ? scrollerRef.scrollY
- : scrollerRef.scrollTop
- const scrollerHeight = scrollerRef === window
- ? scrollerRef.innerHeight
- : scrollerRef.offsetHeight
+ const scrollerRef =
+ this.$el.closest('.sidebar-scroller') ||
+ this.$el.closest('.post-form-modal-view') ||
+ window
+ const currentScroll =
+ scrollerRef === window ? scrollerRef.scrollY : scrollerRef.scrollTop
+ const scrollerHeight =
+ scrollerRef === window
+ ? scrollerRef.innerHeight
+ : scrollerRef.offsetHeight
const scrollerBottomBorder = currentScroll + scrollerHeight
// We check where the bottom border of root element is, this uses findOffset
// to find offset relative to scrollable container (scroller)
- const rootBottomBorder = rootRef.offsetHeight + findOffset(rootRef, scrollerRef).top
+ const rootBottomBorder =
+ rootRef.offsetHeight + findOffset(rootRef, scrollerRef).top
const bottomDelta = Math.max(0, rootBottomBorder - scrollerBottomBorder)
// could also check top delta but there's no case for it
@@ -459,13 +489,13 @@ const EmojiInput = {
}
})
},
- onPickerShown () {
+ onPickerShown() {
this.pickerShown = true
},
- onPickerClosed () {
+ onPickerClosed() {
this.pickerShown = false
},
- onBlur (e) {
+ onBlur(e) {
// Clicking on any suggestion removes focus from autocomplete,
// preventing click handler ever executing.
this.blurTimeout = setTimeout(() => {
@@ -473,10 +503,10 @@ const EmojiInput = {
this.setCaret(e)
}, 200)
},
- onClick (e, suggestion) {
+ onClick(e, suggestion) {
this.replaceText(e, suggestion)
},
- onFocus (e) {
+ onFocus(e) {
if (this.blurTimeout) {
clearTimeout(this.blurTimeout)
this.blurTimeout = null
@@ -486,7 +516,7 @@ const EmojiInput = {
this.setCaret(e)
this.temporarilyHideSuggestions = false
},
- onKeyUp (e) {
+ onKeyUp(e) {
const { key } = e
this.setCaret(e)
@@ -498,10 +528,10 @@ const EmojiInput = {
this.temporarilyHideSuggestions = false
}
},
- onPaste (e) {
+ onPaste(e) {
this.setCaret(e)
},
- onKeyDown (e) {
+ onKeyDown(e) {
const { ctrlKey, shiftKey, key } = e
if (this.newlineOnCtrlEnter && ctrlKey && key === 'Enter') {
this.insert({ insertion: '\n', surroundingSpace: false })
@@ -545,30 +575,30 @@ const EmojiInput = {
}
}
},
- onInput (e) {
+ onInput(e) {
this.setCaret(e)
this.$emit('update:modelValue', e.target.value)
},
- onStickerUploaded (e) {
+ onStickerUploaded(e) {
this.$emit('sticker-uploaded', e)
},
- onStickerUploadFailed (e) {
+ onStickerUploadFailed(e) {
this.$emit('sticker-upload-Failed', e)
},
- setCaret ({ target: { selectionStart } }) {
+ setCaret({ target: { selectionStart } }) {
this.caret = selectionStart
this.$nextTick(() => {
this.$refs.suggestorPopover.updateStyles()
})
},
- autoCompleteItemLabel (suggestion) {
+ autoCompleteItemLabel(suggestion) {
if (suggestion.user) {
return suggestion.displayText + ' ' + suggestion.detailText
} else {
return this.maybeLocalizedEmojiName(suggestion)
}
- }
- }
+ },
+ },
}
export default EmojiInput
diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js
index f2daf2f46..79d97cff7 100644
--- a/src/components/emoji_input/suggestor.js
+++ b/src/components/emoji_input/suggestor.js
@@ -10,7 +10,7 @@
* doesn't support user linking you can just provide only emoji.
*/
-export default data => {
+export default (data) => {
const emojiCurry = suggestEmoji(data.emoji)
const usersCurry = data.store && suggestUsers(data.store)
return (input, nameKeywordLocalizer) => {
@@ -25,22 +25,35 @@ export default data => {
}
}
-export const suggestEmoji = emojis => (input, nameKeywordLocalizer) => {
+export const suggestEmoji = (emojis) => (input, nameKeywordLocalizer) => {
const noPrefix = input.toLowerCase().substr(1)
return emojis
- .map(emoji => ({ ...emoji, ...nameKeywordLocalizer(emoji) }))
- .filter((emoji) => (emoji.names.concat(emoji.keywords)).filter(kw => kw.toLowerCase().match(noPrefix)).length)
- .map(k => {
+ .map((emoji) => ({ ...emoji, ...nameKeywordLocalizer(emoji) }))
+ .filter(
+ (emoji) =>
+ emoji.names
+ .concat(emoji.keywords)
+ .filter((kw) => kw.toLowerCase().match(noPrefix)).length,
+ )
+ .map((k) => {
let score = 0
// An exact match always wins
- score += Math.max(...k.names.map(name => name.toLowerCase() === noPrefix ? 200 : 0), 0)
+ score += Math.max(
+ ...k.names.map((name) => (name.toLowerCase() === noPrefix ? 200 : 0)),
+ 0,
+ )
// Prioritize custom emoji a lot
score += k.imageUrl ? 100 : 0
// Prioritize prefix matches somewhat
- score += Math.max(...k.names.map(kw => kw.toLowerCase().startsWith(noPrefix) ? 10 : 0), 0)
+ score += Math.max(
+ ...k.names.map((kw) =>
+ kw.toLowerCase().startsWith(noPrefix) ? 10 : 0,
+ ),
+ 0,
+ )
// Sort by length
score -= k.displayText.length
@@ -78,7 +91,7 @@ export const suggestUsers = ({ dispatch, state }) => {
})
}
- return async input => {
+ return async (input) => {
const noPrefix = input.toLowerCase().substr(1)
if (previousQuery === noPrefix) return suggestions
@@ -92,37 +105,42 @@ export const suggestUsers = ({ dispatch, state }) => {
await debounceUserSearch(noPrefix)
}
- const newSuggestions = state.users.users.filter(
- user =>
- user.screen_name && user.name && (
- user.screen_name.toLowerCase().startsWith(noPrefix) ||
- user.name.toLowerCase().startsWith(noPrefix))
- ).slice(0, 20).sort((a, b) => {
- let aScore = 0
- let bScore = 0
+ const newSuggestions = state.users.users
+ .filter(
+ (user) =>
+ user.screen_name &&
+ user.name &&
+ (user.screen_name.toLowerCase().startsWith(noPrefix) ||
+ user.name.toLowerCase().startsWith(noPrefix)),
+ )
+ .slice(0, 20)
+ .sort((a, b) => {
+ let aScore = 0
+ let bScore = 0
- // Matches on screen name (i.e. user@instance) makes a priority
- aScore += a.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0
- bScore += b.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0
+ // Matches on screen name (i.e. user@instance) makes a priority
+ aScore += a.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0
+ bScore += b.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0
- // Matches on name takes second priority
- aScore += a.name.toLowerCase().startsWith(noPrefix) ? 1 : 0
- bScore += b.name.toLowerCase().startsWith(noPrefix) ? 1 : 0
+ // Matches on name takes second priority
+ aScore += a.name.toLowerCase().startsWith(noPrefix) ? 1 : 0
+ bScore += b.name.toLowerCase().startsWith(noPrefix) ? 1 : 0
- const diff = (bScore - aScore) * 10
+ const diff = (bScore - aScore) * 10
- // Then sort alphabetically
- const nameAlphabetically = a.name > b.name ? 1 : -1
- const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1
+ // Then sort alphabetically
+ const nameAlphabetically = a.name > b.name ? 1 : -1
+ const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1
- return diff + nameAlphabetically + screenNameAlphabetically
- }).map((user) => ({
- user,
- displayText: user.screen_name_ui,
- detailText: user.name,
- imageUrl: user.profile_image_url_original,
- replacement: '@' + user.screen_name + ' '
- }))
+ return diff + nameAlphabetically + screenNameAlphabetically
+ })
+ .map((user) => ({
+ user,
+ displayText: user.screen_name_ui,
+ detailText: user.name,
+ imageUrl: user.profile_image_url_original,
+ replacement: '@' + user.screen_name + ' ',
+ }))
suggestions = newSuggestions || []
return suggestions
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index 8e572d1d2..e4221f706 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -1,24 +1,26 @@
+import { chunk, debounce, trim } from 'lodash'
import { defineAsyncComponent } from 'vue'
-import Checkbox from '../checkbox/checkbox.vue'
+
import Popover from 'src/components/popover/popover.vue'
-import StillImage from '../still-image/still-image.vue'
import { ensureFinalFallback } from '../../i18n/languages.js'
+import Checkbox from '../checkbox/checkbox.vue'
+import StillImage from '../still-image/still-image.vue'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faBoxOpen,
- faStickyNote,
- faSmileBeam,
- faSmile,
- faUser,
- faPaw,
- faIceCream,
- faBus,
faBasketballBall,
- faLightbulb,
+ faBoxOpen,
+ faBus,
faCode,
- faFlag
+ faFlag,
+ faIceCream,
+ faLightbulb,
+ faPaw,
+ faSmile,
+ faSmileBeam,
+ faStickyNote,
+ faUser,
} from '@fortawesome/free-solid-svg-icons'
-import { debounce, trim, chunk } from 'lodash'
library.add(
faBoxOpen,
@@ -32,7 +34,7 @@ library.add(
faBasketballBall,
faLightbulb,
faCode,
- faFlag
+ faFlag,
)
const UNICODE_EMOJI_GROUP_ICON = {
@@ -44,16 +46,16 @@ const UNICODE_EMOJI_GROUP_ICON = {
activities: 'basketball-ball',
objects: 'lightbulb',
symbols: 'code',
- flags: 'flag'
+ flags: 'flag',
}
const maybeLocalizedKeywords = (emoji, languages, nameLocalizer) => {
const res = [emoji.displayText, nameLocalizer(emoji)]
if (emoji.annotations) {
- languages.forEach(lang => {
+ languages.forEach((lang) => {
const keywords = emoji.annotations[lang]?.keywords || []
const name = emoji.annotations[lang]?.name
- res.push(...(keywords.concat([name]).filter(k => k)))
+ res.push(...keywords.concat([name]).filter((k) => k))
})
}
return res
@@ -66,8 +68,8 @@ const filterByKeyword = (list, keyword = '', languages, nameLocalizer) => {
const orderedEmojiList = []
for (const emoji of list) {
const indices = maybeLocalizedKeywords(emoji, languages, nameLocalizer)
- .map(k => k.toLowerCase().indexOf(keywordLowercase))
- .filter(k => k > -1)
+ .map((k) => k.toLowerCase().indexOf(keywordLowercase))
+ .filter((k) => k > -1)
const indexOfKeyword = indices.length ? Math.min(...indices) : -1
@@ -84,11 +86,13 @@ const filterByKeyword = (list, keyword = '', languages, nameLocalizer) => {
const getOffset = (elem) => {
const style = elem.style.transform
const res = /translateY\((\d+)px\)/.exec(style)
- if (!res) { return 0 }
+ if (!res) {
+ return 0
+ }
return res[1]
}
-const toHeaderId = id => {
+const toHeaderId = (id) => {
return id.replace(/^row-\d+-/, '')
}
@@ -97,20 +101,20 @@ const EmojiPicker = {
enableStickerPicker: {
required: false,
type: Boolean,
- default: true
+ default: true,
},
hideCustomEmoji: {
required: false,
type: Boolean,
- default: false
- }
+ default: false,
+ },
},
inject: {
popoversZLayer: {
- default: ''
- }
+ default: '',
+ },
},
- data () {
+ data() {
return {
keyword: '',
activeGroup: 'custom',
@@ -125,20 +129,22 @@ const EmojiPicker = {
emojiRefs: {},
filteredEmojiGroups: [],
emojiSize: 0,
- width: 0
+ width: 0,
}
},
components: {
- StickerPicker: defineAsyncComponent(() => import('../sticker_picker/sticker_picker.vue')),
+ StickerPicker: defineAsyncComponent(
+ () => import('../sticker_picker/sticker_picker.vue'),
+ ),
Checkbox,
StillImage,
- Popover
+ Popover,
},
methods: {
- groupScroll (e) {
+ groupScroll(e) {
e.currentTarget.scrollLeft += e.deltaY + e.deltaX
},
- updateEmojiSize () {
+ updateEmojiSize() {
const css = window.getComputedStyle(this.$refs.popover.$el)
const fontSize = css.getPropertyValue('font-size') || '1rem'
const emojiSize = css.getPropertyValue('--emojiSize') || '2.2rem'
@@ -163,56 +169,68 @@ const EmojiPicker = {
emojiSizeReal = emojiSizeValue
}
- const fullEmojiSize = emojiSizeReal + (2 * 0.2 * fontSizeMultiplier * 14)
+ const fullEmojiSize = emojiSizeReal + 2 * 0.2 * fontSizeMultiplier * 14
this.emojiSize = fullEmojiSize
},
- showPicker () {
+ showPicker() {
this.$refs.popover.showPopover()
this.$nextTick(() => {
this.onShowing()
})
},
- hidePicker () {
+ hidePicker() {
this.$refs.popover.hidePopover()
},
- setAnchorEl (el) {
+ setAnchorEl(el) {
this.$refs.popover.setAnchorEl(el)
},
- setGroupRef (name) {
- return el => { this.groupRefs[name] = el }
+ setGroupRef(name) {
+ return (el) => {
+ this.groupRefs[name] = el
+ }
},
- onPopoverShown () {
+ onPopoverShown() {
this.$emit('show')
},
- onPopoverClosed () {
+ onPopoverClosed() {
this.$emit('close')
},
- onStickerUploaded (e) {
+ onStickerUploaded(e) {
this.$emit('sticker-uploaded', e)
},
- onStickerUploadFailed (e) {
+ onStickerUploadFailed(e) {
this.$emit('sticker-upload-failed', e)
},
- onEmoji (emoji) {
- const value = emoji.imageUrl ? `:${emoji.displayText}:` : emoji.replacement
+ onEmoji(emoji) {
+ const value = emoji.imageUrl
+ ? `:${emoji.displayText}:`
+ : emoji.replacement
if (!this.keepOpen) {
this.$refs.popover.hidePopover()
}
- this.$emit('emoji', { insertion: value, insertionUrl: emoji.imageUrl, keepOpen: this.keepOpen })
+ this.$emit('emoji', {
+ insertion: value,
+ insertionUrl: emoji.imageUrl,
+ keepOpen: this.keepOpen,
+ })
},
- onScroll (startIndex, endIndex, visibleStartIndex, visibleEndIndex) {
+ onScroll(startIndex, endIndex, visibleStartIndex, visibleEndIndex) {
const target = this.$refs['emoji-groups'].$el
this.scrolledGroup(target, visibleStartIndex, visibleEndIndex)
},
- scrolledGroup (target, start, end) {
+ scrolledGroup(target, start, end) {
const top = target.scrollTop + 5
this.$nextTick(() => {
- this.emojiItems.slice(start, end + 1).forEach(group => {
+ this.emojiItems.slice(start, end + 1).forEach((group) => {
const headerId = toHeaderId(group.id)
const ref = this.groupRefs['group-' + group.id]
- if (!ref) { return }
+ if (!ref) {
+ return
+ }
const elem = ref.$el.parentElement
- if (!elem) { return }
+ if (!elem) {
+ return
+ }
if (elem && getOffset(elem) <= top) {
this.activeGroup = headerId
}
@@ -220,7 +238,7 @@ const EmojiPicker = {
this.scrollHeader()
})
},
- scrollHeader () {
+ scrollHeader() {
// Scroll the active tab's header into view
const headerRef = this.groupRefs['group-header-' + this.activeGroup]
const left = headerRef.offsetLeft
@@ -228,7 +246,9 @@ const EmojiPicker = {
const headerCont = this.$refs.header
const currentScroll = headerCont.scrollLeft
const currentScrollRight = currentScroll + headerCont.clientWidth
- const setScroll = s => { headerCont.scrollLeft = s }
+ const setScroll = (s) => {
+ headerCont.scrollLeft = s
+ }
const margin = 7 // .emoji-tabs-item: padding
if (left - margin < currentScroll) {
@@ -237,12 +257,12 @@ const EmojiPicker = {
setScroll(right + margin - headerCont.clientWidth)
}
},
- highlight (groupId) {
+ highlight(groupId) {
this.setShowStickers(false)
- const indexInList = this.emojiItems.findIndex(k => k.id === groupId)
+ const indexInList = this.emojiItems.findIndex((k) => k.id === groupId)
this.$refs['emoji-groups'].scrollToItem(indexInList)
},
- updateScrolledClass (target) {
+ updateScrolledClass(target) {
if (target.scrollTop <= 5) {
this.groupsScrolledClass = 'scrolled-top'
} else if (target.scrollTop >= target.scrollTopMax - 5) {
@@ -251,16 +271,21 @@ const EmojiPicker = {
this.groupsScrolledClass = 'scrolled-middle'
}
},
- toggleStickers () {
+ toggleStickers() {
this.showingStickers = !this.showingStickers
},
- setShowStickers (value) {
+ setShowStickers(value) {
this.showingStickers = value
},
- filterByKeyword (list, keyword) {
- return filterByKeyword(list, keyword, this.languages, this.maybeLocalizedEmojiName)
+ filterByKeyword(list, keyword) {
+ return filterByKeyword(
+ list,
+ keyword,
+ this.languages,
+ this.maybeLocalizedEmojiName,
+ )
},
- onShowing () {
+ onShowing() {
const oldContentLoaded = this.contentLoaded
this.updateEmojiSize()
this.recalculateItemPerRow()
@@ -277,59 +302,59 @@ const EmojiPicker = {
})
}
},
- getFilteredEmojiGroups () {
+ getFilteredEmojiGroups() {
return this.allEmojiGroups
- .map(group => ({
+ .map((group) => ({
...group,
- emojis: this.filterByKeyword(group.emojis, trim(this.keyword))
+ emojis: this.filterByKeyword(group.emojis, trim(this.keyword)),
}))
- .filter(group => group.emojis.length > 0)
+ .filter((group) => group.emojis.length > 0)
},
- recalculateItemPerRow () {
+ recalculateItemPerRow() {
this.$nextTick(() => {
if (!this.$refs['emoji-groups']) {
return
}
this.width = this.$refs['emoji-groups'].$el.clientWidth
})
- }
+ },
},
watch: {
- keyword () {
+ keyword() {
this.onScroll()
this.debouncedHandleKeywordChange()
},
- allCustomGroups () {
+ allCustomGroups() {
this.filteredEmojiGroups = this.getFilteredEmojiGroups()
- }
+ },
},
computed: {
- minItemSize () {
+ minItemSize() {
return this.emojiSize
},
// used to watch it
- fontSize () {
+ fontSize() {
this.$nextTick(() => {
this.updateEmojiSize()
})
return this.$store.getters.mergedConfig.fontSize
},
- emojiHeight () {
+ emojiHeight() {
return this.emojiSize
},
- itemPerRow () {
+ itemPerRow() {
return this.width ? Math.floor(this.width / this.emojiSize) : 6
},
- activeGroupView () {
+ activeGroupView() {
return this.showingStickers ? '' : this.activeGroup
},
- stickersAvailable () {
+ stickersAvailable() {
if (this.$store.state.instance.stickers) {
return this.$store.state.instance.stickers.length > 0
}
return 0
},
- allCustomGroups () {
+ allCustomGroups() {
if (this.hideCustomEmoji || this.hideCustomEmojiInPicker) {
return {}
}
@@ -339,46 +364,49 @@ const EmojiPicker = {
}
return emojis
},
- defaultGroup () {
+ defaultGroup() {
return Object.keys(this.allCustomGroups)[0]
},
- unicodeEmojiGroups () {
- return this.$store.getters.standardEmojiGroupList.map(group => ({
+ unicodeEmojiGroups() {
+ return this.$store.getters.standardEmojiGroupList.map((group) => ({
id: `standard-${group.id}`,
text: this.$t(`emoji.unicode_groups.${group.id}`),
icon: UNICODE_EMOJI_GROUP_ICON[group.id],
- emojis: group.emojis
+ emojis: group.emojis,
}))
},
- allEmojiGroups () {
+ allEmojiGroups() {
return Object.entries(this.allCustomGroups)
.map(([, v]) => v)
.concat(this.unicodeEmojiGroups)
},
- stickerPickerEnabled () {
+ stickerPickerEnabled() {
return (this.$store.state.instance.stickers || []).length !== 0
},
- debouncedHandleKeywordChange () {
+ debouncedHandleKeywordChange() {
return debounce(() => {
this.filteredEmojiGroups = this.getFilteredEmojiGroups()
}, 500)
},
- emojiItems () {
- return this.filteredEmojiGroups.map(group =>
- chunk(group.emojis, this.itemPerRow)
- .map((items, index) => ({
+ emojiItems() {
+ return this.filteredEmojiGroups
+ .map((group) =>
+ chunk(group.emojis, this.itemPerRow).map((items, index) => ({
...group,
id: index === 0 ? group.id : `row-${index}-${group.id}`,
emojis: items,
- isFirstRow: index === 0
- })))
+ isFirstRow: index === 0,
+ })),
+ )
.reduce((a, c) => a.concat(c), [])
},
- languages () {
- return ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage)
+ languages() {
+ return ensureFinalFallback(
+ this.$store.getters.mergedConfig.interfaceLanguage,
+ )
},
- maybeLocalizedEmojiName () {
- return emoji => {
+ maybeLocalizedEmojiName() {
+ return (emoji) => {
if (!emoji.annotations) {
return emoji.displayText
}
@@ -396,10 +424,10 @@ const EmojiPicker = {
return emoji.displayText
}
},
- isInModal () {
+ isInModal() {
return this.popoversZLayer === 'modals'
- }
- }
+ },
+ },
}
export default EmojiPicker
diff --git a/src/components/emoji_reactions/emoji_reactions.js b/src/components/emoji_reactions/emoji_reactions.js
index f5e1b68f6..8a121befc 100644
--- a/src/components/emoji_reactions/emoji_reactions.js
+++ b/src/components/emoji_reactions/emoji_reactions.js
@@ -1,18 +1,11 @@
+import StillImage from 'src/components/still-image/still-image.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserListPopover from '../user_list_popover/user_list_popover.vue'
-import StillImage from 'src/components/still-image/still-image.vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faPlus,
- faMinus,
- faCheck
-} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faPlus,
- faMinus,
- faCheck
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faCheck, faMinus, faPlus } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faPlus, faMinus, faCheck)
const EMOJI_REACTION_COUNT_CUTOFF = 12
@@ -21,57 +14,62 @@ const EmojiReactions = {
components: {
UserAvatar,
UserListPopover,
- StillImage
+ StillImage,
},
props: ['status'],
data: () => ({
- showAll: false
+ showAll: false,
}),
computed: {
- tooManyReactions () {
+ tooManyReactions() {
return this.status.emoji_reactions.length > EMOJI_REACTION_COUNT_CUTOFF
},
- emojiReactions () {
+ emojiReactions() {
return this.showAll
? this.status.emoji_reactions
: this.status.emoji_reactions.slice(0, EMOJI_REACTION_COUNT_CUTOFF)
},
- showMoreString () {
+ showMoreString() {
return `+${this.status.emoji_reactions.length - EMOJI_REACTION_COUNT_CUTOFF}`
},
- accountsForEmoji () {
+ accountsForEmoji() {
return this.status.emoji_reactions.reduce((acc, reaction) => {
acc[reaction.name] = reaction.accounts || []
return acc
}, {})
},
- loggedIn () {
+ loggedIn() {
return !!this.$store.state.users.currentUser
},
- remoteInteractionLink () {
- return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
- }
+ remoteInteractionLink() {
+ return this.$store.getters.remoteInteractionLink({
+ statusId: this.status.id,
+ })
+ },
},
methods: {
- toggleShowAll () {
+ toggleShowAll() {
this.showAll = !this.showAll
},
- reactedWith (emoji) {
- return this.status.emoji_reactions.find(r => r.name === emoji).me
+ reactedWith(emoji) {
+ return this.status.emoji_reactions.find((r) => r.name === emoji).me
},
- async fetchEmojiReactionsByIfMissing () {
- const hasNoAccounts = this.status.emoji_reactions.find(r => !r.accounts)
+ async fetchEmojiReactionsByIfMissing() {
+ const hasNoAccounts = this.status.emoji_reactions.find((r) => !r.accounts)
if (hasNoAccounts) {
- return await this.$store.dispatch('fetchEmojiReactionsBy', this.status.id)
+ return await this.$store.dispatch(
+ 'fetchEmojiReactionsBy',
+ this.status.id,
+ )
}
},
- reactWith (emoji) {
+ reactWith(emoji) {
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })
},
- unreact (emoji) {
+ unreact(emoji) {
this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })
},
- async emojiOnClick (emoji) {
+ async emojiOnClick(emoji) {
if (!this.loggedIn) return
await this.fetchEmojiReactionsByIfMissing()
@@ -81,19 +79,23 @@ const EmojiReactions = {
this.reactWith(emoji)
}
},
- counterTriggerAttrs (reaction) {
+ counterTriggerAttrs(reaction) {
return {
class: [
'emoji-reaction-count-button',
{
'-picked-reaction': this.reactedWith(reaction.name),
- toggled: this.reactedWith(reaction.name)
- }
+ toggled: this.reactedWith(reaction.name),
+ },
],
- 'aria-label': this.$t('status.reaction_count_label', { num: reaction.count }, reaction.count)
+ 'aria-label': this.$t(
+ 'status.reaction_count_label',
+ { num: reaction.count },
+ reaction.count,
+ ),
}
- }
- }
+ },
+ },
}
export default EmojiReactions
diff --git a/src/components/exporter/exporter.js b/src/components/exporter/exporter.js
index fc75372e3..12213d9e3 100644
--- a/src/components/exporter/exporter.js
+++ b/src/components/exporter/exporter.js
@@ -1,45 +1,47 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faCircleNotch
-)
+library.add(faCircleNotch)
const Exporter = {
props: {
getContent: {
type: Function,
- required: true
+ required: true,
},
filename: {
type: String,
- default: 'export.csv'
+ default: 'export.csv',
},
exportButtonLabel: { type: String },
- processingMessage: { type: String }
+ processingMessage: { type: String },
},
- data () {
+ data() {
return {
- processing: false
+ processing: false,
}
},
methods: {
- process () {
+ process() {
this.processing = true
- this.getContent()
- .then((content) => {
- const fileToDownload = document.createElement('a')
- fileToDownload.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content))
- fileToDownload.setAttribute('download', this.filename)
- fileToDownload.style.display = 'none'
- document.body.appendChild(fileToDownload)
- fileToDownload.click()
- document.body.removeChild(fileToDownload)
- // Add delay before hiding processing state since browser takes some time to handle file download
- setTimeout(() => { this.processing = false }, 2000)
- })
- }
- }
+ this.getContent().then((content) => {
+ const fileToDownload = document.createElement('a')
+ fileToDownload.setAttribute(
+ 'href',
+ 'data:text/plain;charset=utf-8,' + encodeURIComponent(content),
+ )
+ fileToDownload.setAttribute('download', this.filename)
+ fileToDownload.style.display = 'none'
+ document.body.appendChild(fileToDownload)
+ fileToDownload.click()
+ document.body.removeChild(fileToDownload)
+ // Add delay before hiding processing state since browser takes some time to handle file download
+ setTimeout(() => {
+ this.processing = false
+ }, 2000)
+ })
+ },
+ },
}
export default Exporter
diff --git a/src/components/extra_notifications/extra_notifications.js b/src/components/extra_notifications/extra_notifications.js
index 673b28662..1deebd878 100644
--- a/src/components/extra_notifications/extra_notifications.js
+++ b/src/components/extra_notifications/extra_notifications.js
@@ -1,55 +1,72 @@
-import { mapGetters } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
+import { mapGetters } from 'vuex'
+
import { useAnnouncementsStore } from 'src/stores/announcements'
+import { useInterfaceStore } from 'src/stores/interface'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faUserPlus,
+ faBullhorn,
faComments,
- faBullhorn
+ faUserPlus,
} from '@fortawesome/free-solid-svg-icons'
-import { useInterfaceStore } from 'src/stores/interface'
-
-library.add(
- faUserPlus,
- faComments,
- faBullhorn
-)
+library.add(faUserPlus, faComments, faBullhorn)
const ExtraNotifications = {
computed: {
- shouldShowChats () {
- return this.mergedConfig.showExtraNotifications && this.mergedConfig.showChatsInExtraNotifications && this.unreadChatCount
+ shouldShowChats() {
+ return (
+ this.mergedConfig.showExtraNotifications &&
+ this.mergedConfig.showChatsInExtraNotifications &&
+ this.unreadChatCount
+ )
},
- shouldShowAnnouncements () {
- return this.mergedConfig.showExtraNotifications && this.mergedConfig.showAnnouncementsInExtraNotifications && this.unreadAnnouncementCount
+ shouldShowAnnouncements() {
+ return (
+ this.mergedConfig.showExtraNotifications &&
+ this.mergedConfig.showAnnouncementsInExtraNotifications &&
+ this.unreadAnnouncementCount
+ )
},
- shouldShowFollowRequests () {
- return this.mergedConfig.showExtraNotifications && this.mergedConfig.showFollowRequestsInExtraNotifications && this.followRequestCount
+ shouldShowFollowRequests() {
+ return (
+ this.mergedConfig.showExtraNotifications &&
+ this.mergedConfig.showFollowRequestsInExtraNotifications &&
+ this.followRequestCount
+ )
},
- hasAnythingToShow () {
- return this.shouldShowChats || this.shouldShowAnnouncements || this.shouldShowFollowRequests
+ hasAnythingToShow() {
+ return (
+ this.shouldShowChats ||
+ this.shouldShowAnnouncements ||
+ this.shouldShowFollowRequests
+ )
},
- shouldShowCustomizationTip () {
- return this.mergedConfig.showExtraNotificationsTip && this.hasAnythingToShow
+ shouldShowCustomizationTip() {
+ return (
+ this.mergedConfig.showExtraNotificationsTip && this.hasAnythingToShow
+ )
},
- currentUser () {
+ currentUser() {
return this.$store.state.users.currentUser
},
...mapGetters(['unreadChatCount', 'followRequestCount', 'mergedConfig']),
...mapPiniaState(useAnnouncementsStore, {
- unreadAnnouncementCount: 'unreadAnnouncementCount'
- })
+ unreadAnnouncementCount: 'unreadAnnouncementCount',
+ }),
},
methods: {
- openNotificationSettings () {
+ openNotificationSettings() {
return useInterfaceStore().openSettingsModalTab('notifications')
},
- dismissConfigurationTip () {
- return this.$store.dispatch('setOption', { name: 'showExtraNotificationsTip', value: false })
- }
- }
+ dismissConfigurationTip() {
+ return this.$store.dispatch('setOption', {
+ name: 'showExtraNotificationsTip',
+ value: false,
+ })
+ },
+ },
}
export default ExtraNotifications
diff --git a/src/components/features_panel/features_panel.js b/src/components/features_panel/features_panel.js
index d177efebe..e92cb975e 100644
--- a/src/components/features_panel/features_panel.js
+++ b/src/components/features_panel/features_panel.js
@@ -2,15 +2,33 @@ import fileSizeFormatService from '../../services/file_size_format/file_size_for
const FeaturesPanel = {
computed: {
- shout: function () { return this.$store.state.instance.shoutAvailable },
- pleromaChatMessages: function () { return this.$store.state.instance.pleromaChatMessagesAvailable },
- gopher: function () { return this.$store.state.instance.gopherAvailable },
- whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled },
- mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable },
- minimalScopesMode: function () { return this.$store.state.instance.minimalScopesMode },
- textlimit: function () { return this.$store.state.instance.textlimit },
- uploadlimit: function () { return fileSizeFormatService.fileSizeFormat(this.$store.state.instance.uploadlimit) }
- }
+ shout: function () {
+ return this.$store.state.instance.shoutAvailable
+ },
+ pleromaChatMessages: function () {
+ return this.$store.state.instance.pleromaChatMessagesAvailable
+ },
+ gopher: function () {
+ return this.$store.state.instance.gopherAvailable
+ },
+ whoToFollow: function () {
+ return this.$store.state.instance.suggestionsEnabled
+ },
+ mediaProxy: function () {
+ return this.$store.state.instance.mediaProxyAvailable
+ },
+ minimalScopesMode: function () {
+ return this.$store.state.instance.minimalScopesMode
+ },
+ textlimit: function () {
+ return this.$store.state.instance.textlimit
+ },
+ uploadlimit: function () {
+ return fileSizeFormatService.fileSizeFormat(
+ this.$store.state.instance.uploadlimit,
+ )
+ },
+ },
}
export default FeaturesPanel
diff --git a/src/components/flash/flash.js b/src/components/flash/flash.js
index 87c1d650c..3c25abea1 100644
--- a/src/components/flash/flash.js
+++ b/src/components/flash/flash.js
@@ -1,53 +1,54 @@
import RuffleService from '../../services/ruffle_service/ruffle_service.js'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
+ faExclamationTriangle,
faStop,
- faExclamationTriangle
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faStop,
- faExclamationTriangle
-)
+library.add(faStop, faExclamationTriangle)
const Flash = {
props: ['src'],
- data () {
+ data() {
return {
player: false, // can be true, "hidden", false. hidden = element exists
loaded: false,
- ruffleInstance: null
+ ruffleInstance: null,
}
},
methods: {
- openPlayer () {
+ openPlayer() {
if (this.player) return // prevent double-loading, or re-loading on failure
this.player = 'hidden'
RuffleService.getRuffle().then((ruffle) => {
const player = ruffle.newest().createPlayer()
player.config = {
- letterbox: 'on'
+ letterbox: 'on',
}
const container = this.$refs.container
container.appendChild(player)
player.style.width = '100%'
player.style.height = '100%'
- player.load(this.src).then(() => {
- this.player = true
- }).catch((e) => {
- console.error('Error loading ruffle', e)
- this.player = 'error'
- })
+ player
+ .load(this.src)
+ .then(() => {
+ this.player = true
+ })
+ .catch((e) => {
+ console.error('Error loading ruffle', e)
+ this.player = 'error'
+ })
this.ruffleInstance = player
this.$emit('playerOpened')
})
},
- closePlayer () {
+ closePlayer() {
this.ruffleInstance && this.ruffleInstance.remove()
this.player = false
this.$emit('playerClosed')
- }
- }
+ },
+ },
}
export default Flash
diff --git a/src/components/follow_button/follow_button.js b/src/components/follow_button/follow_button.js
index 443aa9bcc..eb545b28d 100644
--- a/src/components/follow_button/follow_button.js
+++ b/src/components/follow_button/follow_button.js
@@ -1,24 +1,27 @@
+import {
+ requestFollow,
+ requestUnfollow,
+} from '../../services/follow_manipulate/follow_manipulate'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
-import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
export default {
props: ['relationship', 'user', 'labelFollowing', 'buttonClass'],
components: {
- ConfirmModal
+ ConfirmModal,
},
- data () {
+ data() {
return {
inProgress: false,
- showingConfirmUnfollow: false
+ showingConfirmUnfollow: false,
}
},
computed: {
- shouldConfirmUnfollow () {
+ shouldConfirmUnfollow() {
return this.$store.getters.mergedConfig.modalOnUnfollow
},
- isPressed () {
+ isPressed() {
return this.inProgress || this.relationship.following
},
- title () {
+ title() {
if (this.inProgress || this.relationship.following) {
return this.$t('user_card.follow_unfollow')
} else if (this.relationship.requested) {
@@ -27,7 +30,7 @@ export default {
return this.$t('user_card.follow')
}
},
- label () {
+ label() {
if (this.inProgress) {
return this.$t('user_card.follow_progress')
} else if (this.relationship.following) {
@@ -38,42 +41,47 @@ export default {
return this.$t('user_card.follow')
}
},
- disabled () {
+ disabled() {
return this.inProgress || this.user.deactivated
- }
+ },
},
methods: {
- showConfirmUnfollow () {
+ showConfirmUnfollow() {
this.showingConfirmUnfollow = true
},
- hideConfirmUnfollow () {
+ hideConfirmUnfollow() {
this.showingConfirmUnfollow = false
},
- onClick () {
- this.relationship.following || this.relationship.requested ? this.unfollow() : this.follow()
+ onClick() {
+ this.relationship.following || this.relationship.requested
+ ? this.unfollow()
+ : this.follow()
},
- follow () {
+ follow() {
this.inProgress = true
requestFollow(this.relationship.id, this.$store).then(() => {
this.inProgress = false
})
},
- unfollow () {
+ unfollow() {
if (this.shouldConfirmUnfollow) {
this.showConfirmUnfollow()
} else {
this.doUnfollow()
}
},
- doUnfollow () {
+ doUnfollow() {
const store = this.$store
this.inProgress = true
requestUnfollow(this.relationship.id, store).then(() => {
this.inProgress = false
- store.commit('removeStatus', { timeline: 'friends', userId: this.relationship.id })
+ store.commit('removeStatus', {
+ timeline: 'friends',
+ userId: this.relationship.id,
+ })
})
this.hideConfirmUnfollow()
- }
- }
+ },
+ },
}
diff --git a/src/components/follow_card/follow_card.js b/src/components/follow_card/follow_card.js
index b26b27a74..e4c84dcdd 100644
--- a/src/components/follow_card/follow_card.js
+++ b/src/components/follow_card/follow_card.js
@@ -1,30 +1,27 @@
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
-import RemoteFollow from '../remote_follow/remote_follow.vue'
import FollowButton from '../follow_button/follow_button.vue'
+import RemoteFollow from '../remote_follow/remote_follow.vue'
import RemoveFollowerButton from '../remove_follower_button/remove_follower_button.vue'
const FollowCard = {
- props: [
- 'user',
- 'noFollowsYou'
- ],
+ props: ['user', 'noFollowsYou'],
components: {
BasicUserCard,
RemoteFollow,
FollowButton,
- RemoveFollowerButton
+ RemoveFollowerButton,
},
computed: {
- isMe () {
+ isMe() {
return this.$store.state.users.currentUser.id === this.user.id
},
- loggedIn () {
+ loggedIn() {
return this.$store.state.users.currentUser
},
- relationship () {
+ relationship() {
return this.$store.getters.relationship(this.user.id)
- }
- }
+ },
+ },
}
export default FollowCard
diff --git a/src/components/follow_request_card/follow_request_card.js b/src/components/follow_request_card/follow_request_card.js
index b0873bb10..c037ddf42 100644
--- a/src/components/follow_request_card/follow_request_card.js
+++ b/src/components/follow_request_card/follow_request_card.js
@@ -1,46 +1,48 @@
+import { notificationsFromStore } from '../../services/notification_utils/notification_utils.js'
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
-import { notificationsFromStore } from '../../services/notification_utils/notification_utils.js'
const FollowRequestCard = {
props: ['user'],
components: {
BasicUserCard,
- ConfirmModal
+ ConfirmModal,
},
- data () {
+ data() {
return {
showingApproveConfirmDialog: false,
- showingDenyConfirmDialog: false
+ showingDenyConfirmDialog: false,
}
},
methods: {
- findFollowRequestNotificationId () {
+ findFollowRequestNotificationId() {
const notif = notificationsFromStore(this.$store).find(
- (notif) => notif.from_profile.id === this.user.id && notif.type === 'follow_request'
+ (notif) =>
+ notif.from_profile.id === this.user.id &&
+ notif.type === 'follow_request',
)
return notif && notif.id
},
- showApproveConfirmDialog () {
+ showApproveConfirmDialog() {
this.showingApproveConfirmDialog = true
},
- hideApproveConfirmDialog () {
+ hideApproveConfirmDialog() {
this.showingApproveConfirmDialog = false
},
- showDenyConfirmDialog () {
+ showDenyConfirmDialog() {
this.showingDenyConfirmDialog = true
},
- hideDenyConfirmDialog () {
+ hideDenyConfirmDialog() {
this.showingDenyConfirmDialog = false
},
- approveUser () {
+ approveUser() {
if (this.shouldConfirmApprove) {
this.showApproveConfirmDialog()
} else {
this.doApprove()
}
},
- doApprove () {
+ doApprove() {
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
this.$store.dispatch('removeFollowRequest', this.user)
@@ -48,40 +50,41 @@ const FollowRequestCard = {
this.$store.dispatch('markSingleNotificationAsSeen', { id: notifId })
this.$store.dispatch('updateNotification', {
id: notifId,
- updater: notification => {
+ updater: (notification) => {
notification.type = 'follow'
- }
+ },
})
this.hideApproveConfirmDialog()
},
- denyUser () {
+ denyUser() {
if (this.shouldConfirmDeny) {
this.showDenyConfirmDialog()
} else {
this.doDeny()
}
},
- doDeny () {
+ doDeny() {
const notifId = this.findFollowRequestNotificationId()
- this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
+ this.$store.state.api.backendInteractor
+ .denyUser({ id: this.user.id })
.then(() => {
this.$store.dispatch('dismissNotificationLocal', { id: notifId })
this.$store.dispatch('removeFollowRequest', this.user)
})
this.hideDenyConfirmDialog()
- }
+ },
},
computed: {
- mergedConfig () {
+ mergedConfig() {
return this.$store.getters.mergedConfig
},
- shouldConfirmApprove () {
+ shouldConfirmApprove() {
return this.mergedConfig.modalOnApproveFollow
},
- shouldConfirmDeny () {
+ shouldConfirmDeny() {
return this.mergedConfig.modalOnDenyFollow
- }
- }
+ },
+ },
}
export default FollowRequestCard
diff --git a/src/components/follow_requests/follow_requests.js b/src/components/follow_requests/follow_requests.js
index 704a76c66..7dbecee53 100644
--- a/src/components/follow_requests/follow_requests.js
+++ b/src/components/follow_requests/follow_requests.js
@@ -2,13 +2,13 @@ import FollowRequestCard from '../follow_request_card/follow_request_card.vue'
const FollowRequests = {
components: {
- FollowRequestCard
+ FollowRequestCard,
},
computed: {
- requests () {
+ requests() {
return this.$store.state.api.followRequests
- }
- }
+ },
+ },
}
export default FollowRequests
diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js
index ffc866788..08d25d52d 100644
--- a/src/components/font_control/font_control.js
+++ b/src/components/font_control/font_control.js
@@ -1,35 +1,29 @@
-import Select from '../select/select.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Popover from 'src/components/popover/popover.vue'
import { useInterfaceStore } from 'src/stores/interface'
+import Select from '../select/select.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faExclamationTriangle,
+ faFont,
faKeyboard,
- faFont
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faExclamationTriangle,
- faKeyboard,
- faFont
-)
+library.add(faExclamationTriangle, faKeyboard, faFont)
export default {
components: {
Select,
Checkbox,
- Popover
+ Popover,
},
- props: [
- 'name', 'label', 'modelValue', 'fallback', 'options', 'no-inherit'
- ],
- mounted () {
+ props: ['name', 'label', 'modelValue', 'fallback', 'options', 'no-inherit'],
+ mounted() {
useInterfaceStore().queryLocalFonts()
},
emits: ['update:modelValue'],
- data () {
+ data() {
return {
manualEntry: false,
availableOptions: [
@@ -37,24 +31,24 @@ export default {
'serif',
'sans-serif',
'monospace',
- ...(this.options || [])
- ].filter(_ => _)
+ ...(this.options || []),
+ ].filter((_) => _),
}
},
methods: {
- toggleManualEntry () {
+ toggleManualEntry() {
this.manualEntry = !this.manualEntry
- }
+ },
},
computed: {
- present () {
+ present() {
return typeof this.modelValue !== 'undefined'
},
- localFontsList () {
+ localFontsList() {
return useInterfaceStore().localFonts
},
- localFontsSize () {
+ localFontsSize() {
return useInterfaceStore().localFonts?.length
- }
- }
+ },
+ },
}
diff --git a/src/components/friends_timeline/friends_timeline.js b/src/components/friends_timeline/friends_timeline.js
index 948b23a49..c0c032a8f 100644
--- a/src/components/friends_timeline/friends_timeline.js
+++ b/src/components/friends_timeline/friends_timeline.js
@@ -1,11 +1,14 @@
import Timeline from '../timeline/timeline.vue'
+
const FriendsTimeline = {
components: {
- Timeline
+ Timeline,
},
computed: {
- timeline () { return this.$store.state.statuses.timelines.friends }
- }
+ timeline() {
+ return this.$store.state.statuses.timelines.friends
+ },
+ },
}
export default FriendsTimeline
diff --git a/src/components/fun_text.style.js b/src/components/fun_text.style.js
index 2d3ac1549..eff88feb7 100644
--- a/src/components/fun_text.style.js
+++ b/src/components/fun_text.style.js
@@ -4,37 +4,37 @@ export default {
virtual: true,
variants: {
greentext: '.greentext',
- cyantext: '.cyantext'
+ cyantext: '.cyantext',
},
states: {
- faint: '.faint'
+ faint: '.faint',
},
defaultRules: [
{
directives: {
textColor: '--text',
- textAuto: 'preserve'
- }
+ textAuto: 'preserve',
+ },
},
{
state: ['faint'],
directives: {
- textOpacity: 0.5
- }
+ textOpacity: 0.5,
+ },
},
{
variant: 'greentext',
directives: {
textColor: '--cGreen',
- textAuto: 'preserve'
- }
+ textAuto: 'preserve',
+ },
},
{
variant: 'cyantext',
directives: {
textColor: '--cBlue',
- textAuto: 'preserve'
- }
- }
- ]
+ textAuto: 'preserve',
+ },
+ },
+ ],
}
diff --git a/src/components/gallery/gallery.js b/src/components/gallery/gallery.js
index 676c830b0..9934a7905 100644
--- a/src/components/gallery/gallery.js
+++ b/src/components/gallery/gallery.js
@@ -1,6 +1,7 @@
+import { set, sumBy } from 'lodash'
+
import { useMediaViewerStore } from 'src/stores/media_viewer'
import Attachment from '../attachment/attachment.vue'
-import { sumBy, set } from 'lodash'
const Gallery = {
props: [
@@ -17,52 +18,71 @@ const Gallery = {
'shiftUpAttachment',
'shiftDnAttachment',
'editAttachment',
- 'grid'
+ 'grid',
],
- data () {
+ data() {
return {
sizes: {},
- hidingLong: true
+ hidingLong: true,
}
},
components: { Attachment },
computed: {
- rows () {
+ rows() {
if (!this.attachments) {
return []
}
- const attachments = this.limit > 0
- ? this.attachments.slice(0, this.limit)
- : this.attachments
+ const attachments =
+ this.limit > 0
+ ? this.attachments.slice(0, this.limit)
+ : this.attachments
if (this.size === 'hide') {
- return attachments.map(item => ({ minimal: true, items: [item] }))
+ return attachments.map((item) => ({ minimal: true, items: [item] }))
}
const rows = this.grid
? [{ grid: true, items: attachments }]
- : attachments.reduce((acc, attachment, i) => {
- if (attachment.mimetype.includes('audio')) {
- return [...acc, { audio: true, items: [attachment] }, { items: [] }]
- }
- if (!(
- attachment.mimetype.includes('image') ||
- attachment.mimetype.includes('video') ||
- attachment.mimetype.includes('flash')
- )) {
- return [...acc, { minimal: true, items: [attachment] }, { items: [] }]
- }
- const maxPerRow = 3
- const attachmentsRemaining = this.attachments.length - i + 1
- const currentRow = acc[acc.length - 1].items
- currentRow.push(attachment)
- if (currentRow.length >= maxPerRow && attachmentsRemaining > maxPerRow) {
- return [...acc, { items: [] }]
- } else {
- return acc
- }
- }, [{ items: [] }]).filter(_ => _.items.length > 0)
+ : attachments
+ .reduce(
+ (acc, attachment, i) => {
+ if (attachment.mimetype.includes('audio')) {
+ return [
+ ...acc,
+ { audio: true, items: [attachment] },
+ { items: [] },
+ ]
+ }
+ if (
+ !(
+ attachment.mimetype.includes('image') ||
+ attachment.mimetype.includes('video') ||
+ attachment.mimetype.includes('flash')
+ )
+ ) {
+ return [
+ ...acc,
+ { minimal: true, items: [attachment] },
+ { items: [] },
+ ]
+ }
+ const maxPerRow = 3
+ const attachmentsRemaining = this.attachments.length - i + 1
+ const currentRow = acc[acc.length - 1].items
+ currentRow.push(attachment)
+ if (
+ currentRow.length >= maxPerRow &&
+ attachmentsRemaining > maxPerRow
+ ) {
+ return [...acc, { items: [] }]
+ } else {
+ return acc
+ }
+ },
+ [{ items: [] }],
+ )
+ .filter((_) => _.items.length > 0)
return rows
},
- attachmentsDimensionalScore () {
+ attachmentsDimensionalScore() {
return this.rows.reduce((acc, row) => {
let size = 0
if (row.minimal) {
@@ -75,7 +95,7 @@ const Gallery = {
return acc + size
}, 0)
},
- tooManyAttachments () {
+ tooManyAttachments() {
if (this.editable || this.size === 'small') {
return false
} else if (this.size === 'hide') {
@@ -83,38 +103,38 @@ const Gallery = {
} else {
return this.attachmentsDimensionalScore > 1
}
- }
+ },
},
methods: {
- onNaturalSizeLoad ({ id, width, height }) {
+ onNaturalSizeLoad({ id, width, height }) {
set(this.sizes, id, { width, height })
},
- rowStyle (row) {
+ rowStyle(row) {
if (row.audio) {
return { 'padding-bottom': '25%' } // fixed reduced height for audio
} else if (!row.minimal && !row.grid) {
- return { 'padding-bottom': `${(100 / (row.items.length + 0.6))}%` }
+ return { 'padding-bottom': `${100 / (row.items.length + 0.6)}%` }
}
},
- itemStyle (id, row) {
- const total = sumBy(row, item => this.getAspectRatio(item.id))
+ itemStyle(id, row) {
+ const total = sumBy(row, (item) => this.getAspectRatio(item.id))
return { flex: `${this.getAspectRatio(id) / total} 1 0%` }
},
- getAspectRatio (id) {
+ getAspectRatio(id) {
const size = this.sizes[id]
return size ? size.width / size.height : 1
},
- toggleHidingLong (event) {
+ toggleHidingLong(event) {
this.hidingLong = event
},
- openGallery () {
+ openGallery() {
useMediaViewerStore().setMedia(this.attachments)
useMediaViewerStore().setCurrentMedia(this.attachments[0])
},
- onMedia () {
+ onMedia() {
useMediaViewerStore().setMedia(this.attachments)
- }
- }
+ },
+ },
}
export default Gallery
diff --git a/src/components/global_notice_list/global_notice_list.js b/src/components/global_notice_list/global_notice_list.js
index cf14d1a07..4a2726d7b 100644
--- a/src/components/global_notice_list/global_notice_list.js
+++ b/src/components/global_notice_list/global_notice_list.js
@@ -1,24 +1,21 @@
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faTimes
-} from '@fortawesome/free-solid-svg-icons'
import { useInterfaceStore } from 'src/stores/interface'
-library.add(
- faTimes
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faTimes } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faTimes)
const GlobalNoticeList = {
computed: {
- notices () {
+ notices() {
return useInterfaceStore().globalNotices
- }
+ },
},
methods: {
- closeNotice (notice) {
+ closeNotice(notice) {
useInterfaceStore().removeGlobalNotice(notice)
- }
- }
+ },
+ },
}
export default GlobalNoticeList
diff --git a/src/components/hashtag_link/hashtag_link.js b/src/components/hashtag_link/hashtag_link.js
index a2433c2ab..09cfaf199 100644
--- a/src/components/hashtag_link/hashtag_link.js
+++ b/src/components/hashtag_link/hashtag_link.js
@@ -5,20 +5,20 @@ const HashtagLink = {
props: {
url: {
required: true,
- type: String
+ type: String,
},
content: {
required: true,
- type: String
+ type: String,
},
tag: {
required: false,
type: String,
- default: ''
- }
+ default: '',
+ },
},
methods: {
- onClick () {
+ onClick() {
const tag = this.tag || extractTagFromUrl(this.url)
if (tag) {
const link = this.generateTagLink(tag)
@@ -27,10 +27,10 @@ const HashtagLink = {
window.open(this.url, '_blank')
}
},
- generateTagLink (tag) {
+ generateTagLink(tag) {
return `/tag/${tag}`
- }
- }
+ },
+ },
}
export default HashtagLink
diff --git a/src/components/icon.style.js b/src/components/icon.style.js
index 4d30f389b..b13485c1b 100644
--- a/src/components/icon.style.js
+++ b/src/components/icon.style.js
@@ -7,8 +7,8 @@ export default {
component: 'Icon',
directives: {
textColor: '$blend(--stack 0.5 --parent--text)',
- textAuto: 'no-auto'
- }
- }
- ]
+ textAuto: 'no-auto',
+ },
+ },
+ ],
}
diff --git a/src/components/image_cropper/image_cropper.js b/src/components/image_cropper/image_cropper.js
index afca328e8..c8529c8e6 100644
--- a/src/components/image_cropper/image_cropper.js
+++ b/src/components/image_cropper/image_cropper.js
@@ -1,29 +1,26 @@
import 'cropperjs' // This adds all of the cropperjs's components into DOM
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faCircleNotch
-} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faCircleNotch
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faCircleNotch)
const ImageCropper = {
props: {
// Mime-types to accept, i.e. which filetypes to accept (.gif, .png, etc.)
mimes: {
type: String,
- default: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon'
+ default: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon',
},
// Fixed aspect-ratio for selection box
aspectRatio: {
- type: Number
- }
+ type: Number,
+ },
},
- data () {
+ data() {
return {
dataUrl: undefined,
- filename: undefined
+ filename: undefined,
}
},
emits: [
@@ -31,12 +28,12 @@ const ImageCropper = {
'close', // cropper is closed
],
methods: {
- destroy () {
+ destroy() {
this.$refs.input.value = ''
this.dataUrl = undefined
this.$emit('close')
},
- submit (cropping = true) {
+ submit(cropping = true) {
let cropperPromise
if (cropping) {
cropperPromise = this.$refs.cropperSelection.$toCanvas()
@@ -44,14 +41,14 @@ const ImageCropper = {
cropperPromise = Promise.resolve()
}
- cropperPromise.then(canvas => {
+ cropperPromise.then((canvas) => {
this.$emit('submit', { canvas, file: this.file })
})
},
- pickImage () {
+ pickImage() {
this.$refs.input.click()
},
- readFile () {
+ readFile() {
const fileInput = this.$refs.input
if (fileInput.files != null && fileInput.files[0] != null) {
this.file = fileInput.files[0]
@@ -66,10 +63,10 @@ const ImageCropper = {
},
inSelection(selection, maxSelection) {
return (
- selection.x >= maxSelection.x
- && selection.y >= maxSelection.y
- && (selection.x + selection.width) <= (maxSelection.x + maxSelection.width)
- && (selection.y + selection.height) <= (maxSelection.y + maxSelection.height)
+ selection.x >= maxSelection.x &&
+ selection.y >= maxSelection.y &&
+ selection.x + selection.width <= maxSelection.x + maxSelection.width &&
+ selection.y + selection.height <= maxSelection.y + maxSelection.height
)
},
onCropperSelectionChange(event) {
@@ -84,11 +81,11 @@ const ImageCropper = {
}
if (!this.inSelection(selection, maxSelection)) {
- event.preventDefault();
+ event.preventDefault()
}
- }
+ },
},
- mounted () {
+ mounted() {
// listen for input file changes
const fileInput = this.$refs.input
fileInput.addEventListener('change', this.readFile)
@@ -96,7 +93,7 @@ const ImageCropper = {
beforeUnmount: function () {
const fileInput = this.$refs.input
fileInput.removeEventListener('change', this.readFile)
- }
+ },
}
export default ImageCropper
diff --git a/src/components/importer/importer.js b/src/components/importer/importer.js
index da86a223c..0403cc944 100644
--- a/src/components/importer/importer.js
+++ b/src/components/importer/importer.js
@@ -1,49 +1,49 @@
import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faCircleNotch,
- faTimes
-} from '@fortawesome/free-solid-svg-icons'
+import { faCircleNotch, faTimes } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faCircleNotch,
- faTimes
-)
+library.add(faCircleNotch, faTimes)
const Importer = {
props: {
submitHandler: {
type: Function,
- required: true
+ required: true,
},
submitButtonLabel: { type: String },
successMessage: { type: String },
- errorMessage: { type: String }
+ errorMessage: { type: String },
},
- data () {
+ data() {
return {
file: null,
error: false,
success: false,
- submitting: false
+ submitting: false,
}
},
methods: {
- change () {
+ change() {
this.file = this.$refs.input.files[0]
},
- submit () {
+ submit() {
this.dismiss()
this.submitting = true
this.submitHandler(this.file)
- .then(() => { this.success = true })
- .catch(() => { this.error = true })
- .finally(() => { this.submitting = false })
+ .then(() => {
+ this.success = true
+ })
+ .catch(() => {
+ this.error = true
+ })
+ .finally(() => {
+ this.submitting = false
+ })
},
- dismiss () {
+ dismiss() {
this.success = false
this.error = false
- }
- }
+ },
+ },
}
export default Importer
diff --git a/src/components/input.style.js b/src/components/input.style.js
index 00f51cbf6..2663392fb 100644
--- a/src/components/input.style.js
+++ b/src/components/input.style.js
@@ -4,91 +4,96 @@ export default {
states: {
hover: ':is(:hover, :focus-visible):not(.disabled)',
focused: ':focus-within',
- disabled: '.disabled'
+ disabled: '.disabled',
},
variants: {
checkbox: '.-checkbox',
- radio: '.-radio'
+ radio: '.-radio',
},
- validInnerComponents: [
- 'Text',
- 'Icon'
- ],
+ validInnerComponents: ['Text', 'Icon'],
defaultRules: [
{
component: 'Root',
directives: {
- '--defaultInputBevel': 'shadow | $borderSide(#FFFFFF bottom 0.2), $borderSide(#000000 top 0.2), inset 0 0 2 #000000 / 0.15, 1 0 1 1 --text / 0.15, -1 0 1 1 --text / 0.15',
+ '--defaultInputBevel':
+ 'shadow | $borderSide(#FFFFFF bottom 0.2), $borderSide(#000000 top 0.2), inset 0 0 2 #000000 / 0.15, 1 0 1 1 --text / 0.15, -1 0 1 1 --text / 0.15',
'--defaultInputHoverGlow': 'shadow | 0 0 4 --text / 0.5',
- '--defaultInputFocusGlow': 'shadow | 0 0 4 4 --link / 0.5'
- }
+ '--defaultInputFocusGlow': 'shadow | 0 0 4 4 --link / 0.5',
+ },
},
{
variant: 'checkbox',
directives: {
- roundness: 1
- }
+ roundness: 1,
+ },
},
{
directives: {
'--font': 'generic | inherit',
background: '--fg, -5',
roundness: 3,
- shadow: [{
- x: 0,
- y: 0,
- blur: 2,
- spread: 0,
- color: '#000000',
- alpha: 1
- }, '--defaultInputBevel']
- }
+ shadow: [
+ {
+ x: 0,
+ y: 0,
+ blur: 2,
+ spread: 0,
+ color: '#000000',
+ alpha: 1,
+ },
+ '--defaultInputBevel',
+ ],
+ },
},
{
state: ['hover'],
directives: {
- shadow: ['--defaultInputHoverGlow', '--defaultInputBevel']
- }
+ shadow: ['--defaultInputHoverGlow', '--defaultInputBevel'],
+ },
},
{
state: ['focused'],
directives: {
- shadow: ['--defaultInputFocusGlow', '--defaultInputBevel']
- }
+ shadow: ['--defaultInputFocusGlow', '--defaultInputBevel'],
+ },
},
{
state: ['focused', 'hover'],
directives: {
- shadow: ['--defaultInputFocusGlow', '--defaultInputHoverGlow', '--defaultInputBevel']
- }
+ shadow: [
+ '--defaultInputFocusGlow',
+ '--defaultInputHoverGlow',
+ '--defaultInputBevel',
+ ],
+ },
},
{
state: ['disabled'],
directives: {
- background: '--parent'
- }
+ background: '--parent',
+ },
},
{
component: 'Text',
parent: {
component: 'Input',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
+ textOpacityMode: 'blend',
+ },
},
{
component: 'Icon',
parent: {
component: 'Input',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
- }
- ]
+ textOpacityMode: 'blend',
+ },
+ },
+ ],
}
diff --git a/src/components/instance_specific_panel/instance_specific_panel.js b/src/components/instance_specific_panel/instance_specific_panel.js
index 09e3d0557..eead52f40 100644
--- a/src/components/instance_specific_panel/instance_specific_panel.js
+++ b/src/components/instance_specific_panel/instance_specific_panel.js
@@ -1,9 +1,9 @@
const InstanceSpecificPanel = {
computed: {
- instanceSpecificPanelContent () {
+ instanceSpecificPanelContent() {
return this.$store.state.instance.instanceSpecificPanelContent
- }
- }
+ },
+ },
}
export default InstanceSpecificPanel
diff --git a/src/components/interactions/interactions.js b/src/components/interactions/interactions.js
index fc441b908..87e9e1b87 100644
--- a/src/components/interactions/interactions.js
+++ b/src/components/interactions/interactions.js
@@ -1,5 +1,5 @@
-import Notifications from '../notifications/notifications.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
+import Notifications from '../notifications/notifications.vue'
const tabModeDict = {
mentions: ['mention'],
@@ -8,26 +8,29 @@ const tabModeDict = {
follows: ['follow'],
reactions: ['pleroma:emoji_reaction'],
reports: ['pleroma:report'],
- moves: ['move']
+ moves: ['move'],
}
const Interactions = {
- data () {
+ data() {
return {
- allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
+ allowFollowingMove:
+ this.$store.state.users.currentUser.allow_following_move,
filterMode: tabModeDict.mentions,
- canSeeReports: this.$store.state.users.currentUser.privileges.includes('reports_manage_reports')
+ canSeeReports: this.$store.state.users.currentUser.privileges.includes(
+ 'reports_manage_reports',
+ ),
}
},
methods: {
- onModeSwitch (key) {
+ onModeSwitch(key) {
this.filterMode = tabModeDict[key]
- }
+ },
},
components: {
Notifications,
- TabSwitcher
- }
+ TabSwitcher,
+ },
}
export default Interactions
diff --git a/src/components/interface_language_switcher/interface_language_switcher.js b/src/components/interface_language_switcher/interface_language_switcher.js
index 721c19887..1cdedadd3 100644
--- a/src/components/interface_language_switcher/interface_language_switcher.js
+++ b/src/components/interface_language_switcher/interface_language_switcher.js
@@ -1,62 +1,63 @@
-import localeService from '../../services/locale/locale.service.js'
+import { v4 as uuidv4 } from 'uuid'
-import Select from '../select/select.vue'
import ProfileSettingIndicator from 'src/components/settings_modal/helpers/profile_setting_indicator.vue'
-
-import { v4 as uuidv4 } from 'uuid';
+import localeService from '../../services/locale/locale.service.js'
+import Select from '../select/select.vue'
export default {
components: {
Select,
- ProfileSettingIndicator
+ ProfileSettingIndicator,
},
props: {
// List of languages (or just one language)
modelValue: {
type: [Array, String],
- required: true
+ required: true,
},
// Is this setting stored in user profile (true) or elsewhere (false)
// Doesn't affect storage, just shows an icon if true
profile: {
type: Boolean,
- default: false
- }
+ default: false,
+ },
},
emits: ['update:modelValue'],
computed: {
- languages () {
+ languages() {
return localeService.languages
},
- uniqueId () {
- return uuidv4()
+ uniqueId() {
+ return uuidv4()
},
controlledLanguage: {
get: function () {
- return Array.isArray(this.modelValue) ? this.modelValue : [this.modelValue]
+ return Array.isArray(this.modelValue)
+ ? this.modelValue
+ : [this.modelValue]
},
set: function (val) {
this.$emit('update:modelValue', val)
- }
- }
+ },
+ },
},
methods: {
- getLanguageName (code) {
+ getLanguageName(code) {
return localeService.getLanguageName(code)
},
- addLanguage () {
+ addLanguage() {
this.controlledLanguage = [...this.controlledLanguage, '']
},
- setLanguageAt (index, val) {
+ setLanguageAt(index, val) {
const lang = [...this.controlledLanguage]
lang[index] = val
this.controlledLanguage = lang
},
- removeLanguageAt (index) {
+ removeLanguageAt(index) {
const lang = [...this.controlledLanguage]
lang.splice(index, 1)
this.controlledLanguage = lang
- }
- }
+ },
+ },
}
diff --git a/src/components/link-preview/link-preview.js b/src/components/link-preview/link-preview.js
index add7c5631..ac91f916d 100644
--- a/src/components/link-preview/link-preview.js
+++ b/src/components/link-preview/link-preview.js
@@ -2,37 +2,31 @@ import { mapGetters } from 'vuex'
const LinkPreview = {
name: 'LinkPreview',
- props: [
- 'card',
- 'size',
- 'nsfw'
- ],
- data () {
+ props: ['card', 'size', 'nsfw'],
+ data() {
return {
- imageLoaded: false
+ imageLoaded: false,
}
},
computed: {
- useImage () {
+ useImage() {
// Currently BE shoudn't give cards if tagged NSFW, this is a bit paranoid
// as it makes sure to hide the image if somehow NSFW tagged preview can
// exist.
return this.card.image && !this.censored && this.size !== 'hide'
},
- censored () {
+ censored() {
return this.nsfw && this.hideNsfwConfig
},
- useDescription () {
+ useDescription() {
return this.card.description && /\S/.test(this.card.description)
},
- hideNsfwConfig () {
+ hideNsfwConfig() {
return this.mergedConfig.hideNsfw
},
- ...mapGetters([
- 'mergedConfig'
- ])
+ ...mapGetters(['mergedConfig']),
},
- created () {
+ created() {
if (this.useImage) {
const newImg = new Image()
newImg.onload = () => {
@@ -40,7 +34,7 @@ const LinkPreview = {
}
newImg.src = this.card.image
}
- }
+ },
}
export default LinkPreview
diff --git a/src/components/link.style.js b/src/components/link.style.js
index d13cef338..141a1f023 100644
--- a/src/components/link.style.js
+++ b/src/components/link.style.js
@@ -3,22 +3,22 @@ export default {
selector: 'a',
virtual: true,
states: {
- faint: '.faint'
+ faint: '.faint',
},
defaultRules: [
{
component: 'Link',
directives: {
- textColor: '--link'
- }
+ textColor: '--link',
+ },
},
{
component: 'Link',
state: ['faint'],
directives: {
textOpacity: 0.5,
- textOpacityMode: 'fake'
- }
- }
- ]
+ textOpacityMode: 'fake',
+ },
+ },
+ ],
}
diff --git a/src/components/list/list.vue b/src/components/list/list.vue
index 5d2c49b3c..f34a5f073 100644
--- a/src/components/list/list.vue
+++ b/src/components/list/list.vue
@@ -29,20 +29,20 @@ export default {
props: {
items: {
type: Array,
- default: () => []
+ default: () => [],
},
getKey: {
type: Function,
- default: item => item.id
+ default: (item) => item.id,
},
getClass: {
type: Function,
- default: () => ''
+ default: () => '',
},
nonInteractive: {
type: Boolean,
- default: false
- }
- }
+ default: false,
+ },
+ },
}
diff --git a/src/components/lists/lists.js b/src/components/lists/lists.js
index 8dcb48b52..446178245 100644
--- a/src/components/lists/lists.js
+++ b/src/components/lists/lists.js
@@ -2,27 +2,27 @@ import { useListsStore } from 'src/stores/lists'
import ListsCard from '../lists_card/lists_card.vue'
const Lists = {
- data () {
+ data() {
return {
- isNew: false
+ isNew: false,
}
},
components: {
- ListsCard
+ ListsCard,
},
computed: {
- lists () {
+ lists() {
return useListsStore().allLists
- }
+ },
},
methods: {
- cancelNewList () {
+ cancelNewList() {
this.isNew = false
},
- newList () {
+ newList() {
this.isNew = true
- }
- }
+ },
+ },
}
export default Lists
diff --git a/src/components/lists_card/lists_card.js b/src/components/lists_card/lists_card.js
index b503caec4..81b811534 100644
--- a/src/components/lists_card/lists_card.js
+++ b/src/components/lists_card/lists_card.js
@@ -1,16 +1,10 @@
import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faEllipsisH
-} from '@fortawesome/free-solid-svg-icons'
+import { faEllipsisH } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faEllipsisH
-)
+library.add(faEllipsisH)
const ListsCard = {
- props: [
- 'list'
- ]
+ props: ['list'],
}
export default ListsCard
diff --git a/src/components/lists_edit/lists_edit.js b/src/components/lists_edit/lists_edit.js
index c62bf9769..64a2e942c 100644
--- a/src/components/lists_edit/lists_edit.js
+++ b/src/components/lists_edit/lists_edit.js
@@ -1,22 +1,18 @@
-import { mapState, mapGetters } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
-import BasicUserCard from '../basic_user_card/basic_user_card.vue'
-import ListsUserSearch from '../lists_user_search/lists_user_search.vue'
+import { mapGetters, mapState } from 'vuex'
+
import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
-import UserAvatar from '../user_avatar/user_avatar.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faSearch,
- faChevronLeft
-} from '@fortawesome/free-solid-svg-icons'
import { useInterfaceStore } from 'src/stores/interface'
import { useListsStore } from 'src/stores/lists'
+import BasicUserCard from '../basic_user_card/basic_user_card.vue'
+import ListsUserSearch from '../lists_user_search/lists_user_search.vue'
+import UserAvatar from '../user_avatar/user_avatar.vue'
-library.add(
- faSearch,
- faChevronLeft
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faChevronLeft, faSearch } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faSearch, faChevronLeft)
const ListsNew = {
components: {
@@ -24,9 +20,9 @@ const ListsNew = {
UserAvatar,
ListsUserSearch,
TabSwitcher,
- PanelLoading
+ PanelLoading,
},
- data () {
+ data() {
return {
title: '',
titleDraft: '',
@@ -35,46 +31,51 @@ const ListsNew = {
searchUserIds: [],
addedUserIds: new Set([]), // users we added from search, to undo
searchLoading: false,
- reallyDelete: false
+ reallyDelete: false,
}
},
- created () {
+ created() {
if (!this.id) return
- useListsStore().fetchList({ listId: this.id })
+ useListsStore()
+ .fetchList({ listId: this.id })
.then(() => {
this.title = this.findListTitle(this.id)
this.titleDraft = this.title
})
- useListsStore().fetchListAccounts({ listId: this.id })
+ useListsStore()
+ .fetchListAccounts({ listId: this.id })
.then(() => {
this.membersUserIds = this.findListAccounts(this.id)
- this.membersUserIds.forEach(userId => {
+ this.membersUserIds.forEach((userId) => {
this.$store.dispatch('fetchUserIfMissing', userId)
})
})
},
computed: {
- id () {
+ id() {
return this.$route.params.id
},
- membersUsers () {
+ membersUsers() {
return [...this.membersUserIds, ...this.addedUserIds]
- .map(userId => this.findUser(userId)).filter(user => user)
+ .map((userId) => this.findUser(userId))
+ .filter((user) => user)
},
- searchUsers () {
- return this.searchUserIds.map(userId => this.findUser(userId)).filter(user => user)
+ searchUsers() {
+ return this.searchUserIds
+ .map((userId) => this.findUser(userId))
+ .filter((user) => user)
},
...mapState({
- currentUser: state => state.users.currentUser
+ currentUser: (state) => state.users.currentUser,
}),
...mapPiniaState(useListsStore, ['findListTitle', 'findListAccounts']),
- ...mapGetters(['findUser'])
+ ...mapGetters(['findUser']),
},
methods: {
- onInput () {
+ onInput() {
this.search(this.query)
},
- toggleRemoveMember (user) {
+ toggleRemoveMember(user) {
if (this.removedUserIds.has(user.id)) {
this.id && this.addUser(user)
this.removedUserIds.delete(user.id)
@@ -83,7 +84,7 @@ const ListsNew = {
this.removedUserIds.add(user.id)
}
},
- toggleAddFromSearch (user) {
+ toggleAddFromSearch(user) {
if (this.addedUserIds.has(user.id)) {
this.id && this.removeUser(user.id)
this.addedUserIds.delete(user.id)
@@ -92,37 +93,41 @@ const ListsNew = {
this.addedUserIds.add(user.id)
}
},
- isRemoved (user) {
+ isRemoved(user) {
return this.removedUserIds.has(user.id)
},
- isAdded (user) {
+ isAdded(user) {
return this.addedUserIds.has(user.id)
},
- addUser (user) {
+ addUser(user) {
useListsStore().addListAccount({ accountId: user.id, listId: this.id })
},
- removeUser (userId) {
+ removeUser(userId) {
useListsStore().removeListAccount({ accountId: userId, listId: this.id })
},
- onSearchLoading () {
+ onSearchLoading() {
this.searchLoading = true
},
- onSearchLoadingDone () {
+ onSearchLoadingDone() {
this.searchLoading = false
},
- onSearchResults (results) {
+ onSearchResults(results) {
this.searchLoading = false
this.searchUserIds = results
},
- updateListTitle () {
+ updateListTitle() {
useListsStore().setList({ listId: this.id, title: this.titleDraft })
this.title = this.findListTitle(this.id)
},
- createList () {
- useListsStore().createList({ title: this.titleDraft })
+ createList() {
+ useListsStore()
+ .createList({ title: this.titleDraft })
.then((list) => {
return useListsStore()
- .setListAccounts({ listId: list.id, accountIds: [...this.addedUserIds] })
+ .setListAccounts({
+ listId: list.id,
+ accountIds: [...this.addedUserIds],
+ })
.then(() => list.id)
})
.then((listId) => {
@@ -132,15 +137,15 @@ const ListsNew = {
useInterfaceStore().pushGlobalNotice({
messageKey: 'lists.error',
messageArgs: [e.message],
- level: 'error'
+ level: 'error',
})
})
},
- deleteList () {
+ deleteList() {
useListsStore().deleteList({ listId: this.id })
this.$router.push({ name: 'lists' })
- }
- }
+ },
+ },
}
export default ListsNew
diff --git a/src/components/lists_menu/lists_menu_content.js b/src/components/lists_menu/lists_menu_content.js
index 726fd5fc4..7574c4c3f 100644
--- a/src/components/lists_menu/lists_menu_content.js
+++ b/src/components/lists_menu/lists_menu_content.js
@@ -1,26 +1,25 @@
-import { mapState } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
-import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
+import { mapState } from 'vuex'
+
import { getListEntries } from 'src/components/navigation/filter.js'
+import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
import { useListsStore } from 'src/stores/lists'
export const ListsMenuContent = {
- props: [
- 'showPin'
- ],
+ props: ['showPin'],
components: {
- NavigationEntry
+ NavigationEntry,
},
computed: {
...mapPiniaState(useListsStore, {
- lists: getListEntries
+ lists: getListEntries,
}),
...mapState({
- currentUser: state => state.users.currentUser,
- privateMode: state => state.instance.private,
- federating: state => state.instance.federating
- })
- }
+ currentUser: (state) => state.users.currentUser,
+ privateMode: (state) => state.instance.private,
+ federating: (state) => state.instance.federating,
+ }),
+ },
}
export default ListsMenuContent
diff --git a/src/components/lists_timeline/lists_timeline.js b/src/components/lists_timeline/lists_timeline.js
index eae82a867..ae1554eb6 100644
--- a/src/components/lists_timeline/lists_timeline.js
+++ b/src/components/lists_timeline/lists_timeline.js
@@ -1,16 +1,19 @@
import { useListsStore } from 'src/stores/lists'
import Timeline from '../timeline/timeline.vue'
+
const ListsTimeline = {
- data () {
+ data() {
return {
- listId: null
+ listId: null,
}
},
components: {
- Timeline
+ Timeline,
},
computed: {
- timeline () { return this.$store.state.statuses.timelines.list }
+ timeline() {
+ return this.$store.state.statuses.timelines.list
+ },
},
watch: {
$route: function (route) {
@@ -19,19 +22,25 @@ const ListsTimeline = {
this.$store.dispatch('stopFetchingTimeline', 'list')
this.$store.commit('clearTimeline', { timeline: 'list' })
useListsStore().fetchList({ listId: this.listId })
- this.$store.dispatch('startFetchingTimeline', { timeline: 'list', listId: this.listId })
+ this.$store.dispatch('startFetchingTimeline', {
+ timeline: 'list',
+ listId: this.listId,
+ })
}
- }
+ },
},
- created () {
+ created() {
this.listId = this.$route.params.id
useListsStore().fetchList({ listId: this.listId })
- this.$store.dispatch('startFetchingTimeline', { timeline: 'list', listId: this.listId })
+ this.$store.dispatch('startFetchingTimeline', {
+ timeline: 'list',
+ listId: this.listId,
+ })
},
- unmounted () {
+ unmounted() {
this.$store.dispatch('stopFetchingTimeline', 'list')
this.$store.commit('clearTimeline', { timeline: 'list' })
- }
+ },
}
export default ListsTimeline
diff --git a/src/components/lists_user_search/lists_user_search.js b/src/components/lists_user_search/lists_user_search.js
index c92ec0eee..699e6c156 100644
--- a/src/components/lists_user_search/lists_user_search.js
+++ b/src/components/lists_user_search/lists_user_search.js
@@ -1,33 +1,29 @@
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faSearch,
- faChevronLeft
-} from '@fortawesome/free-solid-svg-icons'
import { debounce } from 'lodash'
+
import Checkbox from '../checkbox/checkbox.vue'
-library.add(
- faSearch,
- faChevronLeft
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faChevronLeft, faSearch } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faSearch, faChevronLeft)
const ListsUserSearch = {
components: {
- Checkbox
+ Checkbox,
},
emits: ['loading', 'loadingDone', 'results'],
- data () {
+ data() {
return {
loading: false,
query: '',
- followingOnly: true
+ followingOnly: true,
}
},
methods: {
onInput: debounce(function () {
this.search(this.query)
}, 2000),
- search (query) {
+ search(query) {
if (!query) {
this.loading = false
return
@@ -36,16 +32,25 @@ const ListsUserSearch = {
this.loading = true
this.$emit('loading')
this.userIds = []
- this.$store.dispatch('search', { q: query, resolve: true, type: 'accounts', following: this.followingOnly })
- .then(data => {
- this.$emit('results', data.accounts.map(a => a.id))
+ this.$store
+ .dispatch('search', {
+ q: query,
+ resolve: true,
+ type: 'accounts',
+ following: this.followingOnly,
+ })
+ .then((data) => {
+ this.$emit(
+ 'results',
+ data.accounts.map((a) => a.id),
+ )
})
.finally(() => {
this.loading = false
this.$emit('loadingDone')
})
- }
- }
+ },
+ },
}
export default ListsUserSearch
diff --git a/src/components/login_form/login_form.js b/src/components/login_form/login_form.js
index 9566aa903..7c43923c9 100644
--- a/src/components/login_form/login_form.js
+++ b/src/components/login_form/login_form.js
@@ -1,56 +1,61 @@
+import { mapActions, mapState as mapPiniaState, mapStores } from 'pinia'
import { mapState } from 'vuex'
-import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia'
-import oauthApi from '../../services/new_api/oauth.js'
-import { useOAuthStore } from 'src/stores/oauth.js'
-import { useAuthFlowStore } from 'src/stores/auth_flow.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faTimes
-} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faTimes
-)
+import { useAuthFlowStore } from 'src/stores/auth_flow.js'
+import { useOAuthStore } from 'src/stores/oauth.js'
+import oauthApi from '../../services/new_api/oauth.js'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faTimes } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faTimes)
const LoginForm = {
data: () => ({
user: {},
- error: false
+ error: false,
}),
computed: {
- isPasswordAuth () { return this.requiredPassword },
- isTokenAuth () { return this.requiredToken },
+ isPasswordAuth() {
+ return this.requiredPassword
+ },
+ isTokenAuth() {
+ return this.requiredToken
+ },
...mapStores(useOAuthStore),
...mapState({
- registrationOpen: state => state.instance.registrationOpen,
- instance: state => state.instance,
- loggingIn: state => state.users.loggingIn,
+ registrationOpen: (state) => state.instance.registrationOpen,
+ instance: (state) => state.instance,
+ loggingIn: (state) => state.users.loggingIn,
}),
- ...mapPiniaState(useAuthFlowStore, ['requiredPassword', 'requiredToken', 'requiredMFA'])
+ ...mapPiniaState(useAuthFlowStore, [
+ 'requiredPassword',
+ 'requiredToken',
+ 'requiredMFA',
+ ]),
},
methods: {
...mapActions(useAuthFlowStore, ['requireMFA', 'login']),
- submit () {
+ submit() {
this.isTokenAuth ? this.submitToken() : this.submitPassword()
},
- submitToken () {
+ submitToken() {
const data = {
instance: this.instance.server,
- commit: this.$store.commit
+ commit: this.$store.commit,
}
// NOTE: we do not really need the app token, but obtaining a token and
// calling verify_credentials is the only way to ensure the app still works.
- this.oauthStore.ensureAppToken()
- .then(() => {
- const app = {
- clientId: this.oauthStore.clientId,
- clientSecret: this.oauthStore.clientSecret,
- }
- oauthApi.login({ ...app, ...data })
- })
+ this.oauthStore.ensureAppToken().then(() => {
+ const app = {
+ clientId: this.oauthStore.clientId,
+ clientSecret: this.oauthStore.clientSecret,
+ }
+ oauthApi.login({ ...app, ...data })
+ })
},
- submitPassword () {
+ submitPassword() {
this.error = false
// NOTE: we do not really need the app token, but obtaining a token and
@@ -61,38 +66,43 @@ const LoginForm = {
clientSecret: this.oauthStore.clientSecret,
}
- oauthApi.getTokenWithCredentials(
- {
+ oauthApi
+ .getTokenWithCredentials({
...app,
instance: this.instance.server,
username: this.user.username,
- password: this.user.password
- }
- ).then((result) => {
- if (result.error) {
- if (result.error === 'mfa_required') {
- this.requireMFA({ settings: result })
- } else if (result.identifier === 'password_reset_required') {
- this.$router.push({ name: 'password-reset', params: { passwordResetRequested: true } })
- } else {
- this.error = result.error
- this.focusOnPasswordInput()
- }
- return
- }
- this.login(result).then(() => {
- this.$router.push({ name: 'friends' })
+ password: this.user.password,
+ })
+ .then((result) => {
+ if (result.error) {
+ if (result.error === 'mfa_required') {
+ this.requireMFA({ settings: result })
+ } else if (result.identifier === 'password_reset_required') {
+ this.$router.push({
+ name: 'password-reset',
+ params: { passwordResetRequested: true },
+ })
+ } else {
+ this.error = result.error
+ this.focusOnPasswordInput()
+ }
+ return
+ }
+ this.login(result).then(() => {
+ this.$router.push({ name: 'friends' })
+ })
})
- })
})
},
- clearError () { this.error = false },
- focusOnPasswordInput () {
+ clearError() {
+ this.error = false
+ },
+ focusOnPasswordInput() {
const passwordInput = this.$refs.passwordInput
passwordInput.focus()
passwordInput.setSelectionRange(0, passwordInput.value.length)
- }
- }
+ },
+ },
}
export default LoginForm
diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js
index 9a57f8250..6199a6e32 100644
--- a/src/components/media_modal/media_modal.js
+++ b/src/components/media_modal/media_modal.js
@@ -1,26 +1,22 @@
-import StillImage from '../still-image/still-image.vue'
-import VideoAttachment from '../video_attachment/video_attachment.vue'
+import Flash from 'src/components/flash/flash.vue'
+import { useMediaViewerStore } from 'src/stores/media_viewer'
+import fileTypeService from '../../services/file_type/file_type.service.js'
+import GestureService from '../../services/gesture_service/gesture_service'
import Modal from '../modal/modal.vue'
import PinchZoom from '../pinch_zoom/pinch_zoom.vue'
+import StillImage from '../still-image/still-image.vue'
import SwipeClick from '../swipe_click/swipe_click.vue'
-import GestureService from '../../services/gesture_service/gesture_service'
-import Flash from 'src/components/flash/flash.vue'
-import fileTypeService from '../../services/file_type/file_type.service.js'
+import VideoAttachment from '../video_attachment/video_attachment.vue'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faChevronLeft,
faChevronRight,
faCircleNotch,
- faTimes
+ faTimes,
} from '@fortawesome/free-solid-svg-icons'
-import { useMediaViewerStore } from 'src/stores/media_viewer'
-library.add(
- faChevronLeft,
- faChevronRight,
- faCircleNotch,
- faTimes
-)
+library.add(faChevronLeft, faChevronRight, faCircleNotch, faTimes)
const MediaModal = {
components: {
@@ -29,9 +25,9 @@ const MediaModal = {
PinchZoom,
SwipeClick,
Modal,
- Flash
+ Flash,
},
- data () {
+ data() {
return {
loading: false,
swipeDirection: GestureService.DIRECTION_LEFT,
@@ -40,42 +36,42 @@ const MediaModal = {
return window.innerWidth * considerableMoveRatio
},
pinchZoomMinScale: 1,
- pinchZoomScaleResetLimit: 1.2
+ pinchZoomScaleResetLimit: 1.2,
}
},
computed: {
- showing () {
+ showing() {
return useMediaViewerStore().activated
},
- media () {
+ media() {
return useMediaViewerStore().media
},
- description () {
+ description() {
return this.currentMedia.description
},
- currentIndex () {
+ currentIndex() {
return useMediaViewerStore().currentIndex
},
- currentMedia () {
+ currentMedia() {
return this.media[this.currentIndex]
},
- canNavigate () {
+ canNavigate() {
return this.media.length > 1
},
- type () {
+ type() {
return this.currentMedia ? this.getType(this.currentMedia) : null
},
- swipeDisableClickThreshold () {
+ swipeDisableClickThreshold() {
// If there is only one media, allow more mouse movements to close the modal
// because there is less chance that the user wants to switch to another image
- return () => this.canNavigate ? 1 : 30
- }
+ return () => (this.canNavigate ? 1 : 30)
+ },
},
methods: {
- getType (media) {
+ getType(media) {
return fileTypeService.fileType(media.mimetype)
},
- hide () {
+ hide() {
// HACK: Closing immediately via a touch will cause the click
// to be processed on the content below the overlay
const transitionTime = 100 // ms
@@ -83,7 +79,7 @@ const MediaModal = {
useMediaViewerStore().closeMediaViewer()
}, transitionTime)
},
- hideIfNotSwiped (event) {
+ hideIfNotSwiped(event) {
// If we have swiped over SwipeClick, do not trigger hide
const comp = this.$refs.swipeClick
if (!comp) {
@@ -92,9 +88,12 @@ const MediaModal = {
comp.$gesture.click(event)
}
},
- goPrev () {
+ goPrev() {
if (this.canNavigate) {
- const prevIndex = this.currentIndex === 0 ? this.media.length - 1 : (this.currentIndex - 1)
+ const prevIndex =
+ this.currentIndex === 0
+ ? this.media.length - 1
+ : this.currentIndex - 1
const newMedia = this.media[prevIndex]
if (this.getType(newMedia) === 'image') {
this.loading = true
@@ -102,9 +101,12 @@ const MediaModal = {
useMediaViewerStore().setCurrentMedia(newMedia)
}
},
- goNext () {
+ goNext() {
if (this.canNavigate) {
- const nextIndex = this.currentIndex === this.media.length - 1 ? 0 : (this.currentIndex + 1)
+ const nextIndex =
+ this.currentIndex === this.media.length - 1
+ ? 0
+ : this.currentIndex + 1
const newMedia = this.media[nextIndex]
if (this.getType(newMedia) === 'image') {
this.loading = true
@@ -112,13 +114,13 @@ const MediaModal = {
useMediaViewerStore().setCurrentMedia(newMedia)
}
},
- onImageLoaded () {
+ onImageLoaded() {
this.loading = false
},
- handleSwipePreview (offsets) {
+ handleSwipePreview(offsets) {
this.$refs.pinchZoom.setTransform({ scale: 1, x: offsets[0], y: 0 })
},
- handleSwipeEnd (sign) {
+ handleSwipeEnd(sign) {
this.$refs.pinchZoom.setTransform({ scale: 1, x: 0, y: 0 })
if (sign > 0) {
this.goNext()
@@ -126,33 +128,36 @@ const MediaModal = {
this.goPrev()
}
},
- handleKeyupEvent (e) {
- if (this.showing && e.keyCode === 27) { // escape
+ handleKeyupEvent(e) {
+ if (this.showing && e.keyCode === 27) {
+ // escape
this.hide()
}
},
- handleKeydownEvent (e) {
+ handleKeydownEvent(e) {
if (!this.showing) {
return
}
- if (e.keyCode === 39) { // arrow right
+ if (e.keyCode === 39) {
+ // arrow right
this.goNext()
- } else if (e.keyCode === 37) { // arrow left
+ } else if (e.keyCode === 37) {
+ // arrow left
this.goPrev()
}
- }
+ },
},
- mounted () {
+ mounted() {
window.addEventListener('popstate', this.hide)
document.addEventListener('keyup', this.handleKeyupEvent)
document.addEventListener('keydown', this.handleKeydownEvent)
},
- unmounted () {
+ unmounted() {
window.removeEventListener('popstate', this.hide)
document.removeEventListener('keyup', this.handleKeyupEvent)
document.removeEventListener('keydown', this.handleKeydownEvent)
- }
+ },
}
export default MediaModal
diff --git a/src/components/media_upload/media_upload.js b/src/components/media_upload/media_upload.js
index f2cbfc405..8dc3d6c65 100644
--- a/src/components/media_upload/media_upload.js
+++ b/src/components/media_upload/media_upload.js
@@ -1,34 +1,32 @@
/* eslint-env browser */
-import statusPosterService from '../../services/status_poster/status_poster.service.js'
+
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
+import statusPosterService from '../../services/status_poster/status_poster.service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
-import { faUpload, faCircleNotch } from '@fortawesome/free-solid-svg-icons'
+import { faCircleNotch, faUpload } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faUpload,
- faCircleNotch
-)
+library.add(faUpload, faCircleNotch)
const mediaUpload = {
- data () {
+ data() {
return {
uploadCount: 0,
- uploadReady: true
+ uploadReady: true,
}
},
computed: {
- uploading () {
+ uploading() {
return this.uploadCount > 0
- }
+ },
},
methods: {
- onClick () {
+ onClick() {
if (this.uploadReady) {
this.$refs.input.click()
}
},
- async resizeImage (file) {
+ async resizeImage(file) {
// Skip if not an image or if it's a GIF
if (!file.type.startsWith('image/') || file.type === 'image/gif') {
return file
@@ -74,46 +72,67 @@ const mediaUpload = {
// Check WebP support by trying to create a WebP canvas
const testCanvas = document.createElement('canvas')
- const supportsWebP = testCanvas.toDataURL('image/webp').startsWith('data:image/webp')
+ const supportsWebP = testCanvas
+ .toDataURL('image/webp')
+ .startsWith('data:image/webp')
// Convert to WebP if supported and alwaysUseJpeg is false, otherwise JPEG
- const type = (!this.$store.getters.mergedConfig.alwaysUseJpeg && supportsWebP) ? 'image/webp' : 'image/jpeg'
+ const type =
+ !this.$store.getters.mergedConfig.alwaysUseJpeg && supportsWebP
+ ? 'image/webp'
+ : 'image/jpeg'
const extension = type === 'image/webp' ? '.webp' : '.jpg'
// Remove the original extension and add new one
const newFileName = file.name.replace(/\.[^/.]+$/, '') + extension
- canvas.toBlob((blob) => {
- resolve(new File([blob], newFileName, {
- type,
- lastModified: Date.now()
- }))
- }, type, 0.85)
+ canvas.toBlob(
+ (blob) => {
+ resolve(
+ new File([blob], newFileName, {
+ type,
+ lastModified: Date.now(),
+ }),
+ )
+ },
+ type,
+ 0.85,
+ )
}
img.src = URL.createObjectURL(file)
})
},
- async isAnimatedPng (file) {
+ async isAnimatedPng(file) {
const buffer = await file.arrayBuffer()
const view = new Uint8Array(buffer)
// Look for animated PNG chunks (acTL)
for (let i = 0; i < view.length - 8; i++) {
- if (view[i] === 0x61 && // a
- view[i + 1] === 0x63 && // c
- view[i + 2] === 0x54 && // T
- view[i + 3] === 0x4C) { // L
+ if (
+ view[i] === 0x61 && // a
+ view[i + 1] === 0x63 && // c
+ view[i + 2] === 0x54 && // T
+ view[i + 3] === 0x4c
+ ) {
+ // L
return true
}
}
return false
},
- async uploadFile (file) {
+ async uploadFile(file) {
const self = this
const store = this.$store
if (file.size > store.state.instance.uploadlimit) {
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
- const allowedsize = fileSizeFormatService.fileSizeFormat(store.state.instance.uploadlimit)
- self.$emit('upload-failed', 'file_too_big', { filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit })
+ const allowedsize = fileSizeFormatService.fileSizeFormat(
+ store.state.instance.uploadlimit,
+ )
+ self.$emit('upload-failed', 'file_too_big', {
+ filesize: filesize.num,
+ filesizeunit: filesize.unit,
+ allowedsize: allowedsize.num,
+ allowedsizeunit: allowedsize.unit,
+ })
return
}
@@ -125,36 +144,38 @@ const mediaUpload = {
self.$emit('uploading')
self.uploadCount++
- statusPosterService.uploadMedia({ store, formData })
- .then((fileData) => {
+ statusPosterService.uploadMedia({ store, formData }).then(
+ (fileData) => {
self.$emit('uploaded', fileData)
self.decreaseUploadCount()
- }, (error) => {
+ },
+ (error) => {
console.error('Error uploading file', error)
self.$emit('upload-failed', 'default')
self.decreaseUploadCount()
- })
+ },
+ )
},
- decreaseUploadCount () {
+ decreaseUploadCount() {
this.uploadCount--
if (this.uploadCount === 0) {
this.$emit('all-uploaded')
}
},
- clearFile () {
+ clearFile() {
this.uploadReady = false
this.$nextTick(() => {
this.uploadReady = true
})
},
- multiUpload (files) {
+ multiUpload(files) {
for (const file of files) {
this.uploadFile(file)
}
},
- change ({ target }) {
+ change({ target }) {
this.multiUpload(target.files)
- }
+ },
},
props: {
dropFiles: Object,
@@ -162,16 +183,16 @@ const mediaUpload = {
normalButton: Boolean,
acceptTypes: {
type: String,
- default: '*/*'
- }
+ default: '*/*',
+ },
},
watch: {
dropFiles: function (fileInfos) {
if (!this.uploading) {
this.multiUpload(fileInfos)
}
- }
- }
+ },
+ },
}
export default mediaUpload
diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index ca5c24618..4c211b5e9 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -1,155 +1,165 @@
-import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
-import { mapGetters, mapState } from 'vuex'
-import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
-import UserAvatar from '../user_avatar/user_avatar.vue'
-import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
import { defineAsyncComponent } from 'vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faAt
-} from '@fortawesome/free-solid-svg-icons'
+import { mapGetters, mapState } from 'vuex'
-library.add(
- faAt
-)
+import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
+import {
+ highlightClass,
+ highlightStyle,
+} from '../../services/user_highlighter/user_highlighter.js'
+import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
+import UserAvatar from '../user_avatar/user_avatar.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faAt } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faAt)
const MentionLink = {
name: 'MentionLink',
components: {
UserAvatar,
UnicodeDomainIndicator,
- UserPopover: defineAsyncComponent(() => import('../user_popover/user_popover.vue'))
+ UserPopover: defineAsyncComponent(
+ () => import('../user_popover/user_popover.vue'),
+ ),
},
props: {
url: {
required: true,
- type: String
+ type: String,
},
content: {
required: true,
- type: String
+ type: String,
},
userId: {
required: false,
- type: String
+ type: String,
},
userScreenName: {
required: false,
- type: String
- }
+ type: String,
+ },
},
- data () {
+ data() {
return {
- hasSelection: false
+ hasSelection: false,
}
},
methods: {
- onClick () {
+ onClick() {
if (this.shouldShowTooltip) return
const link = generateProfileLink(
this.userId || this.user.id,
- this.userScreenName || this.user.screen_name
+ this.userScreenName || this.user.screen_name,
)
this.$router.push(link)
},
- handleSelection () {
+ handleSelection() {
if (this.$refs.full) {
- this.hasSelection = document.getSelection().containsNode(this.$refs.full, true)
+ this.hasSelection = document
+ .getSelection()
+ .containsNode(this.$refs.full, true)
}
- }
+ },
},
- mounted () {
+ mounted() {
document.addEventListener('selectionchange', this.handleSelection)
},
- unmounted () {
+ unmounted() {
document.removeEventListener('selectionchange', this.handleSelection)
},
computed: {
- user () {
- return this.url && this.$store && this.$store.getters.findUserByUrl(this.url)
+ user() {
+ return (
+ this.url && this.$store && this.$store.getters.findUserByUrl(this.url)
+ )
},
- isYou () {
+ isYou() {
// FIXME why user !== currentUser???
return this.user && this.user.id === this.currentUser.id
},
- userName () {
+ userName() {
return this.user && this.userNameFullUi.split('@')[0]
},
- serverName () {
+ serverName() {
// XXX assumed that domain does not contain @
- return this.user && (this.userNameFullUi.split('@')[1] || this.$store.getters.instanceDomain)
+ return (
+ this.user &&
+ (this.userNameFullUi.split('@')[1] ||
+ this.$store.getters.instanceDomain)
+ )
},
- userNameFull () {
+ userNameFull() {
return this.user && this.user.screen_name
},
- userNameFullUi () {
+ userNameFullUi() {
return this.user && this.user.screen_name_ui
},
- highlight () {
+ highlight() {
return this.user && this.mergedConfig.highlight[this.user.screen_name]
},
- highlightType () {
- return this.highlight && ('-' + this.highlight.type)
+ highlightType() {
+ return this.highlight && '-' + this.highlight.type
},
- highlightClass () {
+ highlightClass() {
if (this.highlight) return highlightClass(this.user)
},
- style () {
+ style() {
if (this.highlight) {
- /* eslint-disable no-unused-vars */
const {
backgroundColor,
backgroundPosition,
backgroundImage,
...rest
} = highlightStyle(this.highlight)
- /* eslint-enable no-unused-vars */
return rest
}
},
- classnames () {
+ classnames() {
return [
{
'-you': this.isYou && this.shouldBoldenYou,
'-highlighted': this.highlight,
- '-has-selection': this.hasSelection
+ '-has-selection': this.hasSelection,
},
- this.highlightType
+ this.highlightType,
]
},
- isRemote () {
+ isRemote() {
return this.userName !== this.userNameFull
},
- shouldShowFullUserName () {
+ shouldShowFullUserName() {
const conf = this.mergedConfig.mentionLinkDisplay
if (conf === 'short') {
return false
} else if (conf === 'full') {
return true
- } else { // full_for_remote
+ } else {
+ // full_for_remote
return this.isRemote
}
},
- shouldShowTooltip () {
+ shouldShowTooltip() {
return this.mergedConfig.mentionLinkShowTooltip
},
- shouldShowAvatar () {
+ shouldShowAvatar() {
return this.mergedConfig.mentionLinkShowAvatar
},
- shouldShowYous () {
+ shouldShowYous() {
return this.mergedConfig.mentionLinkShowYous
},
- shouldBoldenYou () {
+ shouldBoldenYou() {
return this.mergedConfig.mentionLinkBoldenYou
},
- shouldFadeDomain () {
+ shouldFadeDomain() {
return this.mergedConfig.mentionLinkFadeDomain
},
...mapGetters(['mergedConfig']),
...mapState({
- currentUser: state => state.users.currentUser
- })
- }
+ currentUser: (state) => state.users.currentUser,
+ }),
+ },
}
export default MentionLink
diff --git a/src/components/mentions/mentions.js b/src/components/mentions/mentions.js
index 841d5aa48..10167ac77 100644
--- a/src/components/mentions/mentions.js
+++ b/src/components/mentions/mentions.js
@@ -2,13 +2,13 @@ import Timeline from '../timeline/timeline.vue'
const Mentions = {
computed: {
- timeline () {
+ timeline() {
return this.$store.state.statuses.timelines.mentions
- }
+ },
},
components: {
- Timeline
- }
+ Timeline,
+ },
}
export default Mentions
diff --git a/src/components/mentions_line/mentions_line.js b/src/components/mentions_line/mentions_line.js
index a4a0c7246..e6aa392a0 100644
--- a/src/components/mentions_line/mentions_line.js
+++ b/src/components/mentions_line/mentions_line.js
@@ -1,6 +1,7 @@
-import MentionLink from 'src/components/mention_link/mention_link.vue'
import { mapGetters } from 'vuex'
+import MentionLink from 'src/components/mention_link/mention_link.vue'
+
export const MENTIONS_LIMIT = 5
const MentionsLine = {
@@ -8,30 +9,30 @@ const MentionsLine = {
props: {
mentions: {
required: true,
- type: Array
- }
+ type: Array,
+ },
},
data: () => ({ expanded: false }),
components: {
- MentionLink
+ MentionLink,
},
computed: {
- mentionsComputed () {
+ mentionsComputed() {
return this.mentions.slice(0, MENTIONS_LIMIT)
},
- extraMentions () {
+ extraMentions() {
return this.mentions.slice(MENTIONS_LIMIT)
},
- manyMentions () {
+ manyMentions() {
return this.extraMentions.length > 0
},
- ...mapGetters(['mergedConfig'])
+ ...mapGetters(['mergedConfig']),
},
methods: {
- toggleShowMore () {
+ toggleShowMore() {
this.expanded = !this.expanded
- }
- }
+ },
+ },
}
export default MentionsLine
diff --git a/src/components/menu_item.style.js b/src/components/menu_item.style.js
index 859932062..a5567b49b 100644
--- a/src/components/menu_item.style.js
+++ b/src/components/menu_item.style.js
@@ -1,109 +1,105 @@
export default {
name: 'MenuItem',
selector: '.menu-item',
- validInnerComponents: [
- 'Text',
- 'Icon',
- 'Border'
- ],
+ validInnerComponents: ['Text', 'Icon', 'Border'],
states: {
hover: ':is(:hover, :focus-visible, :has(:focus-visible)):not(.disabled)',
active: '.-active',
- disabled: '.disabled'
+ disabled: '.disabled',
},
defaultRules: [
{
directives: {
background: '--bg',
- opacity: 0
- }
+ opacity: 0,
+ },
},
{
state: ['hover'],
directives: {
background: '$mod(--bg 5)',
- opacity: 1
- }
+ opacity: 1,
+ },
},
{
state: ['active'],
directives: {
background: '$mod(--bg 10)',
- opacity: 1
- }
+ opacity: 1,
+ },
},
{
state: ['active', 'hover'],
directives: {
background: '$mod(--bg 15)',
- opacity: 1
- }
+ opacity: 1,
+ },
},
{
component: 'Text',
parent: {
component: 'MenuItem',
- state: ['hover']
+ state: ['hover'],
},
directives: {
textColor: '--link',
- textAuto: 'no-preserve'
- }
+ textAuto: 'no-preserve',
+ },
},
{
component: 'Text',
parent: {
component: 'MenuItem',
- state: ['active']
+ state: ['active'],
},
directives: {
textColor: '--link',
- textAuto: 'no-preserve'
- }
+ textAuto: 'no-preserve',
+ },
},
{
component: 'Icon',
parent: {
component: 'MenuItem',
- state: ['active']
+ state: ['active'],
},
directives: {
textColor: '--link',
- textAuto: 'no-preserve'
- }
+ textAuto: 'no-preserve',
+ },
},
{
component: 'Icon',
parent: {
component: 'MenuItem',
- state: ['hover']
+ state: ['hover'],
},
directives: {
textColor: '--link',
- textAuto: 'no-preserve'
- }
+ textAuto: 'no-preserve',
+ },
},
{
component: 'Text',
parent: {
component: 'MenuItem',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
+ textOpacityMode: 'blend',
+ },
},
{
component: 'Icon',
parent: {
component: 'MenuItem',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
- }
- ]
+ textOpacityMode: 'blend',
+ },
+ },
+ ],
}
diff --git a/src/components/mfa_form/recovery_form.js b/src/components/mfa_form/recovery_form.js
index 84479b1ec..5fa5c187a 100644
--- a/src/components/mfa_form/recovery_form.js
+++ b/src/components/mfa_form/recovery_form.js
@@ -1,42 +1,42 @@
-import mfaApi from '../../services/new_api/mfa.js'
+import { mapActions, mapState as mapPiniaState, mapStores } from 'pinia'
import { mapState } from 'vuex'
-import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia'
-import { useOAuthStore } from 'src/stores/oauth.js'
-import { useAuthFlowStore } from 'src/stores/auth_flow.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faTimes
-} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faTimes
-)
+import { useAuthFlowStore } from 'src/stores/auth_flow.js'
+import { useOAuthStore } from 'src/stores/oauth.js'
+import mfaApi from '../../services/new_api/mfa.js'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faTimes } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faTimes)
export default {
data: () => ({
code: null,
- error: false
+ error: false,
}),
computed: {
...mapPiniaState(useAuthFlowStore, {
- authSettings: store => store.settings
+ authSettings: (store) => store.settings,
}),
...mapStores(useOAuthStore),
...mapState({
instance: 'instance',
- })
+ }),
},
methods: {
...mapActions(useAuthFlowStore, ['requireTOTP', 'abortMFA', 'login']),
- clearError () { this.error = false },
+ clearError() {
+ this.error = false
+ },
- focusOnCodeInput () {
+ focusOnCodeInput() {
const codeInput = this.$refs.codeInput
codeInput.focus()
codeInput.setSelectionRange(0, codeInput.value.length)
},
- submit () {
+ submit() {
const { clientId, clientSecret } = this.oauthStore
const data = {
@@ -44,7 +44,7 @@ export default {
clientSecret,
instance: this.instance.server,
mfaToken: this.authSettings.mfa_token,
- code: this.code
+ code: this.code,
}
mfaApi.verifyRecoveryCode(data).then((result) => {
@@ -59,6 +59,6 @@ export default {
this.$router.push({ name: 'friends' })
})
})
- }
- }
+ },
+ },
}
diff --git a/src/components/mfa_form/totp_form.js b/src/components/mfa_form/totp_form.js
index e369d8a5d..d1378b078 100644
--- a/src/components/mfa_form/totp_form.js
+++ b/src/components/mfa_form/totp_form.js
@@ -1,42 +1,42 @@
-import mfaApi from '../../services/new_api/mfa.js'
+import { mapActions, mapState as mapPiniaState, mapStores } from 'pinia'
import { mapState } from 'vuex'
-import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia'
-import { useOAuthStore } from 'src/stores/oauth.js'
-import { useAuthFlowStore } from 'src/stores/auth_flow.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faTimes
-} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faTimes
-)
+import { useAuthFlowStore } from 'src/stores/auth_flow.js'
+import { useOAuthStore } from 'src/stores/oauth.js'
+import mfaApi from '../../services/new_api/mfa.js'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faTimes } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faTimes)
export default {
data: () => ({
code: null,
- error: false
+ error: false,
}),
computed: {
...mapPiniaState(useAuthFlowStore, {
- authSettings: store => store.settings
+ authSettings: (store) => store.settings,
}),
...mapStores(useOAuthStore),
...mapState({
instance: 'instance',
- })
+ }),
},
methods: {
...mapActions(useAuthFlowStore, ['requireRecovery', 'abortMFA', 'login']),
- clearError () { this.error = false },
+ clearError() {
+ this.error = false
+ },
- focusOnCodeInput () {
+ focusOnCodeInput() {
const codeInput = this.$refs.codeInput
codeInput.focus()
codeInput.setSelectionRange(0, codeInput.value.length)
},
- submit () {
+ submit() {
const { clientId, clientSecret } = this.oauthStore
const data = {
@@ -44,7 +44,7 @@ export default {
clientSecret,
instance: this.instance.server,
mfaToken: this.authSettings.mfa_token,
- code: this.code
+ code: this.code,
}
mfaApi.verifyOTPCode(data).then((result) => {
@@ -59,6 +59,6 @@ export default {
this.$router.push({ name: 'friends' })
})
})
- }
- }
+ },
+ },
}
diff --git a/src/components/mobile_drawer.style.js b/src/components/mobile_drawer.style.js
index 0f2cf4e59..306bd5c17 100644
--- a/src/components/mobile_drawer.style.js
+++ b/src/components/mobile_drawer.style.js
@@ -1,15 +1,13 @@
export default {
name: 'MobileDrawer',
selector: '.mobile-drawer',
- validInnerComponents: [
- 'MenuItem'
- ],
+ validInnerComponents: ['MenuItem'],
defaultRules: [
{
directives: {
background: '--bg',
- backgroundNoCssColor: 'yes'
- }
- }
- ]
+ backgroundNoCssColor: 'yes',
+ },
+ },
+ ],
}
diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js
index 2085d24e3..873bdc40d 100644
--- a/src/components/mobile_nav/mobile_nav.js
+++ b/src/components/mobile_nav/mobile_nav.js
@@ -1,99 +1,98 @@
-import SideDrawer from '../side_drawer/side_drawer.vue'
-import Notifications from '../notifications/notifications.vue'
-import ConfirmModal from '../confirm_modal/confirm_modal.vue'
-import GestureService from '../../services/gesture_service/gesture_service'
-import NavigationPins from 'src/components/navigation/navigation_pins.vue'
-
-import {
- unseenNotificationsFromStore,
- countExtraNotifications
-} from '../../services/notification_utils/notification_utils'
-
-import { mapGetters } from 'vuex'
import { mapState } from 'pinia'
+import { mapGetters } from 'vuex'
+
+import NavigationPins from 'src/components/navigation/navigation_pins.vue'
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
+import GestureService from '../../services/gesture_service/gesture_service'
+import {
+ countExtraNotifications,
+ unseenNotificationsFromStore,
+} from '../../services/notification_utils/notification_utils'
+import ConfirmModal from '../confirm_modal/confirm_modal.vue'
+import Notifications from '../notifications/notifications.vue'
+import SideDrawer from '../side_drawer/side_drawer.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faTimes,
- faBell,
- faBars,
faArrowUp,
+ faBars,
+ faBell,
+ faCheckDouble,
faMinus,
- faCheckDouble
+ faTimes,
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faTimes,
- faBell,
- faBars,
- faArrowUp,
- faMinus,
- faCheckDouble
-)
+library.add(faTimes, faBell, faBars, faArrowUp, faMinus, faCheckDouble)
const MobileNav = {
components: {
SideDrawer,
Notifications,
NavigationPins,
- ConfirmModal
+ ConfirmModal,
},
data: () => ({
notificationsCloseGesture: undefined,
notificationsOpen: false,
notificationsAtTop: true,
- showingConfirmLogout: false
+ showingConfirmLogout: false,
}),
- created () {
+ created() {
this.notificationsCloseGesture = GestureService.swipeGesture(
GestureService.DIRECTION_RIGHT,
() => this.closeMobileNotifications(true),
- 50
+ 50,
)
},
computed: {
- currentUser () {
+ currentUser() {
return this.$store.state.users.currentUser
},
- unseenNotifications () {
+ unseenNotifications() {
return unseenNotificationsFromStore(this.$store)
},
- unseenNotificationsCount () {
- return this.unseenNotifications.length + countExtraNotifications(this.$store)
+ unseenNotificationsCount() {
+ return (
+ this.unseenNotifications.length + countExtraNotifications(this.$store)
+ )
},
- unseenCount () {
+ unseenCount() {
return this.unseenNotifications.length
},
- unseenCountBadgeText () {
+ unseenCountBadgeText() {
return `${this.unseenCount ? this.unseenCount : ''}`
},
- hideSitename () { return this.$store.state.instance.hideSitename },
- sitename () { return this.$store.state.instance.name },
- isChat () {
+ hideSitename() {
+ return this.$store.state.instance.hideSitename
+ },
+ sitename() {
+ return this.$store.state.instance.name
+ },
+ isChat() {
return this.$route.name === 'chat'
},
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
...mapState(useServerSideStorageStore, {
- pinnedItems: store => new Set(store.prefsStorage.collections.pinnedNavItems).has('chats')
+ pinnedItems: (store) =>
+ new Set(store.prefsStorage.collections.pinnedNavItems).has('chats'),
}),
- shouldConfirmLogout () {
+ shouldConfirmLogout() {
return this.$store.getters.mergedConfig.modalOnLogout
},
- closingDrawerMarksAsSeen () {
+ closingDrawerMarksAsSeen() {
return this.$store.getters.mergedConfig.closingDrawerMarksAsSeen
},
- ...mapGetters(['unreadChatCount'])
+ ...mapGetters(['unreadChatCount']),
},
methods: {
- toggleMobileSidebar () {
+ toggleMobileSidebar() {
this.$refs.sideDrawer.toggleDrawer()
},
- openMobileNotifications () {
+ openMobileNotifications() {
this.notificationsOpen = true
},
- closeMobileNotifications (markRead) {
+ closeMobileNotifications(markRead) {
if (this.notificationsOpen) {
// make sure to mark notifs seen only when the notifs were open and not
// from close-calls.
@@ -103,53 +102,53 @@ const MobileNav = {
}
}
},
- notificationsTouchStart (e) {
+ notificationsTouchStart(e) {
GestureService.beginSwipe(e, this.notificationsCloseGesture)
},
- notificationsTouchMove (e) {
+ notificationsTouchMove(e) {
GestureService.updateSwipe(e, this.notificationsCloseGesture)
},
- scrollToTop () {
+ scrollToTop() {
window.scrollTo(0, 0)
},
- scrollMobileNotificationsToTop () {
+ scrollMobileNotificationsToTop() {
this.$refs.mobileNotifications.scrollTo(0, 0)
},
- showConfirmLogout () {
+ showConfirmLogout() {
this.showingConfirmLogout = true
},
- hideConfirmLogout () {
+ hideConfirmLogout() {
this.showingConfirmLogout = false
},
- logout () {
+ logout() {
if (!this.shouldConfirmLogout) {
this.doLogout()
} else {
this.showConfirmLogout()
}
},
- doLogout () {
+ doLogout() {
this.$router.replace('/main/public')
this.$store.dispatch('logout')
this.hideConfirmLogout()
},
- markNotificationsAsSeen () {
+ markNotificationsAsSeen() {
this.$store.dispatch('markNotificationsAsSeen')
},
- onScroll ({ target: { scrollTop, clientHeight, scrollHeight } }) {
+ onScroll({ target: { scrollTop, clientHeight, scrollHeight } }) {
this.notificationsAtTop = scrollTop > 0
if (scrollTop + clientHeight >= scrollHeight) {
this.$refs.notifications.fetchOlderNotifications()
}
- }
+ },
},
watch: {
- $route () {
+ $route() {
// handles closing notificaitons when you press any router-link on the
// notifications.
this.closeMobileNotifications()
- }
- }
+ },
+ },
}
export default MobileNav
diff --git a/src/components/mobile_post_status_button/mobile_post_status_button.js b/src/components/mobile_post_status_button/mobile_post_status_button.js
index 031013559..dfa7b6fe2 100644
--- a/src/components/mobile_post_status_button/mobile_post_status_button.js
+++ b/src/components/mobile_post_status_button/mobile_post_status_button.js
@@ -1,57 +1,55 @@
import { debounce } from 'lodash'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faPen
-} from '@fortawesome/free-solid-svg-icons'
+
import { usePostStatusStore } from 'src/stores/post_status'
-library.add(
- faPen
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faPen } from '@fortawesome/free-solid-svg-icons'
-const HIDDEN_FOR_PAGES = new Set([
- 'chats',
- 'chat',
- 'lists-edit'
-])
+library.add(faPen)
+
+const HIDDEN_FOR_PAGES = new Set(['chats', 'chat', 'lists-edit'])
const MobilePostStatusButton = {
- data () {
+ data() {
return {
hidden: false,
scrollingDown: false,
inputActive: false,
oldScrollPos: 0,
- amountScrolled: 0
+ amountScrolled: 0,
}
},
- created () {
+ created() {
if (this.autohideFloatingPostButton) {
this.activateFloatingPostButtonAutohide()
}
window.addEventListener('resize', this.handleOSK)
},
- unmounted () {
+ unmounted() {
if (this.autohideFloatingPostButton) {
this.deactivateFloatingPostButtonAutohide()
}
window.removeEventListener('resize', this.handleOSK)
},
computed: {
- isLoggedIn () {
+ isLoggedIn() {
return !!this.$store.state.users.currentUser
},
- isHidden () {
- if (HIDDEN_FOR_PAGES.has(this.$route.name)) { return true }
+ isHidden() {
+ if (HIDDEN_FOR_PAGES.has(this.$route.name)) {
+ return true
+ }
- return this.autohideFloatingPostButton && (this.hidden || this.inputActive)
+ return (
+ this.autohideFloatingPostButton && (this.hidden || this.inputActive)
+ )
},
- isPersistent () {
+ isPersistent() {
return !!this.$store.getters.mergedConfig.alwaysShowNewPostButton
},
- autohideFloatingPostButton () {
+ autohideFloatingPostButton() {
return !!this.$store.getters.mergedConfig.autohideFloatingPostButton
- }
+ },
},
watch: {
autohideFloatingPostButton: function (isEnabled) {
@@ -60,21 +58,21 @@ const MobilePostStatusButton = {
} else {
this.deactivateFloatingPostButtonAutohide()
}
- }
+ },
},
methods: {
- activateFloatingPostButtonAutohide () {
+ activateFloatingPostButtonAutohide() {
window.addEventListener('scroll', this.handleScrollStart)
window.addEventListener('scroll', this.handleScrollEnd)
},
- deactivateFloatingPostButtonAutohide () {
+ deactivateFloatingPostButtonAutohide() {
window.removeEventListener('scroll', this.handleScrollStart)
window.removeEventListener('scroll', this.handleScrollEnd)
},
- openPostForm () {
+ openPostForm() {
usePostStatusStore().openPostStatusModal()
},
- handleOSK () {
+ handleOSK() {
// This is a big hack: we're guessing from changed window sizes if the
// on-screen keyboard is active or not. This is only really important
// for phones in portrait mode and it's more important to show the button
@@ -94,20 +92,28 @@ const MobilePostStatusButton = {
this.inputActive = false
}
},
- handleScrollStart: debounce(function () {
- if (window.scrollY > this.oldScrollPos) {
- this.hidden = true
- } else {
- this.hidden = false
- }
- this.oldScrollPos = window.scrollY
- }, 100, { leading: true, trailing: false }),
+ handleScrollStart: debounce(
+ function () {
+ if (window.scrollY > this.oldScrollPos) {
+ this.hidden = true
+ } else {
+ this.hidden = false
+ }
+ this.oldScrollPos = window.scrollY
+ },
+ 100,
+ { leading: true, trailing: false },
+ ),
- handleScrollEnd: debounce(function () {
- this.hidden = false
- this.oldScrollPos = window.scrollY
- }, 100, { leading: false, trailing: true })
- }
+ handleScrollEnd: debounce(
+ function () {
+ this.hidden = false
+ this.oldScrollPos = window.scrollY
+ },
+ 100,
+ { leading: false, trailing: true },
+ ),
+ },
}
export default MobilePostStatusButton
diff --git a/src/components/modal/modal.vue b/src/components/modal/modal.vue
index 032e7dbeb..a022f7427 100644
--- a/src/components/modal/modal.vue
+++ b/src/components/modal/modal.vue
@@ -13,27 +13,27 @@
diff --git a/src/components/modal/modals.style.js b/src/components/modal/modals.style.js
index 1cb4a34a7..9c8c279f7 100644
--- a/src/components/modal/modals.style.js
+++ b/src/components/modal/modals.style.js
@@ -3,8 +3,6 @@ export default {
selector: ['.modal-view', '#modal', '.shout-panel'],
lazy: true,
notEditable: true,
- validInnerComponents: [
- 'Panel'
- ],
- defaultRules: []
+ validInnerComponents: ['Panel'],
+ defaultRules: [],
}
diff --git a/src/components/moderation_tools/moderation_tools.js b/src/components/moderation_tools/moderation_tools.js
index bd57a353a..fdb8a74b6 100644
--- a/src/components/moderation_tools/moderation_tools.js
+++ b/src/components/moderation_tools/moderation_tools.js
@@ -1,9 +1,9 @@
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { faChevronDown } from '@fortawesome/free-solid-svg-icons'
-
import DialogModal from '../dialog_modal/dialog_modal.vue'
import Popover from '../popover/popover.vue'
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faChevronDown } from '@fortawesome/free-solid-svg-icons'
+
library.add(faChevronDown)
const FORCE_NSFW = 'mrf_tag:media-force-nsfw'
@@ -15,10 +15,8 @@ const SANDBOX = 'mrf_tag:sandbox'
const QUARANTINE = 'mrf_tag:quarantine'
const ModerationTools = {
- props: [
- 'user'
- ],
- data () {
+ props: ['user'],
+ data() {
return {
tags: {
FORCE_NSFW,
@@ -27,92 +25,124 @@ const ModerationTools = {
DISABLE_REMOTE_SUBSCRIPTION,
DISABLE_ANY_SUBSCRIPTION,
SANDBOX,
- QUARANTINE
+ QUARANTINE,
},
showDeleteUserDialog: false,
- toggled: false
+ toggled: false,
}
},
components: {
DialogModal,
- Popover
+ Popover,
},
computed: {
- tagsSet () {
+ tagsSet() {
return new Set(this.user.tags)
},
- canGrantRole () {
- return this.user.is_local && !this.user.deactivated && this.$store.state.users.currentUser.role === 'admin'
+ canGrantRole() {
+ return (
+ this.user.is_local &&
+ !this.user.deactivated &&
+ this.$store.state.users.currentUser.role === 'admin'
+ )
},
- canChangeActivationState () {
+ canChangeActivationState() {
return this.privileged('users_manage_activation_state')
},
- canDeleteAccount () {
+ canDeleteAccount() {
return this.privileged('users_delete')
},
- canUseTagPolicy () {
- return this.$store.state.instance.tagPolicyAvailable && this.privileged('users_manage_tags')
- }
+ canUseTagPolicy() {
+ return (
+ this.$store.state.instance.tagPolicyAvailable &&
+ this.privileged('users_manage_tags')
+ )
+ },
},
methods: {
- hasTag (tagName) {
+ hasTag(tagName) {
return this.tagsSet.has(tagName)
},
- privileged (privilege) {
+ privileged(privilege) {
return this.$store.state.users.currentUser.privileges.includes(privilege)
},
- toggleTag (tag) {
+ toggleTag(tag) {
const store = this.$store
if (this.tagsSet.has(tag)) {
- store.state.api.backendInteractor.untagUser({ user: this.user, tag }).then(response => {
- if (!response.ok) { return }
- store.commit('untagUser', { user: this.user, tag })
- })
+ store.state.api.backendInteractor
+ .untagUser({ user: this.user, tag })
+ .then((response) => {
+ if (!response.ok) {
+ return
+ }
+ store.commit('untagUser', { user: this.user, tag })
+ })
} else {
- store.state.api.backendInteractor.tagUser({ user: this.user, tag }).then(response => {
- if (!response.ok) { return }
- store.commit('tagUser', { user: this.user, tag })
- })
+ store.state.api.backendInteractor
+ .tagUser({ user: this.user, tag })
+ .then((response) => {
+ if (!response.ok) {
+ return
+ }
+ store.commit('tagUser', { user: this.user, tag })
+ })
}
},
- toggleRight (right) {
+ toggleRight(right) {
const store = this.$store
if (this.user.rights[right]) {
- store.state.api.backendInteractor.deleteRight({ user: this.user, right }).then(response => {
- if (!response.ok) { return }
- store.commit('updateRight', { user: this.user, right, value: false })
- })
+ store.state.api.backendInteractor
+ .deleteRight({ user: this.user, right })
+ .then((response) => {
+ if (!response.ok) {
+ return
+ }
+ store.commit('updateRight', {
+ user: this.user,
+ right,
+ value: false,
+ })
+ })
} else {
- store.state.api.backendInteractor.addRight({ user: this.user, right }).then(response => {
- if (!response.ok) { return }
- store.commit('updateRight', { user: this.user, right, value: true })
- })
+ store.state.api.backendInteractor
+ .addRight({ user: this.user, right })
+ .then((response) => {
+ if (!response.ok) {
+ return
+ }
+ store.commit('updateRight', { user: this.user, right, value: true })
+ })
}
},
- toggleActivationStatus () {
+ toggleActivationStatus() {
this.$store.dispatch('toggleActivationStatus', { user: this.user })
},
- deleteUserDialog (show) {
+ deleteUserDialog(show) {
this.showDeleteUserDialog = show
},
- deleteUser () {
+ deleteUser() {
const store = this.$store
const user = this.user
const { id, name } = user
- store.state.api.backendInteractor.deleteUser({ user })
- .then(() => {
- this.$store.dispatch('markStatusesAsDeleted', status => user.id === status.user.id)
- const isProfile = this.$route.name === 'external-user-profile' || this.$route.name === 'user-profile'
- const isTargetUser = this.$route.params.name === name || this.$route.params.id === id
- if (isProfile && isTargetUser) {
- window.history.back()
- }
- })
+ store.state.api.backendInteractor.deleteUser({ user }).then(() => {
+ this.$store.dispatch(
+ 'markStatusesAsDeleted',
+ (status) => user.id === status.user.id,
+ )
+ const isProfile =
+ this.$route.name === 'external-user-profile' ||
+ this.$route.name === 'user-profile'
+ const isTargetUser =
+ this.$route.params.name === name || this.$route.params.id === id
+ if (isProfile && isTargetUser) {
+ window.history.back()
+ }
+ })
},
- setToggled (value) {
+ setToggled(value) {
this.toggled = value
- }
- }
+ },
+ },
}
export default ModerationTools
diff --git a/src/components/mrf_transparency_panel/mrf_transparency_panel.js b/src/components/mrf_transparency_panel/mrf_transparency_panel.js
index 13cfb52ee..2bd82f486 100644
--- a/src/components/mrf_transparency_panel/mrf_transparency_panel.js
+++ b/src/components/mrf_transparency_panel/mrf_transparency_panel.js
@@ -1,5 +1,5 @@
-import { mapState } from 'vuex'
import { get } from 'lodash'
+import { mapState } from 'vuex'
/**
* This is for backwards compatibility. We originally didn't recieve
@@ -8,7 +8,7 @@ import { get } from 'lodash'
* to add an extra "info" key.
*/
const toInstanceReasonObject = (instances, info, key) => {
- return instances.map(instance => {
+ return instances.map((instance) => {
if (info[key] && info[key][instance] && info[key][instance].reason) {
return { instance, reason: info[key][instance].reason }
}
@@ -19,56 +19,82 @@ const toInstanceReasonObject = (instances, info, key) => {
const MRFTransparencyPanel = {
computed: {
...mapState({
- federationPolicy: state => get(state, 'instance.federationPolicy'),
- mrfPolicies: state => get(state, 'instance.federationPolicy.mrf_policies', []),
- quarantineInstances: state => toInstanceReasonObject(
- get(state, 'instance.federationPolicy.quarantined_instances', []),
- get(state, 'instance.federationPolicy.quarantined_instances_info', []),
- 'quarantined_instances'
- ),
- acceptInstances: state => toInstanceReasonObject(
- get(state, 'instance.federationPolicy.mrf_simple.accept', []),
- get(state, 'instance.federationPolicy.mrf_simple_info', []),
- 'accept'
- ),
- rejectInstances: state => toInstanceReasonObject(
- get(state, 'instance.federationPolicy.mrf_simple.reject', []),
- get(state, 'instance.federationPolicy.mrf_simple_info', []),
- 'reject'
- ),
- ftlRemovalInstances: state => toInstanceReasonObject(
- get(state, 'instance.federationPolicy.mrf_simple.federated_timeline_removal', []),
- get(state, 'instance.federationPolicy.mrf_simple_info', []),
- 'federated_timeline_removal'
- ),
- mediaNsfwInstances: state => toInstanceReasonObject(
- get(state, 'instance.federationPolicy.mrf_simple.media_nsfw', []),
- get(state, 'instance.federationPolicy.mrf_simple_info', []),
- 'media_nsfw'
- ),
- mediaRemovalInstances: state => toInstanceReasonObject(
- get(state, 'instance.federationPolicy.mrf_simple.media_removal', []),
- get(state, 'instance.federationPolicy.mrf_simple_info', []),
- 'media_removal'
- ),
- keywordsFtlRemoval: state => get(state, 'instance.federationPolicy.mrf_keyword.federated_timeline_removal', []),
- keywordsReject: state => get(state, 'instance.federationPolicy.mrf_keyword.reject', []),
- keywordsReplace: state => get(state, 'instance.federationPolicy.mrf_keyword.replace', [])
+ federationPolicy: (state) => get(state, 'instance.federationPolicy'),
+ mrfPolicies: (state) =>
+ get(state, 'instance.federationPolicy.mrf_policies', []),
+ quarantineInstances: (state) =>
+ toInstanceReasonObject(
+ get(state, 'instance.federationPolicy.quarantined_instances', []),
+ get(
+ state,
+ 'instance.federationPolicy.quarantined_instances_info',
+ [],
+ ),
+ 'quarantined_instances',
+ ),
+ acceptInstances: (state) =>
+ toInstanceReasonObject(
+ get(state, 'instance.federationPolicy.mrf_simple.accept', []),
+ get(state, 'instance.federationPolicy.mrf_simple_info', []),
+ 'accept',
+ ),
+ rejectInstances: (state) =>
+ toInstanceReasonObject(
+ get(state, 'instance.federationPolicy.mrf_simple.reject', []),
+ get(state, 'instance.federationPolicy.mrf_simple_info', []),
+ 'reject',
+ ),
+ ftlRemovalInstances: (state) =>
+ toInstanceReasonObject(
+ get(
+ state,
+ 'instance.federationPolicy.mrf_simple.federated_timeline_removal',
+ [],
+ ),
+ get(state, 'instance.federationPolicy.mrf_simple_info', []),
+ 'federated_timeline_removal',
+ ),
+ mediaNsfwInstances: (state) =>
+ toInstanceReasonObject(
+ get(state, 'instance.federationPolicy.mrf_simple.media_nsfw', []),
+ get(state, 'instance.federationPolicy.mrf_simple_info', []),
+ 'media_nsfw',
+ ),
+ mediaRemovalInstances: (state) =>
+ toInstanceReasonObject(
+ get(state, 'instance.federationPolicy.mrf_simple.media_removal', []),
+ get(state, 'instance.federationPolicy.mrf_simple_info', []),
+ 'media_removal',
+ ),
+ keywordsFtlRemoval: (state) =>
+ get(
+ state,
+ 'instance.federationPolicy.mrf_keyword.federated_timeline_removal',
+ [],
+ ),
+ keywordsReject: (state) =>
+ get(state, 'instance.federationPolicy.mrf_keyword.reject', []),
+ keywordsReplace: (state) =>
+ get(state, 'instance.federationPolicy.mrf_keyword.replace', []),
}),
- hasInstanceSpecificPolicies () {
- return this.quarantineInstances.length ||
+ hasInstanceSpecificPolicies() {
+ return (
+ this.quarantineInstances.length ||
this.acceptInstances.length ||
this.rejectInstances.length ||
this.ftlRemovalInstances.length ||
this.mediaNsfwInstances.length ||
this.mediaRemovalInstances.length
+ )
},
- hasKeywordPolicies () {
- return this.keywordsFtlRemoval.length ||
+ hasKeywordPolicies() {
+ return (
+ this.keywordsFtlRemoval.length ||
this.keywordsReject.length ||
this.keywordsReplace.length
- }
- }
+ )
+ },
+ },
}
export default MRFTransparencyPanel
diff --git a/src/components/mute_card/mute_card.js b/src/components/mute_card/mute_card.js
index 895586888..d5226ef06 100644
--- a/src/components/mute_card/mute_card.js
+++ b/src/components/mute_card/mute_card.js
@@ -1,39 +1,41 @@
-import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
+import BasicUserCard from '../basic_user_card/basic_user_card.vue'
const MuteCard = {
props: ['userId'],
computed: {
- user () {
+ user() {
return this.$store.getters.findUser(this.userId)
},
- relationship () {
+ relationship() {
return this.$store.getters.relationship(this.userId)
},
- muted () {
+ muted() {
return this.relationship.muting
},
- muteExpiryAvailable () {
- return this.user.mute_expires_at !== undefined
+ muteExpiryAvailable() {
+ return Object.hasOwn(this.user, 'mute_expires_at')
},
- muteExpiry () {
- return this.user.mute_expires_at == null
+ muteExpiry() {
+ return this.user.mute_expires_at === false
? this.$t('user_card.mute_expires_forever')
- : this.$t('user_card.mute_expires_at', [new Date(this.user.mute_expires_at).toLocaleString()])
- }
+ : this.$t('user_card.mute_expires_at', [
+ new Date(this.user.mute_expires_at).toLocaleString(),
+ ])
+ },
},
components: {
BasicUserCard,
- UserTimedFilterModal
+ UserTimedFilterModal,
},
methods: {
- unmuteUser () {
+ unmuteUser() {
this.$store.dispatch('unmuteUser', this.userId)
},
- muteUser () {
+ muteUser() {
this.$refs.timedMuteDialog.optionallyPrompt()
- }
- }
+ },
+ },
}
export default MuteCard
diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index a155abe0c..d80cd0a5d 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -1,32 +1,32 @@
-import BookmarkFoldersMenuContent from 'src/components/bookmark_folders_menu/bookmark_folders_menu_content.vue'
-import ListsMenuContent from 'src/components/lists_menu/lists_menu_content.vue'
-import { mapState, mapGetters } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
-import { TIMELINES, ROOT_ITEMS } from 'src/components/navigation/navigation.js'
+import { mapGetters, mapState } from 'vuex'
+
+import BookmarkFoldersMenuContent from 'src/components/bookmark_folders_menu/bookmark_folders_menu_content.vue'
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+import ListsMenuContent from 'src/components/lists_menu/lists_menu_content.vue'
import { filterNavigation } from 'src/components/navigation/filter.js'
+import { ROOT_ITEMS, TIMELINES } from 'src/components/navigation/navigation.js'
import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
-import Checkbox from 'src/components/checkbox/checkbox.vue'
-
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faUsers,
- faGlobe,
- faCity,
+ faBell,
faBookmark,
- faEnvelope,
+ faBullhorn,
faChevronDown,
faChevronUp,
+ faCity,
faComments,
- faBell,
+ faEnvelope,
+ faFilePen,
+ faGlobe,
faInfoCircle,
- faStream,
faList,
- faBullhorn,
- faFilePen
+ faStream,
+ faUsers,
} from '@fortawesome/free-solid-svg-icons'
library.add(
@@ -43,80 +43,92 @@ library.add(
faStream,
faList,
faBullhorn,
- faFilePen
+ faFilePen,
)
const NavPanel = {
props: ['forceExpand', 'forceEditMode'],
- created () {
- },
components: {
BookmarkFoldersMenuContent,
ListsMenuContent,
NavigationEntry,
NavigationPins,
- Checkbox
+ Checkbox,
},
- data () {
+ data() {
return {
editMode: false,
showTimelines: false,
showLists: false,
showBookmarkFolders: false,
- timelinesList: Object.entries(TIMELINES).map(([k, v]) => ({ ...v, name: k })),
- rootList: Object.entries(ROOT_ITEMS).map(([k, v]) => ({ ...v, name: k }))
+ timelinesList: Object.entries(TIMELINES).map(([k, v]) => ({
+ ...v,
+ name: k,
+ })),
+ rootList: Object.entries(ROOT_ITEMS).map(([k, v]) => ({ ...v, name: k })),
}
},
methods: {
- toggleTimelines () {
+ toggleTimelines() {
this.showTimelines = !this.showTimelines
},
- toggleLists () {
+ toggleLists() {
this.showLists = !this.showLists
},
- toggleBookmarkFolders () {
+ toggleBookmarkFolders() {
this.showBookmarkFolders = !this.showBookmarkFolders
},
- toggleEditMode () {
+ toggleEditMode() {
this.editMode = !this.editMode
},
- toggleCollapse () {
- useServerSideStorageStore().setPreference({ path: 'simple.collapseNav', value: !this.collapsed })
+ toggleCollapse() {
+ useServerSideStorageStore().setPreference({
+ path: 'simple.collapseNav',
+ value: !this.collapsed,
+ })
useServerSideStorageStore().pushServerSideStorage()
},
- isPinned (item) {
+ isPinned(item) {
return this.pinnedItems.has(item)
},
- togglePin (item) {
+ togglePin(item) {
if (this.isPinned(item)) {
- useServerSideStorageStore().removeCollectionPreference({ path: 'collections.pinnedNavItems', value: item })
+ useServerSideStorageStore().removeCollectionPreference({
+ path: 'collections.pinnedNavItems',
+ value: item,
+ })
} else {
- useServerSideStorageStore().addCollectionPreference({ path: 'collections.pinnedNavItems', value: item })
+ useServerSideStorageStore().addCollectionPreference({
+ path: 'collections.pinnedNavItems',
+ value: item,
+ })
}
useServerSideStorageStore().pushServerSideStorage()
- }
+ },
},
computed: {
...mapPiniaState(useAnnouncementsStore, {
unreadAnnouncementCount: 'unreadAnnouncementCount',
- supportsAnnouncements: store => store.supportsAnnouncements
+ supportsAnnouncements: (store) => store.supportsAnnouncements,
}),
...mapPiniaState(useServerSideStorageStore, {
- collapsed: store => store.prefsStorage.simple.collapseNav,
- pinnedItems: store => new Set(store.prefsStorage.collections.pinnedNavItems)
+ collapsed: (store) => store.prefsStorage.simple.collapseNav,
+ pinnedItems: (store) =>
+ new Set(store.prefsStorage.collections.pinnedNavItems),
}),
...mapState({
- currentUser: state => state.users.currentUser,
- followRequestCount: state => state.api.followRequests.length,
- privateMode: state => state.instance.private,
- federating: state => state.instance.federating,
- pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
- bookmarkFolders: state => state.instance.pleromaBookmarkFoldersAvailable,
- bubbleTimeline: state => state.instance.localBubbleInstances.length > 0
+ currentUser: (state) => state.users.currentUser,
+ followRequestCount: (state) => state.api.followRequests.length,
+ privateMode: (state) => state.instance.private,
+ federating: (state) => state.instance.federating,
+ pleromaChatMessagesAvailable: (state) =>
+ state.instance.pleromaChatMessagesAvailable,
+ bookmarkFolders: (state) =>
+ state.instance.pleromaBookmarkFoldersAvailable,
+ bubbleTimeline: (state) => state.instance.localBubbleInstances.length > 0,
}),
- timelinesItems () {
+ timelinesItems() {
return filterNavigation(
- Object
- .entries({ ...TIMELINES })
+ Object.entries({ ...TIMELINES })
// do not show in timeliens list since it's in a better place now
.filter(([key]) => key !== 'bookmarks')
.map(([k, v]) => ({ ...v, name: k })),
@@ -127,15 +139,13 @@ const NavPanel = {
isPrivate: this.privateMode,
currentUser: this.currentUser,
supportsBubbleTimeline: this.bubbleTimeline,
- supportsBookmarkFolders: this.bookmarkFolders
- }
+ supportsBookmarkFolders: this.bookmarkFolders,
+ },
)
},
- rootItems () {
+ rootItems() {
return filterNavigation(
- Object
- .entries({ ...ROOT_ITEMS })
- .map(([k, v]) => ({ ...v, name: k })),
+ Object.entries({ ...ROOT_ITEMS }).map(([k, v]) => ({ ...v, name: k })),
{
hasChats: this.pleromaChatMessagesAvailable,
hasAnnouncements: this.supportsAnnouncements,
@@ -143,12 +153,12 @@ const NavPanel = {
isPrivate: this.privateMode,
currentUser: this.currentUser,
supportsBubbleTimeline: this.bubbleTimeline,
- supportsBookmarkFolders: this.bookmarkFolders
- }
+ supportsBookmarkFolders: this.bookmarkFolders,
+ },
)
},
- ...mapGetters(['unreadChatCount'])
- }
+ ...mapGetters(['unreadChatCount']),
+ },
}
export default NavPanel
diff --git a/src/components/navigation/filter.js b/src/components/navigation/filter.js
index 54abb67b4..0255db6aa 100644
--- a/src/components/navigation/filter.js
+++ b/src/components/navigation/filter.js
@@ -1,39 +1,50 @@
-export const filterNavigation = (list = [], {
- hasChats,
- hasAnnouncements,
- isFederating,
- isPrivate,
- currentUser,
- supportsBookmarkFolders,
- supportsBubbleTimeline
-}) => {
+export const filterNavigation = (
+ list = [],
+ {
+ hasChats,
+ hasAnnouncements,
+ isFederating,
+ isPrivate,
+ currentUser,
+ supportsBookmarkFolders,
+ supportsBubbleTimeline,
+ },
+) => {
return list.filter(({ criteria, anon, anonRoute }) => {
const set = new Set(criteria || [])
if (!isFederating && set.has('federating')) return false
if (!currentUser && isPrivate && set.has('!private')) return false
if (!currentUser && !(anon || anonRoute)) return false
- if ((!currentUser || !currentUser.locked) && set.has('lockedUser')) return false
+ if ((!currentUser || !currentUser.locked) && set.has('lockedUser'))
+ return false
if (!hasChats && set.has('chats')) return false
if (!hasAnnouncements && set.has('announcements')) return false
- if (!supportsBubbleTimeline && set.has('supportsBubbleTimeline')) return false
- if (!supportsBookmarkFolders && set.has('supportsBookmarkFolders')) return false
- if (supportsBookmarkFolders && set.has('!supportsBookmarkFolders')) return false
+ if (!supportsBubbleTimeline && set.has('supportsBubbleTimeline'))
+ return false
+ if (!supportsBookmarkFolders && set.has('supportsBookmarkFolders'))
+ return false
+ if (supportsBookmarkFolders && set.has('!supportsBookmarkFolders'))
+ return false
return true
})
}
-export const getListEntries = store => store.allLists.map(list => ({
- name: 'list-' + list.id,
- routeObject: { name: 'lists-timeline', params: { id: list.id } },
- labelRaw: list.title,
- iconLetter: list.title[0]
-}))
+export const getListEntries = (store) =>
+ store.allLists.map((list) => ({
+ name: 'list-' + list.id,
+ routeObject: { name: 'lists-timeline', params: { id: list.id } },
+ labelRaw: list.title,
+ iconLetter: list.title[0],
+ }))
-export const getBookmarkFolderEntries = store => store.allFolders ? store.allFolders.map(folder => ({
- name: 'bookmark-folder-' + folder.id,
- routeObject: { name: 'bookmark-folder', params: { id: folder.id } },
- labelRaw: folder.name,
- iconEmoji: folder.emoji,
- iconEmojiUrl: folder.emoji_url,
- iconLetter: folder.name[0]
-})) : []
+export const getBookmarkFolderEntries = (store) =>
+ store.allFolders
+ ? store.allFolders.map((folder) => ({
+ name: 'bookmark-folder-' + folder.id,
+ routeObject: { name: 'bookmark-folder', params: { id: folder.id } },
+ labelRaw: folder.name,
+ iconEmoji: folder.emoji,
+ iconEmojiUrl: folder.emoji_url,
+ iconLetter: folder.name[0],
+ }))
+ : []
diff --git a/src/components/navigation/navigation.js b/src/components/navigation/navigation.js
index d1c2b6763..66fb0d347 100644
--- a/src/components/navigation/navigation.js
+++ b/src/components/navigation/navigation.js
@@ -4,42 +4,39 @@ export const USERNAME_ROUTES = new Set([
'interactions',
'notifications',
'chat',
- 'chats'
+ 'chats',
])
// routes that take :name property
-export const NAME_ROUTES = new Set([
- 'user-profile',
- 'legacy-user-profile'
-])
+export const NAME_ROUTES = new Set(['user-profile', 'legacy-user-profile'])
export const TIMELINES = {
home: {
route: 'friends',
icon: 'home',
label: 'nav.home_timeline',
- criteria: ['!private']
+ criteria: ['!private'],
},
public: {
route: 'public-timeline',
anon: true,
icon: 'users',
label: 'nav.public_tl',
- criteria: ['!private']
+ criteria: ['!private'],
},
bubble: {
route: 'bubble',
anon: true,
icon: 'city',
label: 'nav.bubble',
- criteria: ['!private', 'federating', 'supportsBubbleTimeline']
+ criteria: ['!private', 'federating', 'supportsBubbleTimeline'],
},
twkn: {
route: 'public-external-timeline',
anon: true,
icon: 'globe',
label: 'nav.twkn',
- criteria: ['!private', 'federating']
+ criteria: ['!private', 'federating'],
},
// bookmarks are still technically a timeline so we should show it in the dropdown
bookmarks: {
@@ -50,13 +47,13 @@ export const TIMELINES = {
favorites: {
routeObject: { name: 'user-profile', query: { tab: 'favorites' } },
icon: 'star',
- label: 'user_card.favorites'
+ label: 'user_card.favorites',
},
dms: {
route: 'dms',
icon: 'envelope',
- label: 'nav.dms'
- }
+ label: 'nav.dms',
+ },
}
export const ROOT_ITEMS = {
@@ -67,12 +64,12 @@ export const ROOT_ITEMS = {
// shows bookmarks entry in a better suited location
// hides it when bookmark folders are supported since
// we show custom component instead of it
- criteria: ['!supportsBookmarkFolders']
+ criteria: ['!supportsBookmarkFolders'],
},
interactions: {
route: 'interactions',
icon: 'bell',
- label: 'nav.interactions'
+ label: 'nav.interactions',
},
chats: {
route: 'chats',
@@ -80,7 +77,7 @@ export const ROOT_ITEMS = {
label: 'nav.chats',
badgeStyle: 'notification',
badgeGetter: 'unreadChatCount',
- criteria: ['chats']
+ criteria: ['chats'],
},
friendRequests: {
route: 'friend-requests',
@@ -88,13 +85,13 @@ export const ROOT_ITEMS = {
label: 'nav.friend_requests',
badgeStyle: 'notification',
criteria: ['lockedUser'],
- badgeGetter: 'followRequestCount'
+ badgeGetter: 'followRequestCount',
},
about: {
route: 'about',
anon: true,
icon: 'info-circle',
- label: 'nav.about'
+ label: 'nav.about',
},
announcements: {
route: 'announcements',
@@ -103,18 +100,18 @@ export const ROOT_ITEMS = {
store: 'announcements',
badgeStyle: 'notification',
badgeGetter: 'unreadAnnouncementCount',
- criteria: ['announcements']
+ criteria: ['announcements'],
},
drafts: {
route: 'drafts',
icon: 'file-pen',
label: 'nav.drafts',
badgeStyle: 'neutral',
- badgeGetter: 'draftCount'
- }
+ badgeGetter: 'draftCount',
+ },
}
-export function routeTo (item, currentUser) {
+export function routeTo(item, currentUser) {
if (!item.route && !item.routeObject) return null
let route
@@ -122,7 +119,7 @@ export function routeTo (item, currentUser) {
if (item.routeObject) {
route = item.routeObject
} else {
- route = { name: (item.anon || currentUser) ? item.route : item.anonRoute }
+ route = { name: item.anon || currentUser ? item.route : item.anonRoute }
}
if (USERNAME_ROUTES.has(route.name)) {
diff --git a/src/components/navigation/navigation_entry.js b/src/components/navigation/navigation_entry.js
index 11db1c9e3..75d4dffdd 100644
--- a/src/components/navigation/navigation_entry.js
+++ b/src/components/navigation/navigation_entry.js
@@ -1,48 +1,56 @@
+import { mapState as mapPiniaState, mapStores } from 'pinia'
import { mapState } from 'vuex'
+
import { routeTo } from 'src/components/navigation/navigation.js'
import OptionalRouterLink from 'src/components/optional_router_link/optional_router_link.vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { faThumbtack } from '@fortawesome/free-solid-svg-icons'
-import { mapStores, mapState as mapPiniaState } from 'pinia'
-
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faThumbtack } from '@fortawesome/free-solid-svg-icons'
+
library.add(faThumbtack)
const NavigationEntry = {
props: ['item', 'showPin'],
components: {
- OptionalRouterLink
+ OptionalRouterLink,
},
methods: {
- isPinned (value) {
+ isPinned(value) {
return this.pinnedItems.has(value)
},
- togglePin (value) {
+ togglePin(value) {
if (this.isPinned(value)) {
- useServerSideStorageStore().removeCollectionPreference({ path: 'collections.pinnedNavItems', value })
+ useServerSideStorageStore().removeCollectionPreference({
+ path: 'collections.pinnedNavItems',
+ value,
+ })
} else {
- useServerSideStorageStore().addCollectionPreference({ path: 'collections.pinnedNavItems', value })
+ useServerSideStorageStore().addCollectionPreference({
+ path: 'collections.pinnedNavItems',
+ value,
+ })
}
useServerSideStorageStore().pushServerSideStorage()
- }
+ },
},
computed: {
- routeTo () {
+ routeTo() {
return routeTo(this.item, this.currentUser)
},
- getters () {
+ getters() {
return this.$store.getters
},
...mapStores(useAnnouncementsStore),
...mapState({
- currentUser: state => state.users.currentUser
+ currentUser: (state) => state.users.currentUser,
}),
...mapPiniaState(useServerSideStorageStore, {
- pinnedItems: store => new Set(store.prefsStorage.collections.pinnedNavItems)
+ pinnedItems: (store) =>
+ new Set(store.prefsStorage.collections.pinnedNavItems),
}),
- }
+ },
}
export default NavigationEntry
diff --git a/src/components/navigation/navigation_pins.js b/src/components/navigation/navigation_pins.js
index f9a900fc6..e14edce14 100644
--- a/src/components/navigation/navigation_pins.js
+++ b/src/components/navigation/navigation_pins.js
@@ -1,27 +1,35 @@
-import { mapState } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
-import { TIMELINES, ROOT_ITEMS, routeTo } from 'src/components/navigation/navigation.js'
-import { getBookmarkFolderEntries, getListEntries, filterNavigation } from 'src/components/navigation/filter.js'
+import { mapState } from 'vuex'
+import {
+ filterNavigation,
+ getBookmarkFolderEntries,
+ getListEntries,
+} from 'src/components/navigation/filter.js'
+import {
+ ROOT_ITEMS,
+ routeTo,
+ TIMELINES,
+} from 'src/components/navigation/navigation.js'
import StillImage from 'src/components/still-image/still-image.vue'
+import { useAnnouncementsStore } from 'src/stores/announcements'
+import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
+import { useListsStore } from 'src/stores/lists'
+import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faUsers,
- faGlobe,
- faCity,
- faBookmark,
- faEnvelope,
- faComments,
faBell,
+ faBookmark,
+ faCity,
+ faComments,
+ faEnvelope,
+ faGlobe,
faInfoCircle,
+ faList,
faStream,
- faList
+ faUsers,
} from '@fortawesome/free-solid-svg-icons'
-import { useListsStore } from 'src/stores/lists'
-import { useAnnouncementsStore } from 'src/stores/announcements'
-import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
-import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
library.add(
faUsers,
@@ -33,72 +41,74 @@ library.add(
faBell,
faInfoCircle,
faStream,
- faList
+ faList,
)
const NavPanel = {
props: ['limit'],
methods: {
- getRouteTo (item) {
+ getRouteTo(item) {
return routeTo(item, this.currentUser)
- }
+ },
},
components: {
- StillImage
+ StillImage,
},
computed: {
- getters () {
+ getters() {
return this.$store.getters
},
...mapPiniaState(useListsStore, {
- lists: getListEntries
+ lists: getListEntries,
}),
...mapPiniaState(useAnnouncementsStore, {
- supportsAnnouncements: store => store.supportsAnnouncements
+ supportsAnnouncements: (store) => store.supportsAnnouncements,
}),
...mapPiniaState(useBookmarkFoldersStore, {
bookmarks: getBookmarkFolderEntries,
}),
...mapPiniaState(useServerSideStorageStore, {
- pinnedItems: store => new Set(store.prefsStorage.collections.pinnedNavItems)
+ pinnedItems: (store) =>
+ new Set(store.prefsStorage.collections.pinnedNavItems),
}),
...mapState({
- currentUser: state => state.users.currentUser,
- followRequestCount: state => state.api.followRequests.length,
- privateMode: state => state.instance.private,
- federating: state => state.instance.federating,
- pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
- bubbleTimeline: state => state.instance.localBubbleInstances.length > 0
+ currentUser: (state) => state.users.currentUser,
+ followRequestCount: (state) => state.api.followRequests.length,
+ privateMode: (state) => state.instance.private,
+ federating: (state) => state.instance.federating,
+ pleromaChatMessagesAvailable: (state) =>
+ state.instance.pleromaChatMessagesAvailable,
+ bubbleTimeline: (state) => state.instance.localBubbleInstances.length > 0,
}),
- pinnedList () {
+ pinnedList() {
if (!this.currentUser) {
- return filterNavigation([
- { ...TIMELINES.public, name: 'public' },
- { ...TIMELINES.twkn, name: 'twkn' },
- { ...ROOT_ITEMS.about, name: 'about' }
- ],
- {
- hasChats: this.pleromaChatMessagesAvailable,
- hasAnnouncements: this.supportsAnnouncements,
- isFederating: this.federating,
- isPrivate: this.privateMode,
- currentUser: this.currentUser,
- supportsBubbleTimeline: this.bubbleTimeline,
- supportsBookmarkFolders: this.bookmarks
- })
+ return filterNavigation(
+ [
+ { ...TIMELINES.public, name: 'public' },
+ { ...TIMELINES.twkn, name: 'twkn' },
+ { ...ROOT_ITEMS.about, name: 'about' },
+ ],
+ {
+ hasChats: this.pleromaChatMessagesAvailable,
+ hasAnnouncements: this.supportsAnnouncements,
+ isFederating: this.federating,
+ isPrivate: this.privateMode,
+ currentUser: this.currentUser,
+ supportsBubbleTimeline: this.bubbleTimeline,
+ supportsBookmarkFolders: this.bookmarks,
+ },
+ )
}
return filterNavigation(
[
- ...Object
- .entries({ ...TIMELINES })
+ ...Object.entries({ ...TIMELINES })
.filter(([k]) => this.pinnedItems.has(k))
.map(([k, v]) => ({ ...v, name: k })),
...this.lists.filter((k) => this.pinnedItems.has(k.name)),
...this.bookmarks.filter((k) => this.pinnedItems.has(k.name)),
- ...Object
- .entries({ ...ROOT_ITEMS })
+ ...Object.entries({ ...ROOT_ITEMS })
.filter(([k]) => this.pinnedItems.has(k))
- .map(([k, v]) => ({ ...v, name: k }))
+ .map(([k, v]) => ({ ...v, name: k })),
],
{
hasChats: this.pleromaChatMessagesAvailable,
@@ -107,11 +117,11 @@ const NavPanel = {
supportsBookmarkFolders: this.bookmarks,
isFederating: this.federating,
isPrivate: this.privateMode,
- currentUser: this.currentUser
- }
+ currentUser: this.currentUser,
+ },
).slice(0, this.limit)
- }
- }
+ },
+ },
}
export default NavPanel
diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js
index 8052e3a73..275827c43 100644
--- a/src/components/notification/notification.js
+++ b/src/components/notification/notification.js
@@ -1,29 +1,34 @@
-import StatusContent from '../status_content/status_content.vue'
import { mapState } from 'vuex'
+
+import RichContent from 'src/components/rich_content/rich_content.jsx'
+import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
+import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
+import {
+ highlightClass,
+ highlightStyle,
+} from '../../services/user_highlighter/user_highlighter.js'
+import ConfirmModal from '../confirm_modal/confirm_modal.vue'
+import Report from '../report/report.vue'
import Status from '../status/status.vue'
+import StatusContent from '../status_content/status_content.vue'
+import Timeago from '../timeago/timeago.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserCard from '../user_card/user_card.vue'
-import Timeago from '../timeago/timeago.vue'
-import Report from '../report/report.vue'
import UserLink from '../user_link/user_link.vue'
-import RichContent from 'src/components/rich_content/rich_content.jsx'
import UserPopover from '../user_popover/user_popover.vue'
-import ConfirmModal from '../confirm_modal/confirm_modal.vue'
-import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
-import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
-import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faCheck,
- faTimes,
- faStar,
- faRetweet,
- faUserPlus,
- faEyeSlash,
- faUser,
- faSuitcaseRolling,
+ faCompressAlt,
faExpandAlt,
- faCompressAlt
+ faEyeSlash,
+ faRetweet,
+ faStar,
+ faSuitcaseRolling,
+ faTimes,
+ faUser,
+ faUserPlus,
} from '@fortawesome/free-solid-svg-icons'
library.add(
@@ -36,17 +41,17 @@ library.add(
faEyeSlash,
faSuitcaseRolling,
faExpandAlt,
- faCompressAlt
+ faCompressAlt,
)
const Notification = {
- data () {
+ data() {
return {
selecting: false,
statusExpanded: false,
unmuted: false,
showingApproveConfirmDialog: false,
- showingDenyConfirmDialog: false
+ showingDenyConfirmDialog: false,
}
},
props: ['notification'],
@@ -61,141 +66,158 @@ const Notification = {
RichContent,
UserPopover,
UserLink,
- ConfirmModal
+ ConfirmModal,
},
- mounted () {
+ mounted() {
document.addEventListener('selectionchange', this.onContentSelect)
},
- unmounted () {
+ unmounted() {
document.removeEventListener('selectionchange', this.onContentSelect)
},
methods: {
- toggleStatusExpanded () {
+ toggleStatusExpanded() {
if (!this.expandable) return
this.statusExpanded = !this.statusExpanded
},
- onContentSelect () {
+ onContentSelect() {
const { isCollapsed, anchorNode, offsetNode } = document.getSelection()
if (isCollapsed) {
this.selecting = false
return
}
- const within = this.$refs.root.contains(anchorNode) || this.$refs.root.contains(offsetNode)
+ const within =
+ this.$refs.root.contains(anchorNode) ||
+ this.$refs.root.contains(offsetNode)
if (within) {
this.selecting = true
} else {
this.selecting = false
}
},
- onContentClick (e) {
- if (!this.selecting && !e.target.closest('a') && !e.target.closest('button')) {
+ onContentClick(e) {
+ if (
+ !this.selecting &&
+ !e.target.closest('a') &&
+ !e.target.closest('button')
+ ) {
this.toggleStatusExpanded()
}
},
- generateUserProfileLink (user) {
- return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
+ generateUserProfileLink(user) {
+ return generateProfileLink(
+ user.id,
+ user.screen_name,
+ this.$store.state.instance.restrictedNicknames,
+ )
},
- getUser (notification) {
+ getUser(notification) {
return this.$store.state.users.usersObject[notification.from_profile.id]
},
- interacted () {
+ interacted() {
this.$emit('interacted')
},
- toggleMute () {
+ toggleMute() {
this.unmuted = !this.unmuted
},
- showApproveConfirmDialog () {
+ showApproveConfirmDialog() {
this.showingApproveConfirmDialog = true
},
- hideApproveConfirmDialog () {
+ hideApproveConfirmDialog() {
this.showingApproveConfirmDialog = false
},
- showDenyConfirmDialog () {
+ showDenyConfirmDialog() {
this.showingDenyConfirmDialog = true
},
- hideDenyConfirmDialog () {
+ hideDenyConfirmDialog() {
this.showingDenyConfirmDialog = false
},
- approveUser () {
+ approveUser() {
if (this.shouldConfirmApprove) {
this.showApproveConfirmDialog()
} else {
this.doApprove()
}
},
- doApprove () {
+ doApprove() {
this.$emit('interacted')
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
this.$store.dispatch('removeFollowRequest', this.user)
- this.$store.dispatch('markSingleNotificationAsSeen', { id: this.notification.id })
+ this.$store.dispatch('markSingleNotificationAsSeen', {
+ id: this.notification.id,
+ })
this.$store.dispatch('updateNotification', {
id: this.notification.id,
- updater: notification => {
+ updater: (notification) => {
notification.type = 'follow'
- }
+ },
})
this.hideApproveConfirmDialog()
},
- denyUser () {
+ denyUser() {
if (this.shouldConfirmDeny) {
this.showDenyConfirmDialog()
} else {
this.doDeny()
}
},
- doDeny () {
+ doDeny() {
this.$emit('interacted')
- this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
+ this.$store.state.api.backendInteractor
+ .denyUser({ id: this.user.id })
.then(() => {
- this.$store.dispatch('dismissNotificationLocal', { id: this.notification.id })
+ this.$store.dispatch('dismissNotificationLocal', {
+ id: this.notification.id,
+ })
this.$store.dispatch('removeFollowRequest', this.user)
})
this.hideDenyConfirmDialog()
- }
+ },
},
computed: {
- userClass () {
+ userClass() {
return highlightClass(this.notification.from_profile)
},
- userStyle () {
+ userStyle() {
const highlight = this.$store.getters.mergedConfig.highlight
const user = this.notification.from_profile
return highlightStyle(highlight[user.screen_name])
},
- expandable () {
- return (new Set(['like', 'pleroma:emoji_reaction', 'repeat', 'poll'])).has(this.notification.type)
+ expandable() {
+ return new Set(['like', 'pleroma:emoji_reaction', 'repeat', 'poll']).has(
+ this.notification.type,
+ )
},
- user () {
+ user() {
return this.$store.getters.findUser(this.notification.from_profile.id)
},
- userProfileLink () {
+ userProfileLink() {
return this.generateUserProfileLink(this.user)
},
- targetUser () {
+ targetUser() {
return this.$store.getters.findUser(this.notification.target.id)
},
- targetUserProfileLink () {
+ targetUserProfileLink() {
return this.generateUserProfileLink(this.targetUser)
},
- needMute () {
+ needMute() {
return this.$store.getters.relationship(this.user.id).muting
},
- isStatusNotification () {
+ isStatusNotification() {
return isStatusNotification(this.notification.type)
},
- mergedConfig () {
+ mergedConfig() {
return this.$store.getters.mergedConfig
},
- shouldConfirmApprove () {
+ shouldConfirmApprove() {
return this.mergedConfig.modalOnApproveFollow
},
- shouldConfirmDeny () {
+ shouldConfirmDeny() {
return this.mergedConfig.modalOnDenyFollow
},
...mapState({
- currentUser: state => state.users.currentUser
- })
- }
+ currentUser: (state) => state.users.currentUser,
+ }),
+ },
}
export default Notification
diff --git a/src/components/notification/notification.style.js b/src/components/notification/notification.style.js
index 05c1f6f23..49e28cf2e 100644
--- a/src/components/notification/notification.style.js
+++ b/src/components/notification/notification.style.js
@@ -7,7 +7,7 @@ export default {
'Icon',
'Border',
'Avatar',
- 'PollGraph'
+ 'PollGraph',
],
- defaultRules: []
+ defaultRules: [],
}
diff --git a/src/components/notifications/notification_filters.vue b/src/components/notifications/notification_filters.vue
index 0b740ea0a..7be8eb76b 100644
--- a/src/components/notifications/notification_filters.vue
+++ b/src/components/notifications/notification_filters.vue
@@ -107,30 +107,29 @@
diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
index ced97d57f..9e349a2eb 100644
--- a/src/components/notifications/notifications.js
+++ b/src/components/notifications/notifications.js
@@ -1,28 +1,30 @@
+import { mapState } from 'pinia'
import { computed } from 'vue'
import { mapGetters } from 'vuex'
-import { mapState } from 'pinia'
-import Notification from '../notification/notification.vue'
-import ExtraNotifications from '../extra_notifications/extra_notifications.vue'
-import NotificationFilters from './notification_filters.vue'
-import notificationsFetcher from '../../services/notifications_fetcher/notifications_fetcher.service.js'
-import {
- notificationsFromStore,
- filteredNotificationsFromStore,
- unseenNotificationsFromStore,
- countExtraNotifications,
- ACTIONABLE_NOTIFICATION_TYPES
-} from '../../services/notification_utils/notification_utils.js'
-import FaviconService from '../../services/favicon_service/favicon_service.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { faCircleNotch, faArrowUp, faMinus } from '@fortawesome/free-solid-svg-icons'
-import { useInterfaceStore } from 'src/stores/interface'
-import { useAnnouncementsStore } from 'src/stores/announcements'
-library.add(
- faCircleNotch,
+import { useAnnouncementsStore } from 'src/stores/announcements'
+import { useInterfaceStore } from 'src/stores/interface'
+import FaviconService from '../../services/favicon_service/favicon_service.js'
+import {
+ ACTIONABLE_NOTIFICATION_TYPES,
+ countExtraNotifications,
+ filteredNotificationsFromStore,
+ notificationsFromStore,
+ unseenNotificationsFromStore,
+} from '../../services/notification_utils/notification_utils.js'
+import notificationsFetcher from '../../services/notifications_fetcher/notifications_fetcher.service.js'
+import ExtraNotifications from '../extra_notifications/extra_notifications.vue'
+import Notification from '../notification/notification.vue'
+import NotificationFilters from './notification_filters.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
faArrowUp,
- faMinus
-)
+ faCircleNotch,
+ faMinus,
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(faCircleNotch, faArrowUp, faMinus)
const DEFAULT_SEEN_TO_DISPLAY_COUNT = 30
@@ -30,7 +32,7 @@ const Notifications = {
components: {
Notification,
NotificationFilters,
- ExtraNotifications
+ ExtraNotifications,
},
props: {
// Disables panel styles, unread mark, potentially other notification-related actions
@@ -41,93 +43,110 @@ const Notifications = {
// Do not show extra notifications
noExtra: {
type: Boolean,
- default: false
+ default: false,
},
// Disable teleporting (i.e. for /users/user/notifications)
- disableTeleport: Boolean
+ disableTeleport: Boolean,
},
- data () {
+ data() {
return {
showScrollTop: false,
bottomedOut: false,
// How many seen notifications to display in the list. The more there are,
// the heavier the page becomes. This count is increased when loading
// older notifications, and cut back to default whenever hitting "Read!".
- seenToDisplayCount: DEFAULT_SEEN_TO_DISPLAY_COUNT
+ seenToDisplayCount: DEFAULT_SEEN_TO_DISPLAY_COUNT,
}
},
- provide () {
+ provide() {
return {
- popoversZLayer: computed(() => this.popoversZLayer)
+ popoversZLayer: computed(() => this.popoversZLayer),
}
},
computed: {
- mainClass () {
+ mainClass() {
return this.minimalMode ? '' : 'panel panel-default'
},
- notifications () {
+ notifications() {
return notificationsFromStore(this.$store)
},
- error () {
+ error() {
return this.$store.state.notifications.error
},
- unseenNotifications () {
+ unseenNotifications() {
return unseenNotificationsFromStore(this.$store)
},
- filteredNotifications () {
+ filteredNotifications() {
if (this.unseenAtTop) {
return [
- ...filteredNotificationsFromStore(this.$store).filter(n => this.shouldShowUnseen(n)),
- ...filteredNotificationsFromStore(this.$store).filter(n => !this.shouldShowUnseen(n))
+ ...filteredNotificationsFromStore(this.$store).filter((n) =>
+ this.shouldShowUnseen(n),
+ ),
+ ...filteredNotificationsFromStore(this.$store).filter(
+ (n) => !this.shouldShowUnseen(n),
+ ),
]
} else {
return filteredNotificationsFromStore(this.$store, this.filterMode)
}
},
- unseenCountBadgeText () {
+ unseenCountBadgeText() {
return `${this.unseenCount ? this.unseenCount : ''}${this.extraNotificationsCount ? '*' : ''}`
},
- unseenCount () {
+ unseenCount() {
return this.unseenNotifications.length
},
- ignoreInactionableSeen () { return this.$store.getters.mergedConfig.ignoreInactionableSeen },
- extraNotificationsCount () {
+ ignoreInactionableSeen() {
+ return this.$store.getters.mergedConfig.ignoreInactionableSeen
+ },
+ extraNotificationsCount() {
return countExtraNotifications(this.$store)
},
- unseenCountTitle () {
- return this.unseenNotifications.length + (this.unreadChatCount) + this.unreadAnnouncementCount
+ unseenCountTitle() {
+ return (
+ this.unseenNotifications.length +
+ this.unreadChatCount +
+ this.unreadAnnouncementCount
+ )
},
- loading () {
+ loading() {
return this.$store.state.notifications.loading
},
- noHeading () {
+ noHeading() {
const { layoutType } = useInterfaceStore()
return this.minimalMode || layoutType === 'mobile'
},
- teleportTarget () {
+ teleportTarget() {
const { layoutType } = useInterfaceStore()
const map = {
wide: '#notifs-column',
- mobile: '#mobile-notifications'
+ mobile: '#mobile-notifications',
}
return map[layoutType] || '#notifs-sidebar'
},
- popoversZLayer () {
+ popoversZLayer() {
const { layoutType } = useInterfaceStore()
return layoutType === 'mobile' ? 'navbar' : null
},
- notificationsToDisplay () {
- return this.filteredNotifications.slice(0, this.unseenCount + this.seenToDisplayCount)
+ notificationsToDisplay() {
+ return this.filteredNotifications.slice(
+ 0,
+ this.unseenCount + this.seenToDisplayCount,
+ )
},
- noSticky () { return this.$store.getters.mergedConfig.disableStickyHeaders },
- unseenAtTop () { return this.$store.getters.mergedConfig.unseenAtTop },
- showExtraNotifications () {
+ noSticky() {
+ return this.$store.getters.mergedConfig.disableStickyHeaders
+ },
+ unseenAtTop() {
+ return this.$store.getters.mergedConfig.unseenAtTop
+ },
+ showExtraNotifications() {
return !this.noExtra
},
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
- ...mapGetters(['unreadChatCount'])
+ ...mapGetters(['unreadChatCount']),
},
- mounted () {
+ mounted() {
this.scrollerRef = this.$refs.root.closest('.column.-scrollable')
if (!this.scrollerRef) {
this.scrollerRef = this.$refs.root.closest('.mobile-notifications')
@@ -137,12 +156,12 @@ const Notifications = {
}
this.scrollerRef.addEventListener('scroll', this.updateScrollPosition)
},
- unmounted () {
+ unmounted() {
if (!this.scrollerRef) return
this.scrollerRef.removeEventListener('scroll', this.updateScrollPosition)
},
watch: {
- unseenCountTitle (count) {
+ unseenCountTitle(count) {
if (count > 0) {
FaviconService.drawFaviconBadge()
useInterfaceStore().setPageTitle(`(${count})`)
@@ -151,10 +170,13 @@ const Notifications = {
useInterfaceStore().setPageTitle('')
}
},
- teleportTarget () {
+ teleportTarget() {
// handle scroller change
this.$nextTick(() => {
- this.scrollerRef.removeEventListener('scroll', this.updateScrollPosition)
+ this.scrollerRef.removeEventListener(
+ 'scroll',
+ this.updateScrollPosition,
+ )
this.scrollerRef = this.$refs.root.closest('.column.-scrollable')
if (!this.scrollerRef) {
this.scrollerRef = this.$refs.root.closest('.mobile-notifications')
@@ -162,17 +184,18 @@ const Notifications = {
this.scrollerRef.addEventListener('scroll', this.updateScrollPosition)
this.updateScrollPosition()
})
- }
+ },
},
methods: {
- scrollToTop () {
+ scrollToTop() {
const scrollable = this.scrollerRef
scrollable.scrollTo({ top: this.$refs.root.offsetTop })
},
- updateScrollPosition () {
- this.showScrollTop = this.$refs.root.offsetTop < this.scrollerRef.scrollTop
+ updateScrollPosition() {
+ this.showScrollTop =
+ this.$refs.root.offsetTop < this.scrollerRef.scrollTop
},
- shouldShowUnseen (notification) {
+ shouldShowUnseen(notification) {
if (notification.seen) return false
const actionable = ACTIONABLE_NOTIFICATION_TYPES.has(notification.type)
@@ -182,26 +205,29 @@ const Notifications = {
* everything else (likes/repeats/reacts) cannot be acted and therefore we just clear
* the "seen" status upon any clicks on them
*/
- notificationClicked (notification) {
+ notificationClicked(notification) {
const { id } = notification
this.$store.dispatch('notificationClicked', { id })
},
- notificationInteracted (notification) {
+ notificationInteracted(notification) {
const { id } = notification
this.$store.dispatch('markSingleNotificationAsSeen', { id })
},
- markAsSeen () {
+ markAsSeen() {
this.$store.dispatch('markNotificationsAsSeen')
this.seenToDisplayCount = DEFAULT_SEEN_TO_DISPLAY_COUNT
},
- fetchOlderNotifications () {
+ fetchOlderNotifications() {
if (this.loading) {
return
}
const seenCount = this.filteredNotifications.length - this.unseenCount
if (this.seenToDisplayCount < seenCount) {
- this.seenToDisplayCount = Math.min(this.seenToDisplayCount + 20, seenCount)
+ this.seenToDisplayCount = Math.min(
+ this.seenToDisplayCount + 20,
+ seenCount,
+ )
return
} else if (this.seenToDisplayCount > seenCount) {
this.seenToDisplayCount = seenCount
@@ -210,19 +236,21 @@ const Notifications = {
const store = this.$store
const credentials = store.state.users.currentUser.credentials
store.commit('setNotificationsLoading', { value: true })
- notificationsFetcher.fetchAndUpdate({
- store,
- credentials,
- older: true
- }).then(notifs => {
- store.commit('setNotificationsLoading', { value: false })
- if (notifs.length === 0) {
- this.bottomedOut = true
- }
- this.seenToDisplayCount += notifs.length
- })
- }
- }
+ notificationsFetcher
+ .fetchAndUpdate({
+ store,
+ credentials,
+ older: true,
+ })
+ .then((notifs) => {
+ store.commit('setNotificationsLoading', { value: false })
+ if (notifs.length === 0) {
+ this.bottomedOut = true
+ }
+ this.seenToDisplayCount += notifs.length
+ })
+ },
+ },
}
export default Notifications
diff --git a/src/components/oauth_callback/oauth_callback.js b/src/components/oauth_callback/oauth_callback.js
index 02e4c9ffc..82c3db047 100644
--- a/src/components/oauth_callback/oauth_callback.js
+++ b/src/components/oauth_callback/oauth_callback.js
@@ -1,25 +1,27 @@
-import oauth from '../../services/new_api/oauth.js'
import { useOAuthStore } from 'src/stores/oauth.js'
+import oauth from '../../services/new_api/oauth.js'
const oac = {
props: ['code'],
- mounted () {
+ mounted() {
if (this.code) {
const oauthStore = useOAuthStore()
const { clientId, clientSecret } = oauthStore
- oauth.getToken({
- clientId,
- clientSecret,
- instance: this.$store.state.instance.server,
- code: this.code
- }).then((result) => {
- oauthStore.setToken(result.access_token)
- this.$store.dispatch('loginUser', result.access_token)
- this.$router.push({ name: 'friends' })
- })
+ oauth
+ .getToken({
+ clientId,
+ clientSecret,
+ instance: this.$store.state.instance.server,
+ code: this.code,
+ })
+ .then((result) => {
+ oauthStore.setToken(result.access_token)
+ this.$store.dispatch('loginUser', result.access_token)
+ this.$router.push({ name: 'friends' })
+ })
}
- }
+ },
}
export default oac
diff --git a/src/components/opacity_input/opacity_input.vue b/src/components/opacity_input/opacity_input.vue
index 19de233d7..b8012741f 100644
--- a/src/components/opacity_input/opacity_input.vue
+++ b/src/components/opacity_input/opacity_input.vue
@@ -36,16 +36,14 @@
import Checkbox from '../checkbox/checkbox.vue'
export default {
components: {
- Checkbox
+ Checkbox,
},
- props: [
- 'name', 'label', 'modelValue', 'fallback', 'disabled'
- ],
+ props: ['name', 'label', 'modelValue', 'fallback', 'disabled'],
emits: ['update:modelValue'],
computed: {
- present () {
+ present() {
return typeof this.modelValue !== 'undefined'
- }
- }
+ },
+ },
}
diff --git a/src/components/optional_router_link/optional_router_link.vue b/src/components/optional_router_link/optional_router_link.vue
index d56ad268a..b0d553801 100644
--- a/src/components/optional_router_link/optional_router_link.vue
+++ b/src/components/optional_router_link/optional_router_link.vue
@@ -18,6 +18,6 @@
diff --git a/src/components/palette_editor/palette_editor.vue b/src/components/palette_editor/palette_editor.vue
index 3040696d0..21b40bccb 100644
--- a/src/components/palette_editor/palette_editor.vue
+++ b/src/components/palette_editor/palette_editor.vue
@@ -49,22 +49,15 @@ import { computed } from 'vue'
import ColorInput from 'src/components/color_input/color_input.vue'
import {
+ newExporter,
newImporter,
- newExporter
} from 'src/services/export_import/export_import.js'
-
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faFileImport,
- faFileExport
-} from '@fortawesome/free-solid-svg-icons'
-
import { useInterfaceStore } from 'src/stores/interface'
-library.add(
- faFileImport,
- faFileExport
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faFileExport, faFileImport } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faFileImport, faFileExport)
const paletteKeys = [
'bg',
@@ -76,30 +69,31 @@ const paletteKeys = [
'cBlue',
'cGreen',
'cOrange',
- 'wallpaper'
+ 'wallpaper',
]
const props = defineProps(['modelValue', 'compact', 'apply', 'disabled'])
const emit = defineEmits(['update:modelValue', 'applyPalette'])
-const getExportedObject = () => paletteKeys.reduce((acc, key) => {
- const value = props.modelValue[key]
- if (value == null) {
- return acc
- } else {
- return { ...acc, [key]: props.modelValue[key] }
- }
-}, {})
+const getExportedObject = () =>
+ paletteKeys.reduce((acc, key) => {
+ const value = props.modelValue[key]
+ if (value == null) {
+ return acc
+ } else {
+ return { ...acc, [key]: props.modelValue[key] }
+ }
+ }, {})
const paletteExporter = newExporter({
filename: 'pleroma_palette',
extension: 'json',
- getExportedObject
+ getExportedObject,
})
const paletteImporter = newImporter({
accept: '.json',
- onImport (parsed) {
+ onImport(parsed) {
emit('update:modelValue', parsed)
- }
+ },
})
const exportPalette = () => {
@@ -136,7 +130,7 @@ const fallback = (key) => {
const updatePalette = (paletteKey, value) => {
emit('update:modelValue', {
...props.modelValue,
- [paletteKey]: value
+ [paletteKey]: value,
})
}
diff --git a/src/components/panel.style.js b/src/components/panel.style.js
index 2c8956ae1..ff8c2bf3b 100644
--- a/src/components/panel.style.js
+++ b/src/components/panel.style.js
@@ -9,15 +9,9 @@ export default {
'PanelHeader',
'Post',
'Notification',
- 'MenuItem'
- ],
- validInnerComponentsLite: [
- 'Text',
- 'Link',
- 'Icon',
- 'Border',
- 'PanelHeader'
+ 'MenuItem',
],
+ validInnerComponentsLite: ['Text', 'Link', 'Icon', 'Border', 'PanelHeader'],
defaultRules: [
{
directives: {
@@ -25,23 +19,25 @@ export default {
background: '--bg',
roundness: 3,
blur: '5px',
- shadow: [{
- x: 0,
- y: 0,
- blur: 3,
- spread: 0,
- color: '#000000',
- alpha: 0.5
- },
- {
- x: 0,
- y: 4,
- blur: 6,
- spread: 3,
- color: '#000000',
- alpha: 0.3
- }]
- }
- }
- ]
+ shadow: [
+ {
+ x: 0,
+ y: 0,
+ blur: 3,
+ spread: 0,
+ color: '#000000',
+ alpha: 0.5,
+ },
+ {
+ x: 0,
+ y: 4,
+ blur: 6,
+ spread: 3,
+ color: '#000000',
+ alpha: 0.3,
+ },
+ ],
+ },
+ },
+ ],
}
diff --git a/src/components/panel_header.style.js b/src/components/panel_header.style.js
index 4e5f97760..67673e1bf 100644
--- a/src/components/panel_header.style.js
+++ b/src/components/panel_header.style.js
@@ -7,7 +7,7 @@ export default {
'Icon',
'Button',
'ButtonUnstyled',
- 'Alert'
+ 'Alert',
],
defaultRules: [
{
@@ -15,24 +15,26 @@ export default {
directives: {
backgroundNoCssColor: 'yes',
background: '--fg',
- shadow: [{
- x: 0,
- y: 1,
- blur: 3,
- spread: 0,
- color: '#000000',
- alpha: 0.4
- },
- {
- x: 0,
- y: 1,
- blur: 0,
- spread: 0,
- color: '#ffffff',
- alpha: 0.2,
- inset: true
- }]
- }
- }
- ]
+ shadow: [
+ {
+ x: 0,
+ y: 1,
+ blur: 3,
+ spread: 0,
+ color: '#000000',
+ alpha: 0.4,
+ },
+ {
+ x: 0,
+ y: 1,
+ blur: 0,
+ spread: 0,
+ color: '#ffffff',
+ alpha: 0.2,
+ inset: true,
+ },
+ ],
+ },
+ },
+ ],
}
diff --git a/src/components/panel_loading/panel_loading.vue b/src/components/panel_loading/panel_loading.vue
index 7a8321220..df29e5df0 100644
--- a/src/components/panel_loading/panel_loading.vue
+++ b/src/components/panel_loading/panel_loading.vue
@@ -15,9 +15,7 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faCircleNotch
-)
+library.add(faCircleNotch)
export default {}
diff --git a/src/components/password_reset/password_reset.js b/src/components/password_reset/password_reset.js
index 3d94f5e72..4fd53f8dd 100644
--- a/src/components/password_reset/password_reset.js
+++ b/src/components/password_reset/password_reset.js
@@ -1,34 +1,32 @@
import { mapState } from 'vuex'
-import passwordResetApi from '../../services/new_api/password_reset.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faTimes
-} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faTimes
-)
+import passwordResetApi from '../../services/new_api/password_reset.js'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faTimes } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faTimes)
const passwordReset = {
data: () => ({
user: {
- email: ''
+ email: '',
},
isPending: false,
success: false,
throttled: false,
- error: null
+ error: null,
}),
computed: {
...mapState({
signedIn: (state) => !!state.users.currentUser,
- instance: state => state.instance
+ instance: (state) => state.instance,
}),
- mailerEnabled () {
+ mailerEnabled() {
return this.instance.mailerEnabled
- }
+ },
},
- created () {
+ created() {
if (this.signedIn) {
this.$router.push({ name: 'root' })
}
@@ -36,36 +34,38 @@ const passwordReset = {
props: {
passwordResetRequested: {
default: false,
- type: Boolean
- }
+ type: Boolean,
+ },
},
methods: {
- dismissError () {
+ dismissError() {
this.error = null
},
- submit () {
+ submit() {
this.isPending = true
const email = this.user.email
const instance = this.instance.server
- passwordResetApi({ instance, email }).then(({ status }) => {
- this.isPending = false
- this.user.email = ''
+ passwordResetApi({ instance, email })
+ .then(({ status }) => {
+ this.isPending = false
+ this.user.email = ''
- if (status === 204) {
- this.success = true
- this.error = null
- } else if (status === 429) {
- this.throttled = true
- this.error = this.$t('password_reset.too_many_requests')
- }
- }).catch(() => {
- this.isPending = false
- this.user.email = ''
- this.error = this.$t('general.generic_error')
- })
- }
- }
+ if (status === 204) {
+ this.success = true
+ this.error = null
+ } else if (status === 429) {
+ this.throttled = true
+ this.error = this.$t('password_reset.too_many_requests')
+ }
+ })
+ .catch(() => {
+ this.isPending = false
+ this.user.email = ''
+ this.error = this.$t('general.generic_error')
+ })
+ },
+ },
}
export default passwordReset
diff --git a/src/components/pinch_zoom/pinch_zoom.js b/src/components/pinch_zoom/pinch_zoom.js
index 82670ddfa..448f90e4b 100644
--- a/src/components/pinch_zoom/pinch_zoom.js
+++ b/src/components/pinch_zoom/pinch_zoom.js
@@ -2,12 +2,12 @@ import PinchZoom from '@kazvmoe-infra/pinch-zoom-element'
export default {
methods: {
- setTransform ({ scale, x, y }) {
+ setTransform({ scale, x, y }) {
this.$el.setTransform({ scale, x, y })
- }
+ },
},
- created () {
+ created() {
// Make lint happy
- (() => PinchZoom)()
- }
+ ;(() => PinchZoom)()
+ },
}
diff --git a/src/components/poll/poll.js b/src/components/poll/poll.js
index a1b7808f2..594a7be88 100644
--- a/src/components/poll/poll.js
+++ b/src/components/poll/poll.js
@@ -1,8 +1,9 @@
-import Timeago from 'components/timeago/timeago.vue'
-import genRandomSeed from '../../services/random_seed/random_seed.service.js'
-import RichContent from 'components/rich_content/rich_content.jsx'
import Checkbox from 'components/checkbox/checkbox.vue'
+import RichContent from 'components/rich_content/rich_content.jsx'
+import Timeago from 'components/timeago/timeago.vue'
+
import { usePollsStore } from 'src/stores/polls'
+import genRandomSeed from '../../services/random_seed/random_seed.service.js'
export default {
name: 'Poll',
@@ -10,83 +11,85 @@ export default {
components: {
Timeago,
RichContent,
- Checkbox
+ Checkbox,
},
- data () {
+ data() {
return {
loading: false,
choices: [],
- randomSeed: genRandomSeed()
+ randomSeed: genRandomSeed(),
}
},
- created () {
+ created() {
if (!usePollsStore().pollsObject[this.pollId]) {
usePollsStore().mergeOrAddPoll(this.basePoll)
}
usePollsStore().trackPoll(this.pollId)
},
- unmounted () {
+ unmounted() {
usePollsStore().untrackPoll(this.pollId)
},
computed: {
- pollId () {
+ pollId() {
return this.basePoll.id
},
- poll () {
+ poll() {
const storePoll = usePollsStore().pollsObject[this.pollId]
return storePoll || {}
},
- options () {
+ options() {
return (this.poll && this.poll.options) || []
},
- expiresAt () {
+ expiresAt() {
return (this.poll && this.poll.expires_at) || null
},
- expired () {
+ expired() {
return (this.poll && this.poll.expired) || false
},
- expirationLabel () {
+ expirationLabel() {
if (this.$store.getters.mergedConfig.useAbsoluteTimeFormat) {
return this.expired ? 'polls.expired_at' : 'polls.expires_at'
} else {
return this.expired ? 'polls.expired' : 'polls.expires_in'
}
},
- loggedIn () {
+ loggedIn() {
return this.$store.state.users.currentUser
},
- showResults () {
+ showResults() {
return this.poll.voted || this.expired || !this.loggedIn
},
- totalVotesCount () {
+ totalVotesCount() {
return this.poll.votes_count
},
- containerClass () {
+ containerClass() {
return {
- loading: this.loading
+ loading: this.loading,
}
},
- choiceIndices () {
+ choiceIndices() {
// Convert array of booleans into an array of indices of the
// items that were 'true', so [true, false, false, true] becomes
// [0, 3].
return this.choices
.map((entry, index) => entry && index)
- .filter(value => typeof value === 'number')
+ .filter((value) => typeof value === 'number')
},
- isDisabled () {
+ isDisabled() {
const noChoice = this.choiceIndices.length === 0
return this.loading || noChoice
- }
+ },
},
methods: {
- percentageForOption (count) {
- return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100)
+ percentageForOption(count) {
+ return this.totalVotesCount === 0
+ ? 0
+ : Math.round((count / this.totalVotesCount) * 100)
},
- resultTitle (option) {
+ resultTitle(option) {
return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`
},
- activateOption (index, value) {
+ activateOption(index, value) {
let result
if (this.poll.multiple) {
result = this.choices || this.options.map(() => false)
@@ -96,17 +99,21 @@ export default {
result[index] = value
this.choices = result
},
- optionId (index) {
+ optionId(index) {
return `poll${this.poll.id}-${index}`
},
- vote () {
+ vote() {
if (this.choiceIndices.length === 0) return
this.loading = true
- usePollsStore().votePoll(
- { id: this.statusId, pollId: this.poll.id, choices: this.choiceIndices }
- ).then(() => {
- this.loading = false
- })
- }
- }
+ usePollsStore()
+ .votePoll({
+ id: this.statusId,
+ pollId: this.poll.id,
+ choices: this.choiceIndices,
+ })
+ .then(() => {
+ this.loading = false
+ })
+ },
+ },
}
diff --git a/src/components/poll/poll_form.js b/src/components/poll/poll_form.js
index 7660db0c2..92b471314 100644
--- a/src/components/poll/poll_form.js
+++ b/src/components/poll/poll_form.js
@@ -1,35 +1,34 @@
import * as DateUtils from 'src/services/date_utils/date_utils.js'
import { pollFallback } from 'src/services/poll/poll.service.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
import Select from '../select/select.vue'
-import {
- faTimes,
- faPlus
-} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faTimes,
- faPlus
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faPlus, faTimes } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faTimes, faPlus)
export default {
components: {
- Select
+ Select,
},
name: 'PollForm',
props: {
visible: {},
params: {
type: Object,
- required: true
- }
+ required: true,
+ },
},
computed: {
pollType: {
- get () { return pollFallback(this.params, 'pollType') },
- set (newVal) { this.params.pollType = newVal }
+ get() {
+ return pollFallback(this.params, 'pollType')
+ },
+ set(newVal) {
+ this.params.pollType = newVal
+ },
},
- options () {
+ options() {
const hasOptions = !!this.params.options
if (!hasOptions) {
this.params.options = pollFallback(this.params, 'options')
@@ -37,54 +36,62 @@ export default {
return this.params.options
},
expiryAmount: {
- get () { return pollFallback(this.params, 'expiryAmount') },
- set (newVal) { this.params.expiryAmount = newVal }
+ get() {
+ return pollFallback(this.params, 'expiryAmount')
+ },
+ set(newVal) {
+ this.params.expiryAmount = newVal
+ },
},
expiryUnit: {
- get () { return pollFallback(this.params, 'expiryUnit') },
- set (newVal) { this.params.expiryUnit = newVal }
+ get() {
+ return pollFallback(this.params, 'expiryUnit')
+ },
+ set(newVal) {
+ this.params.expiryUnit = newVal
+ },
},
- pollLimits () {
+ pollLimits() {
return this.$store.state.instance.pollLimits
},
- maxOptions () {
+ maxOptions() {
return this.pollLimits.max_options
},
- maxLength () {
+ maxLength() {
return this.pollLimits.max_option_chars
},
- expiryUnits () {
+ expiryUnits() {
const allUnits = ['minutes', 'hours', 'days']
const expiry = this.convertExpiryFromUnit
return allUnits.filter(
- unit => this.pollLimits.max_expiration >= expiry(unit, 1)
+ (unit) => this.pollLimits.max_expiration >= expiry(unit, 1),
)
},
- minExpirationInCurrentUnit () {
+ minExpirationInCurrentUnit() {
return Math.ceil(
this.convertExpiryToUnit(
this.expiryUnit,
- this.pollLimits.min_expiration
- )
+ this.pollLimits.min_expiration,
+ ),
)
},
- maxExpirationInCurrentUnit () {
+ maxExpirationInCurrentUnit() {
return Math.floor(
this.convertExpiryToUnit(
this.expiryUnit,
- this.pollLimits.max_expiration
- )
+ this.pollLimits.max_expiration,
+ ),
)
- }
+ },
},
methods: {
- clear () {
+ clear() {
this.pollType = 'single'
this.options = ['', '']
this.expiryAmount = 10
this.expiryUnit = 'minutes'
},
- nextOption (index) {
+ nextOption(index) {
const element = this.$el.querySelector(`#poll-${index + 1}`)
if (element) {
element.focus()
@@ -98,30 +105,34 @@ export default {
}
}
},
- addOption () {
+ addOption() {
if (this.options.length < this.maxOptions) {
this.options.push('')
return true
}
return false
},
- deleteOption (index) {
+ deleteOption(index) {
if (this.options.length > 2) {
this.options.splice(index, 1)
}
},
- convertExpiryToUnit (unit, amount) {
+ convertExpiryToUnit(unit, amount) {
// Note: we want seconds and not milliseconds
return DateUtils.secondsToUnit(unit, amount)
},
- convertExpiryFromUnit (unit, amount) {
+ convertExpiryFromUnit(unit, amount) {
return DateUtils.unitToSeconds(unit, amount)
},
- expiryAmountChange () {
- this.expiryAmount =
- Math.max(this.minExpirationInCurrentUnit, this.expiryAmount)
- this.expiryAmount =
- Math.min(this.maxExpirationInCurrentUnit, this.expiryAmount)
- }
- }
+ expiryAmountChange() {
+ this.expiryAmount = Math.max(
+ this.minExpirationInCurrentUnit,
+ this.expiryAmount,
+ )
+ this.expiryAmount = Math.min(
+ this.maxExpirationInCurrentUnit,
+ this.expiryAmount,
+ )
+ },
+ },
}
diff --git a/src/components/poll/poll_graph.style.js b/src/components/poll/poll_graph.style.js
index 247a266a2..69e2fd3ad 100644
--- a/src/components/poll/poll_graph.style.js
+++ b/src/components/poll/poll_graph.style.js
@@ -5,8 +5,8 @@ export default {
{
directives: {
background: '--accent',
- opacity: 0.5
- }
- }
- ]
+ opacity: 0.5,
+ },
+ },
+ ],
}
diff --git a/src/components/popover.style.js b/src/components/popover.style.js
index 455b5f5e0..22c3e43d2 100644
--- a/src/components/popover.style.js
+++ b/src/components/popover.style.js
@@ -3,25 +3,25 @@ export default {
selector: '.popover',
lazy: true,
variants: {
- modal: '.modal'
+ modal: '.modal',
},
- validInnerComponents: [
- 'MenuItem'
- ],
+ validInnerComponents: ['MenuItem'],
defaultRules: [
{
directives: {
background: '--bg',
blur: '10px',
- shadow: [{
- x: 2,
- y: 2,
- blur: 3,
- spread: 0,
- color: '#000000',
- alpha: 0.5
- }]
- }
- }
- ]
+ shadow: [
+ {
+ x: 2,
+ y: 2,
+ blur: 3,
+ spread: 0,
+ color: '#000000',
+ alpha: 0.5,
+ },
+ ],
+ },
+ },
+ ],
}
diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js
index e8e857918..3b83bd58f 100644
--- a/src/components/popover/popover.js
+++ b/src/components/popover/popover.js
@@ -57,15 +57,16 @@ const Popover = {
triggerAttrs: {
type: Object,
- default: {}
- }
+ default: {},
+ },
},
- inject: { // override popover z layer
+ inject: {
+ // override popover z layer
popoversZLayer: {
- default: ''
- }
+ default: '',
+ },
},
- data () {
+ data() {
return {
// lockReEntry is a flag that is set when mouse cursor is leaving the popover's content
// so that if mouse goes back into popover it won't be re-shown again to prevent annoyance
@@ -83,14 +84,16 @@ const Popover = {
graceTimeout: null,
parentPopover: null,
disableClickOutside: false,
- childrenShown: new Set()
+ childrenShown: new Set(),
}
},
computed: {
- allTriggerAttrs () {
+ allTriggerAttrs() {
if (process.env.NODE_ENV === 'development') {
if ('aria-hidden' in this.triggerAttrs) {
- throw new Error('Do not use aria-hidden in triggerAttrs. Instead set hideTrigger to true')
+ throw new Error(
+ 'Do not use aria-hidden in triggerAttrs. Instead set hideTrigger to true',
+ )
}
}
@@ -104,18 +107,20 @@ const Popover = {
}
return attrs
- }
+ },
},
methods: {
- setAnchorEl (el) {
+ setAnchorEl(el) {
this.anchorEl = el
this.updateStyles()
},
- containerBoundingClientRect () {
- const container = this.boundToSelector ? this.$el.closest(this.boundToSelector) : this.$el.offsetParent
+ containerBoundingClientRect() {
+ const container = this.boundToSelector
+ ? this.$el.closest(this.boundToSelector)
+ : this.$el.offsetParent
return container.getBoundingClientRect()
},
- updateStyles () {
+ updateStyles() {
if (this.hidden) {
this.styles = {}
return
@@ -123,7 +128,10 @@ const Popover = {
// Popover will be anchored around this element, trigger ref is the container, so
// its children are what are inside the slot. Expect only one v-slot:trigger.
- const anchorEl = this.anchorEl || (this.$refs.trigger && this.$refs.trigger.children[0]) || this.$el
+ const anchorEl =
+ this.anchorEl ||
+ (this.$refs.trigger && this.$refs.trigger.children[0]) ||
+ this.$el
// SVGs don't have offsetWidth/Height, use fallback
const anchorHeight = anchorEl.offsetHeight || anchorEl.clientHeight
const anchorWidth = anchorEl.offsetWidth || anchorEl.clientWidth
@@ -138,7 +146,7 @@ const Popover = {
// Screen position of the origin point for popover = center of the anchor
const origin = {
x: anchorScreenBox.left + anchorWidth * 0.5,
- y: anchorScreenBox.top + anchorHeight * 0.5
+ y: anchorScreenBox.top + anchorHeight * 0.5,
}
const content = this.$refs.content
const overlayCenter = this.overlayCenters
@@ -146,7 +154,8 @@ const Popover = {
: null
// Minor optimization, don't call a slow reflow call if we don't have to
- const parentScreenBox = this.boundTo &&
+ const parentScreenBox =
+ this.boundTo &&
(this.boundTo.x === 'container' || this.boundTo.y === 'container') &&
this.containerBoundingClientRect()
@@ -154,25 +163,27 @@ const Popover = {
// What are the screen bounds for the popover? Viewport vs container
// when using viewport, using default margin values to dodge the navbar
- const xBounds = this.boundTo && this.boundTo.x === 'container'
- ? {
- min: parentScreenBox.left + (margin.left || 0),
- max: parentScreenBox.right - (margin.right || 0)
- }
- : {
- min: 0 + (margin.left || 10),
- max: window.innerWidth - (margin.right || 10)
- }
+ const xBounds =
+ this.boundTo && this.boundTo.x === 'container'
+ ? {
+ min: parentScreenBox.left + (margin.left || 0),
+ max: parentScreenBox.right - (margin.right || 0),
+ }
+ : {
+ min: 0 + (margin.left || 10),
+ max: window.innerWidth - (margin.right || 10),
+ }
- const yBounds = this.boundTo && this.boundTo.y === 'container'
- ? {
- min: parentScreenBox.top + (margin.top || 0),
- max: parentScreenBox.bottom - (margin.bottom || 0)
- }
- : {
- min: 0 + (margin.top || 50),
- max: window.innerHeight - (margin.bottom || 5)
- }
+ const yBounds =
+ this.boundTo && this.boundTo.y === 'container'
+ ? {
+ min: parentScreenBox.top + (margin.top || 0),
+ max: parentScreenBox.bottom - (margin.bottom || 0),
+ }
+ : {
+ min: 0 + (margin.top || 50),
+ max: window.innerHeight - (margin.bottom || 5),
+ }
let horizOffset = 0
let vertOffset = 0
@@ -227,8 +238,12 @@ const Popover = {
// Handle special cases, first force to displaying on top if there's no space on bottom,
// regardless of what placement value was. Then check if there's no space on top, and
// force to bottom, again regardless of what placement value was.
- const topBoundary = origin.y - anchorHeight * 0.5 + (this.removePadding ? topPadding : 0)
- const bottomBoundary = origin.y + anchorHeight * 0.5 - (this.removePadding ? bottomPadding : 0)
+ const topBoundary =
+ origin.y - anchorHeight * 0.5 + (this.removePadding ? topPadding : 0)
+ const bottomBoundary =
+ origin.y +
+ anchorHeight * 0.5 -
+ (this.removePadding ? bottomPadding : 0)
if (bottomBoundary + content.offsetHeight > yBounds.max) usingTop = true
if (topBoundary - content.offsetHeight < yBounds.min) usingTop = false
@@ -246,8 +261,10 @@ const Popover = {
// Handle special cases, first force to displaying on left if there's no space on right,
// regardless of what placement value was. Then check if there's no space on right, and
// force to left, again regardless of what placement value was.
- const leftBoundary = origin.x - anchorWidth * 0.5 + (this.removePadding ? leftPadding : 0)
- const rightBoundary = origin.x + anchorWidth * 0.5 - (this.removePadding ? rightPadding : 0)
+ const leftBoundary =
+ origin.x - anchorWidth * 0.5 + (this.removePadding ? leftPadding : 0)
+ const rightBoundary =
+ origin.x + anchorWidth * 0.5 - (this.removePadding ? rightPadding : 0)
if (rightBoundary + content.offsetWidth > xBounds.max) usingLeft = true
if (leftBoundary - content.offsetWidth < xBounds.min) usingLeft = false
@@ -262,17 +279,18 @@ const Popover = {
this.styles = {
left: `${Math.round(translateX)}px`,
- top: `${Math.round(translateY)}px`
+ top: `${Math.round(translateY)}px`,
}
if (this.popoversZLayer) {
- this.styles['--ZI_popover_override'] = `var(--ZI_${this.popoversZLayer}_popovers)`
+ this.styles['--ZI_popover_override'] =
+ `var(--ZI_${this.popoversZLayer}_popovers)`
}
if (parentScreenBox) {
this.styles.maxWidth = `${Math.round(parentScreenBox.width)}px`
}
},
- showPopover () {
+ showPopover() {
if (this.disabled) return
this.disableClickOutside = true
setTimeout(() => {
@@ -291,7 +309,7 @@ const Popover = {
this.updateStyles()
})
},
- hidePopover () {
+ hidePopover() {
if (this.disabled) return
if (!this.hidden) this.$emit('close')
this.hidden = true
@@ -302,12 +320,12 @@ const Popover = {
this.scrollable?.removeEventListener('scroll', this.onScroll)
this.scrollable?.removeEventListener('resize', this.onResize)
},
- resizePopover () {
+ resizePopover() {
setTimeout(() => {
this.updateStyles()
}, 1)
},
- onMouseenter () {
+ onMouseenter() {
if (this.trigger === 'hover') {
this.lockReEntry = false
clearTimeout(this.graceTimeout)
@@ -315,12 +333,12 @@ const Popover = {
this.showPopover()
}
},
- onMouseleave () {
+ onMouseleave() {
if (this.trigger === 'hover' && this.childrenShown.size === 0) {
this.graceTimeout = setTimeout(() => this.hidePopover(), 1)
}
},
- onMouseenterContent () {
+ onMouseenterContent() {
if (this.trigger === 'hover' && !this.lockReEntry) {
this.lockReEntry = true
clearTimeout(this.graceTimeout)
@@ -328,12 +346,12 @@ const Popover = {
this.showPopover()
}
},
- onMouseleaveContent () {
+ onMouseleaveContent() {
if (this.trigger === 'hover' && this.childrenShown.size === 0) {
this.graceTimeout = setTimeout(() => this.hidePopover(), 1)
}
},
- onClick () {
+ onClick() {
if (this.trigger === 'click') {
if (this.hidden) {
this.showPopover()
@@ -342,7 +360,7 @@ const Popover = {
}
}
},
- onClickOutside (e) {
+ onClickOutside(e) {
if (this.disableClickOutside) return
if (this.hidden) return
if (this.$refs.content && this.$refs.content.contains(e.target)) return
@@ -351,35 +369,42 @@ const Popover = {
this.hidePopover()
if (this.parentPopover) this.parentPopover.onClickOutside(e)
},
- onScroll () {
+ onScroll() {
this.updateStyles()
},
- onResize () {
+ onResize() {
const content = this.$refs.content
if (!content) return
- if (this.oldSize.width !== content.offsetWidth || this.oldSize.height !== content.offsetHeight) {
+ if (
+ this.oldSize.width !== content.offsetWidth ||
+ this.oldSize.height !== content.offsetHeight
+ ) {
this.updateStyles()
- this.oldSize = { width: content.offsetWidth, height: content.offsetHeight }
+ this.oldSize = {
+ width: content.offsetWidth,
+ height: content.offsetHeight,
+ }
}
},
- onChildPopoverState (childRef, state) {
+ onChildPopoverState(childRef, state) {
if (state) {
this.childrenShown.add(childRef)
} else {
this.childrenShown.delete(childRef)
}
- }
+ },
},
- updated () {
+ updated() {
// Monitor changes to content size, update styles only when content sizes have changed,
// that should be the only time we need to move the popover box if we don't care about scroll
// or resize
this.onResize()
},
- mounted () {
+ mounted() {
this.teleport = true
- let scrollable = this.$refs.trigger.closest('.column.-scrollable') ||
- this.$refs.trigger.closest('.mobile-notifications')
+ let scrollable =
+ this.$refs.trigger.closest('.column.-scrollable') ||
+ this.$refs.trigger.closest('.mobile-notifications')
if (!scrollable) scrollable = window
this.scrollable = scrollable
let parent = this.$parent
@@ -388,9 +413,9 @@ const Popover = {
}
this.parentPopover = parent
},
- beforeUnmount () {
+ beforeUnmount() {
this.hidePopover()
- }
+ },
}
export default Popover
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index 238be88df..396aa94f0 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -1,41 +1,41 @@
-import statusPoster from '../../services/status_poster/status_poster.service.js'
-import genRandomSeed from '../../services/random_seed/random_seed.service.js'
-import MediaUpload from '../media_upload/media_upload.vue'
-import ScopeSelector from '../scope_selector/scope_selector.vue'
-import EmojiInput from '../emoji_input/emoji_input.vue'
-import PollForm from '../poll/poll_form.vue'
-import Attachment from '../attachment/attachment.vue'
+import { debounce, map, reject, uniqBy } from 'lodash'
+import { mapActions, mapState } from 'pinia'
+import { mapGetters } from 'vuex'
+
+import DraftCloser from 'src/components/draft_closer/draft_closer.vue'
import Gallery from 'src/components/gallery/gallery.vue'
-import StatusContent from '../status_content/status_content.vue'
import Popover from 'src/components/popover/popover.vue'
+import { pollFormToMasto } from 'src/services/poll/poll.service.js'
+import { useInterfaceStore } from 'src/stores/interface.js'
+import { useMediaViewerStore } from 'src/stores/media_viewer.js'
+import { propsToNative } from '../../services/attributes_helper/attributes_helper.service.js'
import fileTypeService from '../../services/file_type/file_type.service.js'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
-import { propsToNative } from '../../services/attributes_helper/attributes_helper.service.js'
-import { pollFormToMasto } from 'src/services/poll/poll.service.js'
-import { reject, map, uniqBy, debounce } from 'lodash'
-import suggestor from '../emoji_input/suggestor.js'
-import { mapGetters } from 'vuex'
-import { mapState, mapActions } from 'pinia'
+import genRandomSeed from '../../services/random_seed/random_seed.service.js'
+import statusPoster from '../../services/status_poster/status_poster.service.js'
+import Attachment from '../attachment/attachment.vue'
import Checkbox from '../checkbox/checkbox.vue'
+import EmojiInput from '../emoji_input/emoji_input.vue'
+import suggestor from '../emoji_input/suggestor.js'
+import MediaUpload from '../media_upload/media_upload.vue'
+import PollForm from '../poll/poll_form.vue'
+import ScopeSelector from '../scope_selector/scope_selector.vue'
import Select from '../select/select.vue'
-import DraftCloser from 'src/components/draft_closer/draft_closer.vue'
+import StatusContent from '../status_content/status_content.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faSmileBeam,
- faPollH,
- faUpload,
faBan,
- faTimes,
- faCircleNotch,
faChevronDown,
faChevronLeft,
- faChevronRight
+ faChevronRight,
+ faCircleNotch,
+ faPollH,
+ faSmileBeam,
+ faTimes,
+ faUpload,
} from '@fortawesome/free-solid-svg-icons'
-import { useInterfaceStore } from 'src/stores/interface.js'
-import { useMediaViewerStore } from 'src/stores/media_viewer.js'
-
library.add(
faSmileBeam,
faPollH,
@@ -45,7 +45,7 @@ library.add(
faCircleNotch,
faChevronDown,
faChevronLeft,
- faChevronRight
+ faChevronRight,
)
const buildMentionsString = ({ user, attentions = [] }, currentUser) => {
@@ -117,7 +117,7 @@ const PostStatusForm = {
'emojiPickerPlacement',
'optimisticPosting',
'profileMention',
- 'draftId'
+ 'draftId',
],
emits: [
'posted',
@@ -126,7 +126,7 @@ const PostStatusForm = {
'mediaplay',
'mediapause',
'can-close',
- 'update'
+ 'update',
],
components: {
MediaUpload,
@@ -139,9 +139,9 @@ const PostStatusForm = {
StatusContent,
Gallery,
DraftCloser,
- Popover
+ Popover,
},
- mounted () {
+ mounted() {
this.updateIdempotencyKey()
this.resize(this.$refs.textarea)
@@ -154,28 +154,41 @@ const PostStatusForm = {
this.$refs.textarea.focus()
}
},
- data () {
+ data() {
const preset = this.$route.query.message
let statusText = preset || ''
const { scopeCopy } = this.$store.getters.mergedConfig
- const [statusType, refId] = typeAndRefId({ replyTo: this.replyTo, profileMention: this.profileMention && this.repliedUser?.id, statusId: this.statusId })
+ const [statusType, refId] = typeAndRefId({
+ replyTo: this.replyTo,
+ profileMention: this.profileMention && this.repliedUser?.id,
+ statusId: this.statusId,
+ })
// If we are starting a new post, do not associate it with old drafts
- let statusParams = !this.disableDraft && (this.draftId || statusType !== 'new') ? this.getDraft(statusType, refId) : null
+ let statusParams =
+ !this.disableDraft && (this.draftId || statusType !== 'new')
+ ? this.getDraft(statusType, refId)
+ : null
if (!statusParams) {
if (statusType === 'reply' || statusType === 'mention') {
const currentUser = this.$store.state.users.currentUser
- statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
+ statusText = buildMentionsString(
+ { user: this.repliedUser, attentions: this.attentions },
+ currentUser,
+ )
}
- const scope = ((this.copyMessageScope && scopeCopy) || this.copyMessageScope === 'direct')
- ? this.copyMessageScope
- : this.$store.state.users.currentUser.default_scope
+ const scope =
+ (this.copyMessageScope && scopeCopy) ||
+ this.copyMessageScope === 'direct'
+ ? this.copyMessageScope
+ : this.$store.state.users.currentUser.default_scope
- const { postContentType: contentType, sensitiveByDefault } = this.$store.getters.mergedConfig
+ const { postContentType: contentType, sensitiveByDefault } =
+ this.$store.getters.mergedConfig
statusParams = {
type: statusType,
@@ -189,7 +202,7 @@ const PostStatusForm = {
mediaDescriptions: {},
visibility: scope,
contentType,
- quoting: false
+ quoting: false,
}
if (statusType === 'edit') {
@@ -205,7 +218,7 @@ const PostStatusForm = {
hasPoll: false,
mediaDescriptions: this.statusMediaDescriptions || {},
visibility: this.statusScope || scope,
- contentType: statusContentType
+ contentType: statusContentType,
}
}
}
@@ -226,101 +239,109 @@ const PostStatusForm = {
emojiInputShown: false,
idempotencyKey: '',
saveInhibited: true,
- saveable: false
+ saveable: false,
}
},
computed: {
- users () {
+ users() {
return this.$store.state.users.users
},
- userDefaultScope () {
+ userDefaultScope() {
return this.$store.state.users.currentUser.default_scope
},
- showAllScopes () {
+ showAllScopes() {
return !this.mergedConfig.minimalScopesMode
},
- hideExtraActions () {
+ hideExtraActions() {
return this.disableDraft || this.hideDraft
},
- emojiUserSuggestor () {
+ emojiUserSuggestor() {
return suggestor({
emoji: [
...this.$store.getters.standardEmojiList,
- ...this.$store.state.instance.customEmoji
+ ...this.$store.state.instance.customEmoji,
],
- store: this.$store
+ store: this.$store,
})
},
- emojiSuggestor () {
+ emojiSuggestor() {
return suggestor({
emoji: [
...this.$store.getters.standardEmojiList,
- ...this.$store.state.instance.customEmoji
- ]
+ ...this.$store.state.instance.customEmoji,
+ ],
})
},
- emoji () {
+ emoji() {
return this.$store.getters.standardEmojiList || []
},
- customEmoji () {
+ customEmoji() {
return this.$store.state.instance.customEmoji || []
},
- statusLength () {
+ statusLength() {
return this.newStatus.status.length
},
- spoilerTextLength () {
+ spoilerTextLength() {
return this.newStatus.spoilerText.length
},
- statusLengthLimit () {
+ statusLengthLimit() {
return this.$store.state.instance.textlimit
},
- hasStatusLengthLimit () {
+ hasStatusLengthLimit() {
return this.statusLengthLimit > 0
},
- charactersLeft () {
- return this.statusLengthLimit - (this.statusLength + this.spoilerTextLength)
+ charactersLeft() {
+ return (
+ this.statusLengthLimit - (this.statusLength + this.spoilerTextLength)
+ )
},
- isOverLengthLimit () {
- return this.hasStatusLengthLimit && (this.charactersLeft < 0)
+ isOverLengthLimit() {
+ return this.hasStatusLengthLimit && this.charactersLeft < 0
},
- minimalScopesMode () {
+ minimalScopesMode() {
return this.$store.state.instance.minimalScopesMode
},
- alwaysShowSubject () {
+ alwaysShowSubject() {
return this.mergedConfig.alwaysShowSubjectInput
},
- postFormats () {
+ postFormats() {
return this.$store.state.instance.postFormats || []
},
- safeDMEnabled () {
+ safeDMEnabled() {
return this.$store.state.instance.safeDM
},
- pollsAvailable () {
- return this.$store.state.instance.pollsAvailable &&
+ pollsAvailable() {
+ return (
+ this.$store.state.instance.pollsAvailable &&
this.$store.state.instance.pollLimits.max_options >= 2 &&
this.disablePolls !== true
+ )
},
- hideScopeNotice () {
- return this.disableNotice || this.$store.getters.mergedConfig.hideScopeNotice
+ hideScopeNotice() {
+ return (
+ this.disableNotice || this.$store.getters.mergedConfig.hideScopeNotice
+ )
},
- pollContentError () {
- return this.pollFormVisible &&
- this.newStatus.poll &&
- this.newStatus.poll.error
+ pollContentError() {
+ return (
+ this.pollFormVisible && this.newStatus.poll && this.newStatus.poll.error
+ )
},
- showPreview () {
+ showPreview() {
return !this.disablePreview && (!!this.preview || this.previewLoading)
},
- emptyStatus () {
- return this.newStatus.status.trim() === '' && this.newStatus.files.length === 0
+ emptyStatus() {
+ return (
+ this.newStatus.status.trim() === '' && this.newStatus.files.length === 0
+ )
},
- uploadFileLimitReached () {
+ uploadFileLimitReached() {
return this.newStatus.files.length >= this.fileLimit
},
- isEdit () {
+ isEdit() {
return typeof this.statusId !== 'undefined' && this.statusId.trim() !== ''
},
- quotable () {
+ quotable() {
if (!this.$store.state.instance.quotingAvailable) {
return false
}
@@ -329,14 +350,17 @@ const PostStatusForm = {
return false
}
- const repliedStatus = this.$store.state.statuses.allStatusesObject[this.replyTo]
+ const repliedStatus =
+ this.$store.state.statuses.allStatusesObject[this.replyTo]
if (!repliedStatus) {
return false
}
- if (repliedStatus.visibility === 'public' ||
- repliedStatus.visibility === 'unlisted' ||
- repliedStatus.visibility === 'local') {
+ if (
+ repliedStatus.visibility === 'public' ||
+ repliedStatus.visibility === 'unlisted' ||
+ repliedStatus.visibility === 'local'
+ ) {
return true
} else if (repliedStatus.visibility === 'private') {
return repliedStatus.user.id === this.$store.state.users.currentUser.id
@@ -344,16 +368,16 @@ const PostStatusForm = {
return false
},
- debouncedMaybeAutoSaveDraft () {
+ debouncedMaybeAutoSaveDraft() {
return debounce(this.maybeAutoSaveDraft, 3000)
},
- pollFormVisible () {
+ pollFormVisible() {
return this.newStatus.hasPoll
},
- shouldAutoSaveDraft () {
+ shouldAutoSaveDraft() {
return this.$store.getters.mergedConfig.autoSaveDraft
},
- autoSaveState () {
+ autoSaveState() {
if (this.saveable) {
return this.$t('post_status.auto_save_saving')
} else if (this.newStatus.id) {
@@ -362,35 +386,39 @@ const PostStatusForm = {
return this.$t('post_status.auto_save_nothing_new')
}
},
- safeToSaveDraft () {
+ safeToSaveDraft() {
return (
- this.newStatus.status ||
- this.newStatus.spoilerText ||
- this.newStatus.files?.length ||
- this.newStatus.hasPoll
- ) && this.saveable
+ (this.newStatus.status ||
+ this.newStatus.spoilerText ||
+ this.newStatus.files?.length ||
+ this.newStatus.hasPoll) &&
+ this.saveable
+ )
},
- hasEmptyDraft () {
- return this.newStatus.id && !(
- this.newStatus.status ||
+ hasEmptyDraft() {
+ return (
+ this.newStatus.id &&
+ !(
+ this.newStatus.status ||
this.newStatus.spoilerText ||
this.newStatus.files?.length ||
this.newStatus.hasPoll
+ )
)
},
...mapGetters(['mergedConfig']),
...mapState(useInterfaceStore, {
- mobileLayout: store => store.mobileLayout
- })
+ mobileLayout: (store) => store.mobileLayout,
+ }),
},
watch: {
newStatus: {
deep: true,
- handler () {
+ handler() {
this.statusChanged()
- }
+ },
},
- saveable (val) {
+ saveable(val) {
// https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event#usage_notes
// MDN says we'd better add the beforeunload event listener only when needed, and remove it when it's no longer needed
if (val) {
@@ -398,22 +426,22 @@ const PostStatusForm = {
} else {
this.removeBeforeUnloadListener()
}
- }
+ },
},
- beforeUnmount () {
+ beforeUnmount() {
this.maybeAutoSaveDraft()
this.removeBeforeUnloadListener()
},
methods: {
...mapActions(useMediaViewerStore, ['increment']),
- statusChanged () {
+ statusChanged() {
this.autoPreview()
this.updateIdempotencyKey()
this.debouncedMaybeAutoSaveDraft()
this.saveable = true
this.saveInhibited = false
},
- clearStatus () {
+ clearStatus() {
const newStatus = this.newStatus
this.saveInhibited = true
this.newStatus = {
@@ -425,7 +453,7 @@ const PostStatusForm = {
poll: {},
hasPoll: false,
mediaDescriptions: {},
- quoting: false
+ quoting: false,
}
this.$refs.mediaUpload && this.$refs.mediaUpload.clearFile()
this.clearPollForm()
@@ -441,23 +469,36 @@ const PostStatusForm = {
if (this.preview) this.previewStatus()
this.saveable = false
},
- async postStatus (event, newStatus) {
- if (this.posting && !this.optimisticPosting) { return }
- if (this.disableSubmit) { return }
- if (this.emojiInputShown) { return }
+ async postStatus(event, newStatus) {
+ if (this.posting && !this.optimisticPosting) {
+ return
+ }
+ if (this.disableSubmit) {
+ return
+ }
+ if (this.emojiInputShown) {
+ return
+ }
if (this.submitOnEnter) {
event.stopPropagation()
event.preventDefault()
}
- if (this.optimisticPosting && (this.emptyStatus || this.isOverLengthLimit)) { return }
+ if (
+ this.optimisticPosting &&
+ (this.emptyStatus || this.isOverLengthLimit)
+ ) {
+ return
+ }
if (this.emptyStatus) {
this.error = this.$t('post_status.empty_status_error')
return
}
- const poll = this.newStatus.hasPoll ? pollFormToMasto(this.newStatus.poll) : {}
+ const poll = this.newStatus.hasPoll
+ ? pollFormToMasto(this.newStatus.poll)
+ : {}
if (this.pollContentError) {
this.error = this.pollContentError
return
@@ -473,7 +514,9 @@ const PostStatusForm = {
return
}
- const replyOrQuoteAttr = newStatus.quoting ? 'quoteId' : 'inReplyToStatusId'
+ const replyOrQuoteAttr = newStatus.quoting
+ ? 'quoteId'
+ : 'inReplyToStatusId'
const postingOptions = {
status: newStatus.status,
@@ -485,10 +528,12 @@ const PostStatusForm = {
[replyOrQuoteAttr]: this.replyTo,
contentType: newStatus.contentType,
poll,
- idempotencyKey: this.idempotencyKey
+ idempotencyKey: this.idempotencyKey,
}
- const postHandler = this.postHandler ? this.postHandler : statusPoster.postStatus
+ const postHandler = this.postHandler
+ ? this.postHandler
+ : statusPoster.postStatus
postHandler(postingOptions).then((data) => {
if (!data.error) {
@@ -501,7 +546,7 @@ const PostStatusForm = {
this.posting = false
})
},
- previewStatus () {
+ previewStatus() {
if (this.emptyStatus && this.newStatus.spoilerText.trim() === '') {
this.preview = { error: this.$t('post_status.preview_empty') }
this.previewLoading = false
@@ -509,89 +554,100 @@ const PostStatusForm = {
}
const newStatus = this.newStatus
this.previewLoading = true
- const replyOrQuoteAttr = newStatus.quoting ? 'quoteId' : 'inReplyToStatusId'
- statusPoster.postStatus({
- status: newStatus.status,
- spoilerText: newStatus.spoilerText || null,
- visibility: newStatus.visibility,
- sensitive: newStatus.nsfw,
- media: [],
- store: this.$store,
- [replyOrQuoteAttr]: this.replyTo,
- contentType: newStatus.contentType,
- poll: {},
- preview: true
- }).then((data) => {
- // Don't apply preview if not loading, because it means
- // user has closed the preview manually.
- if (!this.previewLoading) return
- if (!data.error) {
- this.preview = data
- } else {
- this.preview = { error: data.error }
- }
- }).catch((error) => {
- this.preview = { error }
- }).finally(() => {
- this.previewLoading = false
- })
+ const replyOrQuoteAttr = newStatus.quoting
+ ? 'quoteId'
+ : 'inReplyToStatusId'
+ statusPoster
+ .postStatus({
+ status: newStatus.status,
+ spoilerText: newStatus.spoilerText || null,
+ visibility: newStatus.visibility,
+ sensitive: newStatus.nsfw,
+ media: [],
+ store: this.$store,
+ [replyOrQuoteAttr]: this.replyTo,
+ contentType: newStatus.contentType,
+ poll: {},
+ preview: true,
+ })
+ .then((data) => {
+ // Don't apply preview if not loading, because it means
+ // user has closed the preview manually.
+ if (!this.previewLoading) return
+ if (!data.error) {
+ this.preview = data
+ } else {
+ this.preview = { error: data.error }
+ }
+ })
+ .catch((error) => {
+ this.preview = { error }
+ })
+ .finally(() => {
+ this.previewLoading = false
+ })
},
- debouncePreviewStatus: debounce(function () { this.previewStatus() }, 500),
- autoPreview () {
+ debouncePreviewStatus: debounce(function () {
+ this.previewStatus()
+ }, 500),
+ autoPreview() {
if (!this.preview) return
this.previewLoading = true
this.debouncePreviewStatus()
},
- closePreview () {
+ closePreview() {
this.preview = null
this.previewLoading = false
},
- togglePreview () {
+ togglePreview() {
if (this.showPreview) {
this.closePreview()
} else {
this.previewStatus()
}
},
- addMediaFile (fileInfo) {
+ addMediaFile(fileInfo) {
this.newStatus.files.push(fileInfo)
this.$emit('resize', { delayed: true })
},
- removeMediaFile (fileInfo) {
+ removeMediaFile(fileInfo) {
const index = this.newStatus.files.indexOf(fileInfo)
this.newStatus.files.splice(index, 1)
this.$emit('resize')
},
- editAttachment (fileInfo, newText) {
+ editAttachment(fileInfo, newText) {
this.newStatus.mediaDescriptions[fileInfo.id] = newText
},
- shiftUpMediaFile (fileInfo) {
+ shiftUpMediaFile(fileInfo) {
const { files } = this.newStatus
const index = this.newStatus.files.indexOf(fileInfo)
files.splice(index, 1)
files.splice(index - 1, 0, fileInfo)
},
- shiftDnMediaFile (fileInfo) {
+ shiftDnMediaFile(fileInfo) {
const { files } = this.newStatus
const index = this.newStatus.files.indexOf(fileInfo)
files.splice(index, 1)
files.splice(index + 1, 0, fileInfo)
},
- uploadFailed (errString, templateArgs) {
+ uploadFailed(errString, templateArgs) {
templateArgs = templateArgs || {}
- this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
+ this.error =
+ this.$t('upload.error.base') +
+ ' ' +
+ this.$t('upload.error.' + errString, templateArgs)
},
- startedUploadingFiles () {
+ startedUploadingFiles() {
this.uploadingFiles = true
},
- finishedUploadingFiles () {
+ finishedUploadingFiles() {
this.$emit('resize')
this.uploadingFiles = false
},
- type (fileInfo) {
+ type(fileInfo) {
return fileTypeService.fileType(fileInfo.mimetype)
},
- paste (e) {
+ paste(e) {
this.autoPreview()
this.resize(e)
if (e.clipboardData.files.length > 0) {
@@ -603,7 +659,7 @@ const PostStatusForm = {
this.dropFiles = [e.clipboardData.files[0]]
}
},
- fileDrop (e) {
+ fileDrop(e) {
if (e.dataTransfer && e.dataTransfer.types.includes('Files')) {
e.preventDefault() // allow dropping text like before
this.dropFiles = e.dataTransfer.files
@@ -611,7 +667,7 @@ const PostStatusForm = {
this.showDropIcon = 'hide'
}
},
- fileDragStop () {
+ fileDragStop() {
// The false-setting is done with delay because just using leave-events
// directly caused unwanted flickering, this is not perfect either but
// much less noticable.
@@ -619,21 +675,23 @@ const PostStatusForm = {
this.showDropIcon = 'fade'
this.dropStopTimeout = setTimeout(() => (this.showDropIcon = 'hide'), 500)
},
- fileDrag (e) {
+ fileDrag(e) {
e.dataTransfer.dropEffect = this.uploadFileLimitReached ? 'none' : 'copy'
if (e.dataTransfer && e.dataTransfer.types.includes('Files')) {
clearTimeout(this.dropStopTimeout)
this.showDropIcon = 'show'
}
},
- onEmojiInputInput () {
+ onEmojiInputInput() {
this.$nextTick(() => {
this.resize(this.$refs.textarea)
})
},
- resize (e) {
+ resize(e) {
const target = e.target || e
- if (!(target instanceof window.Element)) { return }
+ if (!(target instanceof window.Element)) {
+ return
+ }
// Reset to default height for empty form, nothing else to do here.
if (target.value === '') {
@@ -648,12 +706,14 @@ const PostStatusForm = {
* replies in notifs) or mobile post form. Note that getting and setting
* scroll is different for `Window` and `Element`s
*/
- const bottomBottomPaddingStr = window.getComputedStyle(bottomRef)['padding-bottom']
+ const bottomBottomPaddingStr =
+ window.getComputedStyle(bottomRef)['padding-bottom']
const bottomBottomPadding = pxStringToNumber(bottomBottomPaddingStr)
- const scrollerRef = this.$el.closest('.column.-scrollable') ||
- this.$el.closest('.post-form-modal-view') ||
- window
+ const scrollerRef =
+ this.$el.closest('.column.-scrollable') ||
+ this.$el.closest('.post-form-modal-view') ||
+ window
// Getting info about padding we have to account for, removing 'px' part
const topPaddingStr = window.getComputedStyle(target)['padding-top']
@@ -682,18 +742,20 @@ const PostStatusForm = {
*/
// this part has to be BEFORE the content size update
- const currentScroll = scrollerRef === window
- ? scrollerRef.scrollY
- : scrollerRef.scrollTop
- const scrollerHeight = scrollerRef === window
- ? scrollerRef.innerHeight
- : scrollerRef.offsetHeight
+ const currentScroll =
+ scrollerRef === window ? scrollerRef.scrollY : scrollerRef.scrollTop
+ const scrollerHeight =
+ scrollerRef === window
+ ? scrollerRef.innerHeight
+ : scrollerRef.offsetHeight
const scrollerBottomBorder = currentScroll + scrollerHeight
// BEGIN content size update
target.style.height = 'auto'
const heightWithoutPadding = Math.floor(target.scrollHeight - vertPadding)
- let newHeight = this.maxHeight ? Math.min(heightWithoutPadding, this.maxHeight) : heightWithoutPadding
+ let newHeight = this.maxHeight
+ ? Math.min(heightWithoutPadding, this.maxHeight)
+ : heightWithoutPadding
// This is a bit of a hack to combat target.scrollHeight being different on every other input
// on some browsers for whatever reason. Don't change the height if difference is 1px or less.
if (Math.abs(newHeight - oldHeight) <= 1) {
@@ -705,7 +767,10 @@ const PostStatusForm = {
// We check where the bottom border of form-bottom element is, this uses findOffset
// to find offset relative to scrollable container (scroller)
- const bottomBottomBorder = bottomRef.offsetHeight + findOffset(bottomRef, scrollerRef).top + bottomBottomPadding
+ const bottomBottomBorder =
+ bottomRef.offsetHeight +
+ findOffset(bottomRef, scrollerRef).top +
+ bottomBottomPadding
const isBottomObstructed = scrollerBottomBorder < bottomBottomBorder
const isFormBiggerThanScroller = scrollerHeight < formRef.offsetHeight
@@ -714,9 +779,13 @@ const PostStatusForm = {
// Keep form-bottom always visible so that submit button is in view EXCEPT
// if form element bigger than scroller and caret isn't at the end, so that
// if you scroll up and edit middle of text you won't get scrolled back to bottom
- const shouldScrollToBottom = isBottomObstructed &&
- !(isFormBiggerThanScroller &&
- this.$refs.textarea.selectionStart !== this.$refs.textarea.value.length)
+ const shouldScrollToBottom =
+ isBottomObstructed &&
+ !(
+ isFormBiggerThanScroller &&
+ this.$refs.textarea.selectionStart !==
+ this.$refs.textarea.value.length
+ )
const totalDelta = shouldScrollToBottom ? bottomChangeDelta : 0
const targetScroll = Math.round(currentScroll + totalDelta)
@@ -726,53 +795,60 @@ const PostStatusForm = {
scrollerRef.scrollTop = targetScroll
}
},
- clearError () {
+ clearError() {
this.error = null
},
- changeVis (visibility) {
+ changeVis(visibility) {
this.newStatus.visibility = visibility
},
- togglePollForm () {
+ togglePollForm() {
this.newStatus.hasPoll = !this.newStatus.hasPoll
},
- setPoll (poll) {
+ setPoll(poll) {
this.newStatus.poll = poll
},
- clearPollForm () {
+ clearPollForm() {
if (this.$refs.pollForm) {
this.$refs.pollForm.clear()
}
},
- dismissScopeNotice () {
- this.$store.dispatch('setOption', { name: 'hideScopeNotice', value: true })
+ dismissScopeNotice() {
+ this.$store.dispatch('setOption', {
+ name: 'hideScopeNotice',
+ value: true,
+ })
},
- setMediaDescription (id) {
+ setMediaDescription(id) {
const description = this.newStatus.mediaDescriptions[id]
if (!description || description.trim() === '') return
- return statusPoster.setMediaDescription({ store: this.$store, id, description })
+ return statusPoster.setMediaDescription({
+ store: this.$store,
+ id,
+ description,
+ })
},
- setAllMediaDescriptions () {
- const ids = this.newStatus.files.map(file => file.id)
- return Promise.all(ids.map(id => this.setMediaDescription(id)))
+ setAllMediaDescriptions() {
+ const ids = this.newStatus.files.map((file) => file.id)
+ return Promise.all(ids.map((id) => this.setMediaDescription(id)))
},
- handleEmojiInputShow (value) {
+ handleEmojiInputShow(value) {
this.emojiInputShown = value
},
- updateIdempotencyKey () {
+ updateIdempotencyKey() {
this.idempotencyKey = Date.now().toString()
},
- openProfileTab () {
+ openProfileTab() {
useInterfaceStore().openSettingsModalTab('profile')
},
- propsToNative (props) {
+ propsToNative(props) {
return propsToNative(props)
},
- saveDraft () {
- if (!this.disableDraft &&
- !this.saveInhibited) {
+ saveDraft() {
+ if (!this.disableDraft && !this.saveInhibited) {
if (this.safeToSaveDraft) {
- return this.$store.dispatch('addOrSaveDraft', { draft: this.newStatus })
- .then(id => {
+ return this.$store
+ .dispatch('addOrSaveDraft', { draft: this.newStatus })
+ .then((id) => {
if (this.newStatus.id !== id) {
this.newStatus.id = id
}
@@ -784,32 +860,34 @@ const PostStatusForm = {
})
} else if (this.hasEmptyDraft) {
// There is a draft, but there is nothing in it, clear it
- return this.abandonDraft()
- .then(() => {
- this.saveable = false
- if (!this.shouldAutoSaveDraft) {
- this.clearStatus()
- this.$emit('draft-done')
- }
- })
+ return this.abandonDraft().then(() => {
+ this.saveable = false
+ if (!this.shouldAutoSaveDraft) {
+ this.clearStatus()
+ this.$emit('draft-done')
+ }
+ })
}
}
return Promise.resolve()
},
- maybeAutoSaveDraft () {
+ maybeAutoSaveDraft() {
if (this.shouldAutoSaveDraft) {
this.saveDraft(false)
}
},
- abandonDraft () {
+ abandonDraft() {
return this.$store.dispatch('abandonDraft', { id: this.newStatus.id })
},
- getDraft (statusType, refId) {
+ getDraft(statusType, refId) {
const maybeDraft = this.$store.state.drafts.drafts[this.draftId]
if (this.draftId && maybeDraft) {
return maybeDraft
} else {
- const existingDrafts = this.$store.getters.draftsByTypeAndRefId(statusType, refId)
+ const existingDrafts = this.$store.getters.draftsByTypeAndRefId(
+ statusType,
+ refId,
+ )
if (existingDrafts.length) {
return existingDrafts[0]
@@ -817,35 +895,35 @@ const PostStatusForm = {
}
// No draft available, fall back
},
- requestClose () {
+ requestClose() {
if (!this.saveable) {
this.$emit('can-close')
} else {
this.$refs.draftCloser.requestClose()
}
},
- saveAndCloseDraft () {
+ saveAndCloseDraft() {
this.saveDraft().then(() => {
this.$emit('can-close')
})
},
- discardAndCloseDraft () {
+ discardAndCloseDraft() {
this.abandonDraft().then(() => {
this.$emit('can-close')
})
},
- addBeforeUnloadListener () {
+ addBeforeUnloadListener() {
this._beforeUnloadListener ||= () => {
this.saveDraft()
}
window.addEventListener('beforeunload', this._beforeUnloadListener)
},
- removeBeforeUnloadListener () {
+ removeBeforeUnloadListener() {
if (this._beforeUnloadListener) {
window.removeEventListener('beforeunload', this._beforeUnloadListener)
}
- }
- }
+ },
+ },
}
export default PostStatusForm
diff --git a/src/components/post_status_modal/post_status_modal.js b/src/components/post_status_modal/post_status_modal.js
index ee6cd6444..2c643e9db 100644
--- a/src/components/post_status_modal/post_status_modal.js
+++ b/src/components/post_status_modal/post_status_modal.js
@@ -1,34 +1,35 @@
-import PostStatusForm from '../post_status_form/post_status_form.vue'
-import Modal from '../modal/modal.vue'
import get from 'lodash/get'
+
import { usePostStatusStore } from 'src/stores/post_status'
+import Modal from '../modal/modal.vue'
+import PostStatusForm from '../post_status_form/post_status_form.vue'
const PostStatusModal = {
components: {
PostStatusForm,
- Modal
+ Modal,
},
- data () {
+ data() {
return {
- resettingForm: false
+ resettingForm: false,
}
},
computed: {
- isLoggedIn () {
+ isLoggedIn() {
return !!this.$store.state.users.currentUser
},
- modalActivated () {
+ modalActivated() {
return usePostStatusStore().modalActivated
},
- isFormVisible () {
+ isFormVisible() {
return this.isLoggedIn && !this.resettingForm && this.modalActivated
},
- params () {
+ params() {
return usePostStatusStore().params || {}
- }
+ },
},
watch: {
- params (newVal, oldVal) {
+ params(newVal, oldVal) {
if (get(newVal, 'repliedUser.id') !== get(oldVal, 'repliedUser.id')) {
this.resettingForm = true
this.$nextTick(() => {
@@ -36,21 +37,23 @@ const PostStatusModal = {
})
}
},
- isFormVisible (val) {
+ isFormVisible(val) {
if (val) {
- this.$nextTick(() => this.$el && this.$el.querySelector('textarea').focus())
+ this.$nextTick(
+ () => this.$el && this.$el.querySelector('textarea').focus(),
+ )
}
- }
+ },
},
methods: {
- closeModal () {
+ closeModal() {
usePostStatusStore().closePostStatusModal()
},
- resetAndClose () {
+ resetAndClose() {
usePostStatusStore().resetPostStatusModal()
usePostStatusStore().closePostStatusModal()
- }
- }
+ },
+ },
}
export default PostStatusModal
diff --git a/src/components/progress_button/progress_button.vue b/src/components/progress_button/progress_button.vue
index 283a51af5..318260409 100644
--- a/src/components/progress_button/progress_button.vue
+++ b/src/components/progress_button/progress_button.vue
@@ -16,23 +16,26 @@
export default {
props: {
disabled: {
- type: Boolean
+ type: Boolean,
},
- click: { // click event handler. Must return a promise
+ click: {
+ // click event handler. Must return a promise
type: Function,
- default: () => Promise.resolve()
- }
+ default: () => Promise.resolve(),
+ },
},
- data () {
+ data() {
return {
- progress: false
+ progress: false,
}
},
methods: {
- onClick () {
+ onClick() {
this.progress = true
- this.click().then(() => { this.progress = false })
- }
- }
+ this.click().then(() => {
+ this.progress = false
+ })
+ },
+ },
}
diff --git a/src/components/public_and_external_timeline/public_and_external_timeline.js b/src/components/public_and_external_timeline/public_and_external_timeline.js
index bfcce6ae6..b6e53a4cf 100644
--- a/src/components/public_and_external_timeline/public_and_external_timeline.js
+++ b/src/components/public_and_external_timeline/public_and_external_timeline.js
@@ -1,17 +1,22 @@
import Timeline from '../timeline/timeline.vue'
+
const PublicAndExternalTimeline = {
components: {
- Timeline
+ Timeline,
},
computed: {
- timeline () { return this.$store.state.statuses.timelines.publicAndExternal }
+ timeline() {
+ return this.$store.state.statuses.timelines.publicAndExternal
+ },
},
- created () {
- this.$store.dispatch('startFetchingTimeline', { timeline: 'publicAndExternal' })
+ created() {
+ this.$store.dispatch('startFetchingTimeline', {
+ timeline: 'publicAndExternal',
+ })
},
- unmounted () {
+ unmounted() {
this.$store.dispatch('stopFetchingTimeline', 'publicAndExternal')
- }
+ },
}
export default PublicAndExternalTimeline
diff --git a/src/components/public_timeline/public_timeline.js b/src/components/public_timeline/public_timeline.js
index 306935445..b9d136e29 100644
--- a/src/components/public_timeline/public_timeline.js
+++ b/src/components/public_timeline/public_timeline.js
@@ -1,18 +1,20 @@
import Timeline from '../timeline/timeline.vue'
+
const PublicTimeline = {
components: {
- Timeline
+ Timeline,
},
computed: {
- timeline () { return this.$store.state.statuses.timelines.public }
+ timeline() {
+ return this.$store.state.statuses.timelines.public
+ },
},
- created () {
+ created() {
this.$store.dispatch('startFetchingTimeline', { timeline: 'public' })
},
- unmounted () {
+ unmounted() {
this.$store.dispatch('stopFetchingTimeline', 'public')
- }
-
+ },
}
export default PublicTimeline
diff --git a/src/components/quick_filter_settings/quick_filter_settings.js b/src/components/quick_filter_settings/quick_filter_settings.js
index f5e4721d0..3572dbb18 100644
--- a/src/components/quick_filter_settings/quick_filter_settings.js
+++ b/src/components/quick_filter_settings/quick_filter_settings.js
@@ -1,99 +1,132 @@
-import Popover from '../popover/popover.vue'
-import { mapGetters } from 'vuex'
import { mapState } from 'pinia'
+import { mapGetters } from 'vuex'
+
+import { useInterfaceStore } from 'src/stores/interface'
+import Popover from '../popover/popover.vue'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import { faFilter, faFont, faWrench } from '@fortawesome/free-solid-svg-icons'
-import { useInterfaceStore } from 'src/stores/interface'
-library.add(
- faFilter,
- faFont,
- faWrench
-)
+library.add(faFilter, faFont, faWrench)
const QuickFilterSettings = {
props: {
conversation: Boolean,
- nested: Boolean
+ nested: Boolean,
},
components: {
- Popover
+ Popover,
},
methods: {
- setReplyVisibility (visibility) {
- this.$store.dispatch('setOption', { name: 'replyVisibility', value: visibility })
+ setReplyVisibility(visibility) {
+ this.$store.dispatch('setOption', {
+ name: 'replyVisibility',
+ value: visibility,
+ })
this.$store.dispatch('queueFlushAll')
},
- openTab (tab) {
+ openTab(tab) {
useInterfaceStore().openSettingsModalTab(tab)
- }
+ },
},
computed: {
...mapGetters(['mergedConfig']),
...mapState(useInterfaceStore, {
- mobileLayout: state => state.layoutType === 'mobile'
+ mobileLayout: (state) => state.layoutType === 'mobile',
}),
- triggerAttrs () {
+ triggerAttrs() {
if (this.mobileLayout) {
return {}
} else {
return {
- title: this.$t('timeline.quick_filter_settings')
+ title: this.$t('timeline.quick_filter_settings'),
}
}
},
- mainClass () {
+ mainClass() {
if (this.mobileLayout) {
return 'main-button'
} else {
return 'dropdown-item'
}
},
- loggedIn () {
+ loggedIn() {
return !!this.$store.state.users.currentUser
},
replyVisibilitySelf: {
- get () { return this.mergedConfig.replyVisibility === 'self' },
- set () { this.setReplyVisibility('self') }
+ get() {
+ return this.mergedConfig.replyVisibility === 'self'
+ },
+ set() {
+ this.setReplyVisibility('self')
+ },
},
replyVisibilityFollowing: {
- get () { return this.mergedConfig.replyVisibility === 'following' },
- set () { this.setReplyVisibility('following') }
+ get() {
+ return this.mergedConfig.replyVisibility === 'following'
+ },
+ set() {
+ this.setReplyVisibility('following')
+ },
},
replyVisibilityAll: {
- get () { return this.mergedConfig.replyVisibility === 'all' },
- set () { this.setReplyVisibility('all') }
+ get() {
+ return this.mergedConfig.replyVisibility === 'all'
+ },
+ set() {
+ this.setReplyVisibility('all')
+ },
},
hideMedia: {
- get () { return this.mergedConfig.hideAttachments || this.mergedConfig.hideAttachmentsInConv },
- set () {
+ get() {
+ return (
+ this.mergedConfig.hideAttachments ||
+ this.mergedConfig.hideAttachmentsInConv
+ )
+ },
+ set() {
const value = !this.hideMedia
this.$store.dispatch('setOption', { name: 'hideAttachments', value })
- this.$store.dispatch('setOption', { name: 'hideAttachmentsInConv', value })
- }
+ this.$store.dispatch('setOption', {
+ name: 'hideAttachmentsInConv',
+ value,
+ })
+ },
},
hideMutedPosts: {
- get () { return this.mergedConfig.hideFilteredStatuses },
- set () {
+ get() {
+ return this.mergedConfig.hideFilteredStatuses
+ },
+ set() {
const value = !this.hideMutedPosts
- this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value })
- }
+ this.$store.dispatch('setOption', {
+ name: 'hideFilteredStatuses',
+ value,
+ })
+ },
},
muteBotStatuses: {
- get () { return this.mergedConfig.muteBotStatuses },
- set () {
+ get() {
+ return this.mergedConfig.muteBotStatuses
+ },
+ set() {
const value = !this.muteBotStatuses
this.$store.dispatch('setOption', { name: 'muteBotStatuses', value })
- }
+ },
},
muteSensitiveStatuses: {
- get () { return this.mergedConfig.muteSensitiveStatuses },
- set () {
+ get() {
+ return this.mergedConfig.muteSensitiveStatuses
+ },
+ set() {
const value = !this.muteSensitiveStatuses
- this.$store.dispatch('setOption', { name: 'muteSensitiveStatuses', value })
- }
- }
- }
+ this.$store.dispatch('setOption', {
+ name: 'muteSensitiveStatuses',
+ value,
+ })
+ },
+ },
+ },
}
export default QuickFilterSettings
diff --git a/src/components/quick_view_settings/quick_view_settings.js b/src/components/quick_view_settings/quick_view_settings.js
index 5c98e0f88..6c5a9f667 100644
--- a/src/components/quick_view_settings/quick_view_settings.js
+++ b/src/components/quick_view_settings/quick_view_settings.js
@@ -1,82 +1,110 @@
+import { mapState } from 'pinia'
+import { mapGetters } from 'vuex'
+
import Popover from 'src/components/popover/popover.vue'
import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue'
-import { mapGetters } from 'vuex'
-import { mapState } from 'pinia'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { faList, faFolderTree, faBars, faWrench } from '@fortawesome/free-solid-svg-icons'
import { useInterfaceStore } from 'src/stores/interface'
-library.add(
- faList,
- faFolderTree,
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
faBars,
- faWrench
-)
+ faFolderTree,
+ faList,
+ faWrench,
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(faList, faFolderTree, faBars, faWrench)
const QuickViewSettings = {
props: {
- conversation: Boolean
+ conversation: Boolean,
},
components: {
Popover,
- QuickFilterSettings
+ QuickFilterSettings,
},
methods: {
- setConversationDisplay (visibility) {
- this.$store.dispatch('setOption', { name: 'conversationDisplay', value: visibility })
+ setConversationDisplay(visibility) {
+ this.$store.dispatch('setOption', {
+ name: 'conversationDisplay',
+ value: visibility,
+ })
},
- openTab (tab) {
+ openTab(tab) {
useInterfaceStore().openSettingsModalTab(tab)
- }
+ },
},
computed: {
...mapGetters(['mergedConfig']),
...mapState(useInterfaceStore, {
- mobileLayout: state => state.layoutType === 'mobile'
+ mobileLayout: (state) => state.layoutType === 'mobile',
}),
- loggedIn () {
+ loggedIn() {
return !!this.$store.state.users.currentUser
},
conversationDisplay: {
- get () { return this.mergedConfig.conversationDisplay },
- set (newVal) { this.setConversationDisplay(newVal) }
+ get() {
+ return this.mergedConfig.conversationDisplay
+ },
+ set(newVal) {
+ this.setConversationDisplay(newVal)
+ },
},
autoUpdate: {
- get () { return this.mergedConfig.streaming },
- set () {
+ get() {
+ return this.mergedConfig.streaming
+ },
+ set() {
const value = !this.autoUpdate
this.$store.dispatch('setOption', { name: 'streaming', value })
- }
+ },
},
collapseWithSubjects: {
- get () { return this.mergedConfig.collapseMessageWithSubject },
- set () {
+ get() {
+ return this.mergedConfig.collapseMessageWithSubject
+ },
+ set() {
const value = !this.collapseWithSubjects
- this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value })
- }
+ this.$store.dispatch('setOption', {
+ name: 'collapseMessageWithSubject',
+ value,
+ })
+ },
},
showUserAvatars: {
- get () { return this.mergedConfig.mentionLinkShowAvatar },
- set () {
+ get() {
+ return this.mergedConfig.mentionLinkShowAvatar
+ },
+ set() {
const value = !this.showUserAvatars
- this.$store.dispatch('setOption', { name: 'mentionLinkShowAvatar', value })
- }
+ this.$store.dispatch('setOption', {
+ name: 'mentionLinkShowAvatar',
+ value,
+ })
+ },
},
muteBotStatuses: {
- get () { return this.mergedConfig.muteBotStatuses },
- set () {
+ get() {
+ return this.mergedConfig.muteBotStatuses
+ },
+ set() {
const value = !this.muteBotStatuses
this.$store.dispatch('setOption', { name: 'muteBotStatuses', value })
- }
+ },
},
muteSensitiveStatuses: {
- get () { return this.mergedConfig.muteSensitiveStatuses },
- set () {
+ get() {
+ return this.mergedConfig.muteSensitiveStatuses
+ },
+ set() {
const value = !this.muteSensitiveStatuses
- this.$store.dispatch('setOption', { name: 'muteSensitiveStatuses', value })
- }
- }
- }
+ this.$store.dispatch('setOption', {
+ name: 'muteSensitiveStatuses',
+ value,
+ })
+ },
+ },
+ },
}
export default QuickViewSettings
diff --git a/src/components/quotes_timeline/quotes_timeline.js b/src/components/quotes_timeline/quotes_timeline.js
index a5f42da56..b9b3e8f10 100644
--- a/src/components/quotes_timeline/quotes_timeline.js
+++ b/src/components/quotes_timeline/quotes_timeline.js
@@ -1,26 +1,36 @@
import Timeline from '../timeline/timeline.vue'
const QuotesTimeline = {
- created () {
+ created() {
this.$store.commit('clearTimeline', { timeline: 'quotes' })
- this.$store.dispatch('startFetchingTimeline', { timeline: 'quotes', statusId: this.statusId })
+ this.$store.dispatch('startFetchingTimeline', {
+ timeline: 'quotes',
+ statusId: this.statusId,
+ })
},
components: {
- Timeline
+ Timeline,
},
computed: {
- statusId () { return this.$route.params.id },
- timeline () { return this.$store.state.statuses.timelines.quotes }
+ statusId() {
+ return this.$route.params.id
+ },
+ timeline() {
+ return this.$store.state.statuses.timelines.quotes
+ },
},
watch: {
- statusId () {
+ statusId() {
this.$store.commit('clearTimeline', { timeline: 'quotes' })
- this.$store.dispatch('startFetchingTimeline', { timeline: 'quotes', statusId: this.statusId })
- }
+ this.$store.dispatch('startFetchingTimeline', {
+ timeline: 'quotes',
+ statusId: this.statusId,
+ })
+ },
},
- unmounted () {
+ unmounted() {
this.$store.dispatch('stopFetchingTimeline', 'quotes')
- }
+ },
}
export default QuotesTimeline
diff --git a/src/components/range_input/range_input.vue b/src/components/range_input/range_input.vue
index 2f8645c0b..91d3dcc3b 100644
--- a/src/components/range_input/range_input.vue
+++ b/src/components/range_input/range_input.vue
@@ -54,13 +54,22 @@
diff --git a/src/components/registration/registration.js b/src/components/registration/registration.js
index 53a678680..8d1081acb 100644
--- a/src/components/registration/registration.js
+++ b/src/components/registration/registration.js
@@ -1,13 +1,16 @@
import useVuelidate from '@vuelidate/core'
import { required, requiredIf, sameAs } from '@vuelidate/validators'
import { mapActions, mapState } from 'vuex'
-import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
-import localeService from '../../services/locale/locale.service.js'
+
import { DAY } from 'src/services/date_utils/date_utils.js'
+import localeService from '../../services/locale/locale.service.js'
+import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue'
const registration = {
- setup () { return { v$: useVuelidate() } },
+ setup() {
+ return { v$: useVuelidate() }
+ },
data: () => ({
user: {
email: '',
@@ -17,15 +20,15 @@ const registration = {
confirm: '',
birthday: '',
reason: '',
- language: ['']
+ language: [''],
},
- captcha: {}
+ captcha: {},
}),
components: {
InterfaceLanguageSwitcher,
- TermsOfServicePanel
+ TermsOfServicePanel,
},
- validations () {
+ validations() {
return {
user: {
email: { required: requiredIf(() => this.accountActivationRequired) },
@@ -34,20 +37,23 @@ const registration = {
password: { required },
confirm: {
required,
- sameAs: sameAs(this.user.password)
+ sameAs: sameAs(this.user.password),
},
birthday: {
required: requiredIf(() => this.birthdayRequired),
- maxValue: value => {
- return !this.birthdayRequired || new Date(value).getTime() <= this.birthdayMin.getTime()
- }
+ maxValue: (value) => {
+ return (
+ !this.birthdayRequired ||
+ new Date(value).getTime() <= this.birthdayMin.getTime()
+ )
+ },
},
reason: { required: requiredIf(() => this.accountApprovalRequired) },
- language: {}
- }
+ language: {},
+ },
}
},
- created () {
+ created() {
if ((!this.registrationOpen && !this.token) || this.signedIn) {
this.$router.push({ name: 'root' })
}
@@ -55,14 +61,16 @@ const registration = {
this.setCaptcha()
},
computed: {
- token () { return this.$route.params.token },
- bioPlaceholder () {
+ token() {
+ return this.$route.params.token
+ },
+ bioPlaceholder() {
return this.replaceNewlines(this.$t('registration.bio_placeholder'))
},
- reasonPlaceholder () {
+ reasonPlaceholder() {
return this.replaceNewlines(this.$t('registration.reason_placeholder'))
},
- birthdayMin () {
+ birthdayMin() {
const minAge = this.birthdayMinAge
const today = new Date()
today.setUTCMilliseconds(0)
@@ -73,12 +81,20 @@ const registration = {
minDate.setTime(today.getTime() - minAge * DAY)
return minDate
},
- birthdayMinAttr () {
+ birthdayMinAttr() {
return this.birthdayMin.toJSON().replace(/T.+$/, '')
},
- birthdayMinFormatted () {
- const browserLocale = localeService.internalToBrowserLocale(this.$i18n.locale)
- return this.user.birthday && new Date(Date.parse(this.birthdayMin)).toLocaleDateString(browserLocale, { timeZone: 'UTC', day: 'numeric', month: 'long', year: 'numeric' })
+ birthdayMinFormatted() {
+ const browserLocale = localeService.internalToBrowserLocale(
+ this.$i18n.locale,
+ )
+ return (
+ this.user.birthday &&
+ new Date(Date.parse(this.birthdayMin)).toLocaleDateString(
+ browserLocale,
+ { timeZone: 'UTC', day: 'numeric', month: 'long', year: 'numeric' },
+ )
+ )
},
...mapState({
registrationOpen: (state) => state.instance.registrationOpen,
@@ -89,15 +105,17 @@ const registration = {
hasSignUpNotice: (state) => !!state.users.signUpNotice.message,
termsOfService: (state) => state.instance.tos,
embeddedToS: (state) => state.instance.embeddedToS,
- accountActivationRequired: (state) => state.instance.accountActivationRequired,
- accountApprovalRequired: (state) => state.instance.accountApprovalRequired,
+ accountActivationRequired: (state) =>
+ state.instance.accountActivationRequired,
+ accountApprovalRequired: (state) =>
+ state.instance.accountApprovalRequired,
birthdayRequired: (state) => state.instance.birthdayRequired,
- birthdayMinAge: (state) => state.instance.birthdayMinAge
- })
+ birthdayMinAge: (state) => state.instance.birthdayMinAge,
+ }),
},
methods: {
...mapActions(['signUp', 'getCaptcha']),
- async submit () {
+ async submit() {
this.user.nickname = this.user.username
this.user.token = this.token
@@ -105,7 +123,9 @@ const registration = {
this.user.captcha_token = this.captcha.token
this.user.captcha_answer_data = this.captcha.answer_data
if (this.user.language) {
- this.user.language = localeService.internalToBackendLocaleMulti(this.user.language.filter(k => k))
+ this.user.language = localeService.internalToBackendLocaleMulti(
+ this.user.language.filter((k) => k),
+ )
}
this.v$.$touch()
@@ -124,13 +144,15 @@ const registration = {
}
}
},
- setCaptcha () {
- this.getCaptcha().then(cpt => { this.captcha = cpt })
+ setCaptcha() {
+ this.getCaptcha().then((cpt) => {
+ this.captcha = cpt
+ })
},
- replaceNewlines (str) {
+ replaceNewlines(str) {
return str.replace(/\s*\n\s*/g, ' \n')
- }
- }
+ },
+ },
}
export default registration
diff --git a/src/components/remote_follow/remote_follow.js b/src/components/remote_follow/remote_follow.js
index 951b59419..a583b6f09 100644
--- a/src/components/remote_follow/remote_follow.js
+++ b/src/components/remote_follow/remote_follow.js
@@ -1,9 +1,9 @@
export default {
props: ['user'],
computed: {
- subscribeUrl () {
+ subscribeUrl() {
const serverUrl = new URL(this.user.statusnet_profile_url)
return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus`
- }
- }
+ },
+ },
}
diff --git a/src/components/remote_user_resolver/remote_user_resolver.js b/src/components/remote_user_resolver/remote_user_resolver.js
index 9b5e511e0..430f56c84 100644
--- a/src/components/remote_user_resolver/remote_user_resolver.js
+++ b/src/components/remote_user_resolver/remote_user_resolver.js
@@ -1,14 +1,16 @@
const RemoteUserResolver = {
data: () => ({
- error: false
+ error: false,
}),
- mounted () {
+ mounted() {
this.redirect()
},
methods: {
- redirect () {
- const acct = this.$route.params.username + '@' + this.$route.params.hostname
- this.$store.state.api.backendInteractor.fetchUser({ id: acct })
+ redirect() {
+ const acct =
+ this.$route.params.username + '@' + this.$route.params.hostname
+ this.$store.state.api.backendInteractor
+ .fetchUser({ id: acct })
.then((externalUser) => {
if (externalUser.error) {
this.error = true
@@ -17,15 +19,15 @@ const RemoteUserResolver = {
const id = externalUser.id
this.$router.replace({
name: 'external-user-profile',
- params: { id }
+ params: { id },
})
}
})
.catch(() => {
this.error = true
})
- }
- }
+ },
+ },
}
export default RemoteUserResolver
diff --git a/src/components/remove_follower_button/remove_follower_button.js b/src/components/remove_follower_button/remove_follower_button.js
index 052a519ff..b8f195815 100644
--- a/src/components/remove_follower_button/remove_follower_button.js
+++ b/src/components/remove_follower_button/remove_follower_button.js
@@ -2,47 +2,49 @@ import ConfirmModal from '../confirm_modal/confirm_modal.vue'
export default {
props: ['user', 'relationship'],
- data () {
+ data() {
return {
inProgress: false,
- showingConfirmRemoveFollower: false
+ showingConfirmRemoveFollower: false,
}
},
components: {
- ConfirmModal
+ ConfirmModal,
},
computed: {
- label () {
+ label() {
if (this.inProgress) {
return this.$t('user_card.follow_progress')
} else {
return this.$t('user_card.remove_follower')
}
},
- shouldConfirmRemoveUserFromFollowers () {
+ shouldConfirmRemoveUserFromFollowers() {
return this.$store.getters.mergedConfig.modalOnRemoveUserFromFollowers
- }
+ },
},
methods: {
- showConfirmRemoveUserFromFollowers () {
+ showConfirmRemoveUserFromFollowers() {
this.showingConfirmRemoveFollower = true
},
- hideConfirmRemoveUserFromFollowers () {
+ hideConfirmRemoveUserFromFollowers() {
this.showingConfirmRemoveFollower = false
},
- onClick () {
+ onClick() {
if (!this.shouldConfirmRemoveUserFromFollowers) {
this.doRemoveUserFromFollowers()
} else {
this.showConfirmRemoveUserFromFollowers()
}
},
- doRemoveUserFromFollowers () {
+ doRemoveUserFromFollowers() {
this.inProgress = true
- this.$store.dispatch('removeUserFromFollowers', this.relationship.id).then(() => {
- this.inProgress = false
- })
+ this.$store
+ .dispatch('removeUserFromFollowers', this.relationship.id)
+ .then(() => {
+ this.inProgress = false
+ })
this.hideConfirmRemoveUserFromFollowers()
- }
- }
+ },
+ },
}
diff --git a/src/components/report/report.js b/src/components/report/report.js
index 6e9f21eea..a4df8eb6c 100644
--- a/src/components/report/report.js
+++ b/src/components/report/report.js
@@ -1,37 +1,43 @@
+import RichContent from 'src/components/rich_content/rich_content.jsx'
+import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { useReportsStore } from 'src/stores/reports'
import Select from '../select/select.vue'
import StatusContent from '../status_content/status_content.vue'
import Timeago from '../timeago/timeago.vue'
-import RichContent from 'src/components/rich_content/rich_content.jsx'
-import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
const Report = {
- props: [
- 'reportId'
- ],
+ props: ['reportId'],
components: {
Select,
StatusContent,
Timeago,
- RichContent
+ RichContent,
},
computed: {
- report () {
+ report() {
return useReportsStore().reports[this.reportId] || {}
},
state: {
- get: function () { return this.report.state },
- set: function (val) { this.setReportState(val) }
- }
+ get: function () {
+ return this.report.state
+ },
+ set: function (val) {
+ this.setReportState(val)
+ },
+ },
},
methods: {
- generateUserProfileLink (user) {
- return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
+ generateUserProfileLink(user) {
+ return generateProfileLink(
+ user.id,
+ user.screen_name,
+ this.$store.state.instance.restrictedNicknames,
+ )
},
- setReportState (state) {
+ setReportState(state) {
return useReportsStore().setReportState({ id: this.report.id, state })
- }
- }
+ },
+ },
}
export default Report
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx
index 5adc2443a..99dd8035d 100644
--- a/src/components/rich_content/rich_content.jsx
+++ b/src/components/rich_content/rich_content.jsx
@@ -1,11 +1,17 @@
-import { unescape, flattenDeep } from 'lodash'
-import { getTagName, processTextForEmoji, getAttrs } from 'src/services/html_converter/utility.service.js'
-import { convertHtmlToTree } from 'src/services/html_converter/html_tree_converter.service.js'
-import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
-import StillImageEmojiPopover from 'src/components/still-image/still-image-emoji-popover.vue'
-import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
-import { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.js'
+import { flattenDeep, unescape as ldUnescape } from 'lodash'
+
import HashtagLink from 'src/components/hashtag_link/hashtag_link.vue'
+import { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.js'
+import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
+import StillImage from 'src/components/still-image/still-image.vue'
+import StillImageEmojiPopover from 'src/components/still-image/still-image-emoji-popover.vue'
+import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
+import { convertHtmlToTree } from 'src/services/html_converter/html_tree_converter.service.js'
+import {
+ getAttrs,
+ getTagName,
+ processTextForEmoji,
+} from 'src/services/html_converter/utility.service.js'
import './rich_content.scss'
@@ -27,7 +33,7 @@ const MAYBE_LINE_BREAKING_ELEMENTS = [
'h2',
'h3',
'h4',
- 'h5'
+ 'h5',
]
/**
@@ -52,46 +58,46 @@ export default {
name: 'RichContent',
components: {
MentionsLine,
- HashtagLink
+ HashtagLink,
},
props: {
// Original html content
html: {
required: true,
- type: String
+ type: String,
},
attentions: {
required: false,
- default: () => []
+ default: () => [],
},
// Emoji object, as in status.emojis, note the "s" at the end...
emoji: {
required: true,
- type: Array
+ type: Array,
},
// Whether to handle links or not (posts: yes, everything else: no)
handleLinks: {
required: false,
type: Boolean,
- default: false
+ default: false,
},
// Meme arrows
greentext: {
required: false,
type: Boolean,
- default: false
+ default: false,
},
// Faint style (for notifs)
faint: {
required: false,
type: Boolean,
- default: false
+ default: false,
},
// Collapse newlines
collapse: {
required: false,
type: Boolean,
- default: false
+ default: false,
},
/* Content comes from current instance
*
@@ -103,11 +109,11 @@ export default {
isLocal: {
required: false,
type: Boolean,
- default: true
- }
+ default: true,
+ },
},
// NEVER EVER TOUCH DATA INSIDE RENDER
- render () {
+ render() {
// Pre-process HTML
const { newHtml: html } = preProcessPerLine(this.html, this.greentext)
let currentMentions = null // Current chain of mentions, we group all mentions together
@@ -124,10 +130,7 @@ export default {
let tagsIndex = 0
const renderImage = (tag) => {
- return
+ return
}
const renderHashtag = (attrs, children, encounteredTextReverse) => {
@@ -137,12 +140,14 @@ export default {
lastTags.push(linkData)
}
const { url, tag, content } = linkData
- return
+ return
}
const renderMention = (attrs, children) => {
const linkData = getLinkData(attrs, children, mentionIndex++)
- linkData.notifying = this.attentions.some(a => a.statusnet_profile_url === linkData.url)
+ linkData.notifying = this.attentions.some(
+ (a) => a.statusnet_profile_url === linkData.url,
+ )
writtenMentions.push(linkData)
if (currentMentions === null) {
currentMentions = []
@@ -152,7 +157,7 @@ export default {
invisibleMentions.push(linkData)
}
if (currentMentions.length === 1) {
- return
+ return
} else {
return ''
}
@@ -171,26 +176,28 @@ export default {
// in MentionsLine
lastSpacing = item
// Don't remove last space in a container (fixes poast mentions)
- return (index !== array.length - 1) && (currentMentions !== null) ? item.trim() : item
+ return index !== array.length - 1 && currentMentions !== null
+ ? item.trim()
+ : item
}
currentMentions = null
if (item.includes(':')) {
- item = ['', processTextForEmoji(
- item,
- this.emoji,
- ({ shortcode, url }) => {
- return
- }
- )]
+ item = [
+ '',
+ processTextForEmoji(item, this.emoji, ({ shortcode, url }) => {
+ return (
+
+ )
+ }),
+ ]
}
return item
}
@@ -209,18 +216,24 @@ export default {
* we have a tag right next to mentions
*/
const mentionsLinePadding =
- // Padding is only needed if we just finished parsing mentions
- previouslyMentions &&
- // Don't add padding if content is string and has padding already
- !(children && typeof children[0] === 'string' && children[0].match(/^\s/))
- ? lastSpacing
- : ''
+ // Padding is only needed if we just finished parsing mentions
+ previouslyMentions &&
+ // Don't add padding if content is string and has padding already
+ !(
+ children &&
+ typeof children[0] === 'string' &&
+ children[0].match(/^\s/)
+ )
+ ? lastSpacing
+ : ''
if (MAYBE_LINE_BREAKING_ELEMENTS.includes(Tag)) {
// all the elements that can cause a line change
currentMentions = null
- } else if (Tag === 'img') { // replace images with StillImage
+ } else if (Tag === 'img') {
+ // replace images with StillImage
return ['', [mentionsLinePadding, renderImage(opener)], '']
- } else if (Tag === 'a' && this.handleLinks) { // replace mentions with MentionLink
+ } else if (Tag === 'a' && this.handleLinks) {
+ // replace mentions with MentionLink
if (fullAttrs.class && fullAttrs.class.includes('mention')) {
// Handling mentions here
return renderMention(attrs, children)
@@ -228,7 +241,11 @@ export default {
currentMentions = null
}
} else if (Tag === 'span') {
- if (this.handleLinks && fullAttrs.class && fullAttrs.class.includes('h-card')) {
+ if (
+ this.handleLinks &&
+ fullAttrs.class &&
+ fullAttrs.class.includes('h-card')
+ ) {
return ['', children.map(processItem), '']
}
}
@@ -236,11 +253,8 @@ export default {
if (children !== undefined) {
return [
'',
- [
- mentionsLinePadding,
- [opener, children.map(processItem), closer]
- ],
- ''
+ [mentionsLinePadding, [opener, children.map(processItem), closer]],
+ '',
]
} else {
return ['', [mentionsLinePadding, item], '']
@@ -256,29 +270,31 @@ export default {
const emptyText = item.trim() === ''
if (emptyText) return item
if (!encounteredTextReverse) encounteredTextReverse = true
- return unescape(item)
+ return ldUnescape(item)
} else if (Array.isArray(item)) {
// Handle tag nodes
const [opener, children] = item
const Tag = opener === '' ? '' : getTagName(opener)
switch (Tag) {
- case 'a': { // replace mentions with MentionLink
+ case 'a': {
+ // replace mentions with MentionLink
if (!this.handleLinks) break
const fullAttrs = getAttrs(opener, () => true)
const attrs = getAttrs(opener, () => true)
// should only be this
if (
(fullAttrs.class && fullAttrs.class.includes('hashtag')) || // Pleroma style
- (fullAttrs.rel === 'tag') // Mastodon style
+ fullAttrs.rel === 'tag' // Mastodon style
) {
return renderHashtag(attrs, children, encounteredTextReverse)
} else {
attrs.target = '_blank'
- const newChildren = [...children].reverse().map(processItemReverse).reverse()
+ const newChildren = [...children]
+ .reverse()
+ .map(processItemReverse)
+ .reverse()
- return
- { newChildren }
-
+ return {newChildren}
}
}
case '':
@@ -290,11 +306,9 @@ export default {
const newChildren = Array.isArray(children)
? [...children].reverse().map(processItemReverse).reverse()
: children
- return
- { newChildren }
-
+ return {newChildren}
} else {
- return
+ return
}
}
return item
@@ -306,30 +320,29 @@ export default {
// DO NOT USE SLOTS they cause a re-render feedback loop here.
// slots updated -> rerender -> emit -> update up the tree -> rerender -> ...
// at least until vue3?
- const result =
-
- {
- this.collapse
- ? pass2.map(x => {
- if (!Array.isArray(x)) return x.replace(/\n/g, ' ')
- return x.map(y => y.type === 'br' ? ' ' : y)
- })
- : pass2
- }
-
+ const result = (
+
+ {this.collapse
+ ? pass2.map((x) => {
+ if (!Array.isArray(x)) return x.replace(/\n/g, ' ')
+ return x.map((y) => (y.type === 'br' ? ' ' : y))
+ })
+ : pass2}
+
+ )
const event = {
lastTags,
writtenMentions,
writtenTags,
- invisibleMentions
+ invisibleMentions,
}
// DO NOT MOVE TO UPDATE. BAD IDEA.
this.$emit('parseReady', event)
return result
- }
+ },
}
const getLinkData = (attrs, children, index) => {
@@ -346,7 +359,7 @@ const getLinkData = (attrs, children, index) => {
url: attrs.href,
tag: attrs['data-tag'],
content: flattenDeep(children).join(''),
- textContent
+ textContent,
}
}
@@ -362,31 +375,36 @@ export const preProcessPerLine = (html, greentext) => {
const greentextHandle = new Set(['p', 'div'])
const lines = convertHtmlToLines(html)
- const newHtml = lines.reverse().map((item, index, array) => {
- if (!item.text) return item
- const string = item.text
+ const newHtml = lines
+ .reverse()
+ .map((item, index, array) => {
+ if (!item.text) return item
+ const string = item.text
- // Greentext stuff
- if (
- // Only if greentext is engaged
- greentext &&
+ // Greentext stuff
+ if (
+ // Only if greentext is engaged
+ greentext &&
// Only handle p's and divs. Don't want to affect blockquotes, code etc
- item.level.every(l => greentextHandle.has(l)) &&
+ item.level.every((l) => greentextHandle.has(l)) &&
// Only if line begins with '>' or '<'
(string.includes('>') || string.includes('<'))
- ) {
- const cleanedString = string.replace(/<[^>]+?>/gi, '') // remove all tags
- .replace(/@\w+/gi, '') // remove mentions (even failed ones)
- .trim()
- if (cleanedString.startsWith('>')) {
- return `${string}`
- } else if (cleanedString.startsWith('<')) {
- return `${string}`
+ ) {
+ const cleanedString = string
+ .replace(/<[^>]+?>/gi, '') // remove all tags
+ .replace(/@\w+/gi, '') // remove mentions (even failed ones)
+ .trim()
+ if (cleanedString.startsWith('>')) {
+ return `${string}`
+ } else if (cleanedString.startsWith('<')) {
+ return `${string}`
+ }
}
- }
- return string
- }).reverse().join('')
+ return string
+ })
+ .reverse()
+ .join('')
return { newHtml }
}
diff --git a/src/components/root.style.js b/src/components/root.style.js
index 5075e33c8..54c4c6095 100644
--- a/src/components/root.style.js
+++ b/src/components/root.style.js
@@ -27,8 +27,8 @@ export default {
// Selection colors
'--selectionBackground': 'color | --accent',
- '--selectionText': 'color | $textColor(--accent --text no-preserve)'
- }
- }
- ]
+ '--selectionText': 'color | $textColor(--accent --text no-preserve)',
+ },
+ },
+ ],
}
diff --git a/src/components/roundness_input/roundness_input.vue b/src/components/roundness_input/roundness_input.vue
index 1da71ca79..04b623e86 100644
--- a/src/components/roundness_input/roundness_input.vue
+++ b/src/components/roundness_input/roundness_input.vue
@@ -36,16 +36,14 @@
import Checkbox from '../checkbox/checkbox.vue'
export default {
components: {
- Checkbox
+ Checkbox,
},
- props: [
- 'name', 'label', 'modelValue', 'fallback', 'disabled'
- ],
+ props: ['name', 'label', 'modelValue', 'fallback', 'disabled'],
emits: ['update:modelValue'],
computed: {
- present () {
+ present() {
return typeof this.modelValue !== 'undefined'
- }
- }
+ },
+ },
}
diff --git a/src/components/scope_selector/scope_selector.js b/src/components/scope_selector/scope_selector.js
index 462892cb6..9d3a3a718 100644
--- a/src/components/scope_selector/scope_selector.js
+++ b/src/components/scope_selector/scope_selector.js
@@ -1,90 +1,92 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faEnvelope,
- faLock,
- faLockOpen,
- faGlobe
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
faEnvelope,
faGlobe,
faLock,
- faLockOpen
-)
+ faLockOpen,
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(faEnvelope, faGlobe, faLock, faLockOpen)
const ScopeSelector = {
props: {
showAll: {
required: true,
- type: Boolean
+ type: Boolean,
},
userDefault: {
required: true,
- type: String
+ type: String,
},
originalScope: {
required: false,
- type: String
+ type: String,
},
initialScope: {
required: false,
- type: String
+ type: String,
},
onScopeChange: {
required: true,
- type: Function
+ type: Function,
},
unstyled: {
required: false,
type: Boolean,
- default: true
- }
+ default: true,
+ },
},
- data () {
+ data() {
return {
- currentScope: this.initialScope
+ currentScope: this.initialScope,
}
},
computed: {
- showNothing () {
- return !this.showPublic && !this.showUnlisted && !this.showPrivate && !this.showDirect
+ showNothing() {
+ return (
+ !this.showPublic &&
+ !this.showUnlisted &&
+ !this.showPrivate &&
+ !this.showDirect
+ )
},
- showPublic () {
+ showPublic() {
return this.originalScope !== 'direct' && this.shouldShow('public')
},
- showUnlisted () {
+ showUnlisted() {
return this.originalScope !== 'direct' && this.shouldShow('unlisted')
},
- showPrivate () {
+ showPrivate() {
return this.originalScope !== 'direct' && this.shouldShow('private')
},
- showDirect () {
+ showDirect() {
return this.shouldShow('direct')
},
- css () {
+ css() {
const style = this.unstyled ? 'button-unstyled' : 'button-default'
return {
public: [style, { toggled: this.currentScope === 'public' }],
unlisted: [style, { toggled: this.currentScope === 'unlisted' }],
private: [style, { toggled: this.currentScope === 'private' }],
- direct: [style, { toggled: this.currentScope === 'direct' }]
+ direct: [style, { toggled: this.currentScope === 'direct' }],
}
- }
+ },
},
methods: {
- shouldShow (scope) {
- return this.showAll ||
+ shouldShow(scope) {
+ return (
+ this.showAll ||
this.currentScope === scope ||
this.originalScope === scope ||
this.userDefault === scope ||
scope === 'direct'
+ )
},
- changeVis (scope) {
+ changeVis(scope) {
this.currentScope = scope
this.onScopeChange && this.onScopeChange(scope)
- }
- }
+ },
+ },
}
export default ScopeSelector
diff --git a/src/components/screen_reader_notice/screen_reader_notice.js b/src/components/screen_reader_notice/screen_reader_notice.js
index 794b855ac..b834be531 100644
--- a/src/components/screen_reader_notice/screen_reader_notice.js
+++ b/src/components/screen_reader_notice/screen_reader_notice.js
@@ -2,20 +2,22 @@ const ScreenReaderNotice = {
props: {
ariaLive: {
type: String,
- default: 'assertive'
- }
+ default: 'assertive',
+ },
},
- data () {
+ data() {
return {
- currentText: ''
+ currentText: '',
}
},
methods: {
- announce (text) {
+ announce(text) {
this.currentText = text
- setTimeout(() => { this.currentText = '' }, 1000)
- }
- }
+ setTimeout(() => {
+ this.currentText = ''
+ }, 1000)
+ },
+ },
}
export default ScreenReaderNotice
diff --git a/src/components/scroll_top_button/scroll_top_button.js b/src/components/scroll_top_button/scroll_top_button.js
index bdc45b9b4..e4b908f0b 100644
--- a/src/components/scroll_top_button/scroll_top_button.js
+++ b/src/components/scroll_top_button/scroll_top_button.js
@@ -3,16 +3,16 @@ const ScrollTopButton = {
fast: {
type: Boolean,
required: false,
- default: false
- }
+ default: false,
+ },
},
methods: {
scrollToTop() {
- const speed = this.fast ? 'instant' : 'smooth';
+ const speed = this.fast ? 'instant' : 'smooth'
window.scrollTo({ top: 0, behavior: speed })
- }
- }
+ },
+ },
}
export default ScrollTopButton
diff --git a/src/components/scrollbar.style.js b/src/components/scrollbar.style.js
index 1168f67d8..fbe952076 100644
--- a/src/components/scrollbar.style.js
+++ b/src/components/scrollbar.style.js
@@ -1,12 +1,16 @@
export default {
name: 'Scrollbar',
- selector: ['::-webkit-scrollbar-button', '::-webkit-scrollbar-thumb', '::-webkit-resizer'],
+ selector: [
+ '::-webkit-scrollbar-button',
+ '::-webkit-scrollbar-thumb',
+ '::-webkit-resizer',
+ ],
notEditable: true, // for now
defaultRules: [
{
directives: {
- background: '--wallpaper'
- }
- }
- ]
+ background: '--wallpaper',
+ },
+ },
+ ],
}
diff --git a/src/components/scrollbar_element.style.js b/src/components/scrollbar_element.style.js
index ef1ea8136..6f238e1f8 100644
--- a/src/components/scrollbar_element.style.js
+++ b/src/components/scrollbar_element.style.js
@@ -5,7 +5,7 @@ const border = (top, shadow) => ({
spread: 0,
color: shadow ? '#000000' : '#FFFFFF',
alpha: 0.2,
- inset: true
+ inset: true,
})
const buttonInsetFakeBorders = [border(true, false), border(false, true)]
@@ -16,7 +16,7 @@ const buttonOuterShadow = {
blur: 2,
spread: 0,
color: '#000000',
- alpha: 1
+ alpha: 1,
}
const hoverGlow = {
@@ -25,7 +25,7 @@ const hoverGlow = {
blur: 4,
spread: 0,
color: '--text',
- alpha: 1
+ alpha: 1,
}
export default {
@@ -35,68 +35,66 @@ export default {
states: {
pressed: ':active',
hover: ':is(:hover, :focus-visible, :has(:focus-visible)):not(:disabled)',
- disabled: ':disabled'
+ disabled: ':disabled',
},
- validInnerComponents: [
- 'Text'
- ],
+ validInnerComponents: ['Text'],
defaultRules: [
{
directives: {
background: '--fg',
shadow: [buttonOuterShadow, ...buttonInsetFakeBorders],
- roundness: 3
- }
+ roundness: 3,
+ },
},
{
state: ['hover'],
directives: {
- shadow: [hoverGlow, ...buttonInsetFakeBorders]
- }
+ shadow: [hoverGlow, ...buttonInsetFakeBorders],
+ },
},
{
state: ['pressed'],
directives: {
- shadow: [buttonOuterShadow, ...inputInsetFakeBorders]
- }
+ shadow: [buttonOuterShadow, ...inputInsetFakeBorders],
+ },
},
{
state: ['hover', 'pressed'],
directives: {
- shadow: [hoverGlow, ...inputInsetFakeBorders]
- }
+ shadow: [hoverGlow, ...inputInsetFakeBorders],
+ },
},
{
state: ['toggled'],
directives: {
background: '--accent,-24.2',
- shadow: [buttonOuterShadow, ...inputInsetFakeBorders]
- }
+ shadow: [buttonOuterShadow, ...inputInsetFakeBorders],
+ },
},
{
state: ['toggled', 'hover'],
directives: {
background: '--accent,-24.2',
- shadow: [hoverGlow, ...inputInsetFakeBorders]
- }
+ shadow: [hoverGlow, ...inputInsetFakeBorders],
+ },
},
{
state: ['disabled'],
directives: {
background: '$blend(--inheritedBackground 0.25 --parent)',
- shadow: [...buttonInsetFakeBorders]
- }
+ shadow: [...buttonInsetFakeBorders],
+ },
},
{
component: 'Text',
parent: {
component: 'Button',
- state: ['disabled']
+ state: ['disabled'],
},
directives: {
textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
- }
- ]
+ textOpacityMode: 'blend',
+ },
+ },
+ ],
}
diff --git a/src/components/search/search.js b/src/components/search/search.js
index 877d6f300..b8812d0ac 100644
--- a/src/components/search/search.js
+++ b/src/components/search/search.js
@@ -1,31 +1,25 @@
-import FollowCard from '../follow_card/follow_card.vue'
-import Conversation from '../conversation/conversation.vue'
-import Status from '../status/status.vue'
-import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
-import map from 'lodash/map'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faCircleNotch,
- faSearch
-} from '@fortawesome/free-solid-svg-icons'
import { uniqBy } from 'lodash'
+import map from 'lodash/map'
-library.add(
- faCircleNotch,
- faSearch
-)
+import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
+import Conversation from '../conversation/conversation.vue'
+import FollowCard from '../follow_card/follow_card.vue'
+import Status from '../status/status.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faCircleNotch, faSearch } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faCircleNotch, faSearch)
const Search = {
components: {
FollowCard,
Conversation,
Status,
- TabSwitcher
+ TabSwitcher,
},
- props: [
- 'query'
- ],
- data () {
+ props: ['query'],
+ data() {
return {
loaded: false,
loading: false,
@@ -37,36 +31,37 @@ const Search = {
statusesOffset: 0,
lastStatusFetchCount: 0,
- lastQuery: ''
+ lastQuery: '',
}
},
computed: {
- users () {
- return this.userIds.map(userId => this.$store.getters.findUser(userId))
+ users() {
+ return this.userIds.map((userId) => this.$store.getters.findUser(userId))
},
- visibleStatuses () {
+ visibleStatuses() {
const allStatusesObject = this.$store.state.statuses.allStatusesObject
- return this.statuses.filter(status =>
- allStatusesObject[status.id] && !allStatusesObject[status.id].deleted
+ return this.statuses.filter(
+ (status) =>
+ allStatusesObject[status.id] && !allStatusesObject[status.id].deleted,
)
- }
+ },
},
- mounted () {
+ mounted() {
this.search(this.query)
},
watch: {
- query (newValue) {
+ query(newValue) {
this.searchTerm = newValue
this.search(newValue)
- }
+ },
},
methods: {
- newQuery (query) {
+ newQuery(query) {
this.$router.push({ name: 'search', query: { query } })
this.$refs.searchInput.focus()
},
- search (query, searchType = null) {
+ search(query, searchType = null) {
if (!query) {
this.loading = false
return
@@ -83,8 +78,14 @@ const Search = {
this.lastStatusFetchCount = 0
}
- this.$store.dispatch('search', { q: query, resolve: true, offset: this.statusesOffset, type: searchType })
- .then(data => {
+ this.$store
+ .dispatch('search', {
+ q: query,
+ resolve: true,
+ offset: this.statusesOffset,
+ type: searchType,
+ })
+ .then((data) => {
this.loading = false
const oldLength = this.statuses.length
@@ -104,14 +105,14 @@ const Search = {
this.lastQuery = query
})
},
- resultCount (tabName) {
+ resultCount(tabName) {
const length = this[tabName].length
return length === 0 ? '' : ` (${length})`
},
- onResultTabSwitch (key) {
+ onResultTabSwitch(key) {
this.currenResultTab = key
},
- getActiveTab () {
+ getActiveTab() {
if (this.visibleStatuses.length > 0) {
return 'statuses'
} else if (this.users.length > 0) {
@@ -122,10 +123,10 @@ const Search = {
return 'statuses'
},
- lastHistoryRecord (hashtag) {
+ lastHistoryRecord(hashtag) {
return hashtag.history && hashtag.history[0]
- }
- }
+ },
+ },
}
export default Search
diff --git a/src/components/search_bar/search_bar.js b/src/components/search_bar/search_bar.js
index 3b297f098..ebe30d303 100644
--- a/src/components/search_bar/search_bar.js
+++ b/src/components/search_bar/search_bar.js
@@ -1,33 +1,27 @@
import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faTimes,
- faSearch
-} from '@fortawesome/free-solid-svg-icons'
+import { faSearch, faTimes } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faTimes,
- faSearch
-)
+library.add(faTimes, faSearch)
const SearchBar = {
data: () => ({
searchTerm: undefined,
hidden: true,
- error: false
+ error: false,
}),
watch: {
$route: function (route) {
if (route.name === 'search') {
this.searchTerm = route.query.query
}
- }
+ },
},
methods: {
- find (searchTerm) {
+ find(searchTerm) {
this.$router.push({ name: 'search', query: { query: searchTerm } })
this.$refs.searchInput.focus()
},
- toggleHidden () {
+ toggleHidden() {
this.hidden = !this.hidden
this.$emit('toggled', this.hidden)
this.$nextTick(() => {
@@ -35,8 +29,8 @@ const SearchBar = {
this.$refs.searchInput.focus()
}
})
- }
- }
+ },
+ },
}
export default SearchBar
diff --git a/src/components/select/select.js b/src/components/select/select.js
index 34d64fd22..9bf9f7e23 100644
--- a/src/components/select/select.js
+++ b/src/components/select/select.js
@@ -1,19 +1,9 @@
import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
+import { faChevronDown } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faChevronDown
-)
+library.add(faChevronDown)
export default {
emits: ['update:modelValue'],
- props: [
- 'modelValue',
- 'disabled',
- 'unstyled',
- 'kind',
- 'attrs'
- ]
+ props: ['modelValue', 'disabled', 'unstyled', 'kind', 'attrs'],
}
diff --git a/src/components/select/select_motion.vue b/src/components/select/select_motion.vue
index 45e278fc6..21262c256 100644
--- a/src/components/select/select_motion.vue
+++ b/src/components/select/select_motion.vue
@@ -54,20 +54,20 @@ import { computed, defineEmits, defineProps, nextTick } from 'vue'
const props = defineProps({
modelValue: {
type: Array,
- required: true
+ required: true,
},
selectedId: {
type: Number,
- required: true
+ required: true,
},
disabled: {
type: Boolean,
- default: false
+ default: false,
},
getAddValue: {
type: Function,
- required: true
- }
+ required: true,
+ },
})
const emit = defineEmits(['update:modelValue', 'update:selectedId'])
@@ -116,7 +116,10 @@ const del = async () => {
emit('update:modelValue', newModel)
await nextTick()
- emit('update:selectedId', newModel.length === 0 ? undefined : Math.max(props.selectedId - 1, 0))
+ emit(
+ 'update:selectedId',
+ newModel.length === 0 ? undefined : Math.max(props.selectedId - 1, 0),
+ )
}
diff --git a/src/components/selectable_list/selectable_list.js b/src/components/selectable_list/selectable_list.js
index 10980d46a..b08a3e9a5 100644
--- a/src/components/selectable_list/selectable_list.js
+++ b/src/components/selectable_list/selectable_list.js
@@ -1,48 +1,48 @@
-import List from '../list/list.vue'
import Checkbox from '../checkbox/checkbox.vue'
+import List from '../list/list.vue'
const SelectableList = {
components: {
List,
- Checkbox
+ Checkbox,
},
props: {
items: {
type: Array,
- default: () => []
+ default: () => [],
},
getKey: {
type: Function,
- default: item => item.id
- }
+ default: (item) => item.id,
+ },
},
- data () {
+ data() {
return {
- selected: []
+ selected: [],
}
},
computed: {
- allKeys () {
+ allKeys() {
return this.items.map(this.getKey)
},
- filteredSelected () {
- return this.allKeys.filter(key => this.selected.indexOf(key) !== -1)
+ filteredSelected() {
+ return this.allKeys.filter((key) => this.selected.indexOf(key) !== -1)
},
- allSelected () {
+ allSelected() {
return this.filteredSelected.length === this.items.length
},
- noneSelected () {
+ noneSelected() {
return this.filteredSelected.length === 0
},
- someSelected () {
+ someSelected() {
return !this.allSelected && !this.noneSelected
- }
+ },
},
methods: {
- isSelected (item) {
+ isSelected(item) {
return this.filteredSelected.indexOf(this.getKey(item)) !== -1
},
- toggle (checked, item) {
+ toggle(checked, item) {
const key = this.getKey(item)
const oldChecked = this.isSelected(key)
if (checked !== oldChecked) {
@@ -53,14 +53,14 @@ const SelectableList = {
}
}
},
- toggleAll (value) {
+ toggleAll(value) {
if (value) {
this.selected = this.allKeys.slice(0)
} else {
this.selected = []
}
- }
- }
+ },
+ },
}
export default SelectableList
diff --git a/src/components/settings_modal/admin_tabs/auth_tab.js b/src/components/settings_modal/admin_tabs/auth_tab.js
index a078291e6..627150587 100644
--- a/src/components/settings_modal/admin_tabs/auth_tab.js
+++ b/src/components/settings_modal/admin_tabs/auth_tab.js
@@ -1,20 +1,19 @@
+import AttachmentSetting from '../helpers/attachment_setting.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
-import TupleSetting from '../helpers/tuple_setting.vue'
import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import ListSetting from '../helpers/list_setting.vue'
import MapSetting from '../helpers/map_setting.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
+import TupleSetting from '../helpers/tuple_setting.vue'
const AuthTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -26,14 +25,16 @@ const AuthTab = {
AttachmentSetting,
GroupSetting,
ListSetting,
- MapSetting
+ MapSetting,
},
computed: {
...SharedComputedObject(),
- LDAPEnabled () {
- return this.$store.state.adminSettings.draft[':pleroma'][':ldap'][':enabled']
+ LDAPEnabled() {
+ return this.$store.state.adminSettings.draft[':pleroma'][':ldap'][
+ ':enabled'
+ ]
},
- }
+ },
}
export default AuthTab
diff --git a/src/components/settings_modal/admin_tabs/emoji_tab.js b/src/components/settings_modal/admin_tabs/emoji_tab.js
index 7c137e35f..e53c2f219 100644
--- a/src/components/settings_modal/admin_tabs/emoji_tab.js
+++ b/src/components/settings_modal/admin_tabs/emoji_tab.js
@@ -1,30 +1,26 @@
-import { clone, assign } from 'lodash'
-import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
-import StringSetting from '../helpers/string_setting.vue'
import Checkbox from 'components/checkbox/checkbox.vue'
-import StillImage from 'components/still-image/still-image.vue'
-import Select from 'components/select/select.vue'
-import Popover from 'components/popover/popover.vue'
import ConfirmModal from 'components/confirm_modal/confirm_modal.vue'
-import ModifiedIndicator from '../helpers/modified_indicator.vue'
-import EmojiEditingPopover from '../helpers/emoji_editing_popover.vue'
-import { useInterfaceStore } from 'src/stores/interface'
+import Popover from 'components/popover/popover.vue'
+import Select from 'components/select/select.vue'
+import StillImage from 'components/still-image/still-image.vue'
+import { assign, clone } from 'lodash'
+import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
+import { useInterfaceStore } from 'src/stores/interface'
+import EmojiEditingPopover from '../helpers/emoji_editing_popover.vue'
+import ModifiedIndicator from '../helpers/modified_indicator.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faArrowsRotate,
+ faDownload,
faFolderOpen,
faServer,
- faDownload
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faArrowsRotate,
- faFolderOpen,
- faDownload,
- faServer
-)
+library.add(faArrowsRotate, faFolderOpen, faDownload, faServer)
const EmojiTab = {
components: {
@@ -36,14 +32,14 @@ const EmojiTab = {
Popover,
ConfirmModal,
ModifiedIndicator,
- EmojiEditingPopover
+ EmojiEditingPopover,
},
- data () {
+ data() {
return {
- knownLocalPacks: { },
- knownRemotePacks: { },
- editedMetadata: { },
+ knownLocalPacks: {},
+ knownRemotePacks: {},
+ editedMetadata: {},
packName: '',
newPackName: '',
deleteModalVisible: false,
@@ -51,20 +47,20 @@ const EmojiTab = {
remotePackDownloadAs: '',
remotePackURL: '',
- remotePackFile: null
+ remotePackFile: null,
}
},
- provide () {
+ provide() {
return { emojiAddr: this.emojiAddr }
},
computed: {
...SharedComputedObject(),
- pack () {
+ pack() {
return this.packName !== '' ? this.knownPacks[this.packName] : undefined
},
- packMeta () {
+ packMeta() {
if (this.packName === '') return {}
if (this.editedMetadata[this.packName] === undefined) {
this.editedMetadata[this.packName] = clone(this.pack.pack)
@@ -72,31 +68,36 @@ const EmojiTab = {
return this.editedMetadata[this.packName]
},
- knownPacks () {
+ knownPacks() {
// Copy the object itself but not the children, so they are still passed by reference and modified
const result = clone(this.knownLocalPacks)
for (const instName in this.knownRemotePacks) {
for (const instPack in this.knownRemotePacks[instName]) {
- result[`${instPack}@${instName}`] = this.knownRemotePacks[instName][instPack]
+ result[`${instPack}@${instName}`] =
+ this.knownRemotePacks[instName][instPack]
}
}
return result
},
- downloadWillReplaceLocal () {
- return (this.remotePackDownloadAs.trim() === '' && this.pack.remote && this.pack.remote.baseName in this.knownLocalPacks) ||
- (this.remotePackDownloadAs in this.knownLocalPacks)
- }
+ downloadWillReplaceLocal() {
+ return (
+ (this.remotePackDownloadAs.trim() === '' &&
+ this.pack.remote &&
+ this.pack.remote.baseName in this.knownLocalPacks) ||
+ this.remotePackDownloadAs in this.knownLocalPacks
+ )
+ },
},
methods: {
- reloadEmoji () {
+ reloadEmoji() {
this.$store.state.api.backendInteractor.reloadEmoji()
},
- importFromFS () {
+ importFromFS() {
this.$store.state.api.backendInteractor.importEmojiFromFS()
},
- emojiAddr (name) {
+ emojiAddr(name) {
if (this.pack.remote !== undefined) {
// Remote pack
return `${this.pack.remote.instance}/emoji/${encodeURIComponent(this.pack.remote.baseName)}/${name}`
@@ -105,115 +106,141 @@ const EmojiTab = {
}
},
- createEmojiPack () {
- this.$store.state.api.backendInteractor.createEmojiPack(
- { name: this.newPackName }
- ).then(resp => resp.json()).then(resp => {
- if (resp === 'ok') {
- return this.refreshPackList()
- } else {
- this.displayError(resp.error)
- return Promise.reject(resp)
- }
- }).then(() => {
- this.packName = this.newPackName
- this.newPackName = ''
- })
+ createEmojiPack() {
+ this.$store.state.api.backendInteractor
+ .createEmojiPack({ name: this.newPackName })
+ .then((resp) => resp.json())
+ .then((resp) => {
+ if (resp === 'ok') {
+ return this.refreshPackList()
+ } else {
+ this.displayError(resp.error)
+ return Promise.reject(resp)
+ }
+ })
+ .then(() => {
+ this.packName = this.newPackName
+ this.newPackName = ''
+ })
},
- deleteEmojiPack () {
- this.$store.state.api.backendInteractor.deleteEmojiPack(
- { name: this.packName }
- ).then(resp => resp.json()).then(resp => {
- if (resp === 'ok') {
- return this.refreshPackList()
- } else {
- this.displayError(resp.error)
- return Promise.reject(resp)
- }
- }).then(() => {
- delete this.editedMetadata[this.packName]
+ deleteEmojiPack() {
+ this.$store.state.api.backendInteractor
+ .deleteEmojiPack({ name: this.packName })
+ .then((resp) => resp.json())
+ .then((resp) => {
+ if (resp === 'ok') {
+ return this.refreshPackList()
+ } else {
+ this.displayError(resp.error)
+ return Promise.reject(resp)
+ }
+ })
+ .then(() => {
+ delete this.editedMetadata[this.packName]
- this.deleteModalVisible = false
- this.packName = ''
- })
+ this.deleteModalVisible = false
+ this.packName = ''
+ })
},
- metaEdited (prop) {
+ metaEdited(prop) {
if (!this.pack) return
const def = this.pack.pack[prop] || ''
const edited = this.packMeta[prop] || ''
return edited !== def
},
- savePackMetadata () {
- this.$store.state.api.backendInteractor.saveEmojiPackMetadata({ name: this.packName, newData: this.packMeta }).then(
- resp => resp.json()
- ).then(resp => {
- if (resp.error !== undefined) {
- this.displayError(resp.error)
- return
- }
+ savePackMetadata() {
+ this.$store.state.api.backendInteractor
+ .saveEmojiPackMetadata({ name: this.packName, newData: this.packMeta })
+ .then((resp) => resp.json())
+ .then((resp) => {
+ if (resp.error !== undefined) {
+ this.displayError(resp.error)
+ return
+ }
- // Update actual pack data
- this.pack.pack = resp
- // Delete edited pack data, should auto-update itself
- delete this.editedMetadata[this.packName]
- })
+ // Update actual pack data
+ this.pack.pack = resp
+ // Delete edited pack data, should auto-update itself
+ delete this.editedMetadata[this.packName]
+ })
},
- updatePackFiles (newFiles, packName) {
+ updatePackFiles(newFiles, packName) {
this.knownPacks[packName].files = newFiles
this.sortPackFiles(packName)
},
- loadPacksPaginated (listFunction) {
+ loadPacksPaginated(listFunction) {
const pageSize = 25
const allPacks = {}
- return listFunction({ instance: this.remotePackInstance, page: 1, pageSize: 0 })
- .then(data => data.json())
- .then(data => {
- if (data.error !== undefined) { return Promise.reject(data.error) }
+ return listFunction({
+ instance: this.remotePackInstance,
+ page: 1,
+ pageSize: 0,
+ })
+ .then((data) => data.json())
+ .then((data) => {
+ if (data.error !== undefined) {
+ return Promise.reject(data.error)
+ }
let resultingPromise = Promise.resolve({})
for (let i = 0; i < Math.ceil(data.count / pageSize); i++) {
- resultingPromise = resultingPromise.then(() => listFunction({ instance: this.remotePackInstance, page: i, pageSize })
- ).then(data => data.json()).then(pageData => {
- if (pageData.error !== undefined) { return Promise.reject(pageData.error) }
+ resultingPromise = resultingPromise
+ .then(() =>
+ listFunction({
+ instance: this.remotePackInstance,
+ page: i,
+ pageSize,
+ }),
+ )
+ .then((data) => data.json())
+ .then((pageData) => {
+ if (pageData.error !== undefined) {
+ return Promise.reject(pageData.error)
+ }
- assign(allPacks, pageData.packs)
- })
+ assign(allPacks, pageData.packs)
+ })
}
return resultingPromise
})
.then(() => allPacks)
- .catch(data => {
+ .catch((data) => {
this.displayError(data)
})
},
- refreshPackList () {
- this.loadPacksPaginated(this.$store.state.api.backendInteractor.listEmojiPacks)
- .then(allPacks => {
- this.knownLocalPacks = allPacks
- for (const name of Object.keys(this.knownLocalPacks)) {
- this.sortPackFiles(name)
- }
- })
+ refreshPackList() {
+ this.loadPacksPaginated(
+ this.$store.state.api.backendInteractor.listEmojiPacks,
+ ).then((allPacks) => {
+ this.knownLocalPacks = allPacks
+ for (const name of Object.keys(this.knownLocalPacks)) {
+ this.sortPackFiles(name)
+ }
+ })
},
- listRemotePacks () {
- this.loadPacksPaginated(this.$store.state.api.backendInteractor.listRemoteEmojiPacks)
- .then(allPacks => {
+ listRemotePacks() {
+ this.loadPacksPaginated(
+ this.$store.state.api.backendInteractor.listRemoteEmojiPacks,
+ )
+ .then((allPacks) => {
let inst = this.remotePackInstance
- if (!inst.startsWith('http')) { inst = 'https://' + inst }
+ if (!inst.startsWith('http')) {
+ inst = 'https://' + inst
+ }
const instUrl = new URL(inst)
inst = instUrl.host
for (const packName in allPacks) {
allPacks[packName].remote = {
baseName: packName,
- instance: instUrl.origin
+ instance: instUrl.origin,
}
}
@@ -222,89 +249,101 @@ const EmojiTab = {
this.sortPackFiles(`${pack}@${inst}`)
}
})
- .catch(data => {
+ .catch((data) => {
this.displayError(data)
})
},
- downloadRemotePack () {
+ downloadRemotePack() {
if (this.remotePackDownloadAs.trim() === '') {
this.remotePackDownloadAs = this.pack.remote.baseName
}
- this.$store.state.api.backendInteractor.downloadRemoteEmojiPack({
- instance: this.pack.remote.instance, packName: this.pack.remote.baseName, as: this.remotePackDownloadAs
- })
- .then(data => data.json())
- .then(resp => {
+ this.$store.state.api.backendInteractor
+ .downloadRemoteEmojiPack({
+ instance: this.pack.remote.instance,
+ packName: this.pack.remote.baseName,
+ as: this.remotePackDownloadAs,
+ })
+ .then((data) => data.json())
+ .then((resp) => {
if (resp === 'ok') {
return this.refreshPackList()
} else {
this.displayError(resp.error)
return Promise.reject(resp)
}
- }).then(() => {
+ })
+ .then(() => {
this.packName = this.remotePackDownloadAs
this.remotePackDownloadAs = ''
})
},
- downloadRemoteURLPack () {
- this.$store.state.api.backendInteractor.downloadRemoteEmojiPackZIP({
- url: this.remotePackURL, packName: this.newPackName
- })
- .then(data => data.json())
- .then(resp => {
+ downloadRemoteURLPack() {
+ this.$store.state.api.backendInteractor
+ .downloadRemoteEmojiPackZIP({
+ url: this.remotePackURL,
+ packName: this.newPackName,
+ })
+ .then((data) => data.json())
+ .then((resp) => {
if (resp === 'ok') {
return this.refreshPackList()
} else {
this.displayError(resp.error)
return Promise.reject(resp)
}
- }).then(() => {
+ })
+ .then(() => {
this.packName = this.newPackName
this.newPackName = ''
this.remotePackURL = ''
})
},
- downloadRemoteFilePack () {
- this.$store.state.api.backendInteractor.downloadRemoteEmojiPackZIP({
- file: this.remotePackFile[0], packName: this.newPackName
- })
- .then(data => data.json())
- .then(resp => {
+ downloadRemoteFilePack() {
+ this.$store.state.api.backendInteractor
+ .downloadRemoteEmojiPackZIP({
+ file: this.remotePackFile[0],
+ packName: this.newPackName,
+ })
+ .then((data) => data.json())
+ .then((resp) => {
if (resp === 'ok') {
return this.refreshPackList()
} else {
this.displayError(resp.error)
return Promise.reject(resp)
}
- }).then(() => {
+ })
+ .then(() => {
this.packName = this.newPackName
this.newPackName = ''
this.remotePackURL = ''
})
},
- displayError (msg) {
+ displayError(msg) {
useInterfaceStore().pushGlobalNotice({
messageKey: 'admin_dash.emoji.error',
messageArgs: [msg],
- level: 'error'
+ level: 'error',
})
},
- sortPackFiles (nameOfPack) {
+ sortPackFiles(nameOfPack) {
// Sort by key
- const sorted = Object.keys(this.knownPacks[nameOfPack].files).sort().reduce((acc, key) => {
- if (key.length === 0) return acc
- acc[key] = this.knownPacks[nameOfPack].files[key]
- return acc
- }, {})
+ const sorted = Object.keys(this.knownPacks[nameOfPack].files)
+ .sort()
+ .reduce((acc, key) => {
+ if (key.length === 0) return acc
+ acc[key] = this.knownPacks[nameOfPack].files[key]
+ return acc
+ }, {})
this.knownPacks[nameOfPack].files = sorted
- }
+ },
},
- mounted () {
+ mounted() {
this.refreshPackList()
- }
+ },
}
export default EmojiTab
diff --git a/src/components/settings_modal/admin_tabs/federation_tab.js b/src/components/settings_modal/admin_tabs/federation_tab.js
index 97b4e0040..33c688eb4 100644
--- a/src/components/settings_modal/admin_tabs/federation_tab.js
+++ b/src/components/settings_modal/admin_tabs/federation_tab.js
@@ -1,19 +1,18 @@
-import BooleanSetting from '../helpers/boolean_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
-import GroupSetting from '../helpers/group_setting.vue'
import AttachmentSetting from '../helpers/attachment_setting.vue'
+import BooleanSetting from '../helpers/boolean_setting.vue'
+import GroupSetting from '../helpers/group_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import ListSetting from '../helpers/list_setting.vue'
import ListTupleSetting from '../helpers/list_tuple_setting.vue'
import MapSetting from '../helpers/map_setting.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
const FederationTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -24,11 +23,11 @@ const FederationTab = {
ListSetting,
ListTupleSetting,
GroupSetting,
- MapSetting
+ MapSetting,
},
computed: {
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default FederationTab
diff --git a/src/components/settings_modal/admin_tabs/frontends_tab.js b/src/components/settings_modal/admin_tabs/frontends_tab.js
index c63e76214..7563adae0 100644
--- a/src/components/settings_modal/admin_tabs/frontends_tab.js
+++ b/src/components/settings_modal/admin_tabs/frontends_tab.js
@@ -1,32 +1,28 @@
+import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
+import Popover from 'src/components/popover/popover.vue'
+import { useInterfaceStore } from 'src/stores/interface'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
import GroupSetting from '../helpers/group_setting.vue'
-import Popover from 'src/components/popover/popover.vue'
-import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
-import { useInterfaceStore } from 'src/stores/interface'
-
+import IntegerSetting from '../helpers/integer_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faGlobe
-} from '@fortawesome/free-solid-svg-icons'
+import StringSetting from '../helpers/string_setting.vue'
-library.add(
- faGlobe
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faGlobe } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faGlobe)
const FrontendsTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
- data () {
+ data() {
return {
- working: false
+ working: false,
}
},
components: {
@@ -36,26 +32,26 @@ const FrontendsTab = {
StringSetting,
GroupSetting,
PanelLoading,
- Popover
+ Popover,
},
- created () {
+ created() {
if (this.user.rights.admin) {
this.$store.dispatch('loadFrontendsStuff')
}
},
computed: {
...SharedComputedObject(),
- frontends () {
+ frontends() {
return this.$store.state.adminSettings.frontends
- }
+ },
},
methods: {
- canInstall (frontend) {
- const fe = this.frontends.find(f => f.name === frontend.name)
+ canInstall(frontend) {
+ const fe = this.frontends.find((f) => f.name === frontend.name)
if (!fe) return false
return fe.refs.includes(frontend.ref)
},
- getSuggestedRef (frontend) {
+ getSuggestedRef(frontend) {
if (this.adminDraft) {
const defaultFe = this.adminDraft[':pleroma'][':frontends'][':primary']
if (defaultFe?.name === frontend.name && this.canInstall(defaultFe)) {
@@ -67,13 +63,14 @@ const FrontendsTab = {
return frontend.refs[0]
}
},
- update (frontend, suggestRef) {
+ update(frontend, suggestRef) {
const ref = suggestRef || this.getSuggestedRef(frontend)
const { name } = frontend
const payload = { name, ref }
this.working = true
- this.$store.state.api.backendInteractor.installFrontend({ payload })
+ this.$store.state.api.backendInteractor
+ .installFrontend({ payload })
.finally(() => {
this.working = false
})
@@ -86,29 +83,32 @@ const FrontendsTab = {
messageKey: 'admin_dash.frontend.failure_installing_frontend',
messageArgs: {
version: name + '/' + ref,
- reason: reason.error
+ reason: reason.error,
},
- timeout: 5000
+ timeout: 5000,
})
} else {
useInterfaceStore().pushGlobalNotice({
level: 'success',
messageKey: 'admin_dash.frontend.success_installing_frontend',
messageArgs: {
- version: name + '/' + ref
+ version: name + '/' + ref,
},
- timeout: 2000
+ timeout: 2000,
})
}
})
},
- setDefault (frontend, suggestRef) {
+ setDefault(frontend, suggestRef) {
const ref = suggestRef || this.getSuggestedRef(frontend)
const { name } = frontend
- this.$store.commit('updateAdminDraft', { path: [':pleroma', ':frontends', ':primary'], value: { name, ref } })
- }
- }
+ this.$store.commit('updateAdminDraft', {
+ path: [':pleroma', ':frontends', ':primary'],
+ value: { name, ref },
+ })
+ },
+ },
}
export default FrontendsTab
diff --git a/src/components/settings_modal/admin_tabs/http_tab.js b/src/components/settings_modal/admin_tabs/http_tab.js
index 82e2bb010..ea76ebe6f 100644
--- a/src/components/settings_modal/admin_tabs/http_tab.js
+++ b/src/components/settings_modal/admin_tabs/http_tab.js
@@ -1,22 +1,22 @@
-import BooleanSetting from '../helpers/boolean_setting.vue'
-import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
-import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
-import ListSetting from '../helpers/list_setting.vue'
-import TupleSetting from '../helpers/tuple_setting.vue'
-import MapSetting from '../helpers/map_setting.vue'
-import ProxySetting from '../helpers/proxy_setting.vue'
-
-import SharedComputedObject from '../helpers/shared_computed_object.js'
import { get } from 'lodash'
+import AttachmentSetting from '../helpers/attachment_setting.vue'
+import BooleanSetting from '../helpers/boolean_setting.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
+import GroupSetting from '../helpers/group_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
+import ListSetting from '../helpers/list_setting.vue'
+import MapSetting from '../helpers/map_setting.vue'
+import ProxySetting from '../helpers/proxy_setting.vue'
+import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
+import TupleSetting from '../helpers/tuple_setting.vue'
+
const HTTPTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -29,18 +29,23 @@ const HTTPTab = {
GroupSetting,
ListSetting,
TupleSetting,
- ProxySetting
+ ProxySetting,
},
computed: {
...SharedComputedObject(),
- sslOptions () {
- const desc = get(this.$store.state.adminSettings.descriptions, ':pleroma.:http.:adapter.:ssl_options.:versions')
- return new Set(desc.suggestions.map(option => ({
- label: option.replace(':tlsv', 'TLS v'),
- value: option
- })))
+ sslOptions() {
+ const desc = get(
+ this.$store.state.adminSettings.descriptions,
+ ':pleroma.:http.:adapter.:ssl_options.:versions',
+ )
+ return new Set(
+ desc.suggestions.map((option) => ({
+ label: option.replace(':tlsv', 'TLS v'),
+ value: option,
+ })),
+ )
},
- }
+ },
}
export default HTTPTab
diff --git a/src/components/settings_modal/admin_tabs/instance_tab.js b/src/components/settings_modal/admin_tabs/instance_tab.js
index ddbd58a88..67d04c303 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.js
+++ b/src/components/settings_modal/admin_tabs/instance_tab.js
@@ -1,22 +1,22 @@
-import BooleanSetting from '../helpers/boolean_setting.vue'
-import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
-import ColorSetting from '../helpers/color_setting.vue'
-import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
-import ListSetting from '../helpers/list_setting.vue'
-import PWAManifestIconsSetting from '../helpers/pwa_manifest_icons_setting.vue'
-import MapSetting from '../helpers/map_setting.vue'
-
-import SharedComputedObject from '../helpers/shared_computed_object.js'
import { get } from 'lodash'
+import AttachmentSetting from '../helpers/attachment_setting.vue'
+import BooleanSetting from '../helpers/boolean_setting.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
+import ColorSetting from '../helpers/color_setting.vue'
+import GroupSetting from '../helpers/group_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
+import ListSetting from '../helpers/list_setting.vue'
+import MapSetting from '../helpers/map_setting.vue'
+import PWAManifestIconsSetting from '../helpers/pwa_manifest_icons_setting.vue'
+import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
+
const InstanceTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -29,25 +29,40 @@ const InstanceTab = {
ListSetting,
PWAManifestIconsSetting,
MapSetting,
- GroupSetting
+ GroupSetting,
},
computed: {
...SharedComputedObject(),
- providersOptions () {
- const desc = get(this.$store.state.adminSettings.descriptions, [':pleroma', 'Pleroma.Web.Metadata', ':providers'])
- return new Set(desc.suggestions.map(option => ({
- label: option.replace('Pleroma.Web.Metadata.Providers.', ''),
- value: option
- })))
+ providersOptions() {
+ const desc = get(this.$store.state.adminSettings.descriptions, [
+ ':pleroma',
+ 'Pleroma.Web.Metadata',
+ ':providers',
+ ])
+ return new Set(
+ desc.suggestions.map((option) => ({
+ label: option.replace('Pleroma.Web.Metadata.Providers.', ''),
+ value: option,
+ })),
+ )
},
- limitLocalContentOptions () {
- const desc = get(this.$store.state.adminSettings.descriptions, [':pleroma', ':instance', ':limit_to_local_content'])
- return new Set(desc.suggestions.map(option => ({
- label: option !== 'false' ? this.$t('admin_dash.instance.' + option) : this.$t('general.no'),
- value: option
- })))
- }
- }
+ limitLocalContentOptions() {
+ const desc = get(this.$store.state.adminSettings.descriptions, [
+ ':pleroma',
+ ':instance',
+ ':limit_to_local_content',
+ ])
+ return new Set(
+ desc.suggestions.map((option) => ({
+ label:
+ option !== 'false'
+ ? this.$t('admin_dash.instance.' + option)
+ : this.$t('general.no'),
+ value: option,
+ })),
+ )
+ },
+ },
}
export default InstanceTab
diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue
index fa55cef41..585fe303c 100644
--- a/src/components/settings_modal/admin_tabs/instance_tab.vue
+++ b/src/components/settings_modal/admin_tabs/instance_tab.vue
@@ -49,10 +49,16 @@
-
+
-
+
diff --git a/src/components/settings_modal/admin_tabs/job_queues_tab.js b/src/components/settings_modal/admin_tabs/job_queues_tab.js
index b0f583c55..66a0e7e18 100644
--- a/src/components/settings_modal/admin_tabs/job_queues_tab.js
+++ b/src/components/settings_modal/admin_tabs/job_queues_tab.js
@@ -1,19 +1,18 @@
+import AttachmentSetting from '../helpers/attachment_setting.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
+import GroupSetting from '../helpers/group_setting.vue'
import IntegerSetting from '../helpers/integer_setting.vue'
+import ListSetting from '../helpers/list_setting.vue'
+import SharedComputedObject from '../helpers/shared_computed_object.js'
import StringSetting from '../helpers/string_setting.vue'
import TupleSetting from '../helpers/tuple_setting.vue'
-import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
-import ListSetting from '../helpers/list_setting.vue'
-
-import SharedComputedObject from '../helpers/shared_computed_object.js'
const JobQueuesTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -24,11 +23,11 @@ const JobQueuesTab = {
TupleSetting,
AttachmentSetting,
GroupSetting,
- ListSetting
+ ListSetting,
},
computed: {
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default JobQueuesTab
diff --git a/src/components/settings_modal/admin_tabs/limits_tab.js b/src/components/settings_modal/admin_tabs/limits_tab.js
index c1126f49c..1f9a7be54 100644
--- a/src/components/settings_modal/admin_tabs/limits_tab.js
+++ b/src/components/settings_modal/admin_tabs/limits_tab.js
@@ -1,20 +1,19 @@
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
const LimitsTab = {
components: {
BooleanSetting,
ChoiceSetting,
IntegerSetting,
- StringSetting
+ StringSetting,
},
computed: {
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default LimitsTab
diff --git a/src/components/settings_modal/admin_tabs/links_tab.js b/src/components/settings_modal/admin_tabs/links_tab.js
index 026b099a5..b3b5f1f2e 100644
--- a/src/components/settings_modal/admin_tabs/links_tab.js
+++ b/src/components/settings_modal/admin_tabs/links_tab.js
@@ -1,21 +1,20 @@
-import BooleanSetting from '../helpers/boolean_setting.vue'
-import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
-import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
-import ListSetting from '../helpers/list_setting.vue'
-
-import Checkbox from 'src/components/checkbox/checkbox.vue'
-
-import SharedComputedObject from '../helpers/shared_computed_object.js'
import { get } from 'lodash'
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+import AttachmentSetting from '../helpers/attachment_setting.vue'
+import BooleanSetting from '../helpers/boolean_setting.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
+import GroupSetting from '../helpers/group_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
+import ListSetting from '../helpers/list_setting.vue'
+import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
+
const LinksTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -26,84 +25,109 @@ const LinksTab = {
AttachmentSetting,
GroupSetting,
ListSetting,
- Checkbox
+ Checkbox,
},
computed: {
- classIsPresent () {
- return this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Formatter'][':class'] !== false
+ classIsPresent() {
+ return (
+ this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Formatter'][
+ ':class'
+ ] !== false
+ )
},
- relIsPresent () {
- return this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Formatter'][':rel'] !== false
+ relIsPresent() {
+ return (
+ this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Formatter'][
+ ':rel'
+ ] !== false
+ )
},
- truncateIsPresent () {
- return this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Formatter'][':truncate'] !== false
+ truncateIsPresent() {
+ return (
+ this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Formatter'][
+ ':truncate'
+ ] !== false
+ )
},
- truncateDescription () {
- return get(this.$store.state.adminSettings.descriptions, [':pleroma', 'Pleroma.Formatter', ':truncate'])
+ truncateDescription() {
+ return get(this.$store.state.adminSettings.descriptions, [
+ ':pleroma',
+ 'Pleroma.Formatter',
+ ':truncate',
+ ])
},
- ttlSettersOptions () {
- const desc = get(this.$store.state.adminSettings.descriptions, ':pleroma.:rich_media.:ttl_setters')
- return new Set(desc.suggestions.map(option => ({
- label: option.replace('Pleroma.Web.RichMedia.Parser.TTL.', ''),
- value: option
- })))
+ ttlSettersOptions() {
+ const desc = get(
+ this.$store.state.adminSettings.descriptions,
+ ':pleroma.:rich_media.:ttl_setters',
+ )
+ return new Set(
+ desc.suggestions.map((option) => ({
+ label: option.replace('Pleroma.Web.RichMedia.Parser.TTL.', ''),
+ value: option,
+ })),
+ )
},
- parsersOptions () {
- const desc = get(this.$store.state.adminSettings.descriptions, ':pleroma.:rich_media.:parsers')
- return new Set(desc.suggestions.map(option => ({
- label: option.replace('Pleroma.Web.RichMedia.Parsers.', ''),
- value: option
- })))
+ parsersOptions() {
+ const desc = get(
+ this.$store.state.adminSettings.descriptions,
+ ':pleroma.:rich_media.:parsers',
+ )
+ return new Set(
+ desc.suggestions.map((option) => ({
+ label: option.replace('Pleroma.Web.RichMedia.Parsers.', ''),
+ value: option,
+ })),
+ )
},
- validateTLDOptions () {
- return [{
- label: this.$t('general.yes'),
- value: true
- }, {
- label: this.$t('general.no'),
- value: false
- }, {
- label: this.$t('admin_dash.links.no_scheme'),
- value: ':no_scheme'
- }]
+ validateTLDOptions() {
+ return [
+ {
+ label: this.$t('general.yes'),
+ value: true,
+ },
+ {
+ label: this.$t('general.no'),
+ value: false,
+ },
+ {
+ label: this.$t('admin_dash.links.no_scheme'),
+ value: ':no_scheme',
+ },
+ ]
},
- mediaProxyEnabled () {
- return this.$store.state.adminSettings.draft[':pleroma'][':media_proxy'][':enabled']
+ mediaProxyEnabled() {
+ return this.$store.state.adminSettings.draft[':pleroma'][':media_proxy'][
+ ':enabled'
+ ]
},
- mediaInvalidationProvider () {
- return this.$store.state.adminSettings.draft[':pleroma'][':media_proxy'][':invalidation'][':provider']
+ mediaInvalidationProvider() {
+ return this.$store.state.adminSettings.draft[':pleroma'][':media_proxy'][
+ ':invalidation'
+ ][':provider']
},
- ...SharedComputedObject()
+ ...SharedComputedObject(),
},
methods: {
- checkRel (e) {
- this.$store.commit(
- 'updateAdminDraft',
- {
- path: [':pleroma','Pleroma.Formatter',':rel'],
- value: e ? '' : false
- }
- )
+ checkRel(e) {
+ this.$store.commit('updateAdminDraft', {
+ path: [':pleroma', 'Pleroma.Formatter', ':rel'],
+ value: e ? '' : false,
+ })
},
- checkClass (e) {
- this.$store.commit(
- 'updateAdminDraft',
- {
- path: [':pleroma','Pleroma.Formatter',':class'],
- value: e ? '' : false
- }
- )
+ checkClass(e) {
+ this.$store.commit('updateAdminDraft', {
+ path: [':pleroma', 'Pleroma.Formatter', ':class'],
+ value: e ? '' : false,
+ })
},
- checkTruncate (e) {
- this.$store.commit(
- 'updateAdminDraft',
- {
- path: [':pleroma','Pleroma.Formatter',':truncate'],
- value: e ? 20 : false
- }
- )
- }
- }
+ checkTruncate(e) {
+ this.$store.commit('updateAdminDraft', {
+ path: [':pleroma', 'Pleroma.Formatter', ':truncate'],
+ value: e ? 20 : false,
+ })
+ },
+ },
}
export default LinksTab
diff --git a/src/components/settings_modal/admin_tabs/mailer_tab.js b/src/components/settings_modal/admin_tabs/mailer_tab.js
index 44b2f33df..0b909334b 100644
--- a/src/components/settings_modal/admin_tabs/mailer_tab.js
+++ b/src/components/settings_modal/admin_tabs/mailer_tab.js
@@ -1,18 +1,17 @@
+import AttachmentSetting from '../helpers/attachment_setting.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
-import GroupSetting from '../helpers/group_setting.vue'
import ColorSetting from '../helpers/color_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
-
+import GroupSetting from '../helpers/group_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
const MailerTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -22,44 +21,50 @@ const MailerTab = {
StringSetting,
AttachmentSetting,
ColorSetting,
- GroupSetting
+ GroupSetting,
},
computed: {
- adaptersLabels () {
+ adaptersLabels() {
const prefix = 'Swoosh.Adapters.'
const descriptions = this.$store.state.adminSettings.descriptions
- const options = descriptions[':pleroma']['Pleroma.Emails.Mailer'][':adapter'].suggestions
+ const options =
+ descriptions[':pleroma']['Pleroma.Emails.Mailer'][':adapter']
+ .suggestions
- return Object.fromEntries(options.map(value => [
- value, value.replace(prefix, '')
- ]))
+ return Object.fromEntries(
+ options.map((value) => [value, value.replace(prefix, '')]),
+ )
},
- startTLSLabels () {
+ startTLSLabels() {
return {
':always': this.$t('admin_dash.generic_enforcement.always'),
':if_available': this.$t('admin_dash.generic_enforcement.if_available'),
- ':never': this.$t('admin_dash.generic_enforcement.never')
+ ':never': this.$t('admin_dash.generic_enforcement.never'),
}
// return Object.fromEntries(options.map(value => [
// value, value.replace(prefix, '')
// ]))
},
- adapter () {
- return this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Emails.Mailer'][':adapter']
+ adapter() {
+ return this.$store.state.adminSettings.draft[':pleroma'][
+ 'Pleroma.Emails.Mailer'
+ ][':adapter']
},
- mailerEnabled () {
- return this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Emails.Mailer'][':enabled']
+ mailerEnabled() {
+ return this.$store.state.adminSettings.draft[':pleroma'][
+ 'Pleroma.Emails.Mailer'
+ ][':enabled']
},
- ...SharedComputedObject()
+ ...SharedComputedObject(),
},
methods: {
- adapterHasKey (key) {
+ adapterHasKey(key) {
const descriptions = this.$store.state.adminSettings.descriptions
const mailerStuff = descriptions[':pleroma']['Pleroma.Emails.Mailer']
const adapterStuff = mailerStuff[':subgroup,' + this.adapter]
- return Object.prototype.hasOwnProperty.call(adapterStuff, key)
- }
- }
+ return Object.hasOwn(adapterStuff, key)
+ },
+ },
}
export default MailerTab
diff --git a/src/components/settings_modal/admin_tabs/media_proxy_tab.js b/src/components/settings_modal/admin_tabs/media_proxy_tab.js
index af82593bc..6c7231312 100644
--- a/src/components/settings_modal/admin_tabs/media_proxy_tab.js
+++ b/src/components/settings_modal/admin_tabs/media_proxy_tab.js
@@ -1,18 +1,17 @@
+import AttachmentSetting from '../helpers/attachment_setting.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import ListSetting from '../helpers/list_setting.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
const MediaProxyTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -22,17 +21,21 @@ const MediaProxyTab = {
StringSetting,
AttachmentSetting,
GroupSetting,
- ListSetting
+ ListSetting,
},
computed: {
- mediaProxyEnabled () {
- return this.$store.state.adminSettings.draft[':pleroma'][':media_proxy'][':enabled']
+ mediaProxyEnabled() {
+ return this.$store.state.adminSettings.draft[':pleroma'][':media_proxy'][
+ ':enabled'
+ ]
},
- mediaInvalidationProvider () {
- return this.$store.state.adminSettings.draft[':pleroma'][':media_proxy'][':invalidation'][':provider']
+ mediaInvalidationProvider() {
+ return this.$store.state.adminSettings.draft[':pleroma'][':media_proxy'][
+ ':invalidation'
+ ][':provider']
},
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default MediaProxyTab
diff --git a/src/components/settings_modal/admin_tabs/monitoring_tab.js b/src/components/settings_modal/admin_tabs/monitoring_tab.js
index 8593b9d69..1ba9770f0 100644
--- a/src/components/settings_modal/admin_tabs/monitoring_tab.js
+++ b/src/components/settings_modal/admin_tabs/monitoring_tab.js
@@ -1,26 +1,22 @@
+import AttachmentSetting from '../helpers/attachment_setting.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import ListSetting from '../helpers/list_setting.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faGlobe
-} from '@fortawesome/free-solid-svg-icons'
+import StringSetting from '../helpers/string_setting.vue'
-library.add(
- faGlobe
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faGlobe } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faGlobe)
const MonitoringTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -30,13 +26,12 @@ const MonitoringTab = {
StringSetting,
AttachmentSetting,
GroupSetting,
- ListSetting
+ ListSetting,
},
computed: {
- ...SharedComputedObject()
+ ...SharedComputedObject(),
},
- methods: {
- }
+ methods: {},
}
export default MonitoringTab
diff --git a/src/components/settings_modal/admin_tabs/other_tab.js b/src/components/settings_modal/admin_tabs/other_tab.js
index dc6550d27..a31bcf307 100644
--- a/src/components/settings_modal/admin_tabs/other_tab.js
+++ b/src/components/settings_modal/admin_tabs/other_tab.js
@@ -1,21 +1,20 @@
+import AttachmentSetting from '../helpers/attachment_setting.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
import ColorSetting from '../helpers/color_setting.vue'
import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import ListSetting from '../helpers/list_setting.vue'
-import PWAManifestIconsSetting from '../helpers/pwa_manifest_icons_setting.vue'
import MapSetting from '../helpers/map_setting.vue'
-
+import PWAManifestIconsSetting from '../helpers/pwa_manifest_icons_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
const OtherTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -28,11 +27,11 @@ const OtherTab = {
ListSetting,
PWAManifestIconsSetting,
MapSetting,
- GroupSetting
+ GroupSetting,
},
computed: {
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default OtherTab
diff --git a/src/components/settings_modal/admin_tabs/posts_tab.js b/src/components/settings_modal/admin_tabs/posts_tab.js
index d9f213594..654b18ed8 100644
--- a/src/components/settings_modal/admin_tabs/posts_tab.js
+++ b/src/components/settings_modal/admin_tabs/posts_tab.js
@@ -1,21 +1,20 @@
+import AttachmentSetting from '../helpers/attachment_setting.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import StringSetting from '../helpers/string_setting.vue'
import ColorSetting from '../helpers/color_setting.vue'
import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import ListSetting from '../helpers/list_setting.vue'
-import PWAManifestIconsSetting from '../helpers/pwa_manifest_icons_setting.vue'
import MapSetting from '../helpers/map_setting.vue'
-
+import PWAManifestIconsSetting from '../helpers/pwa_manifest_icons_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import StringSetting from '../helpers/string_setting.vue'
const PostsTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -28,11 +27,11 @@ const PostsTab = {
ListSetting,
PWAManifestIconsSetting,
MapSetting,
- GroupSetting
+ GroupSetting,
},
computed: {
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default PostsTab
diff --git a/src/components/settings_modal/admin_tabs/rates_tab.js b/src/components/settings_modal/admin_tabs/rates_tab.js
index c602dcc8a..ddf18b035 100644
--- a/src/components/settings_modal/admin_tabs/rates_tab.js
+++ b/src/components/settings_modal/admin_tabs/rates_tab.js
@@ -1,20 +1,19 @@
import RateSetting from '../helpers/rate_setting.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
const RatesTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
RateSetting,
},
computed: {
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default RatesTab
diff --git a/src/components/settings_modal/admin_tabs/registrations_tab.js b/src/components/settings_modal/admin_tabs/registrations_tab.js
index 3ce6c8044..8ec5e0d4b 100644
--- a/src/components/settings_modal/admin_tabs/registrations_tab.js
+++ b/src/components/settings_modal/admin_tabs/registrations_tab.js
@@ -1,19 +1,18 @@
+import AttachmentSetting from '../helpers/attachment_setting.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
+import GroupSetting from '../helpers/group_setting.vue'
import IntegerSetting from '../helpers/integer_setting.vue'
+import ListSetting from '../helpers/list_setting.vue'
+import SharedComputedObject from '../helpers/shared_computed_object.js'
import StringSetting from '../helpers/string_setting.vue'
import TupleSetting from '../helpers/tuple_setting.vue'
-import GroupSetting from '../helpers/group_setting.vue'
-import AttachmentSetting from '../helpers/attachment_setting.vue'
-import ListSetting from '../helpers/list_setting.vue'
-
-import SharedComputedObject from '../helpers/shared_computed_object.js'
const RegistrationsTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
components: {
@@ -24,11 +23,11 @@ const RegistrationsTab = {
TupleSetting,
AttachmentSetting,
GroupSetting,
- ListSetting
+ ListSetting,
},
computed: {
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default RegistrationsTab
diff --git a/src/components/settings_modal/admin_tabs/uploads_tab.js b/src/components/settings_modal/admin_tabs/uploads_tab.js
index 40a184db1..760206499 100644
--- a/src/components/settings_modal/admin_tabs/uploads_tab.js
+++ b/src/components/settings_modal/admin_tabs/uploads_tab.js
@@ -1,46 +1,51 @@
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import IntegerSetting from '../helpers/integer_setting.vue'
+import SharedComputedObject from '../helpers/shared_computed_object.js'
import StringSetting from '../helpers/string_setting.vue'
-import SharedComputedObject from '../helpers/shared_computed_object.js'
-
const UploadsTab = {
- provide () {
+ provide() {
return {
defaultDraftMode: true,
- defaultSource: 'admin'
+ defaultSource: 'admin',
}
},
- data () {
+ data() {
return {
- uploaders: [{
- key: 'Pleroma.Uploaders.Local',
- value: 'Pleroma.Uploaders.Local',
- label: this.$t('admin_dash.uploads.local_uploader')
- }, {
- key: 'Pleroma.Uploaders.IPFS',
- value: 'Pleroma.Uploaders.IPFS',
- label: 'IPFS'
- }, {
- key: 'Pleroma.Uploaders.S3',
- value: 'Pleroma.Uploaders.S3',
- label: 'S3'
- }]
+ uploaders: [
+ {
+ key: 'Pleroma.Uploaders.Local',
+ value: 'Pleroma.Uploaders.Local',
+ label: this.$t('admin_dash.uploads.local_uploader'),
+ },
+ {
+ key: 'Pleroma.Uploaders.IPFS',
+ value: 'Pleroma.Uploaders.IPFS',
+ label: 'IPFS',
+ },
+ {
+ key: 'Pleroma.Uploaders.S3',
+ value: 'Pleroma.Uploaders.S3',
+ label: 'S3',
+ },
+ ],
}
},
components: {
BooleanSetting,
ChoiceSetting,
IntegerSetting,
- StringSetting
+ StringSetting,
},
computed: {
- uploader () {
- return this.$store.state.adminSettings.draft[':pleroma']['Pleroma.Upload'][':uploader']
+ uploader() {
+ return this.$store.state.adminSettings.draft[':pleroma'][
+ 'Pleroma.Upload'
+ ][':uploader']
},
- ...SharedComputedObject()
- }
+ ...SharedComputedObject(),
+ },
}
export default UploadsTab
diff --git a/src/components/settings_modal/helpers/attachment_setting.js b/src/components/settings_modal/helpers/attachment_setting.js
index c4c04b2b6..61e00a353 100644
--- a/src/components/settings_modal/helpers/attachment_setting.js
+++ b/src/components/settings_modal/helpers/attachment_setting.js
@@ -1,7 +1,7 @@
-import Setting from './setting.js'
-import { fileTypeExt } from 'src/services/file_type/file_type.service.js'
-import MediaUpload from 'src/components/media_upload/media_upload.vue'
import Attachment from 'src/components/attachment/attachment.vue'
+import MediaUpload from 'src/components/media_upload/media_upload.vue'
+import { fileTypeExt } from 'src/services/file_type/file_type.service.js'
+import Setting from './setting.js'
export default {
...Setting,
@@ -11,34 +11,36 @@ export default {
acceptTypes: {
type: String,
required: false,
- default: 'image/*'
- }
+ default: 'image/*',
+ },
},
components: {
...Setting.components,
MediaUpload,
- Attachment
+ Attachment,
},
computed: {
...Setting.computed,
- attachment () {
+ attachment() {
const path = this.realDraftMode ? this.draft : this.state
// The "server" part is primarily for local dev, but could be useful for alt-domain or multiuser usage.
- const url = path.includes('://') ? path : this.$store.state.instance.server + path
+ const url = path.includes('://')
+ ? path
+ : this.$store.state.instance.server + path
return {
mimetype: fileTypeExt(url),
- url
+ url,
}
- }
+ },
},
methods: {
...Setting.methods,
- setMediaFile (fileInfo) {
+ setMediaFile(fileInfo) {
if (this.realDraftMode) {
this.draft = fileInfo.url
} else {
this.configSink(this.path, fileInfo.url)
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/boolean_setting.js b/src/components/settings_modal/helpers/boolean_setting.js
index 199d3d0f0..e7b56f58c 100644
--- a/src/components/settings_modal/helpers/boolean_setting.js
+++ b/src/components/settings_modal/helpers/boolean_setting.js
@@ -5,27 +5,27 @@ export default {
...Setting,
props: {
...Setting.props,
- indeterminateState: [String, Object]
+ indeterminateState: [String, Object],
},
components: {
...Setting.components,
- Checkbox
+ Checkbox,
},
computed: {
...Setting.computed,
- isIndeterminate () {
+ isIndeterminate() {
return this.visibleState === this.indeterminateState
- }
+ },
},
methods: {
...Setting.methods,
- getValue (e) {
+ getValue(e) {
// Basic tri-state toggle implementation
if (!!this.indeterminateState && !e && this.visibleState === true) {
// If we have indeterminate state, switching from true to false first goes through indeterminate
return this.indeterminateState
}
return e
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js
index 10e043082..e5bc8420e 100644
--- a/src/components/settings_modal/helpers/choice_setting.js
+++ b/src/components/settings_modal/helpers/choice_setting.js
@@ -5,50 +5,50 @@ export default {
...Setting,
components: {
...Setting.components,
- Select
+ Select,
},
props: {
...Setting.props,
overrideOptions: {
type: Boolean,
- required: false
+ required: false,
},
options: {
type: Array,
- required: false
+ required: false,
},
optionLabelMap: {
type: Object,
required: false,
- default: {}
- }
+ default: {},
+ },
},
computed: {
...Setting.computed,
- realOptions () {
+ realOptions() {
if (this.overrideOptions) {
return this.options
}
if (this.realSource === 'admin') {
if (
!this.backendDescriptionSuggestions?.length ||
- this.backendDescriptionSuggestions?.length === 0
+ this.backendDescriptionSuggestions?.length === 0
) {
return this.options
}
- return this.backendDescriptionSuggestions.map(x => ({
+ return this.backendDescriptionSuggestions.map((x) => ({
key: x,
value: x,
- label: this.optionLabelMap[x] || x
+ label: this.optionLabelMap[x] || x,
}))
}
return this.options
- }
+ },
},
methods: {
...Setting.methods,
- getValue (e) {
+ getValue(e) {
return e
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/color_setting.js b/src/components/settings_modal/helpers/color_setting.js
index 40fa038fe..d9b1e1397 100644
--- a/src/components/settings_modal/helpers/color_setting.js
+++ b/src/components/settings_modal/helpers/color_setting.js
@@ -1,16 +1,16 @@
-import Setting from './setting.js'
import ColorInput from 'src/components/color_input/color_input.vue'
+import Setting from './setting.js'
export default {
...Setting,
components: {
...Setting.components,
- ColorInput
+ ColorInput,
},
methods: {
...Setting.methods,
- getValue (e) {
+ getValue(e) {
return e
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/draft_buttons.vue b/src/components/settings_modal/helpers/draft_buttons.vue
index b07ea1ec4..cc7010619 100644
--- a/src/components/settings_modal/helpers/draft_buttons.vue
+++ b/src/components/settings_modal/helpers/draft_buttons.vue
@@ -58,16 +58,15 @@
diff --git a/src/components/settings_modal/helpers/emoji_editing_popover.vue b/src/components/settings_modal/helpers/emoji_editing_popover.vue
index d25b02da2..9fdcdd233 100644
--- a/src/components/settings_modal/helpers/emoji_editing_popover.vue
+++ b/src/components/settings_modal/helpers/emoji_editing_popover.vue
@@ -149,10 +149,10 @@
diff --git a/src/components/settings_modal/helpers/float_setting.vue b/src/components/settings_modal/helpers/float_setting.vue
index 15edb3c3e..a1c495cd1 100644
--- a/src/components/settings_modal/helpers/float_setting.vue
+++ b/src/components/settings_modal/helpers/float_setting.vue
@@ -10,7 +10,7 @@
import NumberSetting from './number_setting.vue'
export default {
components: {
- NumberSetting
- }
+ NumberSetting,
+ },
}
diff --git a/src/components/settings_modal/helpers/help_indicator.vue b/src/components/settings_modal/helpers/help_indicator.vue
index c48f97b70..add6ab753 100644
--- a/src/components/settings_modal/helpers/help_indicator.vue
+++ b/src/components/settings_modal/helpers/help_indicator.vue
@@ -19,15 +19,14 @@
diff --git a/src/components/settings_modal/helpers/integer_setting.vue b/src/components/settings_modal/helpers/integer_setting.vue
index 8206c0c45..e9b227645 100644
--- a/src/components/settings_modal/helpers/integer_setting.vue
+++ b/src/components/settings_modal/helpers/integer_setting.vue
@@ -11,7 +11,7 @@
import NumberSetting from './number_setting.vue'
export default {
components: {
- NumberSetting
- }
+ NumberSetting,
+ },
}
diff --git a/src/components/settings_modal/helpers/list_setting.js b/src/components/settings_modal/helpers/list_setting.js
index def6064d0..c1d504cd5 100644
--- a/src/components/settings_modal/helpers/list_setting.js
+++ b/src/components/settings_modal/helpers/list_setting.js
@@ -3,43 +3,43 @@ import Setting from './setting.js'
export default {
...Setting,
- data () {
+ data() {
return {
newValue: '',
}
},
components: {
...Setting.components,
- Checkbox
+ Checkbox,
},
props: {
...Setting.props,
ignoreSuggestions: {
required: false,
- type: Boolean
+ type: Boolean,
},
overrideAvailableOptions: {
required: false,
- type: Boolean
+ type: Boolean,
},
options: {
required: false,
- type: Set
+ type: Set,
},
allowNew: {
required: false,
type: Boolean,
- default: true
+ default: true,
},
forceNew: {
required: false,
type: Boolean,
- default: false
- }
+ default: false,
+ },
},
computed: {
...Setting.computed,
- showNew () {
+ showNew() {
if (this.forceNew) return true
if (!this.allowNew) return false
@@ -52,10 +52,10 @@ export default {
return true
}
},
- valueSet () {
+ valueSet() {
return new Set(this.visibleState)
},
- suggestionsSet () {
+ suggestionsSet() {
const suggestions = this.backendDescriptionSuggestions
if (suggestions) {
return new Set(suggestions)
@@ -63,14 +63,14 @@ export default {
return new Set()
}
},
- extraEntries () {
+ extraEntries() {
if (this.ignoreSuggestions) return [...this.valueSet.values()]
if (!this.suggestionsSet) return []
return [...this.valueSet.values()].filter((x) => {
return !this.builtinEntriesValueSet.has(x)
})
},
- builtinEntries () {
+ builtinEntries() {
if (this.ignoreSuggestions) return []
if (this.overrideAvailableOptions) {
return [...this.options]
@@ -80,19 +80,19 @@ export default {
const builtins = [...this.suggestionsSet.values()]
return builtins.map((option) => ({
label: option,
- value: option
+ value: option,
}))
},
- builtinEntriesValueSet () {
- return new Set(this.builtinEntries.map(x => x.value))
- }
+ builtinEntriesValueSet() {
+ return new Set(this.builtinEntries.map((x) => x.value))
+ },
},
methods: {
...Setting.methods,
- optionPresent (option) {
+ optionPresent(option) {
return this.valueSet.has(option)
},
- getValue ({ event, value, index, eventType }) {
+ getValue({ event, value, index, eventType }) {
switch (eventType) {
case 'toggle': {
this.newValue = ''
@@ -128,6 +128,6 @@ export default {
return [...pre, string, ...post]
}
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/list_tuple_setting.js b/src/components/settings_modal/helpers/list_tuple_setting.js
index 2cbd93788..33cc725b1 100644
--- a/src/components/settings_modal/helpers/list_tuple_setting.js
+++ b/src/components/settings_modal/helpers/list_tuple_setting.js
@@ -2,14 +2,14 @@ import ListSetting from './list_setting.js'
export default {
...ListSetting,
- data () {
+ data() {
return {
- newValue: ['','']
+ newValue: ['', ''],
}
},
methods: {
...ListSetting.methods,
- getValue ({ event, index, eventType, tuple }) {
+ getValue({ event, index, eventType, tuple }) {
switch (eventType) {
case 'add': {
if (!this.newValue[0] || !this.newValue[1]) return this.visibleState
@@ -39,6 +39,6 @@ export default {
}
}
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/map_setting.js b/src/components/settings_modal/helpers/map_setting.js
index ad93ceacf..8615c90ca 100644
--- a/src/components/settings_modal/helpers/map_setting.js
+++ b/src/components/settings_modal/helpers/map_setting.js
@@ -7,28 +7,31 @@ export default {
allowNew: {
required: false,
type: Boolean,
- default: true
- }
+ default: true,
+ },
},
- data () {
+ data() {
return {
- newValue: ['',''] // avoiding extra complexity by just using an array instead of an object
+ newValue: ['', ''], // avoiding extra complexity by just using an array instead of an object
}
},
computed: {
...Setting.computed,
// state that we'll show in the UI, i.e. transforming map into list
- displayState () {
+ displayState() {
return Object.entries(this.visibleState)
- }
+ },
},
methods: {
...Setting.methods,
- getValue ({ event, key, eventType, isKey }) {
+ getValue({ event, key, eventType, isKey }) {
switch (eventType) {
case 'add': {
if (key === '') return this.visibleState
- const res = {...this.visibleState, ...Object.fromEntries([this.newValue])}
+ const res = {
+ ...this.visibleState,
+ ...Object.fromEntries([this.newValue]),
+ }
this.newValue = ['', '']
return res
}
@@ -36,35 +39,35 @@ export default {
case 'remove': {
// initial state for this type is empty array
if (Array.isArray(this.visibleState)) return this.visibleState
- const newEntries = Object.entries(this.visibleState).filter(([k]) => k !== key)
+ const newEntries = Object.entries(this.visibleState).filter(
+ ([k]) => k !== key,
+ )
- if (newEntries.length === 0 ) return []
+ if (newEntries.length === 0) return []
return Object.fromEntries(newEntries)
}
case 'edit': {
const string = event.target.value
- const newEntries = Object
- .entries(this.visibleState)
- .map(([k, v]) => {
- if (isKey) {
- if (k === key) {
- return [string, v]
- } else {
- return [k, v]
- }
+ const newEntries = Object.entries(this.visibleState).map(([k, v]) => {
+ if (isKey) {
+ if (k === key) {
+ return [string, v]
} else {
- if (k === key) {
- return [k, string]
- } else {
- return [k, v]
- }
+ return [k, v]
}
- })
+ } else {
+ if (k === key) {
+ return [k, string]
+ } else {
+ return [k, v]
+ }
+ }
+ })
return Object.fromEntries(newEntries)
}
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/modified_indicator.vue b/src/components/settings_modal/helpers/modified_indicator.vue
index a747cebd2..c723dfe19 100644
--- a/src/components/settings_modal/helpers/modified_indicator.vue
+++ b/src/components/settings_modal/helpers/modified_indicator.vue
@@ -24,12 +24,11 @@
diff --git a/src/components/settings_modal/helpers/number_setting.js b/src/components/settings_modal/helpers/number_setting.js
index afbf5ed58..e037ece28 100644
--- a/src/components/settings_modal/helpers/number_setting.js
+++ b/src/components/settings_modal/helpers/number_setting.js
@@ -7,33 +7,33 @@ export default {
min: {
type: Number,
required: false,
- default: 1
+ default: 1,
},
max: {
type: Number,
required: false,
- default: 1
+ default: 1,
},
step: {
type: Number,
required: false,
- default: 1
+ default: 1,
},
truncate: {
type: Number,
required: false,
- default: 1
- }
+ default: 1,
+ },
},
methods: {
...Setting.methods,
- getValue (e) {
+ getValue(e) {
if (!this.truncate === 1) {
return parseInt(e.target.value)
} else if (this.truncate > 1) {
return Math.trunc(e.target.value / this.truncate) * this.truncate
}
return parseFloat(e.target.value)
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/profile_setting_indicator.vue b/src/components/settings_modal/helpers/profile_setting_indicator.vue
index d160781b1..3b45b125d 100644
--- a/src/components/settings_modal/helpers/profile_setting_indicator.vue
+++ b/src/components/settings_modal/helpers/profile_setting_indicator.vue
@@ -24,16 +24,15 @@
diff --git a/src/components/settings_modal/helpers/proxy_setting.js b/src/components/settings_modal/helpers/proxy_setting.js
index ca717b60b..4195b8430 100644
--- a/src/components/settings_modal/helpers/proxy_setting.js
+++ b/src/components/settings_modal/helpers/proxy_setting.js
@@ -1,18 +1,19 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Setting from './setting.js'
-const getUrl = state => state?.tuple ? state.tuple[1] + ':' + state.tuple[2] : state
-const getSocks = state => state?.tuple
+const getUrl = (state) =>
+ state?.tuple ? state.tuple[1] + ':' + state.tuple[2] : state
+const getSocks = (state) => state?.tuple
export default {
...Setting,
- data () {
+ data() {
return {
urlField: '',
- socksField: false
+ socksField: false,
}
},
- created () {
+ created() {
Setting.created()
this.urlField = getUrl(this.realDraftMode ? this.draft : this.state)
this.socksField = getSocks(this.realDraftMode ? this.draft : this.state)
@@ -20,23 +21,23 @@ export default {
computed: {
...Setting.computed,
// state that we'll show in the UI, i.e. transforming map into list
- displayState () {
+ displayState() {
if (this.visibleState?.tuple) {
return this.visibleState.tuple[1] + ':' + this.visibleState.tuple[2]
}
return this.visibleState
},
- socksState () {
+ socksState() {
return getSocks(this.visibleState)
- }
+ },
},
components: {
...Setting.components,
- Checkbox
+ Checkbox,
},
methods: {
...Setting.methods,
- getValue ({ event, isProxy}) {
+ getValue({ event, isProxy }) {
if (isProxy) {
this.socksField = event
} else {
@@ -44,10 +45,10 @@ export default {
}
if (this.socksField) {
- return { tuple: [ ':socks5', ...this.urlField.split(':') ] }
+ return { tuple: [':socks5', ...this.urlField.split(':')] }
} else {
return this.urlField
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/pwa_manifest_icons_setting.js b/src/components/settings_modal/helpers/pwa_manifest_icons_setting.js
index 9986f6f39..6d6cdd121 100644
--- a/src/components/settings_modal/helpers/pwa_manifest_icons_setting.js
+++ b/src/components/settings_modal/helpers/pwa_manifest_icons_setting.js
@@ -1,10 +1,10 @@
import { clone } from 'lodash'
-import { fileTypeExt } from 'src/services/file_type/file_type.service.js'
-import Setting from './setting.js'
-import Select from 'src/components/select/select.vue'
import Attachment from 'src/components/attachment/attachment.vue'
import MediaUpload from 'src/components/media_upload/media_upload.vue'
+import Select from 'src/components/select/select.vue'
+import { fileTypeExt } from 'src/services/file_type/file_type.service.js'
+import Setting from './setting.js'
export default {
...Setting,
@@ -12,60 +12,62 @@ export default {
...Setting.components,
Select,
Attachment,
- MediaUpload
+ MediaUpload,
},
computed: {
...Setting.computed,
- purposeOptions () {
- return ['any','monochrome','maskable'].map(value => ({
+ purposeOptions() {
+ return ['any', 'monochrome', 'maskable'].map((value) => ({
value,
key: value,
- label: this.$t('admin_dash.instance.pwa.icon.' + value)
+ label: this.$t('admin_dash.instance.pwa.icon.' + value),
}))
- }
+ },
},
methods: {
...Setting.methods,
- attachment (e) {
+ attachment(e) {
const path = e[':src']
if (!path) {
return {
mimetype: '',
- url: ''
+ url: '',
}
}
- const url = path.includes('://') ? path : this.$store.state.instance.server + path
+ const url = path.includes('://')
+ ? path
+ : this.$store.state.instance.server + path
return {
mimetype: fileTypeExt(url),
- url
+ url,
}
},
- setMediaFile ({ event, index }) {
+ setMediaFile({ event, index }) {
this.update({
event: {
target: {
- value: event.url
+ value: event.url,
},
},
index,
eventType: 'edit',
- field: ':src'
+ field: ':src',
})
},
- setPurpose ({ event, index }) {
+ setPurpose({ event, index }) {
this.update({
event: {
target: {
- value: event
+ value: event,
},
},
index,
eventType: 'edit',
- field: ':purpose'
+ field: ':purpose',
})
},
- getValue ({ event, field, index, eventType }) {
+ getValue({ event, field, index, eventType }) {
switch (eventType) {
case 'add': {
const res = [...this.visibleState, {}]
@@ -85,7 +87,7 @@ export default {
const item = clone(this.visibleState[index])
const string = event.target.value
- if (!string) {
+ if (!string) {
delete item[field]
} else {
item[field] = string
@@ -94,6 +96,6 @@ export default {
return [...pre, item, ...post]
}
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/pwa_manifest_icons_setting.vue b/src/components/settings_modal/helpers/pwa_manifest_icons_setting.vue
index 20e50fe25..f8054d266 100644
--- a/src/components/settings_modal/helpers/pwa_manifest_icons_setting.vue
+++ b/src/components/settings_modal/helpers/pwa_manifest_icons_setting.vue
@@ -85,8 +85,8 @@
@update:model-value="event => setPurpose({ event, index })"
>
-
- | |
-
- {{ $t('admin_dash.rate_limit.period') }}
- |
-
- {{ $t('admin_dash.rate_limit.amount') }}
- |
-
-
- |
- {{ $t('admin_dash.rate_limit.unauthenticated') }}
- |
-
- {{ $t('admin_dash.rate_limit.rate_limit') }}
- |
-
- update({ event: e, index: 0, side: 0, eventType: 'edit' })"
- >
- |
-
- update({ event: e, index: 1, side: 0, eventType: 'edit' })"
- >
- |
-
-
- |
- {{ $t('admin_dash.rate_limit.authenticated') }}
- |
-
- update({ event: e, index: 0, side: 1, eventType: 'edit' })"
- >
- |
-
- update({ event: e, index: 1, side: 1, eventType: 'edit' })"
- >
- |
-
+
+
+ | |
+
+ {{ $t('admin_dash.rate_limit.period') }}
+ |
+
+ {{ $t('admin_dash.rate_limit.amount') }}
+ |
+
+
+
+
+ |
+ {{ isSeparate ? $t('admin_dash.rate_limit.unauthenticated') : $t('admin_dash.rate_limit.rate_limit') }}
+ |
+
+ update({ event: e, index: 0, side: 0, eventType: 'edit' })"
+ >
+ |
+
+ update({ event: e, index: 1, side: 0, eventType: 'edit' })"
+ >
+ |
+
+
+ |
+ {{ $t('admin_dash.rate_limit.authenticated') }}
+ |
+
+ update({ event: e, index: 0, side: 1, eventType: 'edit' })"
+ >
+ |
+
+ update({ event: e, index: 1, side: 1, eventType: 'edit' })"
+ >
+ |
+
+
p.replace(/\./g, '_DOT_')),
- 'label'
- ].join('.'))
+ return this.$t(
+ [
+ 'admin_dash',
+ 'temp_overrides',
+ ...this.canonPath.map((p) => p.replace(/\./g, '_DOT_')),
+ 'label',
+ ].join('.'),
+ )
} else {
return this.swapDescriptionAndLabel
? this.backendDescription?.description
: this.backendDescription?.label
}
},
- backendDescriptionDescription () {
+ backendDescriptionDescription() {
if (this.description) return this.description
if (this.realSource !== 'admin') return ''
if (this.hideDescription) return null
if (!this.backendDescription || this.overrideBackendDescription) {
- return this.$t([
- 'admin_dash',
- 'temp_overrides',
- ...this.canonPath.map(p => p.replace(/\./g, '_DOT_')),
- 'description'
- ].join('.'))
+ return this.$t(
+ [
+ 'admin_dash',
+ 'temp_overrides',
+ ...this.canonPath.map((p) => p.replace(/\./g, '_DOT_')),
+ 'description',
+ ].join('.'),
+ )
} else {
return this.swapDescriptionAndLabel
? this.backendDescription?.label
: this.backendDescription?.description
}
},
- backendDescriptionSuggestions () {
+ backendDescriptionSuggestions() {
return this.backendDescription?.suggestions || this.suggestions
},
- shouldBeDisabled () {
+ shouldBeDisabled() {
if (this.path == null) {
return this.disabled
}
let parentValue = null
if (this.parentPath !== undefined && this.realSource === 'admin') {
if (this.realDraftMode) {
- parentValue = get(this.$store.state.adminSettings.draft, this.parentPath)
+ parentValue = get(
+ this.$store.state.adminSettings.draft,
+ this.parentPath,
+ )
} else {
parentValue = get(this.configSource, this.parentPath)
}
}
- return this.disabled || (parentValue !== null ? (this.parentInvert ? parentValue : !parentValue) : false)
+ return (
+ this.disabled ||
+ (parentValue !== null
+ ? this.parentInvert
+ ? parentValue
+ : !parentValue
+ : false)
+ )
},
- configSource () {
+ configSource() {
switch (this.realSource) {
case 'profile':
return this.$store.state.profileConfig
@@ -204,24 +234,31 @@ export default {
return this.$store.getters.mergedConfig
}
},
- configSink () {
+ configSink() {
if (this.path == null) {
return (k, v) => this.$emit('update:modelValue', v)
}
switch (this.realSource) {
case 'profile':
- return (k, v) => this.$store.dispatch('setProfileOption', { name: k, value: v })
+ return (k, v) =>
+ this.$store.dispatch('setProfileOption', { name: k, value: v })
case 'admin':
- return (k, v) => this.$store.dispatch('pushAdminSetting', { path: k, value: v })
+ return (k, v) =>
+ this.$store.dispatch('pushAdminSetting', { path: k, value: v })
default:
if (this.timedApplyMode) {
- return (k, v) => this.$store.dispatch('setOptionTemporarily', { name: k, value: v })
+ return (k, v) =>
+ this.$store.dispatch('setOptionTemporarily', {
+ name: k,
+ value: v,
+ })
} else {
- return (k, v) => this.$store.dispatch('setOption', { name: k, value: v })
+ return (k, v) =>
+ this.$store.dispatch('setOption', { name: k, value: v })
}
}
},
- defaultState () {
+ defaultState() {
switch (this.realSource) {
case 'profile':
return {}
@@ -229,10 +266,10 @@ export default {
return get(this.$store.getters.defaultConfig, this.path)
}
},
- isProfileSetting () {
+ isProfileSetting() {
return this.realSource === 'profile'
},
- isChanged () {
+ isChanged() {
if (this.path == null) return false
switch (this.realSource) {
case 'profile':
@@ -242,24 +279,24 @@ export default {
return this.state !== this.defaultState
}
},
- canonPath () {
+ canonPath() {
if (this.path == null) return null
return Array.isArray(this.path) ? this.path : this.path.split('.')
},
- descriptionPath () {
+ descriptionPath() {
if (this.path == null) return null
if (this.descriptionPathOverride) return this.descriptionPathOverride
const path = Array.isArray(this.path) ? this.path : this.path.split('.')
if (this.subgroup) {
return [
- ...path.slice(0, path.length - 1),
- ':subgroup,' + this.subgroup,
- ...path.slice(path.length - 1)
+ ...path.slice(0, path.length - 1),
+ ':subgroup,' + this.subgroup,
+ ...path.slice(path.length - 1),
]
}
return path
},
- isDirty () {
+ isDirty() {
if (this.path == null) return false
if (this.realSource === 'admin' && this.canonPath.length > 3) {
return false // should not show draft buttons for "grouped" values
@@ -267,47 +304,59 @@ export default {
return this.realDraftMode && !isEqual(this.draft, this.state)
}
},
- canHardReset () {
- return this.realSource === 'admin' && this.$store.state.adminSettings.modifiedPaths?.has(this.canonPath.join(' -> '))
+ canHardReset() {
+ return (
+ this.realSource === 'admin' &&
+ this.$store.state.adminSettings.modifiedPaths?.has(
+ this.canonPath.join(' -> '),
+ )
+ )
},
- matchesExpertLevel () {
+ matchesExpertLevel() {
const settingExpertLevel = this.expert || 0
const userToggleExpert = this.$store.state.config.expertLevel || 0
return settingExpertLevel <= userToggleExpert
- }
+ },
},
methods: {
- getValue (e) {
+ getValue(e) {
return e.target.value
},
- update (e) {
+ update(e) {
if (this.realDraftMode) {
this.draft = this.getValue(e)
} else {
this.configSink(this.path, this.getValue(e))
}
},
- commitDraft () {
+ commitDraft() {
if (this.realDraftMode) {
this.configSink(this.path, this.draft)
}
},
- reset () {
+ reset() {
if (this.realDraftMode) {
this.draft = cloneDeep(this.state)
} else {
- set(this.$store.getters.mergedConfig, this.path, cloneDeep(this.defaultState))
+ set(
+ this.$store.getters.mergedConfig,
+ this.path,
+ cloneDeep(this.defaultState),
+ )
}
},
- hardReset () {
+ hardReset() {
switch (this.realSource) {
case 'admin':
- return this.$store.dispatch('resetAdminSetting', { path: this.path })
- .then(() => { this.draft = this.state })
+ return this.$store
+ .dispatch('resetAdminSetting', { path: this.path })
+ .then(() => {
+ this.draft = this.state
+ })
default:
console.warn('Hard reset not implemented yet!')
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/shared_computed_object.js b/src/components/settings_modal/helpers/shared_computed_object.js
index bb3d36ac4..b8197b639 100644
--- a/src/components/settings_modal/helpers/shared_computed_object.js
+++ b/src/components/settings_modal/helpers/shared_computed_object.js
@@ -1,19 +1,19 @@
const SharedComputedObject = () => ({
- user () {
+ user() {
return this.$store.state.users.currentUser
},
- expertLevel () {
+ expertLevel() {
return this.$store.getters.mergedConfig.expertLevel > 0
},
- mergedConfig () {
+ mergedConfig() {
return this.$store.getters.mergedConfig
},
- adminConfig () {
+ adminConfig() {
return this.$store.state.adminSettings.config
},
- adminDraft () {
+ adminDraft() {
return this.$store.state.adminSettings.draft
- }
+ },
})
export default SharedComputedObject
diff --git a/src/components/settings_modal/helpers/string_setting.js b/src/components/settings_modal/helpers/string_setting.js
index b368cfc8c..327654ff1 100644
--- a/src/components/settings_modal/helpers/string_setting.js
+++ b/src/components/settings_modal/helpers/string_setting.js
@@ -1,5 +1,5 @@
import Setting from './setting.js'
export default {
- ...Setting
+ ...Setting,
}
diff --git a/src/components/settings_modal/helpers/tuple_setting.js b/src/components/settings_modal/helpers/tuple_setting.js
index f6f4753c0..88019c901 100644
--- a/src/components/settings_modal/helpers/tuple_setting.js
+++ b/src/components/settings_modal/helpers/tuple_setting.js
@@ -4,13 +4,13 @@ export default {
...Setting,
methods: {
...Setting.methods,
- getValue ({ e, side }) {
+ getValue({ e, side }) {
const [a, b] = this.visibleState || []
if (side === 0) {
- return { tuple: [e.target.value, b]}
+ return { tuple: [e.target.value, b] }
} else {
- return { tuple: [a, e.target.value]}
+ return { tuple: [a, e.target.value] }
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/unit_setting.js b/src/components/settings_modal/helpers/unit_setting.js
index daeddd813..99f4ac38e 100644
--- a/src/components/settings_modal/helpers/unit_setting.js
+++ b/src/components/settings_modal/helpers/unit_setting.js
@@ -1,7 +1,23 @@
import Select from 'src/components/select/select.vue'
import Setting from './setting.js'
-export const allCssUnits = ['cm', 'mm', 'in', 'px', 'pt', 'pc', 'em', 'ex', 'ch', 'rem', 'vw', 'vh', 'vmin', 'vmax', '%']
+export const allCssUnits = [
+ 'cm',
+ 'mm',
+ 'in',
+ 'px',
+ 'pt',
+ 'pc',
+ 'em',
+ 'ex',
+ 'ch',
+ 'rem',
+ 'vw',
+ 'vh',
+ 'vmin',
+ 'vmax',
+ '%',
+]
export const defaultHorizontalUnits = ['px', 'rem', 'vw']
export const defaultVerticalUnits = ['px', 'rem', 'vh']
@@ -9,47 +25,51 @@ export default {
...Setting,
components: {
...Setting.components,
- Select
+ Select,
},
props: {
...Setting.props,
min: Number,
units: {
type: Array,
- default: () => allCssUnits
+ default: () => allCssUnits,
},
unitSet: {
type: String,
- default: 'none'
+ default: 'none',
},
step: {
type: Number,
- default: 1
+ default: 1,
},
resetDefault: {
type: Object,
- default: null
- }
+ default: null,
+ },
},
computed: {
...Setting.computed,
- stateUnit () {
- return typeof this.state === 'string' ? this.state.replace(/[0-9,.]+/, '') : ''
+ stateUnit() {
+ return typeof this.state === 'string'
+ ? this.state.replace(/[0-9,.]+/, '')
+ : ''
+ },
+ stateValue() {
+ return typeof this.state === 'string'
+ ? this.state.replace(/[^0-9,.]+/, '')
+ : ''
},
- stateValue () {
- return typeof this.state === 'string' ? this.state.replace(/[^0-9,.]+/, '') : ''
- }
},
methods: {
...Setting.methods,
- getUnitString (value) {
+ getUnitString(value) {
if (this.unitSet === 'none') return value
return this.$t(['settings', 'units', this.unitSet, value].join('.'))
},
- updateValue (e) {
+ updateValue(e) {
this.configSink(this.path, parseFloat(e.target.value) + this.stateUnit)
},
- updateUnit (e) {
+ updateUnit(e) {
let value = this.stateValue
const newUnit = e.target.value
if (this.resetDefault) {
@@ -59,6 +79,6 @@ export default {
}
}
this.configSink(this.path, value + newUnit)
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/helpers/vertical_tab_switcher.jsx b/src/components/settings_modal/helpers/vertical_tab_switcher.jsx
index de0e1af26..a3238ce2f 100644
--- a/src/components/settings_modal/helpers/vertical_tab_switcher.jsx
+++ b/src/components/settings_modal/helpers/vertical_tab_switcher.jsx
@@ -1,14 +1,16 @@
// eslint-disable-next-line no-unused
-import { h, Fragment } from 'vue'
-import { mapState } from 'pinia'
+
import { throttle } from 'lodash'
-import { mapState as mapPiniaState } from 'pinia'
+import { mapState as mapPiniaState, mapState } from 'pinia'
+import { Fragment, h } from 'vue'
+
import { FontAwesomeIcon as FAIcon } from '@fortawesome/vue-fontawesome'
import './vertical_tab_switcher.scss'
+
import { useInterfaceStore } from 'src/stores/interface'
-const findFirstUsable = (slots) => slots.findIndex(_ => _.props)
+const findFirstUsable = (slots) => slots.findIndex((_) => _.props)
export default {
name: 'VerticalTabSwitcher',
@@ -16,30 +18,30 @@ export default {
renderOnlyFocused: {
required: false,
type: Boolean,
- default: false
+ default: false,
},
onSwitch: {
required: false,
type: Function,
- default: undefined
+ default: undefined,
},
activeTab: {
required: false,
type: String,
- default: undefined
+ default: undefined,
},
bodyScrollLock: {
required: false,
type: Boolean,
- default: false
+ default: false,
},
parentCollapsed: {
required: false,
type: Boolean,
- default: null
- }
+ default: null,
+ },
},
- data () {
+ data() {
return {
active: findFirstUsable(this.slots()),
resizeHandler: null,
@@ -47,82 +49,89 @@ export default {
}
},
computed: {
- activeIndex () {
+ activeIndex() {
// In case of controlled component
if (this.activeTab) {
- return this.slots().findIndex(slot => slot && slot.props && this.activeTab === slot.props.key)
+ return this.slots().findIndex(
+ (slot) => slot && slot.props && this.activeTab === slot.props.key,
+ )
} else {
return this.active
}
},
- isActive () {
- return tabName => {
- const isWanted = slot => slot.props && slot.props['data-tab-name'] === tabName
+ isActive() {
+ return (tabName) => {
+ const isWanted = (slot) =>
+ slot.props && slot.props['data-tab-name'] === tabName
return this.$slots.default().findIndex(isWanted) === this.activeIndex
}
},
...mapPiniaState(useInterfaceStore, {
- mobileLayout: store => store.layoutType === 'mobile'
+ mobileLayout: (store) => store.layoutType === 'mobile',
}),
},
- beforeUpdate () {
+ beforeUpdate() {
const currentSlot = this.slots()[this.active]
if (!currentSlot.props) {
this.active = findFirstUsable(this.slots())
}
},
methods: {
- clickTab (index) {
+ clickTab(index) {
return (e) => {
e.preventDefault()
this.setTab(index)
}
},
- setTab (index) {
+ setTab(index) {
if (typeof this.onSwitch === 'function') {
this.onSwitch.call(null, this.slots()[index].key)
}
this.active = index
this.changeNavSide('content')
},
- changeNavSide (side) {
+ changeNavSide(side) {
if (this.navSide !== side) {
this.navSide = side
}
},
// DO NOT put it to computed, it doesn't work (caching?)
- slots () {
+ slots() {
if (this.$slots.default()[0].type === Fragment) {
return this.$slots.default()[0].children
}
return this.$slots.default()
- }
+ },
},
- render () {
- const tabs = this.slots()
- .map((slot, index) => {
- const props = slot.props
- if (!props) return
- const classesTab = ['vertical-tab', 'menu-item']
- if (this.activeIndex === index && useInterfaceStore().layoutType !== 'mobile') {
- classesTab.push('-active')
- }
- return (
-
- )
- })
+ render() {
+ const tabs = this.slots().map((slot, index) => {
+ const props = slot.props
+ if (!props) return
+ const classesTab = ['vertical-tab', 'menu-item']
+ if (
+ this.activeIndex === index &&
+ useInterfaceStore().layoutType !== 'mobile'
+ ) {
+ classesTab.push('-active')
+ }
+ return (
+
+ )
+ })
const contents = this.slots().map((slot, index) => {
const props = slot.props
@@ -134,9 +143,8 @@ export default {
slot.props['delay-render'] = false
delayRender = false
}
- const renderSlot = (!delayRender && (!this.renderOnlyFocused || active))
- ? slot
- : ''
+ const renderSlot =
+ !delayRender && (!this.renderOnlyFocused || active) ? slot : ''
const headerClasses = ['tab-content-label']
const header = (
@@ -147,17 +155,16 @@ export default {
title={this.$t('nav.back')}
class="button-unstyled"
>
-
+
{props.label}
)
- const wrapperClasses = ['tab-content-wrapper', active ? '-active' : '-hidden' ]
+ const wrapperClasses = [
+ 'tab-content-wrapper',
+ active ? '-active' : '-hidden',
+ ]
const contentClasses = ['tab-content']
if (props['full-width'] || props['full-width'] === '') {
contentClasses.push('-full-width')
@@ -168,14 +175,10 @@ export default {
wrapperClasses.push('-full-height')
}
return (
-
-
+
+
-
- {renderSlot}
-
+
{renderSlot}
)
@@ -193,12 +196,8 @@ export default {
}
return (
-
-
+
+
{tabs}
)
- }
+ },
}
diff --git a/src/components/settings_modal/settings_modal.js b/src/components/settings_modal/settings_modal.js
index 789ebd0ee..4517c3295 100644
--- a/src/components/settings_modal/settings_modal.js
+++ b/src/components/settings_modal/settings_modal.js
@@ -1,27 +1,27 @@
-import Modal from 'src/components/modal/modal.vue'
-import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
+import { cloneDeep, isEqual } from 'lodash'
+import { mapActions, mapState } from 'pinia'
+
import AsyncComponentError from 'src/components/async_component_error/async_component_error.vue'
-import getResettableAsyncComponent from 'src/services/resettable_async_component.js'
-import Popover from '../popover/popover.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { cloneDeep, isEqual } from 'lodash'
-import { mapState, mapActions } from 'pinia'
+import Modal from 'src/components/modal/modal.vue'
+import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
import {
+ newExporter,
newImporter,
- newExporter
} from 'src/services/export_import/export_import.js'
-import {
- faTimes,
- faFileUpload,
- faFileDownload,
- faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-import {
- faWindowMinimize
-} from '@fortawesome/free-regular-svg-icons'
+import getResettableAsyncComponent from 'src/services/resettable_async_component.js'
import { useInterfaceStore } from 'src/stores/interface'
+import Popover from '../popover/popover.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faWindowMinimize } from '@fortawesome/free-regular-svg-icons'
+import {
+ faChevronDown,
+ faFileDownload,
+ faFileUpload,
+ faTimes,
+} from '@fortawesome/free-solid-svg-icons'
const PLEROMAFE_SETTINGS_MAJOR_VERSION = 1
const PLEROMAFE_SETTINGS_MINOR_VERSION = 0
@@ -31,25 +31,25 @@ library.add(
faWindowMinimize,
faFileUpload,
faFileDownload,
- faChevronDown
+ faChevronDown,
)
const SettingsModal = {
- data () {
+ data() {
return {
dataImporter: newImporter({
validator: this.importValidator,
onImport: this.onImport,
- onImportFailure: this.onImportFailure
+ onImportFailure: this.onImportFailure,
}),
dataThemeExporter: newExporter({
filename: 'pleromafe_settings.full',
- getExportedObject: () => this.generateExport(true)
+ getExportedObject: () => this.generateExport(true),
}),
dataExporter: newExporter({
filename: 'pleromafe_settings',
- getExportedObject: () => this.generateExport()
- })
+ getExportedObject: () => this.generateExport(),
+ }),
}
},
components: {
@@ -62,29 +62,29 @@ const SettingsModal = {
{
loadingComponent: PanelLoading,
errorComponent: AsyncComponentError,
- delay: 0
- }
+ delay: 0,
+ },
),
SettingsModalAdminContent: getResettableAsyncComponent(
() => import('./settings_modal_admin_content.vue'),
{
loadingComponent: PanelLoading,
errorComponent: AsyncComponentError,
- delay: 0
- }
- )
+ delay: 0,
+ },
+ ),
},
methods: {
- closeModal () {
+ closeModal() {
useInterfaceStore().closeSettingsModal()
},
- peekModal () {
+ peekModal() {
useInterfaceStore().togglePeekSettingsModal()
},
- importValidator (data) {
+ importValidator(data) {
if (!Array.isArray(data._pleroma_settings_version)) {
return {
- messageKey: 'settings.file_import_export.invalid_file'
+ messageKey: 'settings.file_import_export.invalid_file',
}
}
@@ -95,8 +95,8 @@ const SettingsModal = {
messageKey: 'settings.file_export_import.errors.file_too_new',
messageArgs: {
fileMajor: major,
- feMajor: PLEROMAFE_SETTINGS_MAJOR_VERSION
- }
+ feMajor: PLEROMAFE_SETTINGS_MAJOR_VERSION,
+ },
}
}
@@ -105,94 +105,106 @@ const SettingsModal = {
messageKey: 'settings.file_export_import.errors.file_too_old',
messageArgs: {
fileMajor: major,
- feMajor: PLEROMAFE_SETTINGS_MAJOR_VERSION
- }
+ feMajor: PLEROMAFE_SETTINGS_MAJOR_VERSION,
+ },
}
}
if (minor > PLEROMAFE_SETTINGS_MINOR_VERSION) {
useInterfaceStore().pushGlobalNotice({
level: 'warning',
- messageKey: 'settings.file_export_import.errors.file_slightly_new'
+ messageKey: 'settings.file_export_import.errors.file_slightly_new',
})
}
return true
},
- onImportFailure (result) {
+ onImportFailure(result) {
if (result.error) {
- useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_settings_imported', level: 'error' })
+ useInterfaceStore().pushGlobalNotice({
+ messageKey: 'settings.invalid_settings_imported',
+ level: 'error',
+ })
} else {
- useInterfaceStore().pushGlobalNotice({ ...result.validationResult, level: 'error' })
+ useInterfaceStore().pushGlobalNotice({
+ ...result.validationResult,
+ level: 'error',
+ })
}
},
- onImport (data) {
- if (data) { this.$store.dispatch('loadSettings', data) }
+ onImport(data) {
+ if (data) {
+ this.$store.dispatch('loadSettings', data)
+ }
},
- restore () {
+ restore() {
this.dataImporter.importData()
},
- backup () {
+ backup() {
this.dataExporter.exportData()
},
- backupWithTheme () {
+ backupWithTheme() {
this.dataThemeExporter.exportData()
},
- generateExport (theme = false) {
+ generateExport(theme = false) {
const { config } = this.$store.state
let sample = config
if (!theme) {
const ignoreList = new Set([
'customTheme',
'customThemeSource',
- 'colors'
+ 'colors',
])
sample = Object.fromEntries(
- Object
- .entries(sample)
- .filter(([key]) => !ignoreList.has(key))
+ Object.entries(sample).filter(([key]) => !ignoreList.has(key)),
)
}
const clone = cloneDeep(sample)
clone._pleroma_settings_version = [
PLEROMAFE_SETTINGS_MAJOR_VERSION,
- PLEROMAFE_SETTINGS_MINOR_VERSION
+ PLEROMAFE_SETTINGS_MINOR_VERSION,
]
return clone
},
- resetAdminDraft () {
+ resetAdminDraft() {
this.$store.commit('resetAdminDraft')
},
- pushAdminDraft () {
+ pushAdminDraft() {
this.$store.dispatch('pushAdminDraft')
},
- ...mapActions(useInterfaceStore, ['temporaryChangesRevert', 'temporaryChangesConfirm'])
+ ...mapActions(useInterfaceStore, [
+ 'temporaryChangesRevert',
+ 'temporaryChangesConfirm',
+ ]),
},
computed: {
...mapState(useInterfaceStore, {
- temporaryChangesCountdown: store => store.temporaryChangesCountdown,
- currentSaveStateNotice: store => store.settings.currentSaveStateNotice,
- modalActivated: store => store.settingsModalState !== 'hidden',
- modalMode: store => store.settingsModalMode,
- modalOpenedOnceUser: store => store.settingsModalLoadedUser,
- modalOpenedOnceAdmin: store => store.settingsModalLoadedAdmin,
- modalPeeked: store => store.settingsModalState === 'minimized'
+ temporaryChangesCountdown: (store) => store.temporaryChangesCountdown,
+ currentSaveStateNotice: (store) => store.settings.currentSaveStateNotice,
+ modalActivated: (store) => store.settingsModalState !== 'hidden',
+ modalMode: (store) => store.settingsModalMode,
+ modalOpenedOnceUser: (store) => store.settingsModalLoadedUser,
+ modalOpenedOnceAdmin: (store) => store.settingsModalLoadedAdmin,
+ modalPeeked: (store) => store.settingsModalState === 'minimized',
}),
expertLevel: {
- get () {
+ get() {
return this.$store.state.config.expertLevel > 0
},
- set (value) {
- this.$store.dispatch('setOption', { name: 'expertLevel', value: value ? 1 : 0 })
- }
+ set(value) {
+ this.$store.dispatch('setOption', {
+ name: 'expertLevel',
+ value: value ? 1 : 0,
+ })
+ },
},
- adminDraftAny () {
+ adminDraftAny() {
return !isEqual(
this.$store.state.adminSettings.config,
- this.$store.state.adminSettings.draft
+ this.$store.state.adminSettings.draft,
)
- }
- }
+ },
+ },
}
export default SettingsModal
diff --git a/src/components/settings_modal/settings_modal_admin_content.js b/src/components/settings_modal/settings_modal_admin_content.js
index 77a3d6b81..1a3f10e77 100644
--- a/src/components/settings_modal/settings_modal_admin_content.js
+++ b/src/components/settings_modal/settings_modal_admin_content.js
@@ -1,42 +1,41 @@
-import VerticalTabSwitcher from './helpers/vertical_tab_switcher.jsx'
-
-import InstanceTab from './admin_tabs/instance_tab.vue'
-import LinksTab from './admin_tabs/links_tab.vue'
-import LimitsTab from './admin_tabs/limits_tab.vue'
-import FrontendsTab from './admin_tabs/frontends_tab.vue'
-import MediaProxyTab from './admin_tabs/media_proxy_tab.vue'
-import EmojiTab from './admin_tabs/emoji_tab.vue'
-import UploadsTab from './admin_tabs/uploads_tab.vue'
-import MailerTab from './admin_tabs/mailer_tab.vue'
-import MonitoringTab from './admin_tabs/monitoring_tab.vue'
-import RegistrationsTab from './admin_tabs/registrations_tab.vue'
-import AuthTab from './admin_tabs/auth_tab.vue'
-import HTTPTab from './admin_tabs/http_tab.vue'
-import OtherTab from './admin_tabs/other_tab.vue'
-import RatesTab from './admin_tabs/rates_tab.vue'
-import PostsTab from './admin_tabs/posts_tab.vue'
-import FederationTab from './admin_tabs/federation_tab.vue'
-import JobQueuesTab from './admin_tabs/job_queues_tab.vue'
import { useInterfaceStore } from 'src/stores/interface'
+import AuthTab from './admin_tabs/auth_tab.vue'
+import EmojiTab from './admin_tabs/emoji_tab.vue'
+import FederationTab from './admin_tabs/federation_tab.vue'
+import FrontendsTab from './admin_tabs/frontends_tab.vue'
+import HTTPTab from './admin_tabs/http_tab.vue'
+import InstanceTab from './admin_tabs/instance_tab.vue'
+import JobQueuesTab from './admin_tabs/job_queues_tab.vue'
+import LimitsTab from './admin_tabs/limits_tab.vue'
+import LinksTab from './admin_tabs/links_tab.vue'
+import MailerTab from './admin_tabs/mailer_tab.vue'
+import MediaProxyTab from './admin_tabs/media_proxy_tab.vue'
+import MonitoringTab from './admin_tabs/monitoring_tab.vue'
+import OtherTab from './admin_tabs/other_tab.vue'
+import PostsTab from './admin_tabs/posts_tab.vue'
+import RatesTab from './admin_tabs/rates_tab.vue'
+import RegistrationsTab from './admin_tabs/registrations_tab.vue'
+import UploadsTab from './admin_tabs/uploads_tab.vue'
+import VerticalTabSwitcher from './helpers/vertical_tab_switcher.jsx'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faWrench,
- faHand,
faChain,
- faGlobe,
- faLaptopCode,
- faTowerBroadcast,
- faEnvelope,
faChartLine,
- faDoorOpen,
- faGears,
- faKey,
faCircleNodes,
- faUpload,
- faMessage,
+ faDoorOpen,
faEllipsis,
- faGauge
+ faEnvelope,
+ faGauge,
+ faGears,
+ faGlobe,
+ faHand,
+ faKey,
+ faLaptopCode,
+ faMessage,
+ faTowerBroadcast,
+ faUpload,
+ faWrench,
} from '@fortawesome/free-solid-svg-icons'
library.add(
@@ -55,7 +54,7 @@ library.add(
faUpload,
faMessage,
faEllipsis,
- faGauge
+ faGauge,
)
const SettingsModalAdminContent = {
@@ -78,44 +77,46 @@ const SettingsModalAdminContent = {
MonitoringTab,
RatesTab,
OtherTab,
- PostsTab
+ PostsTab,
},
computed: {
- user () {
+ user() {
return this.$store.state.users.currentUser
},
- isLoggedIn () {
+ isLoggedIn() {
return !!this.$store.state.users.currentUser
},
- open () {
+ open() {
return useInterfaceStore().settingsModalState !== 'hidden'
},
- bodyLock () {
+ bodyLock() {
return useInterfaceStore().settingsModalState === 'visible'
},
- adminDbLoaded () {
+ adminDbLoaded() {
return this.$store.state.adminSettings.loaded
},
- adminDescriptionsLoaded () {
+ adminDescriptionsLoaded() {
return this.$store.state.adminSettings.descriptions !== null
},
- noDb () {
+ noDb() {
return this.$store.state.adminSettings.dbConfigEnabled === false
- }
+ },
},
- created () {
+ created() {
if (this.user.rights.admin) {
this.$store.dispatch('loadAdminStuff')
}
},
methods: {
- onOpen () {
+ onOpen() {
const targetTab = useInterfaceStore().settingsModalTargetTab
// We're being told to open in specific tab
if (targetTab) {
- const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => {
- return elm.props && elm.props['data-tab-name'] === targetTab
- })
+ const tabIndex = this.$refs.tabSwitcher.$slots
+ .default()
+ .findIndex((elm) => {
+ return elm.props && elm.props['data-tab-name'] === targetTab
+ })
if (tabIndex >= 0) {
this.$refs.tabSwitcher.setTab(tabIndex)
}
@@ -123,16 +124,16 @@ const SettingsModalAdminContent = {
// Clear the state of target tab, so that next time settings is opened
// it doesn't force it.
useInterfaceStore().clearSettingsModalTargetTab()
- }
+ },
},
- mounted () {
+ mounted() {
this.onOpen()
},
watch: {
open: function (value) {
if (value) this.onOpen()
- }
- }
+ },
+ },
}
export default SettingsModalAdminContent
diff --git a/src/components/settings_modal/settings_modal_user_content.js b/src/components/settings_modal/settings_modal_user_content.js
index 51718ab26..f66099049 100644
--- a/src/components/settings_modal/settings_modal_user_content.js
+++ b/src/components/settings_modal/settings_modal_user_content.js
@@ -1,39 +1,38 @@
+import { useInterfaceStore } from 'src/stores/interface'
import VerticalTabSwitcher from './helpers/vertical_tab_switcher.jsx'
-
+import AppearanceTab from './tabs/appearance_tab.vue'
+import ClutterTab from './tabs/clutter_tab.vue'
+import ComposingTab from './tabs/composing_tab.vue'
import DataImportExportTab from './tabs/data_import_export_tab.vue'
+import DeveloperTab from './tabs/developer_tab.vue'
+import FilteringTab from './tabs/filtering_tab.vue'
+import GeneralTab from './tabs/general_tab.vue'
+import LayoutTab from './tabs/layout_tab.vue'
import MutesAndBlocksTab from './tabs/mutes_and_blocks_tab.vue'
import NotificationsTab from './tabs/notifications_tab.vue'
-import FilteringTab from './tabs/filtering_tab.vue'
-import SecurityTab from './tabs/security_tab/security_tab.vue'
-import ProfileTab from './tabs/profile_tab.vue'
-import GeneralTab from './tabs/general_tab.vue'
-import PostsTab from './tabs/posts_tab.vue'
-import ComposingTab from './tabs/composing_tab.vue'
-import ClutterTab from './tabs/clutter_tab.vue'
-import LayoutTab from './tabs/layout_tab.vue'
-import AppearanceTab from './tabs/appearance_tab.vue'
-import DeveloperTab from './tabs/developer_tab.vue'
import OldThemeTab from './tabs/old_theme_tab/old_theme_tab.vue'
+import PostsTab from './tabs/posts_tab.vue'
+import ProfileTab from './tabs/profile_tab.vue'
+import SecurityTab from './tabs/security_tab/security_tab.vue'
import StyleTab from './tabs/style_tab/style_tab.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faWrench,
- faUser,
- faMessage,
- faFilter,
- faPaintBrush,
- faPalette,
faBell,
+ faBroom,
+ faCode,
+ faColumns,
faDownload,
faEyeSlash,
- faWindowRestore,
- faCode,
- faBroom,
+ faFilter,
faLock,
- faColumns
+ faMessage,
+ faPaintBrush,
+ faPalette,
+ faUser,
+ faWindowRestore,
+ faWrench,
} from '@fortawesome/free-solid-svg-icons'
-import { useInterfaceStore } from 'src/stores/interface'
library.add(
faWrench,
@@ -49,7 +48,7 @@ library.add(
faDownload,
faPalette,
faPaintBrush,
- faCode
+ faCode,
)
const SettingsModalContent = {
@@ -70,36 +69,38 @@ const SettingsModalContent = {
AppearanceTab,
StyleTab,
DeveloperTab,
- OldThemeTab
+ OldThemeTab,
},
computed: {
- isLoggedIn () {
+ isLoggedIn() {
return !!this.$store.state.users.currentUser
},
- open () {
+ open() {
return useInterfaceStore().settingsModalState !== 'hidden'
},
- bodyLock () {
+ bodyLock() {
return useInterfaceStore().settingsModalState === 'visible'
},
- expertLevel () {
+ expertLevel() {
return this.$store.state.config.expertLevel
- }
+ },
},
- data () {
+ data() {
return {
navCollapsed: false,
- navHideHeader: false
+ navHideHeader: false,
}
},
methods: {
- onOpen () {
+ onOpen() {
const targetTab = useInterfaceStore().settingsModalTargetTab
// We're being told to open in specific tab
if (targetTab) {
- const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => {
- return elm.props && elm.props['data-tab-name'] === targetTab
- })
+ const tabIndex = this.$refs.tabSwitcher.$slots
+ .default()
+ .findIndex((elm) => {
+ return elm.props && elm.props['data-tab-name'] === targetTab
+ })
if (tabIndex >= 0) {
this.$refs.tabSwitcher.setTab(tabIndex)
}
@@ -107,16 +108,16 @@ const SettingsModalContent = {
// Clear the state of target tab, so that next time settings is opened
// it doesn't force it.
useInterfaceStore().clearSettingsModalTargetTab()
- }
+ },
},
- mounted () {
+ mounted() {
this.onOpen()
},
watch: {
open: function (value) {
if (value) this.onOpen()
- }
- }
+ },
+ },
}
export default SettingsModalContent
diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js
index db37774aa..1110505cc 100644
--- a/src/components/settings_modal/tabs/appearance_tab.js
+++ b/src/components/settings_modal/tabs/appearance_tab.js
@@ -1,29 +1,28 @@
+import { mapActions } from 'pinia'
+
+import fileSizeFormatService from 'src/components/../services/file_size_format/file_size_format.js'
+import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
+import { newImporter } from 'src/services/export_import/export_import.js'
+import {
+ adoptStyleSheets,
+ createStyleSheet,
+} from 'src/services/style_setter/style_setter.js'
+import { getCssRules } from 'src/services/theme_data/css_utils.js'
+import { deserialize } from 'src/services/theme_data/iss_deserializer.js'
+import { init } from 'src/services/theme_data/theme_data_3.service.js'
+import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
+import { normalizeThemeData, useInterfaceStore } from 'src/stores/interface'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
import FloatSetting from '../helpers/float_setting.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
+import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
+import SharedComputedObject from '../helpers/shared_computed_object.js'
import UnitSetting from '../helpers/unit_setting.vue'
-import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
import Preview from './old_theme_tab/theme_preview.vue'
-import { newImporter } from 'src/services/export_import/export_import.js'
-import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
-import { init } from 'src/services/theme_data/theme_data_3.service.js'
-import {
- getCssRules
-} from 'src/services/theme_data/css_utils.js'
-import { deserialize } from 'src/services/theme_data/iss_deserializer.js'
-import { createStyleSheet, adoptStyleSheets } from 'src/services/style_setter/style_setter.js'
-import fileSizeFormatService from 'src/components/../services/file_size_format/file_size_format.js'
-
-import SharedComputedObject from '../helpers/shared_computed_object.js'
-import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
-
-import { mapActions } from 'pinia'
-import { useInterfaceStore, normalizeThemeData } from 'src/stores/interface'
-
const AppearanceTab = {
- data () {
+ data() {
return {
availableThemesV3: [],
availableThemesV2: [],
@@ -34,7 +33,7 @@ const AppearanceTab = {
validator: this.importValidator,
onImport: this.onImport,
parser: this.importParser,
- onImportFailure: this.onImportFailure
+ onImportFailure: this.onImportFailure,
}),
palettesKeys: [
'bg',
@@ -44,19 +43,25 @@ const AppearanceTab = {
'cRed',
'cGreen',
'cBlue',
- 'cOrange'
+ 'cOrange',
],
userPalette: {},
intersectionObserver: null,
- forcedRoundnessOptions: ['disabled', 'sharp', 'nonsharp', 'round'].map((mode, i) => ({
- key: mode,
- value: i - 1,
- label: this.$t(`settings.style.themes3.hacks.forced_roundness_mode_${mode}`)
- })),
+ forcedRoundnessOptions: ['disabled', 'sharp', 'nonsharp', 'round'].map(
+ (mode, i) => ({
+ key: mode,
+ value: i - 1,
+ label: this.$t(
+ `settings.style.themes3.hacks.forced_roundness_mode_${mode}`,
+ ),
+ }),
+ ),
underlayOverrideModes: ['none', 'opaque', 'transparent'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.style.themes3.hacks.underlay_override_mode_${mode}`)
+ label: this.$t(
+ `settings.style.themes3.hacks.underlay_override_mode_${mode}`,
+ ),
})),
backgroundUploading: false,
background: null,
@@ -71,9 +76,9 @@ const AppearanceTab = {
UnitSetting,
ProfileSettingIndicator,
Preview,
- PaletteEditor
+ PaletteEditor,
},
- mounted () {
+ mounted() {
useInterfaceStore().getThemeData()
const updateIndex = (resource) => {
@@ -87,120 +92,151 @@ const AppearanceTab = {
promise = useInterfaceStore()[`fetch${capitalizedResource}sIndex`]()
}
- return promise.then(index => {
- return Object
- .entries(index)
- .map(([k, func]) => [k, func()])
+ return promise.then((index) => {
+ return Object.entries(index).map(([k, func]) => [k, func()])
})
}
- updateIndex('style').then(styles => {
- styles.forEach(([key, stylePromise]) => stylePromise.then(data => {
- const meta = data.find(x => x.component === '@meta')
- this.availableThemesV3.push({ key, data, name: meta.directives.name, version: 'v3' })
- }))
+ updateIndex('style').then((styles) => {
+ styles.forEach(([key, stylePromise]) =>
+ stylePromise.then((data) => {
+ const meta = data.find((x) => x.component === '@meta')
+ this.availableThemesV3.push({
+ key,
+ data,
+ name: meta.directives.name,
+ version: 'v3',
+ })
+ }),
+ )
})
- updateIndex('theme').then(themes => {
- themes.forEach(([key, themePromise]) => themePromise.then(data => {
- if (!data) {
- console.warn(`Theme with key ${key} is empty or malformed`)
- } else if (Array.isArray(data)) {
- console.warn(`Theme with key ${key} is a v1 theme and should be moved to static/palettes/index.json`)
- } else if (!data.source && !data.theme) {
- console.warn(`Theme with key ${key} is malformed`)
- } else {
- this.availableThemesV2.push({ key, data, name: data.name, version: 'v2' })
- }
- }))
+ updateIndex('theme').then((themes) => {
+ themes.forEach(([key, themePromise]) =>
+ themePromise.then((data) => {
+ if (!data) {
+ console.warn(`Theme with key ${key} is empty or malformed`)
+ } else if (Array.isArray(data)) {
+ console.warn(
+ `Theme with key ${key} is a v1 theme and should be moved to static/palettes/index.json`,
+ )
+ } else if (!data.source && !data.theme) {
+ console.warn(`Theme with key ${key} is malformed`)
+ } else {
+ this.availableThemesV2.push({
+ key,
+ data,
+ name: data.name,
+ version: 'v2',
+ })
+ }
+ }),
+ )
})
this.userPalette = useInterfaceStore().paletteDataUsed || {}
- updateIndex('palette').then(bundledPalettes => {
- bundledPalettes.forEach(([key, palettePromise]) => palettePromise.then(v => {
- let palette
- if (Array.isArray(v)) {
- const [
- name,
- bg,
- fg,
- text,
- link,
- cRed = '#FF0000',
- cGreen = '#00FF00',
- cBlue = '#0000FF',
- cOrange = '#E3FF00'
- ] = v
- palette = { key, name, bg, fg, text, link, cRed, cBlue, cGreen, cOrange }
- } else {
- palette = { key, ...v }
- }
- if (!palette.key.startsWith('style.')) {
- this.bundledPalettes.push(palette)
- }
- }))
+ updateIndex('palette').then((bundledPalettes) => {
+ bundledPalettes.forEach(([key, palettePromise]) =>
+ palettePromise.then((v) => {
+ let palette
+ if (Array.isArray(v)) {
+ const [
+ name,
+ bg,
+ fg,
+ text,
+ link,
+ cRed = '#FF0000',
+ cGreen = '#00FF00',
+ cBlue = '#0000FF',
+ cOrange = '#E3FF00',
+ ] = v
+ palette = {
+ key,
+ name,
+ bg,
+ fg,
+ text,
+ link,
+ cRed,
+ cBlue,
+ cGreen,
+ cOrange,
+ }
+ } else {
+ palette = { key, ...v }
+ }
+ if (!palette.key.startsWith('style.')) {
+ this.bundledPalettes.push(palette)
+ }
+ }),
+ )
})
this.previewTheme('stock', 'v3')
if (window.IntersectionObserver) {
- this.intersectionObserver = new IntersectionObserver((entries, observer) => {
- entries.forEach(({ target, isIntersecting }) => {
- if (!isIntersecting) return
- const theme = this.availableStyles.find(x => x.key === target.dataset.themeKey)
- this.$nextTick(() => {
- if (theme) this.previewTheme(theme.key, theme.version, theme.data)
+ this.intersectionObserver = new IntersectionObserver(
+ (entries, observer) => {
+ entries.forEach(({ target, isIntersecting }) => {
+ if (!isIntersecting) return
+ const theme = this.availableStyles.find(
+ (x) => x.key === target.dataset.themeKey,
+ )
+ this.$nextTick(() => {
+ if (theme) this.previewTheme(theme.key, theme.version, theme.data)
+ })
+ observer.unobserve(target)
})
- observer.unobserve(target)
- })
- }, {
- root: this.$refs.themeList
- })
+ },
+ {
+ root: this.$refs.themeList,
+ },
+ )
} else {
- this.availableStyles.forEach(theme => this.previewTheme(theme.key, theme.version, theme.data))
+ this.availableStyles.forEach((theme) =>
+ this.previewTheme(theme.key, theme.version, theme.data),
+ )
}
},
- updated () {
+ updated() {
this.$nextTick(() => {
- this.$refs.themeList.querySelectorAll('.theme-preview').forEach(node => {
- this.intersectionObserver.observe(node)
- })
+ this.$refs.themeList
+ .querySelectorAll('.theme-preview')
+ .forEach((node) => {
+ this.intersectionObserver.observe(node)
+ })
})
},
watch: {
- paletteDataUsed () {
+ paletteDataUsed() {
this.userPalette = this.paletteDataUsed || {}
- }
+ },
},
computed: {
- isDefaultBackground () {
- return !(this.$store.state.users.currentUser.background_image)
+ isDefaultBackground() {
+ return !this.$store.state.users.currentUser.background_image
},
- switchInProgress () {
+ switchInProgress() {
return useInterfaceStore().themeChangeInProgress
},
- paletteDataUsed () {
+ paletteDataUsed() {
return useInterfaceStore().paletteDataUsed
},
- availableStyles () {
- return [
- ...this.availableThemesV3,
- ...this.availableThemesV2
- ]
+ availableStyles() {
+ return [...this.availableThemesV3, ...this.availableThemesV2]
},
- availablePalettes () {
- return [
- ...this.bundledPalettes,
- ...this.stylePalettes
- ]
+ availablePalettes() {
+ return [...this.bundledPalettes, ...this.stylePalettes]
},
- stylePalettes () {
+ stylePalettes() {
const ruleset = useInterfaceStore().styleDataUsed || []
if (!ruleset && ruleset.length === 0) return
- const meta = ruleset.find(x => x.component === '@meta')
- const result = ruleset.filter(x => x.component.startsWith('@palette'))
- .map(x => {
+ const meta = ruleset.find((x) => x.component === '@meta')
+ const result = ruleset
+ .filter((x) => x.component.startsWith('@palette'))
+ .map((x) => {
const { variant, directives } = x
const {
bg,
@@ -212,7 +248,7 @@ const AppearanceTab = {
cBlue,
cGreen,
cOrange,
- wallpaper
+ wallpaper,
} = directives
const result = {
@@ -227,94 +263,103 @@ const AppearanceTab = {
cBlue,
cGreen,
cOrange,
- wallpaper
+ wallpaper,
}
return Object.fromEntries(Object.entries(result).filter(([, v]) => v))
})
return result
},
- noIntersectionObserver () {
+ noIntersectionObserver() {
return !window.IntersectionObserver
},
- instanceWallpaper () {
+ instanceWallpaper() {
this.$store.state.instance.background
},
- instanceWallpaperUsed () {
- return this.$store.state.instance.background &&
+ instanceWallpaperUsed() {
+ return (
+ this.$store.state.instance.background &&
!this.$store.state.users.currentUser.background_image
+ )
},
- customThemeVersion () {
+ customThemeVersion() {
const { themeVersion } = useInterfaceStore()
return themeVersion
},
- isCustomThemeUsed () {
+ isCustomThemeUsed() {
const { customTheme, customThemeSource } = this.mergedConfig
return customTheme != null || customThemeSource != null
},
- isCustomStyleUsed () {
+ isCustomStyleUsed() {
const { styleCustomData } = this.mergedConfig
return styleCustomData != null
},
- ...SharedComputedObject()
+ ...SharedComputedObject(),
},
methods: {
- importFile () {
+ importFile() {
this.fileImporter.importData()
},
- importParser (file, filename) {
+ importParser(file, filename) {
if (filename.endsWith('.json')) {
return JSON.parse(file)
} else if (filename.endsWith('.iss')) {
return deserialize(file)
}
},
- onImport (parsed, filename) {
+ onImport(parsed, filename) {
if (filename.endsWith('.json')) {
useInterfaceStore().setThemeCustom(parsed.source || parsed.theme)
} else if (filename.endsWith('.iss')) {
useInterfaceStore().setStyleCustom(parsed)
}
},
- onImportFailure (result) {
+ onImportFailure(result) {
console.error('Failure importing theme:', result)
- useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_theme_imported', level: 'error' })
+ useInterfaceStore().pushGlobalNotice({
+ messageKey: 'settings.invalid_theme_imported',
+ level: 'error',
+ })
},
- importValidator (parsed, filename) {
+ importValidator(parsed, filename) {
if (filename.endsWith('.json')) {
const version = parsed._pleroma_theme_version
return version >= 1 || version <= 2
} else if (filename.endsWith('.iss')) {
if (!Array.isArray(parsed)) return false
if (parsed.length < 1) return false
- if (parsed.find(x => x.component === '@meta') == null) return false
+ if (parsed.find((x) => x.component === '@meta') == null) return false
return true
}
},
- isThemeActive (key) {
- return key === (this.mergedConfig.theme || this.$store.state.instance.theme)
+ isThemeActive(key) {
+ return (
+ key === (this.mergedConfig.theme || this.$store.state.instance.theme)
+ )
},
- isStyleActive (key) {
- return key === (this.mergedConfig.style || this.$store.state.instance.style)
+ isStyleActive(key) {
+ return (
+ key === (this.mergedConfig.style || this.$store.state.instance.style)
+ )
},
- isPaletteActive (key) {
- return key === (this.mergedConfig.palette || this.$store.state.instance.palette)
+ isPaletteActive(key) {
+ return (
+ key ===
+ (this.mergedConfig.palette || this.$store.state.instance.palette)
+ )
},
- ...mapActions(useInterfaceStore, [
- 'setStyle',
- 'setTheme'
- ]),
- setPalette (name, data) {
+ ...mapActions(useInterfaceStore, ['setStyle', 'setTheme']),
+ setPalette(name, data) {
useInterfaceStore().setPalette(name)
this.userPalette = data
},
- setPaletteCustom (data) {
+ setPaletteCustom(data) {
useInterfaceStore().setPaletteCustom(data)
this.userPalette = data
},
- resetTheming () {
+ resetTheming() {
useInterfaceStore().setStyle('stock')
},
- previewTheme (key, version, input) {
+ previewTheme(key, version, input) {
let theme3
if (this.compilationCache[key]) {
theme3 = this.compilationCache[key]
@@ -327,10 +372,10 @@ const AppearanceTab = {
ultimateBackgroundColor: '#000000',
liteMode: true,
debug: true,
- onlyNormalState: true
+ onlyNormalState: true,
})
} else if (version === 'v3') {
- const palette = input.find(x => x.component === '@palette')
+ const palette = input.find((x) => x.component === '@palette')
let paletteRule
if (palette) {
const { directives } = palette
@@ -339,21 +384,20 @@ const AppearanceTab = {
paletteRule = {
component: 'Root',
directives: Object.fromEntries(
- Object
- .entries(directives)
+ Object.entries(directives)
.filter(([k]) => k && k !== 'name')
- .map(([k, v]) => ['--' + k, 'color | ' + v])
- )
+ .map(([k, v]) => ['--' + k, 'color | ' + v]),
+ ),
}
} else {
paletteRule = null
}
theme3 = init({
- inputRuleset: [...input, paletteRule].filter(x => x),
+ inputRuleset: [...input, paletteRule].filter((x) => x),
ultimateBackgroundColor: '#000000',
liteMode: true,
- onlyNormalState: true
+ onlyNormalState: true,
})
}
} else {
@@ -361,7 +405,7 @@ const AppearanceTab = {
inputRuleset: [],
ultimateBackgroundColor: '#000000',
liteMode: true,
- onlyNormalState: true
+ onlyNormalState: true,
})
}
@@ -369,22 +413,29 @@ const AppearanceTab = {
this.compilationCache[key] = theme3
}
-
const sheet = createStyleSheet('appearance-tab-previews', 90)
- sheet.addRule([
- '#theme-preview-', key, ' {\n',
- getCssRules(theme3.eager).join('\n'),
- '\n}'
- ].join(''))
+ sheet.addRule(
+ [
+ '#theme-preview-',
+ key,
+ ' {\n',
+ getCssRules(theme3.eager).join('\n'),
+ '\n}',
+ ].join(''),
+ )
sheet.ready = true
adoptStyleSheets()
},
- uploadFile (slot, e) {
+ uploadFile(slot, e) {
const file = e.target.files[0]
- if (!file) { return }
+ if (!file) {
+ return
+ }
if (file.size > this.$store.state.instance[slot + 'limit']) {
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
- const allowedsize = fileSizeFormatService.fileSizeFormat(this.$store.state.instance[slot + 'limit'])
+ const allowedsize = fileSizeFormatService.fileSizeFormat(
+ this.$store.state.instance[slot + 'limit'],
+ )
useInterfaceStore().pushGlobalNotice({
messageKey: 'upload.error.message',
messageArgs: [
@@ -392,10 +443,10 @@ const AppearanceTab = {
filesize: filesize.num,
filesizeunit: filesize.unit,
allowedsize: allowedsize.num,
- allowedsizeunit: allowedsize.unit
- })
+ allowedsizeunit: allowedsize.unit,
+ }),
],
- level: 'error'
+ level: 'error',
})
return
}
@@ -408,29 +459,36 @@ const AppearanceTab = {
}
reader.readAsDataURL(file)
},
- resetBackground () {
- const confirmed = window.confirm(this.$t('settings.reset_background_confirm'))
+ resetBackground() {
+ const confirmed = window.confirm(
+ this.$t('settings.reset_background_confirm'),
+ )
if (confirmed) {
this.submitBackground('')
}
},
- resetUploadedBackground () {
+ resetUploadedBackground() {
this.backgroundPreview = null
},
- submitBackground (background) {
- if (!this.backgroundPreview && background !== '') { return }
+ submitBackground(background) {
+ if (!this.backgroundPreview && background !== '') {
+ return
+ }
this.backgroundUploading = true
- this.$store.state.api.backendInteractor.updateProfileImages({ background })
+ this.$store.state.api.backendInteractor
+ .updateProfileImages({ background })
.then((data) => {
this.$store.commit('addNewUsers', [data])
this.$store.commit('setCurrentUser', data)
this.backgroundPreview = null
})
.catch(this.displayUploadError)
- .finally(() => { this.backgroundUploading = false })
+ .finally(() => {
+ this.backgroundUploading = false
+ })
},
- }
+ },
}
export default AppearanceTab
diff --git a/src/components/settings_modal/tabs/clutter_tab.js b/src/components/settings_modal/tabs/clutter_tab.js
index d4edf8f66..c0b7b33b2 100644
--- a/src/components/settings_modal/tabs/clutter_tab.js
+++ b/src/components/settings_modal/tabs/clutter_tab.js
@@ -1,19 +1,16 @@
-import { mapState, mapActions } from 'pinia'
+import { mapActions, mapState } from 'pinia'
+import { v4 as uuidv4 } from 'uuid'
import { mapState as mapVuexState } from 'vuex'
-import { v4 as uuidv4 } from 'uuid';
-import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
-
-import BooleanSetting from '../helpers/boolean_setting.vue'
-import ChoiceSetting from '../helpers/choice_setting.vue'
-import UnitSetting from '../helpers/unit_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import HelpIndicator from '../helpers/help_indicator.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Select from 'src/components/select/select.vue'
-
+import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
+import BooleanSetting from '../helpers/boolean_setting.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
+import HelpIndicator from '../helpers/help_indicator.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
-
+import UnitSetting from '../helpers/unit_setting.vue'
const ClutterTab = {
components: {
@@ -23,23 +20,23 @@ const ClutterTab = {
IntegerSetting,
Checkbox,
Select,
- HelpIndicator
+ HelpIndicator,
},
computed: {
- instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
+ instanceSpecificPanelPresent() {
+ return this.$store.state.instance.showInstanceSpecificPanel
+ },
...SharedComputedObject(),
- ...mapState(
- useServerSideStorageStore,
- {
- muteFilters: store => Object.entries(store.prefsStorage.simple.muteFilters),
- muteFiltersObject: store => store.prefsStorage.simple.muteFilters
- }
- ),
+ ...mapState(useServerSideStorageStore, {
+ muteFilters: (store) =>
+ Object.entries(store.prefsStorage.simple.muteFilters),
+ muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
+ }),
...mapVuexState({
- blockExpirationSupported: state => state.instance.blockExpiration
+ blockExpirationSupported: (state) => state.instance.blockExpiration,
}),
onMuteDefaultActionLv1: {
- get () {
+ get() {
const value = this.$store.state.config.onMuteDefaultAction
if (value === 'ask' || value === 'forever') {
return value
@@ -47,16 +44,19 @@ const ClutterTab = {
return 'temporarily'
}
},
- set (value) {
+ set(value) {
let realValue = value
if (value !== 'ask' && value !== 'forever') {
realValue = '14d'
}
- this.$store.dispatch('setOption', { name: 'onMuteDefaultAction', value: realValue })
- }
+ this.$store.dispatch('setOption', {
+ name: 'onMuteDefaultAction',
+ value: realValue,
+ })
+ },
},
onBlockDefaultActionLv1: {
- get () {
+ get() {
const value = this.$store.state.config.onBlockDefaultAction
if (value === 'ask' || value === 'forever') {
return value
@@ -64,29 +64,36 @@ const ClutterTab = {
return 'temporarily'
}
},
- set (value) {
+ set(value) {
let realValue = value
if (value !== 'ask' && value !== 'forever') {
realValue = '14d'
}
- this.$store.dispatch('setOption', { name: 'onBlockDefaultAction', value: realValue })
- }
+ this.$store.dispatch('setOption', {
+ name: 'onBlockDefaultAction',
+ value: realValue,
+ })
+ },
},
- muteFiltersDraft () {
+ muteFiltersDraft() {
return Object.entries(this.muteFiltersDraftObject)
},
- muteFiltersExpired () {
+ muteFiltersExpired() {
const now = Date.now()
- return Object
- .entries(this.muteFiltersDraftObject)
- .filter(([, { expires }]) => expires != null && expires <= now)
- }
+ return Object.entries(this.muteFiltersDraftObject).filter(
+ ([, { expires }]) => expires != null && expires <= now,
+ )
+ },
},
methods: {
- ...mapActions(useServerSideStorageStore, ['setPreference', 'unsetPreference', 'pushServerSideStorage']),
- getDatetimeLocal (timestamp) {
+ ...mapActions(useServerSideStorageStore, [
+ 'setPreference',
+ 'unsetPreference',
+ 'pushServerSideStorage',
+ ]),
+ getDatetimeLocal(timestamp) {
const date = new Date(timestamp)
- const fmt = new Intl.NumberFormat("en-US", {minimumIntegerDigits: 2})
+ const fmt = new Intl.NumberFormat('en-US', { minimumIntegerDigits: 2 })
const datetime = [
date.getFullYear(),
'-',
@@ -96,11 +103,11 @@ const ClutterTab = {
'T',
fmt.format(date.getHours()),
':',
- fmt.format(date.getMinutes())
+ fmt.format(date.getMinutes()),
].join('')
return datetime
},
- checkRegexValid (id) {
+ checkRegexValid(id) {
const filter = this.muteFiltersObject[id]
if (filter.type !== 'regexp') return true
if (filter.type !== 'user_regexp') return true
@@ -114,19 +121,21 @@ const ClutterTab = {
}
return valid
},
- createFilter (filter = {
- type: 'word',
- value: '',
- name: 'New Filter',
- enabled: true,
- expires: null,
- hide: false,
- }) {
+ createFilter(
+ filter = {
+ type: 'word',
+ value: '',
+ name: 'New Filter',
+ enabled: true,
+ expires: null,
+ hide: false,
+ },
+ ) {
const newId = uuidv4()
filter.order = this.muteFilters.length + 2
this.muteFiltersDraftObject[newId] = filter
- this.setPreference({ path: 'simple.muteFilters.' + newId , value: filter })
+ this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
},
exportFilter(id) {
@@ -137,23 +146,23 @@ const ClutterTab = {
importFilter() {
this.filterImporter.importData()
},
- copyFilter (id) {
+ copyFilter(id) {
const filter = { ...this.muteFiltersDraftObject[id] }
const newId = uuidv4()
this.muteFiltersDraftObject[newId] = filter
- this.setPreference({ path: 'simple.muteFilters.' + newId , value: filter })
+ this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
},
- deleteFilter (id) {
+ deleteFilter(id) {
delete this.muteFiltersDraftObject[id]
- this.unsetPreference({ path: 'simple.muteFilters.' + id , value: null })
+ this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
this.pushServerSideStorage()
},
- purgeExpiredFilters () {
+ purgeExpiredFilters() {
this.muteFiltersExpired.forEach(([id]) => {
delete this.muteFiltersDraftObject[id]
- this.unsetPreference({ path: 'simple.muteFilters.' + id , value: null })
+ this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
})
this.pushServerSideStorage()
},
@@ -177,17 +186,20 @@ const ClutterTab = {
this.muteFiltersDraftDirty[id] = true
},
saveFilter(id) {
- this.setPreference({ path: 'simple.muteFilters.' + id , value: this.muteFiltersDraftObject[id] })
+ this.setPreference({
+ path: 'simple.muteFilters.' + id,
+ value: this.muteFiltersDraftObject[id],
+ })
this.pushServerSideStorage()
this.muteFiltersDraftDirty[id] = false
},
},
// Updating nested properties
watch: {
- replyVisibility () {
+ replyVisibility() {
this.$store.dispatch('queueFlushAll')
- }
- }
+ },
+ },
}
export default ClutterTab
diff --git a/src/components/settings_modal/tabs/composing_tab.js b/src/components/settings_modal/tabs/composing_tab.js
index 7efbe7047..0b06922e0 100644
--- a/src/components/settings_modal/tabs/composing_tab.js
+++ b/src/components/settings_modal/tabs/composing_tab.js
@@ -1,89 +1,97 @@
import { mapState } from 'vuex'
+import FontControl from 'src/components/font_control/font_control.vue'
+import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
+import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
+import Select from 'src/components/select/select.vue'
+import localeService from 'src/services/locale/locale.service.js'
+import { cacheKey, clearCache, emojiCacheKey } from 'src/services/sw/sw.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
import FloatSetting from '../helpers/float_setting.vue'
-import UnitSetting from '../helpers/unit_setting.vue'
-import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
-import Select from 'src/components/select/select.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
-import FontControl from 'src/components/font_control/font_control.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import UnitSetting from '../helpers/unit_setting.vue'
-import localeService from 'src/services/locale/locale.service.js'
-import { clearCache, cacheKey, emojiCacheKey } from 'src/services/sw/sw.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
+ faDatabase,
faGlobe,
faMessage,
faPenAlt,
- faDatabase,
- faSliders
+ faSliders,
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faGlobe,
- faMessage,
- faPenAlt,
- faDatabase,
- faSliders
-)
+library.add(faGlobe, faMessage, faPenAlt, faDatabase, faSliders)
const ComposingTab = {
props: {
parentCollapsed: {
required: true,
- type: Boolean
- }
+ type: Boolean,
+ },
},
- data () {
+ data() {
return {
- subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({
+ subjectLineOptions: ['email', 'noop', 'masto'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
+ label: this.$t(
+ `settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`,
+ ),
})),
- conversationDisplayOptions: ['tree', 'linear'].map(mode => ({
+ conversationDisplayOptions: ['tree', 'linear'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.conversation_display_${mode}`)
+ label: this.$t(`settings.conversation_display_${mode}`),
})),
- absoluteTime12hOptions: ['24h', '12h'].map(mode => ({
+ absoluteTime12hOptions: ['24h', '12h'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.absolute_time_format_12h_${mode}`)
+ label: this.$t(`settings.absolute_time_format_12h_${mode}`),
})),
- conversationOtherRepliesButtonOptions: ['below', 'inside'].map(mode => ({
+ conversationOtherRepliesButtonOptions: ['below', 'inside'].map(
+ (mode) => ({
+ key: mode,
+ value: mode,
+ label: this.$t(`settings.conversation_other_replies_button_${mode}`),
+ }),
+ ),
+ mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(
+ (mode) => ({
+ key: mode,
+ value: mode,
+ label: this.$t(`settings.mention_link_display_${mode}`),
+ }),
+ ),
+ userPopoverAvatarActionOptions: ['close', 'zoom', 'open'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.conversation_other_replies_button_${mode}`)
+ label: this.$t(`settings.user_popover_avatar_action_${mode}`),
})),
- mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(mode => ({
+ unsavedPostActionOptions: ['save', 'discard', 'confirm'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.mention_link_display_${mode}`)
- })),
- userPopoverAvatarActionOptions: ['close', 'zoom', 'open'].map(mode => ({
- key: mode,
- value: mode,
- label: this.$t(`settings.user_popover_avatar_action_${mode}`)
- })),
- unsavedPostActionOptions: ['save', 'discard', 'confirm'].map(mode => ({
- key: mode,
- value: mode,
- label: this.$t(`settings.unsaved_post_action_${mode}`)
+ label: this.$t(`settings.unsaved_post_action_${mode}`),
})),
loopSilentAvailable:
- // Firefox
- Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
- // Chrome-likes
- Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
- // Future spec, still not supported in Nightly 63 as of 08/2018
- Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
- emailLanguage: this.$store.state.users.currentUser.language || ['']
+ // Firefox
+ Object.getOwnPropertyDescriptor(
+ HTMLVideoElement.prototype,
+ 'mozHasAudio',
+ ) ||
+ // Chrome-likes
+ Object.getOwnPropertyDescriptor(
+ HTMLMediaElement.prototype,
+ 'webkitAudioDecodedByteCount',
+ ) ||
+ // Future spec, still not supported in Nightly 63 as of 08/2018
+ Object.getOwnPropertyDescriptor(
+ HTMLMediaElement.prototype,
+ 'audioTracks',
+ ),
+ emailLanguage: this.$store.state.users.currentUser.language || [''],
}
},
components: {
@@ -96,61 +104,68 @@ const ComposingTab = {
ProfileSettingIndicator,
ScopeSelector,
Select,
- FontControl
+ FontControl,
},
computed: {
- postFormats () {
+ postFormats() {
return this.$store.state.instance.postFormats || []
},
- postContentOptions () {
- return this.postFormats.map(format => ({
+ postContentOptions() {
+ return this.postFormats.map((format) => ({
key: format,
value: format,
- label: this.$t(`post_status.content_type["${format}"]`)
+ label: this.$t(`post_status.content_type["${format}"]`),
}))
},
language: {
- get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
+ get: function () {
+ return this.$store.getters.mergedConfig.interfaceLanguage
+ },
set: function (val) {
- this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
- }
+ this.$store.dispatch('setOption', {
+ name: 'interfaceLanguage',
+ value: val,
+ })
+ },
},
...SharedComputedObject(),
...mapState({
- blockExpirationSupported: state => state.instance.blockExpiration,
- })
+ blockExpirationSupported: (state) => state.instance.blockExpiration,
+ }),
},
methods: {
- changeDefaultScope (value) {
+ changeDefaultScope(value) {
this.$store.dispatch('setProfileOption', { name: 'defaultScope', value })
},
- clearCache (key) {
+ clearCache(key) {
clearCache(key)
.then(() => {
this.$store.dispatch('settingsSaved', { success: true })
})
- .catch(error => {
+ .catch((error) => {
this.$store.dispatch('settingsSaved', { error })
})
},
- tooSmall () {
+ tooSmall() {
this.$emit('tooSmall')
},
- tooBig () {
+ tooBig() {
this.$emit('tooBig')
},
- getNavMode () {
+ getNavMode() {
return this.$refs.tabSwitcher.getNavMode()
},
- clearAssetCache () {
+ clearAssetCache() {
this.clearCache(cacheKey)
},
- clearEmojiCache () {
+ clearEmojiCache() {
this.clearCache(emojiCacheKey)
},
- updateProfile () {
+ updateProfile() {
const params = {
- language: localeService.internalToBackendLocaleMulti(this.emailLanguage)
+ language: localeService.internalToBackendLocaleMulti(
+ this.emailLanguage,
+ ),
}
this.$store.state.api.backendInteractor
@@ -160,19 +175,19 @@ const ComposingTab = {
this.$store.commit('setCurrentUser', user)
})
},
- updateFont (key, value) {
+ updateFont(key, value) {
this.$store.dispatch('setOption', {
name: 'theme3hacks',
value: {
...this.mergedConfig.theme3hacks,
fonts: {
...this.mergedConfig.theme3hacks.fonts,
- [key]: value
- }
- }
+ [key]: value,
+ },
+ },
})
},
- }
+ },
}
export default ComposingTab
diff --git a/src/components/settings_modal/tabs/data_import_export_tab.js b/src/components/settings_modal/tabs/data_import_export_tab.js
index 4304e59c0..dcd63416b 100644
--- a/src/components/settings_modal/tabs/data_import_export_tab.js
+++ b/src/components/settings_modal/tabs/data_import_export_tab.js
@@ -1,85 +1,89 @@
-import Importer from 'src/components/importer/importer.vue'
-import Exporter from 'src/components/exporter/exporter.vue'
-import Checkbox from 'src/components/checkbox/checkbox.vue'
import { mapState } from 'vuex'
+
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+import Exporter from 'src/components/exporter/exporter.vue'
+import Importer from 'src/components/importer/importer.vue'
import { useOAuthTokensStore } from 'src/stores/oauth_tokens'
const DataImportExportTab = {
- data () {
+ data() {
return {
activeTab: 'profile',
newDomainToMute: '',
listBackupsError: false,
addBackupError: false,
addedBackup: false,
- backups: []
+ backups: [],
}
},
- created () {
+ created() {
useOAuthTokensStore().fetchTokens()
this.fetchBackups()
},
components: {
Importer,
Exporter,
- Checkbox
+ Checkbox,
},
computed: {
...mapState({
backendInteractor: (state) => state.api.backendInteractor,
- user: (state) => state.users.currentUser
- })
+ user: (state) => state.users.currentUser,
+ }),
},
methods: {
- getFollowsContent () {
- return this.backendInteractor.exportFriends({ id: this.user.id })
+ getFollowsContent() {
+ return this.backendInteractor
+ .exportFriends({ id: this.user.id })
.then(this.generateExportableUsersContent)
},
- getBlocksContent () {
- return this.backendInteractor.fetchBlocks()
+ getBlocksContent() {
+ return this.backendInteractor
+ .fetchBlocks()
.then(this.generateExportableUsersContent)
},
- getMutesContent () {
- return this.backendInteractor.fetchMutes()
+ getMutesContent() {
+ return this.backendInteractor
+ .fetchMutes()
.then(this.generateExportableUsersContent)
},
- importFollows (file) {
- return this.backendInteractor.importFollows({ file })
- .then((status) => {
- if (!status) {
- throw new Error('failed')
- }
- })
- },
- importBlocks (file) {
- return this.backendInteractor.importBlocks({ file })
- .then((status) => {
- if (!status) {
- throw new Error('failed')
- }
- })
- },
- importMutes (file) {
- return this.backendInteractor.importMutes({ file })
- .then((status) => {
- if (!status) {
- throw new Error('failed')
- }
- })
- },
- generateExportableUsersContent (users) {
- // Get addresses
- return users.map((user) => {
- // check is it's a local user
- if (user && user.is_local) {
- // append the instance address
- return user.screen_name + '@' + location.hostname
+ importFollows(file) {
+ return this.backendInteractor.importFollows({ file }).then((status) => {
+ if (!status) {
+ throw new Error('failed')
}
- return user.screen_name
- }).join('\n')
+ })
},
- addBackup () {
- this.$store.state.api.backendInteractor.addBackup()
+ importBlocks(file) {
+ return this.backendInteractor.importBlocks({ file }).then((status) => {
+ if (!status) {
+ throw new Error('failed')
+ }
+ })
+ },
+ importMutes(file) {
+ return this.backendInteractor.importMutes({ file }).then((status) => {
+ if (!status) {
+ throw new Error('failed')
+ }
+ })
+ },
+ generateExportableUsersContent(users) {
+ // Get addresses
+ return users
+ .map((user) => {
+ // check is it's a local user
+ if (user && user.is_local) {
+ // append the instance address
+ return user.screen_name + '@' + location.hostname
+ }
+ return user.screen_name
+ })
+ .join('\n')
+ },
+ addBackup() {
+ this.$store.state.api.backendInteractor
+ .addBackup()
.then(() => {
this.addedBackup = true
this.addBackupError = false
@@ -90,8 +94,9 @@ const DataImportExportTab = {
})
.then(() => this.fetchBackups())
},
- fetchBackups () {
- this.$store.state.api.backendInteractor.listBackups()
+ fetchBackups() {
+ this.$store.state.api.backendInteractor
+ .listBackups()
.then((res) => {
this.backups = res
this.listBackupsError = false
@@ -99,8 +104,8 @@ const DataImportExportTab = {
.catch((error) => {
this.listBackupsError = error.error
})
- }
- }
+ },
+ },
}
export default DataImportExportTab
diff --git a/src/components/settings_modal/tabs/developer_tab.js b/src/components/settings_modal/tabs/developer_tab.js
index f8f21e9f4..60f2ecb36 100644
--- a/src/components/settings_modal/tabs/developer_tab.js
+++ b/src/components/settings_modal/tabs/developer_tab.js
@@ -1,46 +1,45 @@
+import { cacheKey, clearCache, emojiCacheKey } from 'src/services/sw/sw.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
-import { clearCache, cacheKey, emojiCacheKey } from 'src/services/sw/sw.js'
-
-const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
+const pleromaFeCommitUrl =
+ 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
const VersionTab = {
- data () {
+ data() {
const instance = this.$store.state.instance
return {
backendVersion: instance.backendVersion,
backendRepository: instance.backendRepository,
- frontendVersion: instance.frontendVersion
+ frontendVersion: instance.frontendVersion,
}
},
components: {
- BooleanSetting
+ BooleanSetting,
},
computed: {
- frontendVersionLink () {
+ frontendVersionLink() {
return pleromaFeCommitUrl + this.frontendVersion
},
...SharedComputedObject(),
},
methods: {
- clearAssetCache () {
+ clearAssetCache() {
this.clearCache(cacheKey)
},
- clearEmojiCache () {
+ clearEmojiCache() {
this.clearCache(emojiCacheKey)
},
- clearCache (key) {
+ clearCache(key) {
clearCache(key)
.then(() => {
this.$store.dispatch('settingsSaved', { success: true })
})
- .catch(error => {
+ .catch((error) => {
this.$store.dispatch('settingsSaved', { error })
})
- }
- }
+ },
+ },
}
export default VersionTab
diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js
index 594ce3f58..8bd2b913d 100644
--- a/src/components/settings_modal/tabs/filtering_tab.js
+++ b/src/components/settings_modal/tabs/filtering_tab.js
@@ -1,50 +1,49 @@
import { cloneDeep } from 'lodash'
-import { mapState, mapActions } from 'pinia'
+import { mapActions, mapState } from 'pinia'
+import { v4 as uuidv4 } from 'uuid'
import { mapState as mapVuexState } from 'vuex'
-import { v4 as uuidv4 } from 'uuid';
-import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
-import { useInterfaceStore } from 'src/stores/interface'
-
-import {
- newImporter,
- newExporter
-} from 'src/services/export_import/export_import.js'
-
-import BooleanSetting from '../helpers/boolean_setting.vue'
-import ChoiceSetting from '../helpers/choice_setting.vue'
-import UnitSetting from '../helpers/unit_setting.vue'
-import IntegerSetting from '../helpers/integer_setting.vue'
-import HelpIndicator from '../helpers/help_indicator.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Select from 'src/components/select/select.vue'
-
+import {
+ newExporter,
+ newImporter,
+} from 'src/services/export_import/export_import.js'
+import { useInterfaceStore } from 'src/stores/interface'
+import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
+import BooleanSetting from '../helpers/boolean_setting.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
+import HelpIndicator from '../helpers/help_indicator.vue'
+import IntegerSetting from '../helpers/integer_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import UnitSetting from '../helpers/unit_setting.vue'
const SUPPORTED_TYPES = new Set(['word', 'regexp', 'user', 'user_regexp'])
const FilteringTab = {
- data () {
+ data() {
return {
- replyVisibilityOptions: ['all', 'following', 'self'].map(mode => ({
+ replyVisibilityOptions: ['all', 'following', 'self'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.reply_visibility_${mode}`)
+ label: this.$t(`settings.reply_visibility_${mode}`),
})),
- muteBlockLv1Options: ['ask', 'forever', 'temporarily'].map(mode => ({
+ muteBlockLv1Options: ['ask', 'forever', 'temporarily'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`user_card.mute_block_${mode}`)
+ label: this.$t(`user_card.mute_block_${mode}`),
})),
- muteFiltersDraftObject: cloneDeep(useServerSideStorageStore().prefsStorage.simple.muteFilters),
+ muteFiltersDraftObject: cloneDeep(
+ useServerSideStorageStore().prefsStorage.simple.muteFilters,
+ ),
muteFiltersDraftDirty: Object.fromEntries(
Object.entries(
- useServerSideStorageStore().prefsStorage.simple.muteFilters
- ).map(([k]) => [k, false])
+ useServerSideStorageStore().prefsStorage.simple.muteFilters,
+ ).map(([k]) => [k, false]),
),
exportedFilter: null,
filterImporter: newImporter({
- validator (parsed) {
+ validator(parsed) {
if (Array.isArray(parsed)) return false
if (!SUPPORTED_TYPES.has(parsed.type)) return false
return true
@@ -55,7 +54,7 @@ const FilteringTab = {
expires = null,
hide = false,
name = '',
- value = ''
+ value = '',
} = data
this.createFilter({
@@ -63,22 +62,21 @@ const FilteringTab = {
expires,
hide,
name,
- value
+ value,
})
},
- onImportFailure (result) {
+ onImportFailure(result) {
console.error('Failure importing filter:', result)
- useInterfaceStore()
- .pushGlobalNotice({
- messageKey: 'settings.filter.import_failure',
- level: 'error'
- })
- }
+ useInterfaceStore().pushGlobalNotice({
+ messageKey: 'settings.filter.import_failure',
+ level: 'error',
+ })
+ },
}),
filterExporter: newExporter({
filename: 'pleromafe_mute-filter',
- getExportedObject: () => this.exportedFilter
- })
+ getExportedObject: () => this.exportedFilter,
+ }),
}
},
components: {
@@ -88,23 +86,23 @@ const FilteringTab = {
IntegerSetting,
Checkbox,
Select,
- HelpIndicator
+ HelpIndicator,
},
computed: {
- instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
+ instanceSpecificPanelPresent() {
+ return this.$store.state.instance.showInstanceSpecificPanel
+ },
...SharedComputedObject(),
- ...mapState(
- useServerSideStorageStore,
- {
- muteFilters: store => Object.entries(store.prefsStorage.simple.muteFilters),
- muteFiltersObject: store => store.prefsStorage.simple.muteFilters
- }
- ),
+ ...mapState(useServerSideStorageStore, {
+ muteFilters: (store) =>
+ Object.entries(store.prefsStorage.simple.muteFilters),
+ muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
+ }),
...mapVuexState({
- blockExpirationSupported: state => state.instance.blockExpiration
+ blockExpirationSupported: (state) => state.instance.blockExpiration,
}),
onMuteDefaultActionLv1: {
- get () {
+ get() {
const value = this.$store.state.config.onMuteDefaultAction
if (value === 'ask' || value === 'forever') {
return value
@@ -112,16 +110,19 @@ const FilteringTab = {
return 'temporarily'
}
},
- set (value) {
+ set(value) {
let realValue = value
if (value !== 'ask' && value !== 'forever') {
realValue = '14d'
}
- this.$store.dispatch('setOption', { name: 'onMuteDefaultAction', value: realValue })
- }
+ this.$store.dispatch('setOption', {
+ name: 'onMuteDefaultAction',
+ value: realValue,
+ })
+ },
},
onBlockDefaultActionLv1: {
- get () {
+ get() {
const value = this.$store.state.config.onBlockDefaultAction
if (value === 'ask' || value === 'forever') {
return value
@@ -129,29 +130,36 @@ const FilteringTab = {
return 'temporarily'
}
},
- set (value) {
+ set(value) {
let realValue = value
if (value !== 'ask' && value !== 'forever') {
realValue = '14d'
}
- this.$store.dispatch('setOption', { name: 'onBlockDefaultAction', value: realValue })
- }
+ this.$store.dispatch('setOption', {
+ name: 'onBlockDefaultAction',
+ value: realValue,
+ })
+ },
},
- muteFiltersDraft () {
+ muteFiltersDraft() {
return Object.entries(this.muteFiltersDraftObject)
},
- muteFiltersExpired () {
+ muteFiltersExpired() {
const now = Date.now()
- return Object
- .entries(this.muteFiltersDraftObject)
- .filter(([, { expires }]) => expires != null && expires <= now)
- }
+ return Object.entries(this.muteFiltersDraftObject).filter(
+ ([, { expires }]) => expires != null && expires <= now,
+ )
+ },
},
methods: {
- ...mapActions(useServerSideStorageStore, ['setPreference', 'unsetPreference', 'pushServerSideStorage']),
- getDatetimeLocal (timestamp) {
+ ...mapActions(useServerSideStorageStore, [
+ 'setPreference',
+ 'unsetPreference',
+ 'pushServerSideStorage',
+ ]),
+ getDatetimeLocal(timestamp) {
const date = new Date(timestamp)
- const fmt = new Intl.NumberFormat("en-US", {minimumIntegerDigits: 2})
+ const fmt = new Intl.NumberFormat('en-US', { minimumIntegerDigits: 2 })
const datetime = [
date.getFullYear(),
'-',
@@ -161,11 +169,11 @@ const FilteringTab = {
'T',
fmt.format(date.getHours()),
':',
- fmt.format(date.getMinutes())
+ fmt.format(date.getMinutes()),
].join('')
return datetime
},
- checkRegexValid (id) {
+ checkRegexValid(id) {
const filter = this.muteFiltersObject[id]
if (filter.type !== 'regexp') return true
if (filter.type !== 'user_regexp') return true
@@ -179,19 +187,21 @@ const FilteringTab = {
}
return valid
},
- createFilter (filter = {
- type: 'word',
- value: '',
- name: 'New Filter',
- enabled: true,
- expires: null,
- hide: false,
- }) {
+ createFilter(
+ filter = {
+ type: 'word',
+ value: '',
+ name: 'New Filter',
+ enabled: true,
+ expires: null,
+ hide: false,
+ },
+ ) {
const newId = uuidv4()
filter.order = this.muteFilters.length + 2
this.muteFiltersDraftObject[newId] = filter
- this.setPreference({ path: 'simple.muteFilters.' + newId , value: filter })
+ this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
},
exportFilter(id) {
@@ -202,23 +212,23 @@ const FilteringTab = {
importFilter() {
this.filterImporter.importData()
},
- copyFilter (id) {
+ copyFilter(id) {
const filter = { ...this.muteFiltersDraftObject[id] }
const newId = uuidv4()
this.muteFiltersDraftObject[newId] = filter
- this.setPreference({ path: 'simple.muteFilters.' + newId , value: filter })
+ this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
},
- deleteFilter (id) {
+ deleteFilter(id) {
delete this.muteFiltersDraftObject[id]
- this.unsetPreference({ path: 'simple.muteFilters.' + id , value: null })
+ this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
this.pushServerSideStorage()
},
- purgeExpiredFilters () {
+ purgeExpiredFilters() {
this.muteFiltersExpired.forEach(([id]) => {
delete this.muteFiltersDraftObject[id]
- this.unsetPreference({ path: 'simple.muteFilters.' + id , value: null })
+ this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
})
this.pushServerSideStorage()
},
@@ -242,17 +252,20 @@ const FilteringTab = {
this.muteFiltersDraftDirty[id] = true
},
saveFilter(id) {
- this.setPreference({ path: 'simple.muteFilters.' + id , value: this.muteFiltersDraftObject[id] })
+ this.setPreference({
+ path: 'simple.muteFilters.' + id,
+ value: this.muteFiltersDraftObject[id],
+ })
this.pushServerSideStorage()
this.muteFiltersDraftDirty[id] = false
},
},
// Updating nested properties
watch: {
- replyVisibility () {
+ replyVisibility() {
this.$store.dispatch('queueFlushAll')
- }
- }
+ },
+ },
}
export default FilteringTab
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index 4d3b01c46..cf98fd182 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -1,32 +1,30 @@
import { mapState } from 'vuex'
+import FontControl from 'src/components/font_control/font_control.vue'
+import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
+import localeService from 'src/services/locale/locale.service.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import UnitSetting from '../helpers/unit_setting.vue'
import FloatSetting from '../helpers/float_setting.vue'
-import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
-import FontControl from 'src/components/font_control/font_control.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
-
-import localeService from 'src/services/locale/locale.service.js'
+import UnitSetting from '../helpers/unit_setting.vue'
const GeneralTab = {
props: {
parentCollapsed: {
required: true,
- type: Boolean
- }
+ type: Boolean,
+ },
},
- data () {
+ data() {
return {
- absoluteTime12hOptions: ['24h', '12h'].map(mode => ({
+ absoluteTime12hOptions: ['24h', '12h'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.absolute_time_format_12h_${mode}`)
+ label: this.$t(`settings.absolute_time_format_12h_${mode}`),
})),
- emailLanguage: this.$store.state.users.currentUser.language || ['']
+ emailLanguage: this.$store.state.users.currentUser.language || [''],
}
},
components: {
@@ -36,24 +34,31 @@ const GeneralTab = {
FloatSetting,
FontControl,
InterfaceLanguageSwitcher,
- ProfileSettingIndicator
+ ProfileSettingIndicator,
},
computed: {
language: {
- get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
+ get: function () {
+ return this.$store.getters.mergedConfig.interfaceLanguage
+ },
set: function (val) {
- this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
- }
+ this.$store.dispatch('setOption', {
+ name: 'interfaceLanguage',
+ value: val,
+ })
+ },
},
...SharedComputedObject(),
...mapState({
- blockExpirationSupported: state => state.instance.blockExpiration,
- })
+ blockExpirationSupported: (state) => state.instance.blockExpiration,
+ }),
},
methods: {
- updateProfile () {
+ updateProfile() {
const params = {
- language: localeService.internalToBackendLocaleMulti(this.emailLanguage)
+ language: localeService.internalToBackendLocaleMulti(
+ this.emailLanguage,
+ ),
}
this.$store.state.api.backendInteractor
@@ -63,19 +68,19 @@ const GeneralTab = {
this.$store.commit('setCurrentUser', user)
})
},
- updateFont (key, value) {
+ updateFont(key, value) {
this.$store.dispatch('setOption', {
name: 'theme3hacks',
value: {
...this.mergedConfig.theme3hacks,
fonts: {
...this.mergedConfig.theme3hacks.fonts,
- [key]: value
- }
- }
+ [key]: value,
+ },
+ },
})
},
- }
+ },
}
export default GeneralTab
diff --git a/src/components/settings_modal/tabs/layout_tab.js b/src/components/settings_modal/tabs/layout_tab.js
index 48b6eb971..3fc18491c 100644
--- a/src/components/settings_modal/tabs/layout_tab.js
+++ b/src/components/settings_modal/tabs/layout_tab.js
@@ -1,50 +1,56 @@
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
-import UnitSetting from '../helpers/unit_setting.vue'
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
+import UnitSetting from '../helpers/unit_setting.vue'
const GeneralTab = {
props: {
parentCollapsed: {
required: true,
- type: Boolean
- }
+ type: Boolean,
+ },
},
- data () {
+ data() {
return {
- thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({
- key: mode,
- value: mode,
- label: this.$t(`settings.third_column_mode_${mode}`)
- }))
+ thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(
+ (mode) => ({
+ key: mode,
+ value: mode,
+ label: this.$t(`settings.third_column_mode_${mode}`),
+ }),
+ ),
}
},
components: {
BooleanSetting,
ChoiceSetting,
UnitSetting,
- ProfileSettingIndicator
+ ProfileSettingIndicator,
},
computed: {
- postFormats () {
+ postFormats() {
return this.$store.state.instance.postFormats || []
},
- instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable },
- columns () {
+ instanceShoutboxPresent() {
+ return this.$store.state.instance.shoutAvailable
+ },
+ columns() {
const mode = this.$store.getters.mergedConfig.thirdColumnMode
const notif = mode === 'none' ? [] : ['notifs']
- if (this.$store.getters.mergedConfig.sidebarRight || mode === 'postform') {
+ if (
+ this.$store.getters.mergedConfig.sidebarRight ||
+ mode === 'postform'
+ ) {
return [...notif, 'content', 'sidebar']
} else {
return ['sidebar', 'content', ...notif]
}
},
...SharedComputedObject(),
- }
+ },
}
export default GeneralTab
diff --git a/src/components/settings_modal/tabs/mutes_and_blocks_tab.js b/src/components/settings_modal/tabs/mutes_and_blocks_tab.js
index 36dc8a090..55087d1e2 100644
--- a/src/components/settings_modal/tabs/mutes_and_blocks_tab.js
+++ b/src/components/settings_modal/tabs/mutes_and_blocks_tab.js
@@ -1,45 +1,52 @@
import get from 'lodash/get'
import map from 'lodash/map'
import reject from 'lodash/reject'
-import Autosuggest from 'src/components/autosuggest/autosuggest.vue'
-import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
-import BlockCard from 'src/components/block_card/block_card.vue'
-import MuteCard from 'src/components/mute_card/mute_card.vue'
-import DomainMuteCard from 'src/components/domain_mute_card/domain_mute_card.vue'
-import SelectableList from 'src/components/selectable_list/selectable_list.vue'
-import ProgressButton from 'src/components/progress_button/progress_button.vue'
-import withSubscription from 'src/components/../hocs/with_subscription/with_subscription'
+
import withLoadMore from 'src/components/../hocs/with_load_more/with_load_more'
+import withSubscription from 'src/components/../hocs/with_subscription/with_subscription'
+import Autosuggest from 'src/components/autosuggest/autosuggest.vue'
+import BlockCard from 'src/components/block_card/block_card.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
+import DomainMuteCard from 'src/components/domain_mute_card/domain_mute_card.vue'
+import MuteCard from 'src/components/mute_card/mute_card.vue'
+import ProgressButton from 'src/components/progress_button/progress_button.vue'
+import SelectableList from 'src/components/selectable_list/selectable_list.vue'
+import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import { useOAuthTokensStore } from 'src/stores/oauth_tokens'
const BlockList = withLoadMore({
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
- select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
- destroy: () => {},
- childPropName: 'items'
+ select: (props, $store) =>
+ get($store.state.users.currentUser, 'blockIds', []),
+ destroy: () => {
+ /* no-op */
+ },
+ childPropName: 'items',
})(SelectableList)
const MuteList = withLoadMore({
fetch: (props, $store) => $store.dispatch('fetchMutes'),
select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
- destroy: () => {},
- childPropName: 'items'
+ destroy: () => {
+ /* no-op */
+ },
+ childPropName: 'items',
})(SelectableList)
const DomainMuteList = withSubscription({
fetch: (props, $store) => $store.dispatch('fetchDomainMutes'),
- select: (props, $store) => get($store.state.users.currentUser, 'domainMutes', []),
- childPropName: 'items'
+ select: (props, $store) =>
+ get($store.state.users.currentUser, 'domainMutes', []),
+ childPropName: 'items',
})(SelectableList)
const MutesAndBlocks = {
- data () {
+ data() {
return {
- activeTab: 'profile'
+ activeTab: 'profile',
}
},
- created () {
+ created() {
useOAuthTokensStore().fetchTokens()
this.$store.dispatch('getKnownDomains')
},
@@ -53,87 +60,94 @@ const MutesAndBlocks = {
DomainMuteCard,
ProgressButton,
Autosuggest,
- Checkbox
+ Checkbox,
},
computed: {
- knownDomains () {
+ knownDomains() {
return this.$store.state.instance.knownDomains
},
- user () {
+ user() {
return this.$store.state.users.currentUser
- }
+ },
},
methods: {
- importFollows (file) {
- return this.$store.state.api.backendInteractor.importFollows({ file })
+ importFollows(file) {
+ return this.$store.state.api.backendInteractor
+ .importFollows({ file })
.then((status) => {
if (!status) {
throw new Error('failed')
}
})
},
- importBlocks (file) {
- return this.$store.state.api.backendInteractor.importBlocks({ file })
+ importBlocks(file) {
+ return this.$store.state.api.backendInteractor
+ .importBlocks({ file })
.then((status) => {
if (!status) {
throw new Error('failed')
}
})
},
- generateExportableUsersContent (users) {
+ generateExportableUsersContent(users) {
// Get addresses
- return users.map((user) => {
- // check is it's a local user
- if (user && user.is_local) {
- // append the instance address
- return user.screen_name + '@' + location.hostname
- }
- return user.screen_name
- }).join('\n')
+ return users
+ .map((user) => {
+ // check is it's a local user
+ if (user && user.is_local) {
+ // append the instance address
+ return user.screen_name + '@' + location.hostname
+ }
+ return user.screen_name
+ })
+ .join('\n')
},
- activateTab (tabName) {
+ activateTab(tabName) {
this.activeTab = tabName
},
- filterUnblockedUsers (userIds) {
+ filterUnblockedUsers(userIds) {
return reject(userIds, (userId) => {
const relationship = this.$store.getters.relationship(this.userId)
return relationship.blocking || userId === this.user.id
})
},
- filterUnMutedUsers (userIds) {
+ filterUnMutedUsers(userIds) {
return reject(userIds, (userId) => {
const relationship = this.$store.getters.relationship(this.userId)
return relationship.muting || userId === this.user.id
})
},
- queryUserIds (query) {
- return this.$store.dispatch('searchUsers', { query })
+ queryUserIds(query) {
+ return this.$store
+ .dispatch('searchUsers', { query })
.then((users) => map(users, 'id'))
},
- blockUsers (ids) {
+ blockUsers(ids) {
return this.$store.dispatch('blockUsers', ids)
},
- unblockUsers (ids) {
+ unblockUsers(ids) {
return this.$store.dispatch('unblockUsers', ids)
},
- muteUsers (ids) {
+ muteUsers(ids) {
return this.$store.dispatch('muteUsers', ids)
},
- unmuteUsers (ids) {
+ unmuteUsers(ids) {
return this.$store.dispatch('unmuteUsers', ids)
},
- filterUnMutedDomains (urls) {
- return urls.filter(url => !this.user.domainMutes.includes(url))
+ filterUnMutedDomains(urls) {
+ return urls.filter((url) => !this.user.domainMutes.includes(url))
},
- queryKnownDomains (query) {
+ queryKnownDomains(query) {
return new Promise((resolve) => {
- resolve(this.knownDomains.filter(url => url.toLowerCase().includes(query)))
+ resolve(
+ this.knownDomains.filter((url) => url.toLowerCase().includes(query)),
+ )
})
},
- unmuteDomains (domains) {
+ unmuteDomains(domains) {
return this.$store.dispatch('unmuteDomains', domains)
- }
- }
+ },
+ },
}
export default MutesAndBlocks
diff --git a/src/components/settings_modal/tabs/notifications_tab.js b/src/components/settings_modal/tabs/notifications_tab.js
index c53b5889d..c863a7b9f 100644
--- a/src/components/settings_modal/tabs/notifications_tab.js
+++ b/src/components/settings_modal/tabs/notifications_tab.js
@@ -2,32 +2,36 @@ import BooleanSetting from '../helpers/boolean_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
const NotificationsTab = {
- data () {
+ data() {
return {
activeTab: 'profile',
- notificationSettings: this.$store.state.users.currentUser.notification_settings,
- newDomainToMute: ''
+ notificationSettings:
+ this.$store.state.users.currentUser.notification_settings,
+ newDomainToMute: '',
}
},
components: {
- BooleanSetting
+ BooleanSetting,
},
computed: {
- user () {
+ user() {
return this.$store.state.users.currentUser
},
- canReceiveReports () {
- if (!this.user) { return false }
+ canReceiveReports() {
+ if (!this.user) {
+ return false
+ }
return this.user.privileges.includes('reports_manage_reports')
},
- ...SharedComputedObject()
+ ...SharedComputedObject(),
},
methods: {
- updateNotificationSettings () {
- this.$store.state.api.backendInteractor
- .updateNotificationSettings({ settings: this.notificationSettings })
- }
- }
+ updateNotificationSettings() {
+ this.$store.state.api.backendInteractor.updateNotificationSettings({
+ settings: this.notificationSettings,
+ })
+ },
+ },
}
export default NotificationsTab
diff --git a/src/components/settings_modal/tabs/old_theme_tab/old_theme_tab.js b/src/components/settings_modal/tabs/old_theme_tab/old_theme_tab.js
index 4b558471f..c79c72e70 100644
--- a/src/components/settings_modal/tabs/old_theme_tab/old_theme_tab.js
+++ b/src/components/settings_modal/tabs/old_theme_tab/old_theme_tab.js
@@ -1,50 +1,48 @@
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+import ColorInput from 'src/components/color_input/color_input.vue'
+import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
+import FontControl from 'src/components/font_control/font_control.vue'
+import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
+import RangeInput from 'src/components/range_input/range_input.vue'
+import Select from 'src/components/select/select.vue'
+import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
+import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import {
- rgb2hex,
- hex2rgb,
getContrastRatioLayers,
- relativeLuminance
+ hex2rgb,
+ relativeLuminance,
+ rgb2hex,
} from 'src/services/color_convert/color_convert.js'
import {
+ newExporter,
newImporter,
- newExporter
} from 'src/services/export_import/export_import.js'
import {
- SLOT_INHERITANCE
-} from 'src/services/theme_data/pleromafe.js'
-import {
- CURRENT_VERSION,
- OPACITIES,
- getLayers,
- getOpacitySlot,
- DEFAULT_SHADOWS,
- generateColors,
- generateShadows,
- generateRadii,
- generateFonts,
- shadows2to3,
- colors2to3
-} from 'src/services/theme_data/theme_data.service.js'
-
-import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
-import { init } from 'src/services/theme_data/theme_data_3.service.js'
+ adoptStyleSheets,
+ createStyleSheet,
+} from 'src/services/style_setter/style_setter.js'
import {
getCssRules,
- getScopedVersion
+ getScopedVersion,
} from 'src/services/theme_data/css_utils.js'
-import { createStyleSheet, adoptStyleSheets } from 'src/services/style_setter/style_setter.js'
-
-import ColorInput from 'src/components/color_input/color_input.vue'
-import RangeInput from 'src/components/range_input/range_input.vue'
-import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
-import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
-import FontControl from 'src/components/font_control/font_control.vue'
-import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
-import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
-import Checkbox from 'src/components/checkbox/checkbox.vue'
-import Select from 'src/components/select/select.vue'
-
-import Preview from './theme_preview.vue'
+import { SLOT_INHERITANCE } from 'src/services/theme_data/pleromafe.js'
+import {
+ CURRENT_VERSION,
+ colors2to3,
+ DEFAULT_SHADOWS,
+ generateColors,
+ generateFonts,
+ generateRadii,
+ generateShadows,
+ getLayers,
+ getOpacitySlot,
+ OPACITIES,
+ shadows2to3,
+} from 'src/services/theme_data/theme_data.service.js'
+import { init } from 'src/services/theme_data/theme_data_3.service.js'
+import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
import { useInterfaceStore } from 'src/stores/interface'
+import Preview from './theme_preview.vue'
// List of color values used in v1
const v1OnlyNames = [
@@ -55,8 +53,8 @@ const v1OnlyNames = [
'cRed',
'cGreen',
'cBlue',
- 'cOrange'
-].map(_ => _ + 'ColorLocal')
+ 'cOrange',
+].map((_) => _ + 'ColorLocal')
const colorConvert = (color) => {
if (color.startsWith('--') || color === 'transparent') {
@@ -67,16 +65,16 @@ const colorConvert = (color) => {
}
export default {
- data () {
+ data() {
return {
themeImporter: newImporter({
validator: this.importValidator,
onImport: this.onImport,
- onImportFailure: this.onImportFailure
+ onImportFailure: this.onImportFailure,
}),
themeExporter: newExporter({
filename: 'pleroma_theme',
- getExportedObject: () => this.exportedTheme
+ getExportedObject: () => this.exportedTheme,
}),
availableStyles: [],
selected: '',
@@ -98,12 +96,18 @@ export default {
keepFonts: false,
...Object.keys(SLOT_INHERITANCE)
- .map(key => [key, ''])
- .reduce((acc, [key, val]) => ({ ...acc, [key + 'ColorLocal']: val }), {}),
+ .map((key) => [key, ''])
+ .reduce(
+ (acc, [key, val]) => ({ ...acc, [key + 'ColorLocal']: val }),
+ {},
+ ),
...Object.keys(OPACITIES)
- .map(key => [key, ''])
- .reduce((acc, [key, val]) => ({ ...acc, [key + 'OpacityLocal']: val }), {}),
+ .map((key) => [key, ''])
+ .reduce(
+ (acc, [key, val]) => ({ ...acc, [key + 'OpacityLocal']: val }),
+ {},
+ ),
shadowSelected: undefined,
shadowsLocal: {},
@@ -117,10 +121,10 @@ export default {
avatarAltRadiusLocal: '',
attachmentRadiusLocal: '',
tooltipRadiusLocal: '',
- chatMessageRadiusLocal: ''
+ chatMessageRadiusLocal: '',
}
},
- created () {
+ created() {
const currentIndex = this.$store.state.instance.themesIndex
let promise
@@ -130,50 +134,48 @@ export default {
promise = useInterfaceStore().fetchThemesIndex()
}
- promise.then(themesIndex => {
- Object
- .values(themesIndex)
- .forEach(themeFunc => {
- themeFunc().then(themeData => themeData && this.availableStyles.push(themeData))
- })
+ promise.then((themesIndex) => {
+ Object.values(themesIndex).forEach((themeFunc) => {
+ themeFunc().then(
+ (themeData) => themeData && this.availableStyles.push(themeData),
+ )
+ })
})
},
- mounted () {
+ mounted() {
if (typeof this.shadowSelected === 'undefined') {
this.shadowSelected = this.shadowsAvailable[0]
}
},
computed: {
- themeWarningHelp () {
+ themeWarningHelp() {
if (!this.themeWarning) return
const t = this.$t
const pre = 'settings.style.switcher.help.'
- const {
- origin,
- themeEngineVersion,
- type,
- noActionsPossible
- } = this.themeWarning
+ const { origin, themeEngineVersion, type, noActionsPossible } =
+ this.themeWarning
if (origin === 'file') {
// Loaded v2 theme from file
if (themeEngineVersion === 2 && type === 'wrong_version') {
return t(pre + 'v2_imported')
}
if (themeEngineVersion > CURRENT_VERSION) {
- return t(pre + 'future_version_imported') + ' ' +
- (
- noActionsPossible
- ? t(pre + 'snapshot_missing')
- : t(pre + 'snapshot_present')
- )
+ return (
+ t(pre + 'future_version_imported') +
+ ' ' +
+ (noActionsPossible
+ ? t(pre + 'snapshot_missing')
+ : t(pre + 'snapshot_present'))
+ )
}
if (themeEngineVersion < CURRENT_VERSION) {
- return t(pre + 'future_version_imported') + ' ' +
- (
- noActionsPossible
- ? t(pre + 'snapshot_missing')
- : t(pre + 'snapshot_present')
- )
+ return (
+ t(pre + 'future_version_imported') +
+ ' ' +
+ (noActionsPossible
+ ? t(pre + 'snapshot_missing')
+ : t(pre + 'snapshot_present'))
+ )
}
} else if (origin === 'localStorage') {
if (type === 'snapshot_source_mismatch') {
@@ -185,38 +187,40 @@ export default {
}
// Admin downgraded FE
if (themeEngineVersion > CURRENT_VERSION) {
- return t(pre + 'fe_downgraded') + ' ' +
- (
- noActionsPossible
- ? t(pre + 'migration_snapshot_ok')
- : t(pre + 'migration_snapshot_gone')
- )
+ return (
+ t(pre + 'fe_downgraded') +
+ ' ' +
+ (noActionsPossible
+ ? t(pre + 'migration_snapshot_ok')
+ : t(pre + 'migration_snapshot_gone'))
+ )
}
// Admin upgraded FE
if (themeEngineVersion < CURRENT_VERSION) {
- return t(pre + 'fe_upgraded') + ' ' +
- (
- noActionsPossible
- ? t(pre + 'migration_snapshot_ok')
- : t(pre + 'migration_snapshot_gone')
- )
+ return (
+ t(pre + 'fe_upgraded') +
+ ' ' +
+ (noActionsPossible
+ ? t(pre + 'migration_snapshot_ok')
+ : t(pre + 'migration_snapshot_gone'))
+ )
}
}
},
- selectedVersion () {
+ selectedVersion() {
return Array.isArray(this.selectedTheme) ? 1 : 2
},
- currentColors () {
+ currentColors() {
return Object.keys(SLOT_INHERITANCE)
- .map(key => [key, this[key + 'ColorLocal']])
+ .map((key) => [key, this[key + 'ColorLocal']])
.reduce((acc, [key, val]) => ({ ...acc, [key]: val }), {})
},
- currentOpacity () {
+ currentOpacity() {
return Object.keys(OPACITIES)
- .map(key => [key, this[key + 'OpacityLocal']])
+ .map((key) => [key, this[key + 'OpacityLocal']])
.reduce((acc, [key, val]) => ({ ...acc, [key]: val }), {})
},
- currentRadii () {
+ currentRadii() {
return {
btn: this.btnRadiusLocal,
input: this.inputRadiusLocal,
@@ -226,11 +230,11 @@ export default {
avatarAlt: this.avatarAltRadiusLocal,
tooltip: this.tooltipRadiusLocal,
attachment: this.attachmentRadiusLocal,
- chatMessage: this.chatMessageRadiusLocal
+ chatMessage: this.chatMessageRadiusLocal,
}
},
// This needs optimization maybe
- previewContrast () {
+ previewContrast() {
try {
if (!this.previewTheme.colors.bg) return {}
const colors = this.previewTheme.colors
@@ -243,113 +247,124 @@ export default {
aaa: ratio >= 7,
// same but for 18pt+ texts
laa: ratio >= 3,
- laaa: ratio >= 4.5
+ laaa: ratio >= 4.5,
})
- const colorsConverted = Object.entries(colors).reduce((acc, [key, value]) => ({ ...acc, [key]: colorConvert(value) }), {})
+ const colorsConverted = Object.entries(colors).reduce(
+ (acc, [key, value]) => ({ ...acc, [key]: colorConvert(value) }),
+ {},
+ )
- const ratios = Object.entries(SLOT_INHERITANCE).reduce((acc, [key, value]) => {
- const slotIsBaseText = key === 'text' || key === 'link'
- const slotIsText = slotIsBaseText || (
- typeof value === 'object' && value !== null && value.textColor
- )
- if (!slotIsText) return acc
- const { layer, variant } = slotIsBaseText ? { layer: 'bg' } : value
- const background = variant || layer
- const opacitySlot = getOpacitySlot(background)
- const textColors = [
- key,
- ...(background === 'bg' ? ['cRed', 'cGreen', 'cBlue', 'cOrange'] : [])
- ]
+ const ratios = Object.entries(SLOT_INHERITANCE).reduce(
+ (acc, [key, value]) => {
+ const slotIsBaseText = key === 'text' || key === 'link'
+ const slotIsText =
+ slotIsBaseText ||
+ (typeof value === 'object' && value !== null && value.textColor)
+ if (!slotIsText) return acc
+ const { layer, variant } = slotIsBaseText ? { layer: 'bg' } : value
+ const background = variant || layer
+ const opacitySlot = getOpacitySlot(background)
+ const textColors = [
+ key,
+ ...(background === 'bg'
+ ? ['cRed', 'cGreen', 'cBlue', 'cOrange']
+ : []),
+ ]
- const layers = getLayers(
- layer,
- variant || layer,
- opacitySlot,
- colorsConverted,
- opacity
- )
+ const layers = getLayers(
+ layer,
+ variant || layer,
+ opacitySlot,
+ colorsConverted,
+ opacity,
+ )
- // Temporary patch for null-y value errors
- if (layers.flat().some(v => v == null)) return acc
+ // Temporary patch for null-y value errors
+ if (layers.flat().some((v) => v == null)) return acc
- return {
- ...acc,
- ...textColors.reduce((acc, textColorKey) => {
- const newKey = slotIsBaseText
- ? 'bg' + textColorKey[0].toUpperCase() + textColorKey.slice(1)
- : textColorKey
- return {
- ...acc,
- [newKey]: getContrastRatioLayers(
- colorsConverted[textColorKey],
- layers,
- colorsConverted[textColorKey]
- )
- }
- }, {})
- }
+ return {
+ ...acc,
+ ...textColors.reduce((acc, textColorKey) => {
+ const newKey = slotIsBaseText
+ ? 'bg' + textColorKey[0].toUpperCase() + textColorKey.slice(1)
+ : textColorKey
+ return {
+ ...acc,
+ [newKey]: getContrastRatioLayers(
+ colorsConverted[textColorKey],
+ layers,
+ colorsConverted[textColorKey],
+ ),
+ }
+ }, {}),
+ }
+ },
+ {},
+ )
+
+ return Object.entries(ratios).reduce((acc, [k, v]) => {
+ acc[k] = hints(v)
+ return acc
}, {})
-
- return Object.entries(ratios).reduce((acc, [k, v]) => { acc[k] = hints(v); return acc }, {})
} catch (e) {
console.warn('Failure computing contrasts', e)
return {}
}
},
- themeDataUsed () {
+ themeDataUsed() {
return useInterfaceStore().themeDataUsed
},
- shadowsAvailable () {
+ shadowsAvailable() {
return Object.keys(DEFAULT_SHADOWS).sort()
},
currentShadowOverriden: {
- get () {
+ get() {
return !!this.currentShadow
},
- set (val) {
+ set(val) {
if (val) {
- this.shadowsLocal[this.shadowSelected] = (this.currentShadowFallback || [])
- .map(s => ({
- name: null,
- x: 0,
- y: 0,
- blur: 0,
- spread: 0,
- inset: false,
- color: '#000000',
- alpha: 1,
- ...s
- }))
+ this.shadowsLocal[this.shadowSelected] = (
+ this.currentShadowFallback || []
+ ).map((s) => ({
+ name: null,
+ x: 0,
+ y: 0,
+ blur: 0,
+ spread: 0,
+ inset: false,
+ color: '#000000',
+ alpha: 1,
+ ...s,
+ }))
} else {
delete this.shadowsLocal[this.shadowSelected]
}
- }
+ },
},
- currentShadowFallback () {
+ currentShadowFallback() {
return (this.previewTheme.shadows || {})[this.shadowSelected]
},
currentShadow: {
- get () {
+ get() {
return this.shadowsLocal[this.shadowSelected]
},
- set (v) {
+ set(v) {
this.shadowsLocal[this.shadowSelected] = v
- }
+ },
},
- themeValid () {
+ themeValid() {
return !this.shadowsInvalid && !this.colorsInvalid && !this.radiiInvalid
},
- exportedTheme () {
- const saveEverything = (
+ exportedTheme() {
+ const saveEverything =
!this.keepFonts &&
!this.keepShadows &&
!this.keepOpacity &&
!this.keepRoundness &&
!this.keepColor
- )
const source = {
- themeEngineVersion: CURRENT_VERSION
+ themeEngineVersion: CURRENT_VERSION,
}
if (this.keepFonts || saveEverything) {
@@ -370,18 +385,20 @@ export default {
const theme = {
themeEngineVersion: CURRENT_VERSION,
- ...this.previewTheme
+ ...this.previewTheme,
}
return {
// To separate from other random JSON files and possible future source formats
- _pleroma_theme_version: 2, theme, source
+ _pleroma_theme_version: 2,
+ theme,
+ source,
}
},
- isActive () {
+ isActive() {
const tabSwitcher = this.$parent
return tabSwitcher ? tabSwitcher.isActive('theme') : false
- }
+ },
},
components: {
ColorInput,
@@ -393,70 +410,65 @@ export default {
TabSwitcher,
Preview,
Checkbox,
- Select
+ Select,
},
methods: {
- loadTheme (
- {
- theme,
- source,
- _pleroma_theme_version: fileVersion
- },
+ loadTheme(
+ { theme, source, _pleroma_theme_version: fileVersion },
origin,
- forceUseSource = false
+ forceUseSource = false,
) {
this.dismissWarning()
- const version = (origin === 'localStorage' && !theme.colors)
- ? 'l1'
- : fileVersion
+ const version =
+ origin === 'localStorage' && !theme.colors ? 'l1' : fileVersion
const snapshotEngineVersion = (theme || {}).themeEngineVersion
const themeEngineVersion = (source || {}).themeEngineVersion || 2
const versionsMatch = themeEngineVersion === CURRENT_VERSION
- const sourceSnapshotMismatch = (
+ const sourceSnapshotMismatch =
theme !== undefined &&
- source !== undefined &&
- themeEngineVersion !== snapshotEngineVersion
- )
+ source !== undefined &&
+ themeEngineVersion !== snapshotEngineVersion
// Force loading of source if user requested it or if snapshot
// is unavailable
const forcedSourceLoad = (source && forceUseSource) || !theme
- if (!(versionsMatch && !sourceSnapshotMismatch) &&
- !forcedSourceLoad &&
- version !== 'l1' &&
- origin !== 'defaults'
+ if (
+ !(versionsMatch && !sourceSnapshotMismatch) &&
+ !forcedSourceLoad &&
+ version !== 'l1' &&
+ origin !== 'defaults'
) {
if (sourceSnapshotMismatch && origin === 'localStorage') {
this.themeWarning = {
origin,
themeEngineVersion,
- type: 'snapshot_source_mismatch'
+ type: 'snapshot_source_mismatch',
}
} else if (!theme) {
this.themeWarning = {
origin,
noActionsPossible: true,
themeEngineVersion,
- type: 'no_snapshot_old_version'
+ type: 'no_snapshot_old_version',
}
} else if (!versionsMatch) {
this.themeWarning = {
origin,
noActionsPossible: !source,
themeEngineVersion,
- type: 'wrong_version'
+ type: 'wrong_version',
}
}
}
this.normalizeLocalState(theme, version, source, forcedSourceLoad)
},
- forceLoadLocalStorage () {
+ forceLoadLocalStorage() {
this.loadThemeFromLocalStorage(true)
},
- dismissWarning () {
+ dismissWarning() {
this.themeWarning = undefined
this.tempImportFile = undefined
},
- forceLoad () {
+ forceLoad() {
const { origin } = this.themeWarning
switch (origin) {
case 'localStorage':
@@ -468,7 +480,7 @@ export default {
}
this.dismissWarning()
},
- forceSnapshot () {
+ forceSnapshot() {
const { origin } = this.themeWarning
switch (origin) {
case 'localStorage':
@@ -480,25 +492,25 @@ export default {
}
this.dismissWarning()
},
- loadThemeFromLocalStorage (confirmLoadSource = false) {
+ loadThemeFromLocalStorage(confirmLoadSource = false) {
const theme = this.themeDataUsed?.source
if (theme) {
this.loadTheme(
{
- theme
+ theme,
},
'localStorage',
- confirmLoadSource
+ confirmLoadSource,
)
}
},
- setCustomTheme () {
+ setCustomTheme() {
useInterfaceStore().setThemeV2({
customTheme: {
ignore: true,
themeFileVersion: this.selectedVersion,
themeEngineVersion: CURRENT_VERSION,
- ...this.previewTheme
+ ...this.previewTheme,
},
customThemeSource: {
themeFileVersion: this.selectedVersion,
@@ -507,77 +519,84 @@ export default {
fonts: this.fontsLocal,
opacity: this.currentOpacity,
colors: this.currentColors,
- radii: this.currentRadii
- }
+ radii: this.currentRadii,
+ },
})
},
- updatePreviewColors () {
+ updatePreviewColors() {
const result = generateColors({
opacity: this.currentOpacity,
- colors: this.currentColors
+ colors: this.currentColors,
})
this.previewTheme.colors = result.theme.colors
this.previewTheme.opacity = result.theme.opacity
},
- updatePreviewShadows () {
+ updatePreviewShadows() {
this.previewTheme.shadows = generateShadows(
{
shadows: this.shadowsLocal,
opacity: this.previewTheme.opacity,
- themeEngineVersion: this.engineVersion
+ themeEngineVersion: this.engineVersion,
},
this.previewTheme.colors,
- relativeLuminance(this.previewTheme.colors.bg) < 0.5 ? 1 : -1
+ relativeLuminance(this.previewTheme.colors.bg) < 0.5 ? 1 : -1,
).theme.shadows
},
- importTheme () { this.themeImporter.importData() },
- exportTheme () { this.themeExporter.exportData() },
- onImport (parsed, forceSource = false) {
+ importTheme() {
+ this.themeImporter.importData()
+ },
+ exportTheme() {
+ this.themeExporter.exportData()
+ },
+ onImport(parsed, forceSource = false) {
this.tempImportFile = parsed
this.loadTheme(parsed, 'file', forceSource)
},
- onImportFailure () {
- useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_theme_imported', level: 'error' })
+ onImportFailure() {
+ useInterfaceStore().pushGlobalNotice({
+ messageKey: 'settings.invalid_theme_imported',
+ level: 'error',
+ })
},
- importValidator (parsed) {
+ importValidator(parsed) {
const version = parsed._pleroma_theme_version
return version >= 1 || version <= 2
},
- clearAll () {
+ clearAll() {
this.loadThemeFromLocalStorage()
},
// Clears all the extra stuff when loading V1 theme
- clearV1 () {
+ clearV1() {
Object.keys(this.$data)
- .filter(_ => _.endsWith('ColorLocal') || _.endsWith('OpacityLocal'))
- .filter(_ => !v1OnlyNames.includes(_))
- .forEach(key => {
+ .filter((_) => _.endsWith('ColorLocal') || _.endsWith('OpacityLocal'))
+ .filter((_) => !v1OnlyNames.includes(_))
+ .forEach((key) => {
this.$data[key] = undefined
})
},
- clearRoundness () {
+ clearRoundness() {
Object.keys(this.$data)
- .filter(_ => _.endsWith('RadiusLocal'))
- .forEach(key => {
+ .filter((_) => _.endsWith('RadiusLocal'))
+ .forEach((key) => {
this.$data[key] = undefined
})
},
- clearOpacity () {
+ clearOpacity() {
Object.keys(this.$data)
- .filter(_ => _.endsWith('OpacityLocal'))
- .forEach(key => {
+ .filter((_) => _.endsWith('OpacityLocal'))
+ .forEach((key) => {
this.$data[key] = undefined
})
},
- clearShadows () {
+ clearShadows() {
this.shadowsLocal = {}
},
- clearFonts () {
+ clearFonts() {
this.fontsLocal = {}
},
@@ -594,7 +613,7 @@ export default {
* @param {Boolean} source - by default source won't be used if version doesn't match since it might render differently
* this allows importing source anyway
*/
- normalizeLocalState (theme, version = 0, source, forceSource = false) {
+ normalizeLocalState(theme, version = 0, source, forceSource = false) {
let input
if (typeof source !== 'undefined') {
if (forceSource || source?.themeEngineVersion === CURRENT_VERSION) {
@@ -618,11 +637,17 @@ export default {
if (version === 0) {
if (input.version) version = input.version
// Old v1 naming: fg is text, btn is foreground
- if (typeof colors.text === 'undefined' && typeof colors.fg !== 'undefined') {
+ if (
+ typeof colors.text === 'undefined' &&
+ typeof colors.fg !== 'undefined'
+ ) {
version = 1
}
// New v2 naming: text is text, fg is foreground
- if (typeof colors.text !== 'undefined' && typeof colors.fg !== 'undefined') {
+ if (
+ typeof colors.text !== 'undefined' &&
+ typeof colors.fg !== 'undefined'
+ ) {
version = 2
}
}
@@ -648,7 +673,7 @@ export default {
.add('cOrange')
}
- keys.forEach(key => {
+ keys.forEach((key) => {
const color = colors[key]
const hex = rgb2hex(colors[key])
this[key + 'ColorLocal'] = hex === '#aN' ? color : hex
@@ -689,33 +714,32 @@ export default {
this.fontsLocal = fonts
}
},
- updateTheme3Preview () {
+ updateTheme3Preview() {
const theme2 = convertTheme2To3(this.previewTheme)
const theme3 = init({
inputRuleset: theme2,
ultimateBackgroundColor: '#000000',
- liteMode: true
+ liteMode: true,
})
const sheet = createStyleSheet('theme-tab-overall-preview', 90)
- const rule = getScopedVersion(
- getCssRules(theme3.eager),
- '&'
- ).join('\n')
+ const rule = getScopedVersion(getCssRules(theme3.eager), '&').join('\n')
sheet.clear()
sheet.addRule('#theme-preview {\n' + rule + '\n}')
sheet.ready = true
adoptStyleSheets()
- }
+ },
},
watch: {
- themeDataUsed () {
+ themeDataUsed() {
this.loadThemeFromLocalStorage()
},
- currentRadii () {
+ currentRadii() {
try {
- this.previewTheme.radii = generateRadii({ radii: this.currentRadii }).theme.radii
+ this.previewTheme.radii = generateRadii({
+ radii: this.currentRadii,
+ }).theme.radii
this.radiiInvalid = false
} catch (e) {
this.radiiInvalid = true
@@ -723,7 +747,7 @@ export default {
}
},
shadowsLocal: {
- handler () {
+ handler() {
try {
this.updatePreviewShadows()
this.shadowsInvalid = false
@@ -732,21 +756,23 @@ export default {
console.warn(e)
}
},
- deep: true
+ deep: true,
},
fontsLocal: {
- handler () {
+ handler() {
try {
- this.previewTheme.fonts = generateFonts({ fonts: this.fontsLocal }).theme.fonts
+ this.previewTheme.fonts = generateFonts({
+ fonts: this.fontsLocal,
+ }).theme.fonts
this.fontsInvalid = false
} catch (e) {
this.fontsInvalid = true
console.warn(e)
}
},
- deep: true
+ deep: true,
},
- currentColors () {
+ currentColors() {
try {
this.updatePreviewColors()
this.colorsInvalid = false
@@ -755,23 +781,25 @@ export default {
console.warn(e)
}
},
- currentOpacity () {
+ currentOpacity() {
try {
this.updatePreviewColors()
} catch (e) {
console.warn(e)
}
},
- selected () {
- this.selectedTheme = Object.entries(this.availableStyles).find(([, s]) => {
- if (Array.isArray(s)) {
- return s[0] === this.selected
- } else {
- return s.name === this.selected
- }
- })[1]
+ selected() {
+ this.selectedTheme = Object.entries(this.availableStyles).find(
+ ([, s]) => {
+ if (Array.isArray(s)) {
+ return s[0] === this.selected
+ } else {
+ return s.name === this.selected
+ }
+ },
+ )[1]
},
- selectedTheme () {
+ selectedTheme() {
this.dismissWarning()
if (this.selectedVersion === 1) {
if (!this.keepRoundness) {
@@ -799,8 +827,12 @@ export default {
this.cOrangeColorLocal = this.selectedTheme[8]
}
} else if (this.selectedVersion >= 2) {
- this.normalizeLocalState(this.selectedTheme.theme, 2, this.selectedTheme.source)
+ this.normalizeLocalState(
+ this.selectedTheme.theme,
+ 2,
+ this.selectedTheme.source,
+ )
}
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/tabs/old_theme_tab/theme_preview.vue b/src/components/settings_modal/tabs/old_theme_tab/theme_preview.vue
index df2d9f9e9..778e92c3b 100644
--- a/src/components/settings_modal/tabs/old_theme_tab/theme_preview.vue
+++ b/src/components/settings_modal/tabs/old_theme_tab/theme_preview.vue
@@ -119,25 +119,21 @@
diff --git a/src/components/settings_modal/tabs/posts_tab.js b/src/components/settings_modal/tabs/posts_tab.js
index 094583c15..dfc4d4f8b 100644
--- a/src/components/settings_modal/tabs/posts_tab.js
+++ b/src/components/settings_modal/tabs/posts_tab.js
@@ -1,52 +1,64 @@
+import FontControl from 'src/components/font_control/font_control.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import IntegerSetting from '../helpers/integer_setting.vue'
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
-import FontControl from 'src/components/font_control/font_control.vue'
-
import SharedComputedObject from '../helpers/shared_computed_object.js'
const GeneralTab = {
props: {
parentCollapsed: {
required: true,
- type: Boolean
- }
+ type: Boolean,
+ },
},
- data () {
+ data() {
return {
- conversationDisplayOptions: ['tree', 'linear'].map(mode => ({
+ conversationDisplayOptions: ['tree', 'linear'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.conversation_display_${mode}`)
+ label: this.$t(`settings.conversation_display_${mode}`),
})),
- conversationOtherRepliesButtonOptions: ['below', 'inside'].map(mode => ({
+ conversationOtherRepliesButtonOptions: ['below', 'inside'].map(
+ (mode) => ({
+ key: mode,
+ value: mode,
+ label: this.$t(`settings.conversation_other_replies_button_${mode}`),
+ }),
+ ),
+ mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(
+ (mode) => ({
+ key: mode,
+ value: mode,
+ label: this.$t(`settings.mention_link_display_${mode}`),
+ }),
+ ),
+ userPopoverAvatarActionOptions: ['close', 'zoom', 'open'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.conversation_other_replies_button_${mode}`)
+ label: this.$t(`settings.user_popover_avatar_action_${mode}`),
})),
- mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(mode => ({
+ unsavedPostActionOptions: ['save', 'discard', 'confirm'].map((mode) => ({
key: mode,
value: mode,
- label: this.$t(`settings.mention_link_display_${mode}`)
- })),
- userPopoverAvatarActionOptions: ['close', 'zoom', 'open'].map(mode => ({
- key: mode,
- value: mode,
- label: this.$t(`settings.user_popover_avatar_action_${mode}`)
- })),
- unsavedPostActionOptions: ['save', 'discard', 'confirm'].map(mode => ({
- key: mode,
- value: mode,
- label: this.$t(`settings.unsaved_post_action_${mode}`)
+ label: this.$t(`settings.unsaved_post_action_${mode}`),
})),
loopSilentAvailable:
- // Firefox
- Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
- // Chrome-likes
- Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
- // Future spec, still not supported in Nightly 63 as of 08/2018
- Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks')
+ // Firefox
+ Object.getOwnPropertyDescriptor(
+ HTMLVideoElement.prototype,
+ 'mozHasAudio',
+ ) ||
+ // Chrome-likes
+ Object.getOwnPropertyDescriptor(
+ HTMLMediaElement.prototype,
+ 'webkitAudioDecodedByteCount',
+ ) ||
+ // Future spec, still not supported in Nightly 63 as of 08/2018
+ Object.getOwnPropertyDescriptor(
+ HTMLMediaElement.prototype,
+ 'audioTracks',
+ ),
}
},
components: {
@@ -54,25 +66,25 @@ const GeneralTab = {
ChoiceSetting,
IntegerSetting,
FontControl,
- ProfileSettingIndicator
+ ProfileSettingIndicator,
},
computed: {
...SharedComputedObject(),
},
methods: {
- updateFont (key, value) {
+ updateFont(key, value) {
this.$store.dispatch('setOption', {
name: 'theme3hacks',
value: {
...this.mergedConfig.theme3hacks,
fonts: {
...this.mergedConfig.theme3hacks.fonts,
- [key]: value
- }
- }
+ [key]: value,
+ },
+ },
})
},
- }
+ },
}
export default GeneralTab
diff --git a/src/components/settings_modal/tabs/profile_tab.js b/src/components/settings_modal/tabs/profile_tab.js
index 9e13eed69..acfc0c674 100644
--- a/src/components/settings_modal/tabs/profile_tab.js
+++ b/src/components/settings_modal/tabs/profile_tab.js
@@ -1,24 +1,20 @@
-import UserCard from 'src/components/user_card/user_card.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
+import UserCard from 'src/components/user_card/user_card.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
-import SharedComputedObject from '../helpers/shared_computed_object.js'
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
+import SharedComputedObject from '../helpers/shared_computed_object.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faTimes,
+ faCircleNotch,
faPlus,
- faCircleNotch
+ faTimes,
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faTimes,
- faPlus,
- faCircleNotch
-)
+library.add(faTimes, faPlus, faCircleNotch)
const ProfileTab = {
- data () {
+ data() {
return {
// Whether user is locked or not
locked: this.$store.state.users.currentUser.locked,
@@ -28,18 +24,18 @@ const ProfileTab = {
UserCard,
Checkbox,
BooleanSetting,
- ProfileSettingIndicator
+ ProfileSettingIndicator,
},
computed: {
- user () {
+ user() {
return this.$store.state.users.currentUser
},
- ...SharedComputedObject()
+ ...SharedComputedObject(),
},
methods: {
- updateProfile () {
+ updateProfile() {
const params = {
- locked: this.locked
+ locked: this.locked,
}
this.$store.state.api.backendInteractor
@@ -51,13 +47,13 @@ const ProfileTab = {
.catch((error) => {
this.displayUploadError(error)
})
- }
+ },
},
watch: {
- locked () {
+ locked() {
this.updateProfile()
- }
- }
+ },
+ },
}
export default ProfileTab
diff --git a/src/components/settings_modal/tabs/security_tab/confirm.js b/src/components/settings_modal/tabs/security_tab/confirm.js
index 0f4ddfc9b..a8d0fc53a 100644
--- a/src/components/settings_modal/tabs/security_tab/confirm.js
+++ b/src/components/settings_modal/tabs/security_tab/confirm.js
@@ -1,9 +1,15 @@
const Confirm = {
props: ['disabled'],
- data: () => ({}),
+ data: () => ({
+ /* no-op */
+ }),
methods: {
- confirm () { this.$emit('confirm') },
- cancel () { this.$emit('cancel') }
- }
+ confirm() {
+ this.$emit('confirm')
+ },
+ cancel() {
+ this.$emit('cancel')
+ },
+ },
}
export default Confirm
diff --git a/src/components/settings_modal/tabs/security_tab/mfa.js b/src/components/settings_modal/tabs/security_tab/mfa.js
index b24a35cd4..a998fdb4b 100644
--- a/src/components/settings_modal/tabs/security_tab/mfa.js
+++ b/src/components/settings_modal/tabs/security_tab/mfa.js
@@ -1,118 +1,130 @@
-import RecoveryCodes from './mfa_backup_codes.vue'
-import TOTP from './mfa_totp.vue'
-import Confirm from './confirm.vue'
import VueQrcode from '@chenfengyuan/vue-qrcode'
import { mapState } from 'vuex'
+import Confirm from './confirm.vue'
+import RecoveryCodes from './mfa_backup_codes.vue'
+import TOTP from './mfa_totp.vue'
+
const Mfa = {
data: () => ({
- settings: { // current settings of MFA
+ settings: {
+ // current settings of MFA
available: false,
enabled: false,
- totp: false
+ totp: false,
},
- setupState: { // setup mfa
+ setupState: {
+ // setup mfa
state: '', // state of setup. '' -> 'getBackupCodes' -> 'setupOTP' -> 'complete'
- setupOTPState: '' // state of setup otp. '' -> 'prepare' -> 'confirm' -> 'complete'
+ setupOTPState: '', // state of setup otp. '' -> 'prepare' -> 'confirm' -> 'complete'
},
backupCodes: {
getNewCodes: false,
inProgress: false, // progress of fetch codes
- codes: []
+ codes: [],
},
- otpSettings: { // pre-setup setting of OTP. secret key, qrcode url.
+ otpSettings: {
+ // pre-setup setting of OTP. secret key, qrcode url.
provisioning_uri: '',
- key: ''
+ key: '',
},
currentPassword: null,
otpConfirmToken: null,
error: null,
- readyInit: false
+ readyInit: false,
}),
components: {
'recovery-codes': RecoveryCodes,
'totp-item': TOTP,
qrcode: VueQrcode,
- confirm: Confirm
+ confirm: Confirm,
},
computed: {
- canSetupOTP () {
+ canSetupOTP() {
return (
- (this.setupInProgress && this.backupCodesPrepared) ||
- this.settings.enabled
- ) && !this.settings.totp && !this.setupOTPInProgress
+ ((this.setupInProgress && this.backupCodesPrepared) ||
+ this.settings.enabled) &&
+ !this.settings.totp &&
+ !this.setupOTPInProgress
+ )
},
- setupInProgress () {
- return this.setupState.state !== '' && this.setupState.state !== 'complete'
+ setupInProgress() {
+ return (
+ this.setupState.state !== '' && this.setupState.state !== 'complete'
+ )
},
- setupOTPInProgress () {
+ setupOTPInProgress() {
return this.setupState.state === 'setupOTP' && !this.completedOTP
},
- prepareOTP () {
+ prepareOTP() {
return this.setupState.setupOTPState === 'prepare'
},
- confirmOTP () {
+ confirmOTP() {
return this.setupState.setupOTPState === 'confirm'
},
- completedOTP () {
+ completedOTP() {
return this.setupState.setupOTPState === 'completed'
},
- backupCodesPrepared () {
+ backupCodesPrepared() {
return !this.backupCodes.inProgress && this.backupCodes.codes.length > 0
},
- confirmNewBackupCodes () {
+ confirmNewBackupCodes() {
return this.backupCodes.getNewCodes
},
...mapState({
- backendInteractor: (state) => state.api.backendInteractor
- })
+ backendInteractor: (state) => state.api.backendInteractor,
+ }),
},
methods: {
- activateOTP () {
+ activateOTP() {
if (!this.settings.enabled) {
this.setupState.state = 'getBackupcodes'
this.fetchBackupCodes()
}
},
- fetchBackupCodes () {
+ fetchBackupCodes() {
this.backupCodes.inProgress = true
this.backupCodes.codes = []
- return this.backendInteractor.generateMfaBackupCodes()
- .then((res) => {
- this.backupCodes.codes = res.codes
- this.backupCodes.inProgress = false
- })
+ return this.backendInteractor.generateMfaBackupCodes().then((res) => {
+ this.backupCodes.codes = res.codes
+ this.backupCodes.inProgress = false
+ })
},
- getBackupCodes () { // get a new backup codes
+ getBackupCodes() {
+ // get a new backup codes
this.backupCodes.getNewCodes = true
},
- confirmBackupCodes () { // confirm getting new backup codes
+ confirmBackupCodes() {
+ // confirm getting new backup codes
this.fetchBackupCodes().then(() => {
this.backupCodes.getNewCodes = false
})
},
- cancelBackupCodes () { // cancel confirm form of new backup codes
+ cancelBackupCodes() {
+ // cancel confirm form of new backup codes
this.backupCodes.getNewCodes = false
},
// Setup OTP
- setupOTP () { // prepare setup OTP
+ setupOTP() {
+ // prepare setup OTP
this.setupState.state = 'setupOTP'
this.setupState.setupOTPState = 'prepare'
- this.backendInteractor.mfaSetupOTP()
- .then((res) => {
- this.otpSettings = res
- this.setupState.setupOTPState = 'confirm'
- })
- },
- doConfirmOTP () { // handler confirm enable OTP
- this.error = null
- this.backendInteractor.mfaConfirmOTP({
- token: this.otpConfirmToken,
- password: this.currentPassword
+ this.backendInteractor.mfaSetupOTP().then((res) => {
+ this.otpSettings = res
+ this.setupState.setupOTPState = 'confirm'
})
+ },
+ doConfirmOTP() {
+ // handler confirm enable OTP
+ this.error = null
+ this.backendInteractor
+ .mfaConfirmOTP({
+ token: this.otpConfirmToken,
+ password: this.currentPassword,
+ })
.then((res) => {
if (res.error) {
this.error = res.error
@@ -122,14 +134,15 @@ const Mfa = {
})
},
- completeSetup () {
+ completeSetup() {
this.setupState.setupOTPState = 'complete'
this.setupState.state = 'complete'
this.currentPassword = null
this.error = null
this.fetchSettings()
},
- cancelSetup () { // cancel setup
+ cancelSetup() {
+ // cancel setup
this.setupState.setupOTPState = ''
this.setupState.state = ''
this.currentPassword = null
@@ -138,18 +151,18 @@ const Mfa = {
// end Setup OTP
// fetch settings from server
- async fetchSettings () {
+ async fetchSettings() {
const result = await this.backendInteractor.settingsMFA()
if (result.error) return
this.settings = result.settings
this.settings.available = true
return result
- }
+ },
},
- mounted () {
+ mounted() {
this.fetchSettings().then(() => {
this.readyInit = true
})
- }
+ },
}
export default Mfa
diff --git a/src/components/settings_modal/tabs/security_tab/mfa_backup_codes.js b/src/components/settings_modal/tabs/security_tab/mfa_backup_codes.js
index f0a984ecd..ad47bfdb7 100644
--- a/src/components/settings_modal/tabs/security_tab/mfa_backup_codes.js
+++ b/src/components/settings_modal/tabs/security_tab/mfa_backup_codes.js
@@ -4,14 +4,22 @@ export default {
type: Object,
default: () => ({
inProgress: false,
- codes: []
- })
- }
+ codes: [],
+ }),
+ },
},
- data: () => ({}),
+ data: () => ({
+ /* no-op */
+ }),
computed: {
- inProgress () { return this.backupCodes.inProgress },
- ready () { return this.backupCodes.codes.length > 0 },
- displayTitle () { return this.inProgress || this.ready }
- }
+ inProgress() {
+ return this.backupCodes.inProgress
+ },
+ ready() {
+ return this.backupCodes.codes.length > 0
+ },
+ displayTitle() {
+ return this.inProgress || this.ready
+ },
+ },
}
diff --git a/src/components/settings_modal/tabs/security_tab/mfa_totp.js b/src/components/settings_modal/tabs/security_tab/mfa_totp.js
index b0adb530d..e011fd638 100644
--- a/src/components/settings_modal/tabs/security_tab/mfa_totp.js
+++ b/src/components/settings_modal/tabs/security_tab/mfa_totp.js
@@ -1,40 +1,45 @@
-import Confirm from './confirm.vue'
import { mapState } from 'vuex'
+import Confirm from './confirm.vue'
+
export default {
props: ['settings'],
data: () => ({
error: false,
currentPassword: '',
deactivate: false,
- inProgress: false // progress peform request to disable otp method
+ inProgress: false, // progress peform request to disable otp method
}),
components: {
- confirm: Confirm
+ confirm: Confirm,
},
computed: {
- isActivated () {
+ isActivated() {
return this.settings.totp
},
...mapState({
- backendInteractor: (state) => state.api.backendInteractor
- })
+ backendInteractor: (state) => state.api.backendInteractor,
+ }),
},
methods: {
- doActivate () {
+ doActivate() {
this.$emit('activate')
},
- cancelDeactivate () { this.deactivate = false },
- doDeactivate () {
+ cancelDeactivate() {
+ this.deactivate = false
+ },
+ doDeactivate() {
this.error = null
this.deactivate = true
},
- confirmDeactivate () { // confirm deactivate TOTP method
+ confirmDeactivate() {
+ // confirm deactivate TOTP method
this.error = null
this.inProgress = true
- this.backendInteractor.mfaDisableOTP({
- password: this.currentPassword
- })
+ this.backendInteractor
+ .mfaDisableOTP({
+ password: this.currentPassword,
+ })
.then((res) => {
this.inProgress = false
if (res.error) {
@@ -44,6 +49,6 @@ export default {
this.deactivate = false
this.$emit('deactivate')
})
- }
- }
+ },
+ },
}
diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.js b/src/components/settings_modal/tabs/security_tab/security_tab.js
index 04e0328cd..3bc02829a 100644
--- a/src/components/settings_modal/tabs/security_tab/security_tab.js
+++ b/src/components/settings_modal/tabs/security_tab/security_tab.js
@@ -1,11 +1,11 @@
-import ProgressButton from 'src/components/progress_button/progress_button.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
-import Mfa from './mfa.vue'
+import ProgressButton from 'src/components/progress_button/progress_button.vue'
import localeService from 'src/services/locale/locale.service.js'
import { useOAuthTokensStore } from 'src/stores/oauth_tokens'
+import Mfa from './mfa.vue'
const SecurityTab = {
- data () {
+ data() {
return {
newEmail: '',
changeEmailError: false,
@@ -25,41 +25,44 @@ const SecurityTab = {
listAliasesError: false,
addAliasTarget: '',
addedAlias: false,
- addAliasError: false
+ addAliasError: false,
}
},
- created () {
+ created() {
useOAuthTokensStore().fetchTokens()
this.fetchAliases()
},
components: {
ProgressButton,
Mfa,
- Checkbox
+ Checkbox,
},
computed: {
- user () {
+ user() {
return this.$store.state.users.currentUser
},
- pleromaExtensionsAvailable () {
+ pleromaExtensionsAvailable() {
return this.$store.state.instance.pleromaExtensionsAvailable
},
- oauthTokens () {
- return useOAuthTokensStore().tokens.map(oauthToken => {
+ oauthTokens() {
+ return useOAuthTokensStore().tokens.map((oauthToken) => {
return {
id: oauthToken.id,
appName: oauthToken.app_name,
- validUntil: new Date(oauthToken.valid_until).toLocaleDateString(localeService.internalToBrowserLocale(this.$i18n.locale))
+ validUntil: new Date(oauthToken.valid_until).toLocaleDateString(
+ localeService.internalToBrowserLocale(this.$i18n.locale),
+ ),
}
})
- }
+ },
},
methods: {
- confirmDelete () {
+ confirmDelete() {
this.deletingAccount = true
},
- deleteAccount () {
- this.$store.state.api.backendInteractor.deleteAccount({ password: this.deleteAccountConfirmPasswordInput })
+ deleteAccount() {
+ this.$store.state.api.backendInteractor
+ .deleteAccount({ password: this.deleteAccountConfirmPasswordInput })
.then((res) => {
if (res.status === 'success') {
this.$store.dispatch('logout')
@@ -69,13 +72,14 @@ const SecurityTab = {
}
})
},
- changePassword () {
+ changePassword() {
const params = {
password: this.changePasswordInputs[0],
newPassword: this.changePasswordInputs[1],
- newPasswordConfirmation: this.changePasswordInputs[2]
+ newPasswordConfirmation: this.changePasswordInputs[2],
}
- this.$store.state.api.backendInteractor.changePassword(params)
+ this.$store.state.api.backendInteractor
+ .changePassword(params)
.then((res) => {
if (res.status === 'success') {
this.changedPassword = true
@@ -87,12 +91,13 @@ const SecurityTab = {
}
})
},
- changeEmail () {
+ changeEmail() {
const params = {
email: this.newEmail,
- password: this.changeEmailPassword
+ password: this.changeEmailPassword,
}
- this.$store.state.api.backendInteractor.changeEmail(params)
+ this.$store.state.api.backendInteractor
+ .changeEmail(params)
.then((res) => {
if (res.status === 'success') {
this.changedEmail = true
@@ -103,12 +108,13 @@ const SecurityTab = {
}
})
},
- moveAccount () {
+ moveAccount() {
const params = {
targetAccount: this.moveAccountTarget,
- password: this.moveAccountPassword
+ password: this.moveAccountPassword,
}
- this.$store.state.api.backendInteractor.moveAccount(params)
+ this.$store.state.api.backendInteractor
+ .moveAccount(params)
.then((res) => {
if (res.status === 'success') {
this.movedAccount = true
@@ -119,12 +125,14 @@ const SecurityTab = {
}
})
},
- removeAlias (alias) {
- this.$store.state.api.backendInteractor.deleteAlias({ alias })
+ removeAlias(alias) {
+ this.$store.state.api.backendInteractor
+ .deleteAlias({ alias })
.then(() => this.fetchAliases())
},
- addAlias () {
- this.$store.state.api.backendInteractor.addAlias({ alias: this.addAliasTarget })
+ addAlias() {
+ this.$store.state.api.backendInteractor
+ .addAlias({ alias: this.addAliasTarget })
.then(() => {
this.addedAlias = true
this.addAliasError = false
@@ -136,8 +144,9 @@ const SecurityTab = {
})
.then(() => this.fetchAliases())
},
- fetchAliases () {
- this.$store.state.api.backendInteractor.listAliases()
+ fetchAliases() {
+ this.$store.state.api.backendInteractor
+ .listAliases()
.then((res) => {
this.aliases = res.aliases
this.listAliasesError = false
@@ -146,16 +155,16 @@ const SecurityTab = {
this.listAliasesError = error.error
})
},
- logout () {
+ logout() {
this.$store.dispatch('logout')
this.$router.replace('/')
},
- revokeToken (id) {
+ revokeToken(id) {
if (window.confirm(`${this.$i18n.t('settings.revoke_token')}?`)) {
useOAuthTokensStore().revokeToken(id)
}
- }
- }
+ },
+ },
}
export default SecurityTab
diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.js b/src/components/settings_modal/tabs/style_tab/style_tab.js
index 35626a103..7fa55761a 100644
--- a/src/components/settings_modal/tabs/style_tab/style_tab.js
+++ b/src/components/settings_modal/tabs/style_tab/style_tab.js
@@ -1,62 +1,70 @@
-import { ref, reactive, computed, watch, provide, getCurrentInstance } from 'vue'
-import { useInterfaceStore } from 'src/stores/interface'
-import { get, set, unset, throttle } from 'lodash'
+import { get, set, throttle, unset } from 'lodash'
+import {
+ computed,
+ getCurrentInstance,
+ provide,
+ reactive,
+ ref,
+ watch,
+} from 'vue'
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+import ColorInput from 'src/components/color_input/color_input.vue'
+import ComponentPreview from 'src/components/component_preview/component_preview.vue'
+import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
+import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
+import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
+import RoundnessInput from 'src/components/roundness_input/roundness_input.vue'
import Select from 'src/components/select/select.vue'
import SelectMotion from 'src/components/select/select_motion.vue'
-import Checkbox from 'src/components/checkbox/checkbox.vue'
-import ComponentPreview from 'src/components/component_preview/component_preview.vue'
-import StringSetting from '../../helpers/string_setting.vue'
import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
-import ColorInput from 'src/components/color_input/color_input.vue'
-import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
-import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
-import RoundnessInput from 'src/components/roundness_input/roundness_input.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import Tooltip from 'src/components/tooltip/tooltip.vue'
-import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
-import Preview from '../old_theme_tab/theme_preview.vue'
-
-import VirtualDirectivesTab from './virtual_directives_tab.vue'
-
-import { createStyleSheet, adoptStyleSheets } from 'src/services/style_setter/style_setter.js'
-import { init, findColor } from 'src/services/theme_data/theme_data_3.service.js'
-import { getCssRules } from 'src/services/theme_data/css_utils.js'
-import { serialize } from 'src/services/theme_data/iss_serializer.js'
-import { deserializeShadow, deserialize } from 'src/services/theme_data/iss_deserializer.js'
import {
- rgb2hex,
+ getContrastRatio,
hex2rgb,
- getContrastRatio
+ rgb2hex,
} from 'src/services/color_convert/color_convert.js'
import {
+ newExporter,
newImporter,
- newExporter
} from 'src/services/export_import/export_import.js'
+import {
+ adoptStyleSheets,
+ createStyleSheet,
+} from 'src/services/style_setter/style_setter.js'
+import { getCssRules } from 'src/services/theme_data/css_utils.js'
+import {
+ deserialize,
+ deserializeShadow,
+} from 'src/services/theme_data/iss_deserializer.js'
+import { serialize } from 'src/services/theme_data/iss_serializer.js'
+import {
+ findColor,
+ init,
+} from 'src/services/theme_data/theme_data_3.service.js'
+import { useInterfaceStore } from 'src/stores/interface'
+import StringSetting from '../../helpers/string_setting.vue'
+import Preview from '../old_theme_tab/theme_preview.vue'
+import VirtualDirectivesTab from './virtual_directives_tab.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
+ faArrowsRotate,
+ faCheck,
+ faFile,
faFloppyDisk,
faFolderOpen,
- faFile,
- faArrowsRotate,
- faCheck
} from '@fortawesome/free-solid-svg-icons'
// helper for debugging
-// eslint-disable-next-line no-unused-vars
-const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
+// const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
// helper to make states comparable
-const normalizeStates = (states) => ['normal', ...(states?.filter(x => x !== 'normal') || [])].join(':')
+const normalizeStates = (states) =>
+ ['normal', ...(states?.filter((x) => x !== 'normal') || [])].join(':')
-library.add(
- faFile,
- faFloppyDisk,
- faFolderOpen,
- faArrowsRotate,
- faCheck
-)
+library.add(faFile, faFloppyDisk, faFolderOpen, faArrowsRotate, faCheck)
export default {
components: {
@@ -74,18 +82,22 @@ export default {
RoundnessInput,
ContrastRatio,
Preview,
- VirtualDirectivesTab
+ VirtualDirectivesTab,
},
- setup () {
+ setup() {
const exports = {}
const interfaceStore = useInterfaceStore()
// All rules that are made by editor
const allEditedRules = ref(interfaceStore.styleDataUsed || {})
const styleDataUsed = computed(() => interfaceStore.styleDataUsed)
- watch([styleDataUsed], () => {
- onImport(interfaceStore.styleDataUsed)
- }, { once: true })
+ watch(
+ [styleDataUsed],
+ () => {
+ onImport(interfaceStore.styleDataUsed)
+ },
+ { once: true },
+ )
exports.isActive = computed(() => {
const tabSwitcher = getCurrentInstance().parent.ctx
@@ -105,7 +117,7 @@ export default {
` author: ${exports.author.value};`,
` license: ${exports.license.value};`,
` website: ${exports.website.value};`,
- '}'
+ '}',
].join('\n')
})
@@ -115,8 +127,8 @@ export default {
name: exports.name.value,
author: exports.author.value,
license: exports.license.value,
- website: exports.website.value
- }
+ website: exports.website.value,
+ },
}))
// ## Palette stuff
@@ -131,7 +143,7 @@ export default {
cRed: '#FF0000',
cBlue: '#0095ff',
cGreen: '#0fa00f',
- cOrange: '#ffa500'
+ cOrange: '#ffa500',
},
{
name: 'light',
@@ -144,8 +156,8 @@ export default {
cRed: '#d31014',
cGreen: '#0fa00f',
cOrange: '#ffa500',
- border: '#d8e6f9'
- }
+ border: '#d8e6f9',
+ },
])
exports.palettes = palettes
@@ -163,12 +175,12 @@ export default {
const selectedPaletteId = ref(0)
const selectedPalette = computed({
- get () {
+ get() {
return palettes[selectedPaletteId.value]
},
- set (newPalette) {
+ set(newPalette) {
palettes[selectedPaletteId.value] = newPalette
- }
+ },
})
exports.selectedPaletteId = selectedPaletteId
exports.selectedPalette = selectedPalette
@@ -186,49 +198,50 @@ export default {
cRed: '#FF0000',
cBlue: '#0095ff',
cGreen: '#0fa00f',
- cOrange: '#ffa500'
+ cOrange: '#ffa500',
})
// Raw format
const palettesRule = computed(() => {
- return palettes.map(palette => {
+ return palettes.map((palette) => {
const { name, ...rest } = palette
return {
component: '@palette',
variant: name,
- directives: Object
- .entries(rest)
+ directives: Object.entries(rest)
.filter(([k, v]) => v && k)
- .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {})
+ .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}),
}
})
})
// Text format
const palettesOut = computed(() => {
- return palettes.map(({ name, ...palette }) => {
- const entries = Object
- .entries(palette)
- .filter(([k, v]) => v && k)
- .map(([slot, data]) => ` ${slot}: ${data};`)
- .join('\n')
+ return palettes
+ .map(({ name, ...palette }) => {
+ const entries = Object.entries(palette)
+ .filter(([k, v]) => v && k)
+ .map(([slot, data]) => ` ${slot}: ${data};`)
+ .join('\n')
- return `@palette.${name} {\n${entries}\n}`
- }).join('\n\n')
+ return `@palette.${name} {\n${entries}\n}`
+ })
+ .join('\n\n')
})
// ## Components stuff
// Getting existing components
const componentsContext = import.meta.glob(
['/src/**/*.style.js', '/src/**/*.style.json'],
- { eager: true }
+ { eager: true },
)
const componentKeysAll = Object.keys(componentsContext)
const componentsMap = new Map(
componentKeysAll
- .map(
- key => [key, componentsContext[key].default]
- ).filter(([, component]) => !component.virtual && !component.notEditable)
+ .map((key) => [key, componentsContext[key].default])
+ .filter(
+ ([, component]) => !component.virtual && !component.notEditable,
+ ),
)
exports.componentsMap = componentsMap
const componentKeys = [...componentsMap.keys()]
@@ -238,16 +251,24 @@ export default {
const selectedComponentKey = ref(componentsMap.keys().next().value)
exports.selectedComponentKey = selectedComponentKey
- const selectedComponent = computed(() => componentsMap.get(selectedComponentKey.value))
+ const selectedComponent = computed(() =>
+ componentsMap.get(selectedComponentKey.value),
+ )
const selectedComponentName = computed(() => selectedComponent.value.name)
// Selection basis
exports.selectedComponentVariants = computed(() => {
- return Object.keys({ normal: null, ...(selectedComponent.value.variants || {}) })
+ return Object.keys({
+ normal: null,
+ ...(selectedComponent.value.variants || {}),
+ })
})
exports.selectedComponentStates = computed(() => {
- const all = Object.keys({ normal: null, ...(selectedComponent.value.states || {}) })
- return all.filter(x => x !== 'normal')
+ const all = Object.keys({
+ normal: null,
+ ...(selectedComponent.value.states || {}),
+ })
+ return all.filter((x) => x !== 'normal')
})
// selection
@@ -269,51 +290,49 @@ export default {
selectedState.clear()
}
- watch(
- selectedComponentName,
- updateSelectedComponent
- )
+ watch(selectedComponentName, updateSelectedComponent)
// ### Rules stuff aka meat and potatoes
// The native structure of separate rules and the child -> parent
// relation isn't very convenient for editor, we replace the array
// and child -> parent structure with map and parent -> child structure
- const rulesToEditorFriendly = (rules, root = {}) => rules.reduce((acc, rule) => {
- const { parent: rParent, component: rComponent } = rule
- const parent = rParent ?? rule
- const hasChildren = !!rParent
- const child = hasChildren ? rule : null
+ const rulesToEditorFriendly = (rules, root = {}) =>
+ rules.reduce((acc, rule) => {
+ const { parent: rParent, component: rComponent } = rule
+ const parent = rParent ?? rule
+ const hasChildren = !!rParent
+ const child = hasChildren ? rule : null
- const {
- component: pComponent,
- variant: pVariant = 'normal',
- state: pState = [] // no relation to Intel CPUs whatsoever
- } = parent
-
- const pPath = `${hasChildren ? pComponent : rComponent}.${pVariant}.${normalizeStates(pState)}`
-
- let output = get(acc, pPath)
- if (!output) {
- set(acc, pPath, {})
- output = get(acc, pPath)
- }
-
- if (hasChildren) {
- output._children = output._children ?? {}
const {
- component: cComponent,
- variant: cVariant = 'normal',
- state: cState = [],
- directives
- } = child
+ component: pComponent,
+ variant: pVariant = 'normal',
+ state: pState = [], // no relation to Intel CPUs whatsoever
+ } = parent
- const cPath = `${cComponent}.${cVariant}.${normalizeStates(cState)}`
- set(output._children, cPath, { directives })
- } else {
- output.directives = parent.directives
- }
- return acc
- }, root)
+ const pPath = `${hasChildren ? pComponent : rComponent}.${pVariant}.${normalizeStates(pState)}`
+
+ let output = get(acc, pPath)
+ if (!output) {
+ set(acc, pPath, {})
+ output = get(acc, pPath)
+ }
+
+ if (hasChildren) {
+ output._children = output._children ?? {}
+ const {
+ component: cComponent,
+ variant: cVariant = 'normal',
+ state: cState = [],
+ directives,
+ } = child
+
+ const cPath = `${cComponent}.${cVariant}.${normalizeStates(cState)}`
+ set(output._children, cPath, { directives })
+ } else {
+ output.directives = parent.directives
+ }
+ return acc
+ }, root)
const editorFriendlyFallbackStructure = computed(() => {
const root = {}
@@ -323,7 +342,7 @@ export default {
const { defaultRules, name } = componentValue
rulesToEditorFriendly(
defaultRules.map((rule) => ({ ...rule, component: name })),
- root
+ root,
)
})
@@ -333,79 +352,111 @@ export default {
// Checking whether component can support some "directives" which
// are actually virtual subcomponents, i.e. Text, Link etc
exports.componentHas = (subComponent) => {
- return !!selectedComponent.value.validInnerComponents?.find(x => x === subComponent)
+ return !!selectedComponent.value.validInnerComponents?.find(
+ (x) => x === subComponent,
+ )
}
// Path for lodash's get and set
const getPath = (component, directive) => {
- const pathSuffix = component ? `._children.${component}.normal.normal` : ''
+ const pathSuffix = component
+ ? `._children.${component}.normal.normal`
+ : ''
const path = `${selectedComponentName.value}.${selectedVariant.value}.${normalizeStates([...selectedState])}${pathSuffix}.directives.${directive}`
return path
}
// Templates for directives
- const isElementPresent = (component, directive, defaultValue = '') => computed({
- get () {
- return get(allEditedRules.value, getPath(component, directive)) != null
- },
- set (value) {
- if (value) {
- const fallback = get(
- editorFriendlyFallbackStructure.value,
- getPath(component, directive)
+ const isElementPresent = (component, directive, defaultValue = '') =>
+ computed({
+ get() {
+ return (
+ get(allEditedRules.value, getPath(component, directive)) != null
)
- set(allEditedRules.value, getPath(component, directive), fallback ?? defaultValue)
- } else {
- unset(allEditedRules.value, getPath(component, directive))
- }
- exports.updateOverallPreview()
- }
- })
+ },
+ set(value) {
+ if (value) {
+ const fallback = get(
+ editorFriendlyFallbackStructure.value,
+ getPath(component, directive),
+ )
+ set(
+ allEditedRules.value,
+ getPath(component, directive),
+ fallback ?? defaultValue,
+ )
+ } else {
+ unset(allEditedRules.value, getPath(component, directive))
+ }
+ exports.updateOverallPreview()
+ },
+ })
- const getEditedElement = (component, directive, postProcess = x => x) => computed({
- get () {
- let usedRule
- const fallback = editorFriendlyFallbackStructure.value
- const real = allEditedRules.value
- const path = getPath(component, directive)
+ const getEditedElement = (component, directive, postProcess = (x) => x) =>
+ computed({
+ get() {
+ let usedRule
+ const fallback = editorFriendlyFallbackStructure.value
+ const real = allEditedRules.value
+ const path = getPath(component, directive)
- usedRule = get(real, path) // get real
- if (usedRule === '') {
- return usedRule
- }
- if (!usedRule) {
- usedRule = get(fallback, path)
- }
+ usedRule = get(real, path) // get real
+ if (usedRule === '') {
+ return usedRule
+ }
+ if (!usedRule) {
+ usedRule = get(fallback, path)
+ }
- return postProcess(usedRule)
- },
- set (value) {
- if (value != null) {
- set(allEditedRules.value, getPath(component, directive), value)
- } else {
- unset(allEditedRules.value, getPath(component, directive))
- }
- exports.updateOverallPreview()
- }
- })
+ return postProcess(usedRule)
+ },
+ set(value) {
+ if (value != null) {
+ set(allEditedRules.value, getPath(component, directive), value)
+ } else {
+ unset(allEditedRules.value, getPath(component, directive))
+ }
+ exports.updateOverallPreview()
+ },
+ })
// All the editable stuff for the component
exports.editedBackgroundColor = getEditedElement(null, 'background')
- exports.isBackgroundColorPresent = isElementPresent(null, 'background', '#FFFFFF')
+ exports.isBackgroundColorPresent = isElementPresent(
+ null,
+ 'background',
+ '#FFFFFF',
+ )
exports.editedOpacity = getEditedElement(null, 'opacity')
exports.isOpacityPresent = isElementPresent(null, 'opacity', 1)
exports.editedRoundness = getEditedElement(null, 'roundness')
exports.isRoundnessPresent = isElementPresent(null, 'roundness', '0')
exports.editedTextColor = getEditedElement('Text', 'textColor')
- exports.isTextColorPresent = isElementPresent('Text', 'textColor', '#000000')
+ exports.isTextColorPresent = isElementPresent(
+ 'Text',
+ 'textColor',
+ '#000000',
+ )
exports.editedTextAuto = getEditedElement('Text', 'textAuto')
exports.isTextAutoPresent = isElementPresent('Text', 'textAuto', '#000000')
exports.editedLinkColor = getEditedElement('Link', 'textColor')
- exports.isLinkColorPresent = isElementPresent('Link', 'textColor', '#000080')
+ exports.isLinkColorPresent = isElementPresent(
+ 'Link',
+ 'textColor',
+ '#000080',
+ )
exports.editedIconColor = getEditedElement('Icon', 'textColor')
- exports.isIconColorPresent = isElementPresent('Icon', 'textColor', '#909090')
+ exports.isIconColorPresent = isElementPresent(
+ 'Icon',
+ 'textColor',
+ '#909090',
+ )
exports.editedBorderColor = getEditedElement('Border', 'textColor')
- exports.isBorderColorPresent = isElementPresent('Border', 'textColor', '#909090')
+ exports.isBorderColorPresent = isElementPresent(
+ 'Border',
+ 'textColor',
+ '#909090',
+ )
const getContrast = (bg, text) => {
try {
@@ -422,7 +473,7 @@ export default {
aaa: ratio >= 7,
// same but for 18pt+ texts
laa: ratio >= 3,
- laaa: ratio >= 4.5
+ laaa: ratio >= 4.5,
}
} catch (e) {
console.warn('Failure computing contrast', e)
@@ -431,7 +482,7 @@ export default {
}
const normalizeShadows = (shadows) => {
- return shadows?.map(shadow => {
+ return shadows?.map((shadow) => {
if (typeof shadow === 'object') {
return shadow
}
@@ -455,7 +506,8 @@ export default {
const editedSubShadowId = ref(null)
exports.editedSubShadowId = editedSubShadowId
const editedSubShadow = computed(() => {
- if (editedShadow.value == null || editedSubShadowId.value == null) return null
+ if (editedShadow.value == null || editedSubShadowId.value == null)
+ return null
return editedShadow.value[editedSubShadowId.value]
})
exports.editedSubShadow = editedSubShadow
@@ -473,7 +525,7 @@ export default {
newEditedShadow[editedSubShadowId.value] = {
...newEditedShadow[editedSubShadowId.value],
- [axis]: value
+ [axis]: value,
}
editedShadow.value = newEditedShadow
@@ -513,12 +565,12 @@ export default {
component,
variant,
state,
- directives: stateData.directives || {}
+ directives: stateData.directives || {},
}
if (parent) {
result.parent = {
- component: parent
+ component: parent,
}
}
@@ -526,13 +578,15 @@ export default {
// Currently we only support single depth for simplicity's sake
if (!parent) {
- Object.entries(stateData._children || {}).forEach(([cName, child]) => convert(cName, child, component))
+ Object.entries(stateData._children || {}).forEach(
+ ([cName, child]) => convert(cName, child, component),
+ )
}
})
})
}
- [...componentsMap.values()].forEach(({ name }) => {
+ ;[...componentsMap.values()].forEach(({ name }) => {
convert(name, allEditedRules.value[name])
})
@@ -540,21 +594,20 @@ export default {
})
const allCustomVirtualDirectives = [...componentsMap.values()]
- .map(c => {
- return c
- .defaultRules
- .filter(c => c.component === 'Root')
- .map(x => Object.entries(x.directives))
+ .map((c) => {
+ return c.defaultRules
+ .filter((c) => c.component === 'Root')
+ .map((x) => Object.entries(x.directives))
.flat()
})
- .filter(x => x)
+ .filter((x) => x)
.flat()
.map(([name, value]) => {
const [valType, valVal] = value.split('|')
return {
name: name.substring(2),
valType: valType?.trim(),
- value: valVal?.trim()
+ value: valVal?.trim(),
}
})
@@ -568,8 +621,11 @@ export default {
const virtualDirectivesRule = computed(() => ({
component: 'Root',
directives: Object.fromEntries(
- virtualDirectives.value.map(vd => [`--${vd.name}`, `${vd.valType} | ${vd.value}`])
- )
+ virtualDirectives.value.map((vd) => [
+ `--${vd.name}`,
+ `${vd.valType} | ${vd.value}`,
+ ]),
+ ),
}))
// Text format
@@ -577,16 +633,19 @@ export default {
return [
'Root {',
...virtualDirectives.value
- .filter(vd => vd.name && vd.valType && vd.value)
- .map(vd => ` --${vd.name}: ${vd.valType} | ${vd.value};`),
- '}'
+ .filter((vd) => vd.name && vd.valType && vd.value)
+ .map((vd) => ` --${vd.name}: ${vd.valType} | ${vd.value};`),
+ '}',
].join('\n')
})
exports.computeColor = (color) => {
let computedColor
try {
- computedColor = findColor(color, { dynamicVars: dynamicVars.value, staticVars: staticVars.value })
+ computedColor = findColor(color, {
+ dynamicVars: dynamicVars.value,
+ staticVars: staticVars.value,
+ })
if (computedColor) {
return rgb2hex(computedColor)
}
@@ -600,7 +659,7 @@ export default {
exports.contrast = computed(() => {
return getContrast(
exports.computeColor(previewColors.value.background),
- exports.computeColor(previewColors.value.text)
+ exports.computeColor(previewColors.value.text),
)
})
@@ -609,30 +668,38 @@ export default {
filename: () => exports.name.value ?? 'pleroma_theme',
mime: 'text/plain',
extension: 'iss',
- getExportedObject: () => exportStyleData.value
+ getExportedObject: () => exportStyleData.value,
})
- const onImport = parsed => {
- const editorComponents = parsed.filter(x => x.component.startsWith('@'))
- const rootComponent = parsed.find(x => x.component === 'Root')
- const rules = parsed.filter(x => !x.component.startsWith('@') && x.component !== 'Root')
- const metaIn = editorComponents.find(x => x.component === '@meta').directives
- const palettesIn = editorComponents.filter(x => x.component === '@palette')
+ const onImport = (parsed) => {
+ const editorComponents = parsed.filter((x) => x.component.startsWith('@'))
+ const rootComponent = parsed.find((x) => x.component === 'Root')
+ const rules = parsed.filter(
+ (x) => !x.component.startsWith('@') && x.component !== 'Root',
+ )
+ const metaIn = editorComponents.find(
+ (x) => x.component === '@meta',
+ ).directives
+ const palettesIn = editorComponents.filter(
+ (x) => x.component === '@palette',
+ )
exports.name.value = metaIn.name
exports.license.value = metaIn.license
exports.author.value = metaIn.author
exports.website.value = metaIn.website
- const newVirtualDirectives = Object
- .entries(rootComponent.directives)
- .map(([name, value]) => {
- const [valType, valVal] = value.split('|').map(x => x.trim())
+ const newVirtualDirectives = Object.entries(rootComponent.directives).map(
+ ([name, value]) => {
+ const [valType, valVal] = value.split('|').map((x) => x.trim())
return { name: name.substring(2), valType, value: valVal }
- })
+ },
+ )
virtualDirectives.value = newVirtualDirectives
- onPalettesUpdate(palettesIn.map(x => ({ name: x.variant, ...x.directives })))
+ onPalettesUpdate(
+ palettesIn.map((x) => ({ name: x.variant, ...x.directives })),
+ )
allEditedRules.value = rulesToEditorFriendly(rules)
@@ -641,12 +708,17 @@ export default {
const styleImporter = newImporter({
accept: '.iss',
- parser (string) { return deserialize(string) },
- onImportFailure (result) {
- console.error('Failure importing style:', result)
- useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_theme_imported', level: 'error' })
+ parser(string) {
+ return deserialize(string)
},
- onImport
+ onImportFailure(result) {
+ console.error('Failure importing style:', result)
+ useInterfaceStore().pushGlobalNotice({
+ messageKey: 'settings.invalid_theme_imported',
+ level: 'error',
+ })
+ },
+ onImport,
})
// Raw format
@@ -654,7 +726,7 @@ export default {
metaRule.value,
...palettesRule.value,
virtualDirectivesRule.value,
- ...editorFriendlyToOriginal.value
+ ...editorFriendlyToOriginal.value,
])
// Text format
@@ -663,7 +735,7 @@ export default {
metaOut.value,
palettesOut.value,
virtualDirectivesOut.value,
- serialize(editorFriendlyToOriginal.value)
+ serialize(editorFriendlyToOriginal.value),
].join('\n\n')
})
@@ -689,7 +761,9 @@ export default {
watch([overallPreviewRules], () => {
let css = null
try {
- css = getCssRules(overallPreviewRules.value).map(r => r.replace('html', '&'))
+ css = getCssRules(overallPreviewRules.value).map((r) =>
+ r.replace('html', '&'),
+ )
} catch (e) {
console.error(e)
return
@@ -698,11 +772,9 @@ export default {
const sheet = createStyleSheet('style-tab-overall-preview', 90)
sheet.clear()
- sheet.addRule([
- '#edited-style-preview {\n',
- css.join('\n'),
- '\n}'
- ].join(''))
+ sheet.addRule(
+ ['#edited-style-preview {\n', css.join('\n'), '\n}'].join(''),
+ )
sheet.ready = true
adoptStyleSheets()
})
@@ -715,15 +787,14 @@ export default {
{
component: 'Root',
directives: Object.fromEntries(
- Object
- .entries(selectedPalette.value)
+ Object.entries(selectedPalette.value)
.filter(([k, v]) => k && v && k !== 'name')
- .map(([k, v]) => [`--${k}`, `color | ${v}`])
- )
- }
+ .map(([k, v]) => [`--${k}`, `color | ${v}`]),
+ ),
+ },
],
ultimateBackgroundColor: '#000000',
- debug: true
+ debug: true,
}).eager
} catch (e) {
console.error('Could not compile preview theme', e)
@@ -733,30 +804,32 @@ export default {
//
// Apart from "hover" we can't really show how component looks like in
// certain states, so we have to fake them.
- const simulatePseudoSelectors = (css, prefix) => css
- .replace(prefix, '.preview-block')
- .replace(':active', '.preview-active')
- .replace(':hover', '.preview-hover')
- .replace(':active', '.preview-active')
- .replace(':focus', '.preview-focus')
- .replace(':focus-within', '.preview-focus-within')
- .replace(':disabled', '.preview-disabled')
+ const simulatePseudoSelectors = (css, prefix) =>
+ css
+ .replace(prefix, '.preview-block')
+ .replace(':active', '.preview-active')
+ .replace(':hover', '.preview-hover')
+ .replace(':active', '.preview-active')
+ .replace(':focus', '.preview-focus')
+ .replace(':focus-within', '.preview-focus-within')
+ .replace(':disabled', '.preview-disabled')
const previewRules = computed(() => {
- const filtered = overallPreviewRules.value.filter(r => {
+ const filtered = overallPreviewRules.value.filter((r) => {
const componentMatch = r.component === selectedComponentName.value
- const parentComponentMatch = r.parent?.component === selectedComponentName.value
+ const parentComponentMatch =
+ r.parent?.component === selectedComponentName.value
if (!componentMatch && !parentComponentMatch) return false
const rule = parentComponentMatch ? r.parent : r
if (rule.component !== selectedComponentName.value) return false
if (rule.variant !== selectedVariant.value) return false
- const ruleState = new Set(rule.state.filter(x => x !== 'normal'))
- const differenceA = [...ruleState].filter(x => !selectedState.has(x))
- const differenceB = [...selectedState].filter(x => !ruleState.has(x))
- return (differenceA.length + differenceB.length) === 0
+ const ruleState = new Set(rule.state.filter((x) => x !== 'normal'))
+ const differenceA = [...ruleState].filter((x) => !selectedState.has(x))
+ const differenceB = [...selectedState].filter((x) => !ruleState.has(x))
+ return differenceA.length + differenceB.length === 0
})
const sorted = [...filtered]
- .filter(x => x.component === selectedComponentName.value)
+ .filter((x) => x.component === selectedComponentName.value)
.sort((a, b) => {
const aSelectorLength = a.selector.split(/ /g).length
const bSelectorLength = b.selector.split(/ /g).length
@@ -765,27 +838,32 @@ export default {
const prefix = sorted[0].selector
- return filtered.filter(x => x.selector.startsWith(prefix))
+ return filtered.filter((x) => x.selector.startsWith(prefix))
})
exports.previewClass = computed(() => {
const selectors = []
- if (!!selectedComponent.value.variants?.normal || selectedVariant.value !== 'normal') {
+ if (
+ !!selectedComponent.value.variants?.normal ||
+ selectedVariant.value !== 'normal'
+ ) {
selectors.push(selectedComponent.value.variants[selectedVariant.value])
}
if (selectedState.size > 0) {
- selectedState.forEach(state => {
+ selectedState.forEach((state) => {
const original = selectedComponent.value.states[state]
selectors.push(simulatePseudoSelectors(original))
})
}
- return selectors.map(x => x.substring(1)).join('')
+ return selectors.map((x) => x.substring(1)).join('')
})
exports.previewCss = computed(() => {
try {
const prefix = previewRules.value[0].selector
- const scoped = getCssRules(previewRules.value).map(x => simulatePseudoSelectors(x, prefix))
+ const scoped = getCssRules(previewRules.value).map((x) =>
+ simulatePseudoSelectors(x, prefix),
+ )
return scoped.join('\n')
} catch (e) {
console.error('Invalid ruleset', e)
@@ -798,7 +876,7 @@ export default {
})
const staticVars = computed(() => {
- const rootComponent = overallPreviewRules.value.find(r => {
+ const rootComponent = overallPreviewRules.value.find((r) => {
return r.component === 'Root'
})
const rootDirectivesEntries = Object.entries(rootComponent.directives)
@@ -807,7 +885,10 @@ export default {
.filter(([k, v]) => k.startsWith('--') && v.startsWith('color | '))
.map(([k, v]) => [k.substring(2), v.substring('color | '.length)])
.forEach(([k, v]) => {
- directives[k] = findColor(v, { dynamicVars: {}, staticVars: directives })
+ directives[k] = findColor(v, {
+ dynamicVars: {},
+ staticVars: directives,
+ })
})
return directives
})
@@ -816,13 +897,18 @@ export default {
const previewColors = computed(() => {
const stacked = dynamicVars.value.stacked
- const background = typeof stacked === 'string' ? stacked : rgb2hex(stacked)
+ const background =
+ typeof stacked === 'string' ? stacked : rgb2hex(stacked)
return {
- text: previewRules.value.find(r => r.component === 'Text')?.virtualDirectives['--text'],
- link: previewRules.value.find(r => r.component === 'Link')?.virtualDirectives['--link'],
- border: previewRules.value.find(r => r.component === 'Border')?.virtualDirectives['--border'],
- icon: previewRules.value.find(r => r.component === 'Icon')?.virtualDirectives['--icon'],
- background
+ text: previewRules.value.find((r) => r.component === 'Text')
+ ?.virtualDirectives['--text'],
+ link: previewRules.value.find((r) => r.component === 'Link')
+ ?.virtualDirectives['--link'],
+ border: previewRules.value.find((r) => r.component === 'Border')
+ ?.virtualDirectives['--border'],
+ icon: previewRules.value.find((r) => r.component === 'Icon')
+ ?.virtualDirectives['--icon'],
+ background,
}
})
exports.previewColors = previewColors
@@ -836,11 +922,11 @@ export default {
palettes,
selectedPalette,
selectedState,
- selectedVariant
+ selectedVariant,
],
- updateOverallPreview
+ updateOverallPreview,
)
return exports
- }
+ },
}
diff --git a/src/components/settings_modal/tabs/style_tab/virtual_directives_tab.js b/src/components/settings_modal/tabs/style_tab/virtual_directives_tab.js
index d98dea615..d52c0084c 100644
--- a/src/components/settings_modal/tabs/style_tab/virtual_directives_tab.js
+++ b/src/components/settings_modal/tabs/style_tab/virtual_directives_tab.js
@@ -1,26 +1,24 @@
-import { ref, computed, watch, inject } from 'vue'
+import { computed, inject, ref, watch } from 'vue'
+import ColorInput from 'src/components/color_input/color_input.vue'
import Select from 'src/components/select/select.vue'
import SelectMotion from 'src/components/select/select_motion.vue'
import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
-import ColorInput from 'src/components/color_input/color_input.vue'
-
import { serializeShadow } from 'src/services/theme_data/iss_serializer.js'
// helper for debugging
-// eslint-disable-next-line no-unused-vars
-const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
+// const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
export default {
components: {
Select,
SelectMotion,
ShadowControl,
- ColorInput
+ ColorInput,
},
props: ['modelValue'],
emits: ['update:modelValue'],
- setup (props, context) {
+ setup(props, context) {
const exports = {}
const emit = context.emit
@@ -32,23 +30,23 @@ export default {
exports.selectedVirtualDirectiveId = selectedVirtualDirectiveId
const selectedVirtualDirective = computed({
- get () {
+ get() {
return props.modelValue[selectedVirtualDirectiveId.value]
},
- set (value) {
+ set(value) {
const newVD = [...props.modelValue]
newVD[selectedVirtualDirectiveId.value] = value
emit('update:modelValue', newVD)
- }
+ },
})
exports.selectedVirtualDirective = selectedVirtualDirective
exports.selectedVirtualDirectiveValType = computed({
- get () {
+ get() {
return props.modelValue[selectedVirtualDirectiveId.value].valType
},
- set (value) {
+ set(value) {
const newValType = value
let newValue
switch (value) {
@@ -65,9 +63,9 @@ export default {
props.modelValue[selectedVirtualDirectiveId.value] = {
name: newName,
value: newValue,
- valType: newValType
+ valType: newValType,
}
- }
+ },
})
const draftVirtualDirectiveValid = ref(true)
@@ -83,7 +81,9 @@ export default {
if (Array.isArray(directive.value)) {
draftVirtualDirective.value = normalizeShadows(directive.value)
} else {
- const splitShadow = directive.value.split(/,/g).map(x => x.trim())
+ const splitShadow = directive.value
+ .split(/,/g)
+ .map((x) => x.trim())
draftVirtualDirective.value = normalizeShadows(splitShadow)
}
break
@@ -96,7 +96,7 @@ export default {
break
}
},
- { immediate: true }
+ { immediate: true },
)
watch(
@@ -106,11 +106,12 @@ export default {
switch (selectedVirtualDirective.value.valType) {
case 'shadow': {
props.modelValue[selectedVirtualDirectiveId.value].value =
- directive.map(x => serializeShadow(x)).join(', ')
+ directive.map((x) => serializeShadow(x)).join(', ')
break
}
default:
- props.modelValue[selectedVirtualDirectiveId.value].value = directive
+ props.modelValue[selectedVirtualDirectiveId.value].value =
+ directive
}
draftVirtualDirectiveValid.value = true
} catch (e) {
@@ -118,15 +119,15 @@ export default {
draftVirtualDirectiveValid.value = false
}
},
- { immediate: true }
+ { immediate: true },
)
exports.getNewVirtualDirective = () => ({
name: 'newDirective',
valType: 'generic',
- value: 'foobar'
+ value: 'foobar',
})
return exports
- }
+ },
}
diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js
index 1722454db..a7613923c 100644
--- a/src/components/shadow_control/shadow_control.js
+++ b/src/components/shadow_control/shadow_control.js
@@ -1,30 +1,33 @@
+import { flattenDeep, throttle } from 'lodash'
+
+import Checkbox from 'src/components/checkbox/checkbox.vue'
import ColorInput from 'src/components/color_input/color_input.vue'
+import ComponentPreview from 'src/components/component_preview/component_preview.vue'
import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
+import Popover from 'src/components/popover/popover.vue'
import Select from 'src/components/select/select.vue'
import SelectMotion from 'src/components/select/select_motion.vue'
-import Checkbox from 'src/components/checkbox/checkbox.vue'
-import Popover from 'src/components/popover/popover.vue'
-import ComponentPreview from 'src/components/component_preview/component_preview.vue'
import { rgb2hex } from 'src/services/color_convert/color_convert.js'
-import { serializeShadow } from 'src/services/theme_data/iss_serializer.js'
-import { deserializeShadow } from 'src/services/theme_data/iss_deserializer.js'
-import { getCssShadow, getCssShadowFilter } from 'src/services/theme_data/css_utils.js'
-import { findShadow, findColor } from 'src/services/theme_data/theme_data_3.service.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { throttle, flattenDeep } from 'lodash'
import {
- faTimes,
+ getCssShadow,
+ getCssShadowFilter,
+} from 'src/services/theme_data/css_utils.js'
+import { deserializeShadow } from 'src/services/theme_data/iss_deserializer.js'
+import { serializeShadow } from 'src/services/theme_data/iss_serializer.js'
+import {
+ findColor,
+ findShadow,
+} from 'src/services/theme_data/theme_data_3.service.js'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
faChevronDown,
faChevronUp,
- faPlus
+ faPlus,
+ faTimes,
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faChevronDown,
- faChevronUp,
- faTimes,
- faPlus
-)
+library.add(faChevronDown, faChevronUp, faTimes, faPlus)
const toModel = (input) => {
if (typeof input === 'object') {
@@ -36,7 +39,7 @@ const toModel = (input) => {
inset: false,
color: '#000000',
alpha: 1,
- ...input
+ ...input,
}
} else if (typeof input === 'string') {
return input
@@ -51,13 +54,13 @@ export default {
'noPreview',
'disabled',
'staticVars',
- 'compact'
+ 'compact',
],
emits: ['update:modelValue', 'subShadowSelected'],
- data () {
+ data() {
return {
selectedId: 0,
- invalid: false
+ invalid: false,
}
},
components: {
@@ -67,27 +70,27 @@ export default {
SelectMotion,
Checkbox,
Popover,
- ComponentPreview
+ ComponentPreview,
},
computed: {
cValue: {
- get () {
+ get() {
return (this.modelValue ?? this.fallback ?? []).map(toModel)
},
- set (newVal) {
+ set(newVal) {
this.$emit('update:modelValue', newVal)
- }
+ },
},
selectedType: {
- get () {
+ get() {
return typeof this.selected
},
- set (newType) {
+ set(newType) {
this.selected = toModel(newType === 'object' ? {} : '')
- }
+ },
},
selected: {
- get () {
+ get() {
const selected = this.cValue[this.selectedId]
if (selected && typeof selected === 'object') {
return { ...selected }
@@ -96,24 +99,28 @@ export default {
}
return null
},
- set (value) {
+ set(value) {
this.cValue[this.selectedId] = toModel(value)
this.$emit('update:modelValue', this.cValue)
- }
+ },
},
- present () {
+ present() {
return this.selected != null && this.modelValue != null
},
- shadowsAreNull () {
+ shadowsAreNull() {
return this.modelValue == null
},
- currentFallback () {
+ currentFallback() {
return this.fallback?.[this.selectedId]
},
- getColorFallback () {
+ getColorFallback() {
if (this.staticVars && this.selected?.color) {
try {
- const computedColor = findColor(this.selected.color, { dynamicVars: {}, staticVars: this.staticVars }, true)
+ const computedColor = findColor(
+ this.selected.color,
+ { dynamicVars: {}, staticVars: this.staticVars },
+ true,
+ )
if (computedColor) return rgb2hex(computedColor)
return null
} catch (e) {
@@ -124,22 +131,30 @@ export default {
return this.currentFallback?.color
}
},
- style () {
+ style() {
try {
let result
- const serialized = this.cValue.map(x => serializeShadow(x)).join(',')
+ const serialized = this.cValue.map((x) => serializeShadow(x)).join(',')
serialized.split(/,/).map(deserializeShadow) // validate
- const expandedShadow = flattenDeep(findShadow(this.cValue, { dynamicVars: {}, staticVars: this.staticVars }))
- const fixedShadows = expandedShadow.map(x => ({ ...x, color: rgb2hex(x.color) }))
+ const expandedShadow = flattenDeep(
+ findShadow(this.cValue, {
+ dynamicVars: {},
+ staticVars: this.staticVars,
+ }),
+ )
+ const fixedShadows = expandedShadow.map((x) => ({
+ ...x,
+ color: rgb2hex(x.color),
+ }))
if (this.separateInset) {
result = {
filter: getCssShadowFilter(fixedShadows),
- boxShadow: getCssShadow(fixedShadows, true)
+ boxShadow: getCssShadow(fixedShadows, true),
}
} else {
result = {
- boxShadow: getCssShadow(fixedShadows)
+ boxShadow: getCssShadow(fixedShadows),
}
}
this.invalid = false
@@ -148,23 +163,26 @@ export default {
console.error('Invalid shadow', e)
this.invalid = true
}
- }
+ },
},
watch: {
- selected () {
+ selected() {
this.$emit('subShadowSelected', this.selectedId)
- }
+ },
},
methods: {
- getNewSubshadow () {
+ getNewSubshadow() {
return toModel(this.selected)
},
- onSelectChange (id) {
+ onSelectChange(id) {
this.selectedId = id
},
- getSubshadowLabel (shadow, index) {
+ getSubshadowLabel(shadow, index) {
if (typeof shadow === 'object') {
- return shadow?.name ?? this.$t('settings.style.shadows.shadow_id', { value: index })
+ return (
+ shadow?.name ??
+ this.$t('settings.style.shadows.shadow_id', { value: index })
+ )
} else if (typeof shadow === 'string') {
return shadow || this.$t('settings.style.shadows.empty_expression')
}
@@ -175,6 +193,6 @@ export default {
this.cValue[this.selectedId].spread = 0
}
this.$emit('update:modelValue', this.cValue)
- }, 100)
- }
+ }, 100),
+ },
}
diff --git a/src/components/shout_panel/shout_panel.js b/src/components/shout_panel/shout_panel.js
index af5e90364..6cb6a53b0 100644
--- a/src/components/shout_panel/shout_panel.js
+++ b/src/components/shout_panel/shout_panel.js
@@ -1,54 +1,56 @@
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faBullhorn,
- faTimes
-} from '@fortawesome/free-solid-svg-icons'
import { useShoutStore } from 'src/stores/shout'
-library.add(
- faBullhorn,
- faTimes
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faBullhorn, faTimes } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faBullhorn, faTimes)
const shoutPanel = {
props: ['floating'],
- data () {
+ data() {
return {
currentMessage: '',
channel: null,
- collapsed: true
+ collapsed: true,
}
},
computed: {
- messages () {
+ messages() {
return useShoutStore().messages
- }
+ },
},
methods: {
- submit (message) {
+ submit(message) {
useShoutStore().channel.push('new_msg', { text: message }, 10000)
this.currentMessage = ''
},
- togglePanel () {
+ togglePanel() {
this.collapsed = !this.collapsed
},
- userProfileLink (user) {
- return generateProfileLink(user.id, user.username, this.$store.state.instance.restrictedNicknames)
- }
+ userProfileLink(user) {
+ return generateProfileLink(
+ user.id,
+ user.username,
+ this.$store.state.instance.restrictedNicknames,
+ )
+ },
},
watch: {
- messages () {
+ messages() {
const scrollEl = this.$el.querySelector('.chat-window')
if (!scrollEl) return
- if (scrollEl.scrollTop + scrollEl.offsetHeight + 20 > scrollEl.scrollHeight) {
+ if (
+ scrollEl.scrollTop + scrollEl.offsetHeight + 20 >
+ scrollEl.scrollHeight
+ ) {
this.$nextTick(() => {
if (!scrollEl) return
scrollEl.scrollTop = scrollEl.scrollHeight - scrollEl.offsetHeight
})
}
- }
- }
+ },
+ },
}
export default shoutPanel
diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js
index 7dbd38cb5..b12cef86e 100644
--- a/src/components/side_drawer/side_drawer.js
+++ b/src/components/side_drawer/side_drawer.js
@@ -1,29 +1,31 @@
-import { mapState, mapGetters } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
-import UserCard from '../user_card/user_card.vue'
-import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
-import GestureService from '../../services/gesture_service/gesture_service'
+import { mapGetters, mapState } from 'vuex'
+
import { USERNAME_ROUTES } from 'src/components/navigation/navigation.js'
+import { useAnnouncementsStore } from 'src/stores/announcements'
+import { useInterfaceStore } from 'src/stores/interface'
+import { useShoutStore } from 'src/stores/shout'
+import GestureService from '../../services/gesture_service/gesture_service'
+import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
+import UserCard from '../user_card/user_card.vue'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
+ faBell,
+ faBullhorn,
+ faCog,
+ faComments,
+ faCompass,
+ faFilePen,
+ faHome,
+ faInfoCircle,
+ faList,
+ faSearch,
faSignInAlt,
faSignOutAlt,
- faHome,
- faComments,
- faBell,
- faUserPlus,
- faBullhorn,
- faSearch,
faTachometerAlt,
- faCog,
- faInfoCircle,
- faCompass,
- faList,
- faFilePen
+ faUserPlus,
} from '@fortawesome/free-solid-svg-icons'
-import { useShoutStore } from 'src/stores/shout'
-import { useInterfaceStore } from 'src/stores/interface'
-import { useAnnouncementsStore } from 'src/stores/announcements'
library.add(
faSignInAlt,
@@ -39,17 +41,20 @@ library.add(
faInfoCircle,
faCompass,
faList,
- faFilePen
+ faFilePen,
)
const SideDrawer = {
props: ['logout'],
data: () => ({
closed: true,
- closeGesture: undefined
+ closeGesture: undefined,
}),
- created () {
- this.closeGesture = GestureService.swipeGesture(GestureService.DIRECTION_LEFT, this.toggleDrawer)
+ created() {
+ this.closeGesture = GestureService.swipeGesture(
+ GestureService.DIRECTION_LEFT,
+ this.toggleDrawer,
+ )
if (this.currentUser && this.currentUser.locked) {
this.$store.dispatch('startFetchingFollowRequests')
@@ -57,38 +62,40 @@ const SideDrawer = {
},
components: { UserCard },
computed: {
- currentUser () {
+ currentUser() {
return this.$store.state.users.currentUser
},
- shout () { return useShoutStore().joined },
- unseenNotifications () {
+ shout() {
+ return useShoutStore().joined
+ },
+ unseenNotifications() {
return unseenNotificationsFromStore(this.$store)
},
- unseenNotificationsCount () {
+ unseenNotificationsCount() {
return this.unseenNotifications.length
},
- suggestionsEnabled () {
+ suggestionsEnabled() {
return this.$store.state.instance.suggestionsEnabled
},
- logo () {
+ logo() {
return this.$store.state.instance.logo
},
- hideSitename () {
+ hideSitename() {
return this.$store.state.instance.hideSitename
},
- sitename () {
+ sitename() {
return this.$store.state.instance.name
},
- followRequestCount () {
+ followRequestCount() {
return this.$store.state.api.followRequests.length
},
- privateMode () {
+ privateMode() {
return this.$store.state.instance.private
},
- federating () {
+ federating() {
return this.$store.state.instance.federating
},
- timelinesRoute () {
+ timelinesRoute() {
let name
if (useInterfaceStore().lastTimeline) {
name = useInterfaceStore().lastTimeline
@@ -101,35 +108,36 @@ const SideDrawer = {
}
},
...mapPiniaState(useAnnouncementsStore, {
- supportsAnnouncements: store => store.supportsAnnouncements,
- unreadAnnouncementCount: 'unreadAnnouncementCount'
+ supportsAnnouncements: (store) => store.supportsAnnouncements,
+ unreadAnnouncementCount: 'unreadAnnouncementCount',
}),
...mapState({
- pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
+ pleromaChatMessagesAvailable: (state) =>
+ state.instance.pleromaChatMessagesAvailable,
}),
- ...mapGetters(['unreadChatCount', 'draftCount'])
+ ...mapGetters(['unreadChatCount', 'draftCount']),
},
methods: {
- toggleDrawer () {
+ toggleDrawer() {
this.closed = !this.closed
},
- doLogout () {
+ doLogout() {
this.logout()
this.toggleDrawer()
},
- touchStart (e) {
+ touchStart(e) {
GestureService.beginSwipe(e, this.closeGesture)
},
- touchMove (e) {
+ touchMove(e) {
GestureService.updateSwipe(e, this.closeGesture)
},
- openSettingsModal () {
+ openSettingsModal() {
useInterfaceStore().openSettingsModal('user')
},
- openAdminModal () {
+ openAdminModal() {
useInterfaceStore().openSettingsModal('admin')
- }
- }
+ },
+ },
}
export default SideDrawer
diff --git a/src/components/staff_panel/staff_panel.js b/src/components/staff_panel/staff_panel.js
index 46a92ac78..0b7dc8b57 100644
--- a/src/components/staff_panel/staff_panel.js
+++ b/src/components/staff_panel/staff_panel.js
@@ -1,33 +1,36 @@
-import map from 'lodash/map'
import groupBy from 'lodash/groupBy'
+import map from 'lodash/map'
import { mapGetters, mapState } from 'vuex'
+
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
const StaffPanel = {
- created () {
+ created() {
const nicknames = this.$store.state.instance.staffAccounts
- nicknames.forEach(nickname => this.$store.dispatch('fetchUserIfMissing', nickname))
+ nicknames.forEach((nickname) =>
+ this.$store.dispatch('fetchUserIfMissing', nickname),
+ )
},
components: {
- BasicUserCard
+ BasicUserCard,
},
computed: {
- groupedStaffAccounts () {
- const staffAccounts = map(this.staffAccounts, this.findUserByName).filter(_ => _)
+ groupedStaffAccounts() {
+ const staffAccounts = map(this.staffAccounts, this.findUserByName).filter(
+ (_) => _,
+ )
const groupedStaffAccounts = groupBy(staffAccounts, 'role')
return [
{ role: 'admin', users: groupedStaffAccounts.admin },
- { role: 'moderator', users: groupedStaffAccounts.moderator }
- ].filter(group => group.users)
+ { role: 'moderator', users: groupedStaffAccounts.moderator },
+ ].filter((group) => group.users)
},
- ...mapGetters([
- 'findUserByName'
- ]),
+ ...mapGetters(['findUserByName']),
...mapState({
- staffAccounts: state => state.instance.staffAccounts
- })
- }
+ staffAccounts: (state) => state.instance.staffAccounts,
+ }),
+ },
}
export default StaffPanel
diff --git a/src/components/status/post.style.js b/src/components/status/post.style.js
index 43e21a16e..a988aef76 100644
--- a/src/components/status/post.style.js
+++ b/src/components/status/post.style.js
@@ -2,7 +2,7 @@ export default {
name: 'Post',
selector: '.Status',
states: {
- selected: '.-focused'
+ selected: '.-focused',
},
validInnerComponents: [
'Text',
@@ -10,19 +10,19 @@ export default {
'Icon',
'Border',
'Avatar',
- 'PollGraph'
+ 'PollGraph',
],
defaultRules: [
{
directives: {
- background: '--bg'
- }
+ background: '--bg',
+ },
},
{
state: ['selected'],
directives: {
- background: '--inheritedBackground, 10'
- }
- }
- ]
+ background: '--inheritedBackground, 10',
+ },
+ },
+ ],
}
diff --git a/src/components/status/status.js b/src/components/status/status.js
index eebae459b..1673a6933 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -1,44 +1,48 @@
-import PostStatusForm from '../post_status_form/post_status_form.vue'
-import UserAvatar from '../user_avatar/user_avatar.vue'
-import AvatarList from '../avatar_list/avatar_list.vue'
-import Timeago from '../timeago/timeago.vue'
-import StatusContent from '../status_content/status_content.vue'
-import RichContent from 'src/components/rich_content/rich_content.jsx'
-import StatusPopover from '../status_popover/status_popover.vue'
-import UserPopover from '../user_popover/user_popover.vue'
-import UserListPopover from '../user_list_popover/user_list_popover.vue'
-import EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
-import UserLink from '../user_link/user_link.vue'
-import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
+import { unescape as ldUnescape, uniqBy } from 'lodash'
+
import MentionLink from 'src/components/mention_link/mention_link.vue'
+import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
+import RichContent from 'src/components/rich_content/rich_content.jsx'
import StatusActionButtons from 'src/components/status_action_buttons/status_action_buttons.vue'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
-import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
-import { muteFilterHits } from '../../services/status_parser/status_parser.js'
-import { unescape, uniqBy } from 'lodash'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
+import { muteFilterHits } from '../../services/status_parser/status_parser.js'
+import {
+ highlightClass,
+ highlightStyle,
+} from '../../services/user_highlighter/user_highlighter.js'
+import AvatarList from '../avatar_list/avatar_list.vue'
+import EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
+import PostStatusForm from '../post_status_form/post_status_form.vue'
+import StatusContent from '../status_content/status_content.vue'
+import StatusPopover from '../status_popover/status_popover.vue'
+import Timeago from '../timeago/timeago.vue'
+import UserAvatar from '../user_avatar/user_avatar.vue'
+import UserLink from '../user_link/user_link.vue'
+import UserListPopover from '../user_list_popover/user_list_popover.vue'
+import UserPopover from '../user_popover/user_popover.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
+ faAngleDoubleRight,
+ faChevronDown,
+ faChevronUp,
+ faEllipsisH,
faEnvelope,
- faLock,
- faLockOpen,
+ faEye,
+ faEyeSlash,
faGlobe,
faIgloo,
- faTimes,
- faRetweet,
- faReply,
+ faLock,
+ faLockOpen,
+ faPlay,
faPlusSquare,
+ faReply,
+ faRetweet,
faSmileBeam,
- faEllipsisH,
faStar,
- faEyeSlash,
- faEye,
faThumbtack,
- faChevronUp,
- faChevronDown,
- faAngleDoubleRight,
- faPlay
+ faTimes,
} from '@fortawesome/free-solid-svg-icons'
library.add(
@@ -60,21 +64,26 @@ library.add(
faChevronUp,
faChevronDown,
faAngleDoubleRight,
- faPlay
+ faPlay,
)
-const camelCase = name => name.charAt(0).toUpperCase() + name.slice(1)
+const camelCase = (name) => name.charAt(0).toUpperCase() + name.slice(1)
-const controlledOrUncontrolledGetters = list => list.reduce((res, name) => {
- const camelized = camelCase(name)
- const toggle = `controlledToggle${camelized}`
- const controlledName = `controlled${camelized}`
- const uncontrolledName = `uncontrolled${camelized}`
- res[name] = function () {
- return ((this.$data[toggle] !== undefined || this.$props[toggle] !== undefined) && this[toggle]) ? this[controlledName] : this[uncontrolledName]
- }
- return res
-}, {})
+const controlledOrUncontrolledGetters = (list) =>
+ list.reduce((res, name) => {
+ const camelized = camelCase(name)
+ const toggle = `controlledToggle${camelized}`
+ const controlledName = `controlled${camelized}`
+ const uncontrolledName = `uncontrolled${camelized}`
+ res[name] = function () {
+ return (this.$data[toggle] !== undefined ||
+ this.$props[toggle] !== undefined) &&
+ this[toggle]
+ ? this[controlledName]
+ : this[uncontrolledName]
+ }
+ return res
+ }, {})
const controlledOrUncontrolledToggle = (obj, name) => {
const camelized = camelCase(name)
@@ -114,7 +123,7 @@ const Status = {
MentionsLine,
UserPopover,
UserLink,
- StatusActionButtons
+ StatusActionButtons,
},
props: [
'statusoid',
@@ -147,10 +156,10 @@ const Status = {
'controlledToggleReplying',
'controlledMediaPlaying',
'controlledSetMediaPlaying',
- 'dive'
+ 'dive',
],
emits: ['interacted'],
- data () {
+ data() {
return {
uncontrolledReplying: false,
unmuted: false,
@@ -159,128 +168,164 @@ const Status = {
suspendable: true,
error: null,
headTailLinks: null,
- displayQuote: !this.inQuote
+ displayQuote: !this.inQuote,
}
},
computed: {
...controlledOrUncontrolledGetters(['replying', 'mediaPlaying']),
- showReasonMutedThread () {
+ showReasonMutedThread() {
return (
- this.status.thread_muted ||
- (this.status.reblog && this.status.reblog.thread_muted)
- ) && !this.inConversation
+ (this.status.thread_muted ||
+ (this.status.reblog && this.status.reblog.thread_muted)) &&
+ !this.inConversation
+ )
},
- repeaterClass () {
+ repeaterClass() {
const user = this.statusoid.user
return highlightClass(user)
},
- userClass () {
- const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user
+ userClass() {
+ const user = this.retweet
+ ? this.statusoid.retweeted_status.user
+ : this.statusoid.user
return highlightClass(user)
},
- deleted () {
+ deleted() {
return this.statusoid.deleted
},
- repeaterStyle () {
+ repeaterStyle() {
const user = this.statusoid.user
const highlight = this.mergedConfig.highlight
return highlightStyle(highlight[user.screen_name])
},
- userStyle () {
+ userStyle() {
if (this.noHeading) return
- const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user
+ const user = this.retweet
+ ? this.statusoid.retweeted_status.user
+ : this.statusoid.user
const highlight = this.mergedConfig.highlight
return highlightStyle(highlight[user.screen_name])
},
- userProfileLink () {
- return this.generateUserProfileLink(this.status.user.id, this.status.user.screen_name)
+ userProfileLink() {
+ return this.generateUserProfileLink(
+ this.status.user.id,
+ this.status.user.screen_name,
+ )
},
- replyProfileLink () {
+ replyProfileLink() {
if (this.isReply) {
- const user = this.$store.getters.findUser(this.status.in_reply_to_user_id)
+ const user = this.$store.getters.findUser(
+ this.status.in_reply_to_user_id,
+ )
// FIXME Why user not found sometimes???
return user ? user.statusnet_profile_url : 'NOT_FOUND'
}
},
- retweet () { return !!this.statusoid.retweeted_status },
- retweeterUser () { return this.statusoid.user },
- retweeter () { return this.statusoid.user.name || this.statusoid.user.screen_name_ui },
- retweeterHtml () { return this.statusoid.user.name },
- retweeterProfileLink () { return this.generateUserProfileLink(this.statusoid.user.id, this.statusoid.user.screen_name) },
- status () {
+ retweet() {
+ return !!this.statusoid.retweeted_status
+ },
+ retweeterUser() {
+ return this.statusoid.user
+ },
+ retweeter() {
+ return this.statusoid.user.name || this.statusoid.user.screen_name_ui
+ },
+ retweeterHtml() {
+ return this.statusoid.user.name
+ },
+ retweeterProfileLink() {
+ return this.generateUserProfileLink(
+ this.statusoid.user.id,
+ this.statusoid.user.screen_name,
+ )
+ },
+ status() {
if (this.retweet) {
return this.statusoid.retweeted_status
} else {
return this.statusoid
}
},
- statusFromGlobalRepository () {
+ statusFromGlobalRepository() {
// NOTE: Consider to replace status with statusFromGlobalRepository
return this.$store.state.statuses.allStatusesObject[this.status.id]
},
- loggedIn () {
+ loggedIn() {
return !!this.currentUser
},
- muteFilterHits () {
+ muteFilterHits() {
return muteFilterHits(
- Object.values(useServerSideStorageStore().prefsStorage.simple.muteFilters),
- this.status
+ Object.values(
+ useServerSideStorageStore().prefsStorage.simple.muteFilters,
+ ),
+ this.status,
)
},
- botStatus () {
+ botStatus() {
return this.status.user.actor_type === 'Service'
},
- showActorTypeIndicator () {
+ showActorTypeIndicator() {
return !this.hideBotIndication
},
- sensitiveStatus () {
+ sensitiveStatus() {
return this.status.nsfw
},
- mentionsLine () {
+ mentionsLine() {
if (!this.headTailLinks) return []
- const writtenSet = new Set(this.headTailLinks.writtenMentions.map(_ => _.url))
- return this.status.attentions.filter(attn => {
- // no reply user
- return attn.id !== this.status.in_reply_to_user_id &&
- // no self-replies
- attn.statusnet_profile_url !== this.status.user.statusnet_profile_url &&
- // don't include if mentions is written
- !writtenSet.has(attn.statusnet_profile_url)
- }).map(attn => ({
- url: attn.statusnet_profile_url,
- content: attn.screen_name,
- userId: attn.id
- }))
+ const writtenSet = new Set(
+ this.headTailLinks.writtenMentions.map((_) => _.url),
+ )
+ return this.status.attentions
+ .filter((attn) => {
+ // no reply user
+ return (
+ attn.id !== this.status.in_reply_to_user_id &&
+ // no self-replies
+ attn.statusnet_profile_url !==
+ this.status.user.statusnet_profile_url &&
+ // don't include if mentions is written
+ !writtenSet.has(attn.statusnet_profile_url)
+ )
+ })
+ .map((attn) => ({
+ url: attn.statusnet_profile_url,
+ content: attn.screen_name,
+ userId: attn.id,
+ }))
},
- hasMentionsLine () {
+ hasMentionsLine() {
return this.mentionsLine.length > 0
},
- muteReasons () {
+ muteReasons() {
return [
this.userIsMuted ? 'user' : null,
this.status.thread_muted ? 'thread' : null,
- (this.muteFilterHits.length > 0) ? 'filtered' : null,
- (this.muteBotStatuses && this.botStatus) ? 'bot' : null,
- (this.muteSensitiveStatuses && this.sensitiveStatus) ? 'nsfw' : null
- ].filter(_ => _)
+ this.muteFilterHits.length > 0 ? 'filtered' : null,
+ this.muteBotStatuses && this.botStatus ? 'bot' : null,
+ this.muteSensitiveStatuses && this.sensitiveStatus ? 'nsfw' : null,
+ ].filter((_) => _)
},
- muteLocalized () {
+ muteLocalized() {
if (this.muteReasons.length === 0) return null
const mainReason = () => {
switch (this.muteReasons[0]) {
- case 'user': return this.$t('status.muted_user')
- case 'thread': return this.$t('status.thread_muted')
+ case 'user':
+ return this.$t('status.muted_user')
+ case 'thread':
+ return this.$t('status.thread_muted')
case 'filtered':
return this.$t(
'status.muted_filters',
{
name: this.muteFilterHits[0].name,
- filterMore: this.muteFilterHits.length - 1
+ filterMore: this.muteFilterHits.length - 1,
},
- this.muteFilterHits.length
+ this.muteFilterHits.length,
)
- case 'bot': return this.$t('status.bot_muted')
- case 'nsfw': return this.$t('status.sensitive_muted')
+ case 'bot':
+ return this.$t('status.bot_muted')
+ case 'nsfw':
+ return this.$t('status.sensitive_muted')
}
}
if (this.muteReasons.length > 1) {
@@ -288,72 +333,74 @@ const Status = {
'status.multi_reason_mute',
{
main: mainReason(),
- numReasonsMore: this.muteReasons.length - 1
+ numReasonsMore: this.muteReasons.length - 1,
},
- this.muteReasons.length - 1
+ this.muteReasons.length - 1,
)
} else {
return mainReason()
}
},
- muted () {
+ muted() {
if (this.statusoid.user.id === this.currentUser.id) return false
return !this.unmuted && !this.shouldNotMute && this.muteReasons.length > 0
},
- userIsMuted () {
+ userIsMuted() {
if (this.statusoid.user.id === this.currentUser.id) return false
const { status } = this
const { reblog } = status
const relationship = this.$store.getters.relationship(status.user.id)
- const relationshipReblog = reblog && this.$store.getters.relationship(reblog.user.id)
- return (status.muted && !status.thread_muted) ||
+ const relationshipReblog =
+ reblog && this.$store.getters.relationship(reblog.user.id)
+ return (
+ (status.muted && !status.thread_muted) ||
// Reprööt of a muted post according to BE
(reblog && reblog.muted && !reblog.thread_muted) ||
// Muted user
relationship.muting ||
// Muted user of a reprööt
(relationshipReblog && relationshipReblog.muting)
+ )
},
- shouldNotMute () {
+ shouldNotMute() {
if (this.isFocused) return true
const { status } = this
const { reblog } = status
return (
- (
- this.inProfile && (
- // Don't mute user's posts on user timeline (except reblogs)
- (!reblog && status.user.id === this.profileUserId) ||
+ ((this.inProfile &&
+ // Don't mute user's posts on user timeline (except reblogs)
+ ((!reblog && status.user.id === this.profileUserId) ||
// Same as above but also allow self-reblogs
- (reblog && reblog.user.id === this.profileUserId)
- )
- ) ||
- // Don't mute statuses in muted conversation when said conversation is opened
- (this.inConversation && status.thread_muted)
+ (reblog && reblog.user.id === this.profileUserId))) ||
+ // Don't mute statuses in muted conversation when said conversation is opened
+ (this.inConversation && status.thread_muted)) &&
// No excuses if post has muted words
- ) && !this.muteFilterHits.length > 0
- },
- hideMutedUsers () {
- return this.mergedConfig.hideMutedPosts
- },
- hideMutedThreads () {
- return this.mergedConfig.hideMutedThreads
- },
- hideFilteredStatuses () {
- return this.mergedConfig.hideFilteredStatuses
- },
- hideWordFilteredPosts () {
- return this.mergedConfig.hideWordFilteredPosts
- },
- hideStatus () {
- return (!this.shouldNotMute) && (
- (this.muted && this.hideFilteredStatuses) ||
- (this.userIsMuted && this.hideMutedUsers) ||
- (this.status.thread_muted && this.hideMutedThreads) ||
- (this.muteFilterHits.length > 0 && this.hideWordFilteredPosts) ||
- (this.muteFilterHits.some(x => x.hide))
+ !this.muteFilterHits.length > 0
)
},
- isFocused () {
+ hideMutedUsers() {
+ return this.mergedConfig.hideMutedPosts
+ },
+ hideMutedThreads() {
+ return this.mergedConfig.hideMutedThreads
+ },
+ hideFilteredStatuses() {
+ return this.mergedConfig.hideFilteredStatuses
+ },
+ hideWordFilteredPosts() {
+ return this.mergedConfig.hideWordFilteredPosts
+ },
+ hideStatus() {
+ return (
+ !this.shouldNotMute &&
+ ((this.muted && this.hideFilteredStatuses) ||
+ (this.userIsMuted && this.hideMutedUsers) ||
+ (this.status.thread_muted && this.hideMutedThreads) ||
+ (this.muteFilterHits.length > 0 && this.hideWordFilteredPosts) ||
+ this.muteFilterHits.some((x) => x.hide))
+ )
+ },
+ isFocused() {
// retweet or root of an expanded conversation
if (this.focused) {
return true
@@ -363,20 +410,24 @@ const Status = {
// use conversation highlight only when in conversation
return this.status.id === this.highlight
},
- isReply () {
- return !!(this.status.in_reply_to_status_id && this.status.in_reply_to_user_id)
+ isReply() {
+ return !!(
+ this.status.in_reply_to_status_id && this.status.in_reply_to_user_id
+ )
},
- replyToName () {
+ replyToName() {
if (this.status.in_reply_to_screen_name) {
return this.status.in_reply_to_screen_name
} else {
- const user = this.$store.getters.findUser(this.status.in_reply_to_user_id)
+ const user = this.$store.getters.findUser(
+ this.status.in_reply_to_user_id,
+ )
return user && user.screen_name_ui
}
},
- replySubject () {
+ replySubject() {
if (!this.status.summary) return ''
- const decodedSummary = unescape(this.status.summary)
+ const decodedSummary = ldUnescape(this.status.summary)
const behavior = this.mergedConfig.subjectLineBehavior
const startsWithRe = decodedSummary.match(/^re[: ]/i)
if ((behavior !== 'noop' && startsWithRe) || behavior === 'masto') {
@@ -387,70 +438,79 @@ const Status = {
return ''
}
},
- combinedFavsAndRepeatsUsers () {
+ combinedFavsAndRepeatsUsers() {
// Use the status from the global status repository since favs and repeats are saved in it
const combinedUsers = [].concat(
this.statusFromGlobalRepository.favoritedBy,
- this.statusFromGlobalRepository.rebloggedBy
+ this.statusFromGlobalRepository.rebloggedBy,
)
return uniqBy(combinedUsers, 'id')
},
- tags () {
- // eslint-disable-next-line no-prototype-builtins
- return this.status.tags.filter(tagObj => tagObj.hasOwnProperty('name')).map(tagObj => tagObj.name).join(' ')
+ tags() {
+ return this.status.tags
+ .filter((tagObj) => Object.hasOwn(tagObj, 'name'))
+ .map((tagObj) => tagObj.name)
+ .join(' ')
},
- hidePostStats () {
+ hidePostStats() {
return this.mergedConfig.hidePostStats
},
- shouldDisplayFavsAndRepeats () {
- return !this.hidePostStats && this.isFocused && (this.combinedFavsAndRepeatsUsers.length > 0 || this.statusFromGlobalRepository.quotes_count)
+ shouldDisplayFavsAndRepeats() {
+ return (
+ !this.hidePostStats &&
+ this.isFocused &&
+ (this.combinedFavsAndRepeatsUsers.length > 0 ||
+ this.statusFromGlobalRepository.quotes_count)
+ )
},
- muteBotStatuses () {
+ muteBotStatuses() {
return this.mergedConfig.muteBotStatuses
},
- muteSensitiveStatuses () {
+ muteSensitiveStatuses() {
return this.mergedConfig.muteSensitiveStatuses
},
- hideBotIndication () {
+ hideBotIndication() {
return this.mergedConfig.hideBotIndication
},
- currentUser () {
+ currentUser() {
return this.$store.state.users.currentUser
},
- mergedConfig () {
+ mergedConfig() {
return this.$store.getters.mergedConfig
},
- isSuspendable () {
+ isSuspendable() {
return !this.replying && this.mediaPlaying.length === 0
},
- inThreadForest () {
+ inThreadForest() {
return !!this.controlledThreadDisplayStatus
},
- threadShowing () {
+ threadShowing() {
return this.controlledThreadDisplayStatus === 'showing'
},
- visibilityLocalized () {
+ visibilityLocalized() {
return this.$i18n.t('general.scope_in_timeline.' + this.status.visibility)
},
- isEdited () {
+ isEdited() {
return this.status.edited_at !== null
},
- editingAvailable () {
+ editingAvailable() {
return this.$store.state.instance.editingAvailable
},
- hasVisibleQuote () {
+ hasVisibleQuote() {
return this.status.quote_url && this.status.quote_visible
},
- hasInvisibleQuote () {
+ hasInvisibleQuote() {
return this.status.quote_url && !this.status.quote_visible
},
- quotedStatus () {
- return this.status.quote_id ? this.$store.state.statuses.allStatusesObject[this.status.quote_id] : undefined
+ quotedStatus() {
+ return this.status.quote_id
+ ? this.$store.state.statuses.allStatusesObject[this.status.quote_id]
+ : undefined
},
- shouldDisplayQuote () {
+ shouldDisplayQuote() {
return this.quotedStatus && this.displayQuote
},
- scrobblePresent () {
+ scrobblePresent() {
if (this.mergedConfig.hideScrobbles) return false
if (!this.status.user?.latestScrobble) return false
const value = this.mergedConfig.hideScrobblesAfter.match(/\d+/gs)[0]
@@ -473,12 +533,12 @@ const Status = {
if (age > maxAge) return false
return this.status.user.latestScrobble.artist
},
- scrobble () {
+ scrobble() {
return this.status.user?.latestScrobble
- }
+ },
},
methods: {
- visibilityIcon (visibility) {
+ visibilityIcon(visibility) {
switch (visibility) {
case 'private':
return 'lock'
@@ -492,14 +552,14 @@ const Status = {
return 'globe'
}
},
- showError (error) {
+ showError(error) {
this.error = error
},
- clearError () {
+ clearError() {
this.$emit('interacted')
this.error = undefined
},
- toggleReplying () {
+ toggleReplying() {
this.$emit('interacted')
if (this.replying) {
this.$refs.postStatusForm.requestClose()
@@ -507,39 +567,51 @@ const Status = {
this.doToggleReplying()
}
},
- doToggleReplying () {
+ doToggleReplying() {
controlledOrUncontrolledToggle(this, 'replying')
},
- gotoOriginal (id) {
+ gotoOriginal(id) {
if (this.inConversation) {
this.$emit('goto', id)
}
},
- toggleExpanded () {
+ toggleExpanded() {
this.$emit('toggleExpanded')
},
- toggleMute () {
+ toggleMute() {
this.unmuted = !this.unmuted
},
- toggleUserExpanded () {
+ toggleUserExpanded() {
this.userExpanded = !this.userExpanded
},
- generateUserProfileLink (id, name) {
- return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames)
+ generateUserProfileLink(id, name) {
+ return generateProfileLink(
+ id,
+ name,
+ this.$store.state.instance.restrictedNicknames,
+ )
},
- addMediaPlaying (id) {
- controlledOrUncontrolledSet(this, 'mediaPlaying', this.mediaPlaying.concat(id))
+ addMediaPlaying(id) {
+ controlledOrUncontrolledSet(
+ this,
+ 'mediaPlaying',
+ this.mediaPlaying.concat(id),
+ )
},
- removeMediaPlaying (id) {
- controlledOrUncontrolledSet(this, 'mediaPlaying', this.mediaPlaying.filter(mediaId => mediaId !== id))
+ removeMediaPlaying(id) {
+ controlledOrUncontrolledSet(
+ this,
+ 'mediaPlaying',
+ this.mediaPlaying.filter((mediaId) => mediaId !== id),
+ )
},
- setHeadTailLinks (headTailLinks) {
+ setHeadTailLinks(headTailLinks) {
this.headTailLinks = headTailLinks
},
- toggleThreadDisplay () {
+ toggleThreadDisplay() {
this.controlledToggleThreadDisplay()
},
- scrollIfHighlighted (highlightId) {
+ scrollIfHighlighted(highlightId) {
if (this.$el.getBoundingClientRect == null) return
const id = highlightId
if (this.status.id === id) {
@@ -547,7 +619,7 @@ const Status = {
if (rect.top < 100) {
// Post is above screen, match its top to screen top
window.scrollBy(0, rect.top - 100)
- } else if (rect.height >= (window.innerHeight - 50)) {
+ } else if (rect.height >= window.innerHeight - 50) {
// Post we want to see is taller than screen so match its top to screen top
window.scrollBy(0, rect.top - 100)
} else if (rect.bottom > window.innerHeight - 50) {
@@ -556,18 +628,17 @@ const Status = {
}
}
},
- toggleDisplayQuote () {
+ toggleDisplayQuote() {
if (this.shouldDisplayQuote) {
this.displayQuote = false
} else if (!this.quotedStatus) {
- this.$store.dispatch('fetchStatus', this.status.quote_id)
- .then(() => {
- this.displayQuote = true
- })
+ this.$store.dispatch('fetchStatus', this.status.quote_id).then(() => {
+ this.displayQuote = true
+ })
} else {
this.displayQuote = true
}
- }
+ },
},
watch: {
highlight: function (id) {
@@ -575,20 +646,28 @@ const Status = {
},
'status.repeat_num': function (num) {
// refetch repeats when repeat_num is changed in any way
- if (this.isFocused && this.statusFromGlobalRepository.rebloggedBy && this.statusFromGlobalRepository.rebloggedBy.length !== num) {
+ if (
+ this.isFocused &&
+ this.statusFromGlobalRepository.rebloggedBy &&
+ this.statusFromGlobalRepository.rebloggedBy.length !== num
+ ) {
this.$store.dispatch('fetchRepeats', this.status.id)
}
},
'status.fave_num': function (num) {
// refetch favs when fave_num is changed in any way
- if (this.isFocused && this.statusFromGlobalRepository.favoritedBy && this.statusFromGlobalRepository.favoritedBy.length !== num) {
+ if (
+ this.isFocused &&
+ this.statusFromGlobalRepository.favoritedBy &&
+ this.statusFromGlobalRepository.favoritedBy.length !== num
+ ) {
this.$store.dispatch('fetchFavs', this.status.id)
}
},
isSuspendable: function (val) {
this.suspendable = val
- }
- }
+ },
+ },
}
export default Status
diff --git a/src/components/status_action_buttons/action_button.js b/src/components/status_action_buttons/action_button.js
index 8a65b9184..5badd87e7 100644
--- a/src/components/status_action_buttons/action_button.js
+++ b/src/components/status_action_buttons/action_button.js
@@ -1,34 +1,31 @@
-import StatusBookmarkFolderMenu from 'src/components/status_bookmark_folder_menu/status_bookmark_folder_menu.vue'
import EmojiPicker from 'src/components/emoji_picker/emoji_picker.vue'
import Popover from 'src/components/popover/popover.vue'
+import StatusBookmarkFolderMenu from 'src/components/status_bookmark_folder_menu/status_bookmark_folder_menu.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faPlus,
- faMinus,
+ faBookmark as faBookmarkRegular,
+ faStar as faStarRegular,
+} from '@fortawesome/free-regular-svg-icons'
+import {
+ faBookmark,
faCheck,
- faTimes,
- faWrench,
-
faChevronRight,
faChevronUp,
-
+ faExternalLinkAlt,
+ faEyeSlash,
+ faHistory,
+ faMinus,
+ faPlus,
faReply,
faRetweet,
- faStar,
- faSmileBeam,
-
- faBookmark,
- faEyeSlash,
- faThumbtack,
faShareAlt,
- faExternalLinkAlt,
- faHistory
+ faSmileBeam,
+ faStar,
+ faThumbtack,
+ faTimes,
+ faWrench,
} from '@fortawesome/free-solid-svg-icons'
-import {
- faStar as faStarRegular,
- faBookmark as faBookmarkRegular
-} from '@fortawesome/free-regular-svg-icons'
library.add(
faPlus,
@@ -52,7 +49,7 @@ library.add(
faThumbtack,
faShareAlt,
faExternalLinkAlt,
- faHistory
+ faHistory,
)
export default {
@@ -65,66 +62,78 @@ export default {
'getClass',
'getComponent',
'doAction',
- 'outerClose'
- ],
- emits: [
- 'interacted'
+ 'outerClose',
],
+ emits: ['interacted'],
components: {
StatusBookmarkFolderMenu,
EmojiPicker,
- Popover
+ Popover,
},
data: () => ({
- animationState: false
+ animationState: false,
}),
computed: {
- buttonClass () {
+ buttonClass() {
return [
this.button.name + '-button',
{
'-with-extra': this.button.name === 'bookmark',
'-extra': this.extra,
- '-quick': !this.extra
- }
+ '-quick': !this.extra,
+ },
]
},
- userIsMuted () {
+ userIsMuted() {
return this.$store.getters.relationship(this.status.user.id).muting
},
- threadIsMuted () {
+ threadIsMuted() {
return this.status.thread_muted
},
- hideCustomEmoji () {
+ hideCustomEmoji() {
return !this.$store.state.instance.pleromaCustomEmojiReactionsAvailable
},
- buttonInnerClass () {
+ buttonInnerClass() {
return [
this.button.name + '-button',
{
'main-button': this.extra,
'button-unstyled': !this.extra,
'-active': this.button.active?.(this.funcArg),
- disabled: this.button.interactive ? !this.button.interactive(this.funcArg) : false
- }
+ disabled: this.button.interactive
+ ? !this.button.interactive(this.funcArg)
+ : false,
+ },
]
},
- remoteInteractionLink () {
- return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
- }
+ remoteInteractionLink() {
+ return this.$store.getters.remoteInteractionLink({
+ statusId: this.status.id,
+ })
+ },
},
methods: {
- addReaction (event) {
+ addReaction(event) {
const emoji = event.insertion
- const existingReaction = this.status.emoji_reactions.find(r => r.name === emoji)
+ const existingReaction = this.status.emoji_reactions.find(
+ (r) => r.name === emoji,
+ )
if (existingReaction && existingReaction.me) {
this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })
} else {
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })
}
},
- doActionWrap (button, close = () => {}) {
- if (this.button.interactive ? !this.button.interactive(this.funcArg) : false) return
+ doActionWrap(
+ button,
+ close = () => {
+ /* no-op */
+ },
+ ) {
+ if (
+ this.button.interactive ? !this.button.interactive(this.funcArg) : false
+ )
+ return
this.$emit('interacted')
if (button.name === 'emoji') {
this.$refs.picker.showPicker()
@@ -136,6 +145,6 @@ export default {
}, 500)
close()
}
- }
- }
+ },
+ },
}
diff --git a/src/components/status_action_buttons/action_button_container.js b/src/components/status_action_buttons/action_button_container.js
index a8f20800b..58b382b26 100644
--- a/src/components/status_action_buttons/action_button_container.js
+++ b/src/components/status_action_buttons/action_button_container.js
@@ -1,92 +1,90 @@
-import ActionButton from './action_button.vue'
-import Popover from 'src/components/popover/popover.vue'
import MuteConfirm from 'src/components/confirm_modal/mute_confirm.vue'
+import Popover from 'src/components/popover/popover.vue'
import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
+import ActionButton from './action_button.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
- faUser,
+ faFolderTree,
faGlobe,
- faFolderTree
+ faUser,
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faUser,
- faGlobe,
- faFolderTree
-)
+library.add(faUser, faGlobe, faFolderTree)
export default {
components: {
ActionButton,
Popover,
MuteConfirm,
- UserTimedFilterModal
+ UserTimedFilterModal,
},
props: ['button', 'status'],
emits: ['interacted'],
- mounted () {
+ mounted() {
if (this.button.name === 'mute') {
this.$store.dispatch('fetchDomainMutes')
}
},
computed: {
- buttonClass () {
+ buttonClass() {
return [
this.button.name + '-button',
{
'-with-extra': this.button.name === 'bookmark',
'-extra': this.extra,
- '-quick': !this.extra
- }
+ '-quick': !this.extra,
+ },
]
},
- user () {
+ user() {
return this.status.user
},
- userIsMuted () {
+ userIsMuted() {
return this.$store.getters.relationship(this.user.id).muting
},
- conversationIsMuted () {
+ conversationIsMuted() {
return this.status.thread_muted
},
- domain () {
+ domain() {
return this.user.fqn.split('@')[1]
},
- domainIsMuted () {
- return new Set(this.$store.state.users.currentUser.domainMutes).has(this.domain)
- }
+ domainIsMuted() {
+ return new Set(this.$store.state.users.currentUser.domainMutes).has(
+ this.domain,
+ )
+ },
},
methods: {
- unmuteUser () {
+ unmuteUser() {
return this.$store.dispatch('unmuteUser', this.user.id)
},
- unmuteConversation () {
+ unmuteConversation() {
return this.$store.dispatch('unmuteConversation', { id: this.status.id })
},
- unmuteDomain () {
- return this.$store.dispatch('unmuteDomain', this.user.id)
+ unmuteDomain() {
+ return this.$store.dispatch('unmuteDomain', this.domain)
},
- toggleUserMute () {
+ toggleUserMute() {
if (this.userIsMuted) {
this.unmuteUser()
} else {
this.$refs.confirmUser.optionallyPrompt()
}
},
- toggleConversationMute () {
+ toggleConversationMute() {
if (this.conversationIsMuted) {
this.unmuteConversation()
} else {
this.$refs.confirmConversation.optionallyPrompt()
}
},
- toggleDomainMute () {
+ toggleDomainMute() {
if (this.domainIsMuted) {
this.unmuteDomain()
} else {
this.$refs.confirmDomain.optionallyPrompt()
}
- }
- }
+ },
+ },
}
diff --git a/src/components/status_action_buttons/buttons_definitions.js b/src/components/status_action_buttons/buttons_definitions.js
index bc1e45a98..d1a6845d1 100644
--- a/src/components/status_action_buttons/buttons_definitions.js
+++ b/src/components/status_action_buttons/buttons_definitions.js
@@ -4,257 +4,282 @@ import { useStatusHistoryStore } from 'src/stores/statusHistory.js'
const PRIVATE_SCOPES = new Set(['private', 'direct'])
const PUBLIC_SCOPES = new Set(['public', 'unlisted'])
-export const BUTTONS = [{
- // =========
- // REPLY
- // =========
- name: 'reply',
- label: 'tool_tip.reply',
- icon: 'reply',
- active: ({ replying }) => replying,
- counter: ({ status }) => status.replies_count,
- anon: true,
- anonLink: true,
- toggleable: true,
- closeIndicator: 'times',
- activeIndicator: 'none',
- action ({ emit }) {
- emit('toggleReplying')
- return Promise.resolve()
- }
-}, {
- // =========
- // REPEAT
- // =========
- name: 'retweet',
- label: ({ status }) => status.repeated
- ? 'tool_tip.unrepeat'
- : 'tool_tip.repeat',
- icon ({ status, currentUser }) {
- if (currentUser.id !== status.user.id && PRIVATE_SCOPES.has(status.visibility)) {
- return 'lock'
- }
- return 'retweet'
+export const BUTTONS = [
+ {
+ // =========
+ // REPLY
+ // =========
+ name: 'reply',
+ label: 'tool_tip.reply',
+ icon: 'reply',
+ active: ({ replying }) => replying,
+ counter: ({ status }) => status.replies_count,
+ anon: true,
+ anonLink: true,
+ toggleable: true,
+ closeIndicator: 'times',
+ activeIndicator: 'none',
+ action({ emit }) {
+ emit('toggleReplying')
+ return Promise.resolve()
+ },
},
- animated: true,
- active: ({ status }) => status.repeated,
- counter: ({ status }) => status.repeat_num,
- anonLink: true,
- interactive: ({ status, currentUser }) => !!currentUser && (currentUser.id === status.user.id || !PRIVATE_SCOPES.has(status.visibility)),
- toggleable: true,
- confirm: ({ status, getters }) => !status.repeated && getters.mergedConfig.modalOnRepeat,
- confirmStrings: {
- title: 'status.repeat_confirm_title',
- body: 'status.repeat_confirm',
- confirm: 'status.repeat_confirm_accept_button',
- cancel: 'status.repeat_confirm_cancel_button'
+ {
+ // =========
+ // REPEAT
+ // =========
+ name: 'retweet',
+ label: ({ status }) =>
+ status.repeated ? 'tool_tip.unrepeat' : 'tool_tip.repeat',
+ icon({ status, currentUser }) {
+ if (
+ currentUser.id !== status.user.id &&
+ PRIVATE_SCOPES.has(status.visibility)
+ ) {
+ return 'lock'
+ }
+ return 'retweet'
+ },
+ animated: true,
+ active: ({ status }) => status.repeated,
+ counter: ({ status }) => status.repeat_num,
+ anonLink: true,
+ interactive: ({ status, currentUser }) =>
+ !!currentUser &&
+ (currentUser.id === status.user.id ||
+ !PRIVATE_SCOPES.has(status.visibility)),
+ toggleable: true,
+ confirm: ({ status, getters }) =>
+ !status.repeated && getters.mergedConfig.modalOnRepeat,
+ confirmStrings: {
+ title: 'status.repeat_confirm_title',
+ body: 'status.repeat_confirm',
+ confirm: 'status.repeat_confirm_accept_button',
+ cancel: 'status.repeat_confirm_cancel_button',
+ },
+ action({ status, dispatch }) {
+ if (!status.repeated) {
+ return dispatch('retweet', { id: status.id })
+ } else {
+ return dispatch('unretweet', { id: status.id })
+ }
+ },
},
- action ({ status, dispatch }) {
- if (!status.repeated) {
- return dispatch('retweet', { id: status.id })
- } else {
- return dispatch('unretweet', { id: status.id })
- }
- }
-}, {
- // =========
- // FAVORITE
- // =========
- name: 'favorite',
- label: ({ status }) => status.favorited
- ? 'tool_tip.unfavorite'
- : 'tool_tip.favorite',
- icon: ({ status }) => status.favorited
- ? ['fas', 'star']
- : ['far', 'star'],
- animated: true,
- active: ({ status }) => status.favorited,
- counter: ({ status }) => status.fave_num,
- anonLink: true,
- toggleable: true,
- action ({ status, dispatch }) {
- if (!status.favorited) {
- return dispatch('favorite', { id: status.id })
- } else {
- return dispatch('unfavorite', { id: status.id })
- }
- }
-}, {
- // =========
- // EMOJI REACTIONS
- // =========
- name: 'emoji',
- label: 'tool_tip.add_reaction',
- icon: ['far', 'smile-beam'],
- anonLink: true
-}, {
- // =========
- // MUTE
- // =========
- name: 'mute',
- icon: 'eye-slash',
- label: 'status.mute_ellipsis',
- if: ({ loggedIn }) => loggedIn,
- toggleable: true,
- dropdown: true
- // action ({ status, dispatch, emit }) {
- // }
-}, {
- // =========
- // PIN STATUS
- // =========
- name: 'pin',
- icon: 'thumbtack',
- label: ({ status }) => status.pinned
- ? 'status.unpin'
- : 'status.pin',
- if ({ status, loggedIn, currentUser }) {
- return loggedIn &&
- status.user.id === currentUser.id &&
- PUBLIC_SCOPES.has(status.visibility)
+ {
+ // =========
+ // FAVORITE
+ // =========
+ name: 'favorite',
+ label: ({ status }) =>
+ status.favorited ? 'tool_tip.unfavorite' : 'tool_tip.favorite',
+ icon: ({ status }) =>
+ status.favorited ? ['fas', 'star'] : ['far', 'star'],
+ animated: true,
+ active: ({ status }) => status.favorited,
+ counter: ({ status }) => status.fave_num,
+ anonLink: true,
+ toggleable: true,
+ action({ status, dispatch }) {
+ if (!status.favorited) {
+ return dispatch('favorite', { id: status.id })
+ } else {
+ return dispatch('unfavorite', { id: status.id })
+ }
+ },
},
- action ({ status, dispatch }) {
- if (status.pinned) {
- return dispatch('unpinStatus', status.id)
- } else {
- return dispatch('pinStatus', status.id)
- }
- }
-}, {
- // =========
- // BOOKMARK
- // =========
- name: 'bookmark',
- icon: ({ status }) => status.bookmarked
- ? ['fas', 'bookmark']
- : ['far', 'bookmark'],
- toggleable: true,
- active: ({ status }) => status.bookmarked,
- label: ({ status }) => status.bookmarked
- ? 'status.unbookmark'
- : 'status.bookmark',
- if: ({ loggedIn }) => loggedIn,
- action ({ status, dispatch }) {
- if (status.bookmarked) {
- return dispatch('unbookmark', { id: status.id })
- } else {
- return dispatch('bookmark', { id: status.id })
- }
- }
-}, {
- // =========
- // EDIT HISTORY
- // =========
- name: 'editHistory',
- icon: 'history',
- label: 'status.status_history',
- if ({ status, state }) {
- return state.instance.editingAvailable &&
- status.edited_at !== null
+ {
+ // =========
+ // EMOJI REACTIONS
+ // =========
+ name: 'emoji',
+ label: 'tool_tip.add_reaction',
+ icon: ['far', 'smile-beam'],
+ anonLink: true,
},
- action ({ status }) {
- const originalStatus = { ...status }
- const stripFieldsList = [
- 'attachments',
- 'created_at',
- 'emojis',
- 'text',
- 'raw_html',
- 'nsfw',
- 'poll',
- 'summary',
- 'summary_raw_html'
- ]
- stripFieldsList.forEach(p => delete originalStatus[p])
- useStatusHistoryStore().openStatusHistoryModal(originalStatus)
- return Promise.resolve()
- }
-}, {
- // =========
- // EDIT
- // =========
- name: 'edit',
- icon: 'pen',
- label: 'status.edit',
- if ({ status, loggedIn, currentUser, state }) {
- return loggedIn &&
- state.instance.editingAvailable &&
- status.user.id === currentUser.id
+ {
+ // =========
+ // MUTE
+ // =========
+ name: 'mute',
+ icon: 'eye-slash',
+ label: 'status.mute_ellipsis',
+ if: ({ loggedIn }) => loggedIn,
+ toggleable: true,
+ dropdown: true,
+ // action ({ status, dispatch, emit }) {
+ // }
},
- action ({ dispatch, status }) {
- return dispatch('fetchStatusSource', { id: status.id })
- .then(data => useEditStatusStore().openEditStatusModal({
- statusId: status.id,
- subject: data.spoiler_text,
- statusText: data.text,
- statusIsSensitive: status.nsfw,
- statusPoll: status.poll,
- statusFiles: [...status.attachments],
- visibility: status.visibility,
- statusContentType: data.content_type
- }))
- }
-}, {
- // =========
- // DELETE
- // =========
- name: 'delete',
- icon: 'times',
- label: 'status.delete',
- if ({ status, loggedIn, currentUser }) {
- return loggedIn && (
- status.user.id === currentUser.id ||
- currentUser.privileges.includes('messages_delete')
- )
+ {
+ // =========
+ // PIN STATUS
+ // =========
+ name: 'pin',
+ icon: 'thumbtack',
+ label: ({ status }) => (status.pinned ? 'status.unpin' : 'status.pin'),
+ if({ status, loggedIn, currentUser }) {
+ return (
+ loggedIn &&
+ status.user.id === currentUser.id &&
+ PUBLIC_SCOPES.has(status.visibility)
+ )
+ },
+ action({ status, dispatch }) {
+ if (status.pinned) {
+ return dispatch('unpinStatus', status.id)
+ } else {
+ return dispatch('pinStatus', status.id)
+ }
+ },
},
- confirm: ({ getters }) => getters.mergedConfig.modalOnDelete,
- confirmStrings: {
- title: 'status.delete_confirm_title',
- body: 'status.delete_confirm',
- confirm: 'status.delete_confirm_accept_button',
- cancel: 'status.delete_confirm_cancel_button'
+ {
+ // =========
+ // BOOKMARK
+ // =========
+ name: 'bookmark',
+ icon: ({ status }) =>
+ status.bookmarked ? ['fas', 'bookmark'] : ['far', 'bookmark'],
+ toggleable: true,
+ active: ({ status }) => status.bookmarked,
+ label: ({ status }) =>
+ status.bookmarked ? 'status.unbookmark' : 'status.bookmark',
+ if: ({ loggedIn }) => loggedIn,
+ action({ status, dispatch }) {
+ if (status.bookmarked) {
+ return dispatch('unbookmark', { id: status.id })
+ } else {
+ return dispatch('bookmark', { id: status.id })
+ }
+ },
},
- action ({ dispatch, status }) {
- return dispatch('deleteStatus', { id: status.id })
- }
-}, {
- // =========
- // SHARE/COPY
- // =========
- name: 'share',
- icon: 'share-alt',
- label: 'status.copy_link',
- action ({ state, status, router }) {
- navigator.clipboard.writeText([
- state.instance.server,
- router.resolve({ name: 'conversation', params: { id: status.id } }).href
- ].join(''))
- return Promise.resolve()
- }
-}, {
- // =========
- // EXTERNAL
- // =========
- name: 'external',
- icon: 'external-link-alt',
- label: 'status.external_source',
- link: ({ status }) => status.external_url
-}, {
- // =========
- // REPORT
- // =========
- name: 'report',
- icon: 'flag',
- label: 'user_card.report',
- if: ({ loggedIn }) => loggedIn,
- action ({ status }) {
- return useReportsStore().openUserReportingModal({ userId: status.user.id, statusIds: [status.id] })
- }
-}].map(button => {
+ {
+ // =========
+ // EDIT HISTORY
+ // =========
+ name: 'editHistory',
+ icon: 'history',
+ label: 'status.status_history',
+ if({ status, state }) {
+ return state.instance.editingAvailable && status.edited_at !== null
+ },
+ action({ status }) {
+ const originalStatus = { ...status }
+ const stripFieldsList = [
+ 'attachments',
+ 'created_at',
+ 'emojis',
+ 'text',
+ 'raw_html',
+ 'nsfw',
+ 'poll',
+ 'summary',
+ 'summary_raw_html',
+ ]
+ stripFieldsList.forEach((p) => delete originalStatus[p])
+ useStatusHistoryStore().openStatusHistoryModal(originalStatus)
+ return Promise.resolve()
+ },
+ },
+ {
+ // =========
+ // EDIT
+ // =========
+ name: 'edit',
+ icon: 'pen',
+ label: 'status.edit',
+ if({ status, loggedIn, currentUser, state }) {
+ return (
+ loggedIn &&
+ state.instance.editingAvailable &&
+ status.user.id === currentUser.id
+ )
+ },
+ action({ dispatch, status }) {
+ return dispatch('fetchStatusSource', { id: status.id }).then((data) =>
+ useEditStatusStore().openEditStatusModal({
+ statusId: status.id,
+ subject: data.spoiler_text,
+ statusText: data.text,
+ statusIsSensitive: status.nsfw,
+ statusPoll: status.poll,
+ statusFiles: [...status.attachments],
+ visibility: status.visibility,
+ statusContentType: data.content_type,
+ }),
+ )
+ },
+ },
+ {
+ // =========
+ // DELETE
+ // =========
+ name: 'delete',
+ icon: 'times',
+ label: 'status.delete',
+ if({ status, loggedIn, currentUser }) {
+ return (
+ loggedIn &&
+ (status.user.id === currentUser.id ||
+ currentUser.privileges.includes('messages_delete'))
+ )
+ },
+ confirm: ({ getters }) => getters.mergedConfig.modalOnDelete,
+ confirmStrings: {
+ title: 'status.delete_confirm_title',
+ body: 'status.delete_confirm',
+ confirm: 'status.delete_confirm_accept_button',
+ cancel: 'status.delete_confirm_cancel_button',
+ },
+ action({ dispatch, status }) {
+ return dispatch('deleteStatus', { id: status.id })
+ },
+ },
+ {
+ // =========
+ // SHARE/COPY
+ // =========
+ name: 'share',
+ icon: 'share-alt',
+ label: 'status.copy_link',
+ action({ state, status, router }) {
+ navigator.clipboard.writeText(
+ [
+ state.instance.server,
+ router.resolve({ name: 'conversation', params: { id: status.id } })
+ .href,
+ ].join(''),
+ )
+ return Promise.resolve()
+ },
+ },
+ {
+ // =========
+ // EXTERNAL
+ // =========
+ name: 'external',
+ icon: 'external-link-alt',
+ label: 'status.external_source',
+ link: ({ status }) => status.external_url,
+ },
+ {
+ // =========
+ // REPORT
+ // =========
+ name: 'report',
+ icon: 'flag',
+ label: 'user_card.report',
+ if: ({ loggedIn }) => loggedIn,
+ action({ status }) {
+ return useReportsStore().openUserReportingModal({
+ userId: status.user.id,
+ statusIds: [status.id],
+ })
+ },
+ },
+].map((button) => {
return Object.fromEntries(
Object.entries(button).map(([k, v]) => [
k,
- (typeof v === 'function' || k === 'name') ? v : () => v
- ])
+ typeof v === 'function' || k === 'name' ? v : () => v,
+ ]),
)
})
diff --git a/src/components/status_action_buttons/status_action_buttons.js b/src/components/status_action_buttons/status_action_buttons.js
index 6f84ce8b5..8473a0db1 100644
--- a/src/components/status_action_buttons/status_action_buttons.js
+++ b/src/components/status_action_buttons/status_action_buttons.js
@@ -1,59 +1,56 @@
import { mapState } from 'pinia'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
-import ActionButtonContainer from './action_button_container.vue'
import Popover from 'src/components/popover/popover.vue'
import genRandomSeed from 'src/services/random_seed/random_seed.service.js'
-
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
-
+import ActionButtonContainer from './action_button_container.vue'
import { BUTTONS } from './buttons_definitions.js'
import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faEllipsisH
-} from '@fortawesome/free-solid-svg-icons'
+import { faEllipsisH } from '@fortawesome/free-solid-svg-icons'
-library.add(
- faEllipsisH
-)
+library.add(faEllipsisH)
const StatusActionButtons = {
props: ['status', 'replying'],
emits: ['toggleReplying', 'interacted'],
- data () {
+ data() {
return {
showPin: false,
showingConfirmDialog: false,
currentConfirmTitle: '',
currentConfirmOkText: '',
currentConfirmCancelText: '',
- currentConfirmAction: () => {},
- randomSeed: genRandomSeed()
+ currentConfirmAction: () => {
+ /* no-op */
+ },
+ randomSeed: genRandomSeed(),
}
},
components: {
Popover,
ConfirmModal,
- ActionButtonContainer
+ ActionButtonContainer,
},
computed: {
...mapState(useServerSideStorageStore, {
- pinnedItems: store => new Set(store.prefsStorage.collections.pinnedStatusActions)
+ pinnedItems: (store) =>
+ new Set(store.prefsStorage.collections.pinnedStatusActions),
}),
- buttons () {
- return BUTTONS.filter(x => x.if ? x.if(this.funcArg) : true)
+ buttons() {
+ return BUTTONS.filter((x) => (x.if ? x.if(this.funcArg) : true))
},
- quickButtons () {
- return this.buttons.filter(x => this.pinnedItems.has(x.name))
+ quickButtons() {
+ return this.buttons.filter((x) => this.pinnedItems.has(x.name))
},
- extraButtons () {
- return this.buttons.filter(x => !this.pinnedItems.has(x.name))
+ extraButtons() {
+ return this.buttons.filter((x) => !this.pinnedItems.has(x.name))
},
- currentUser () {
+ currentUser() {
return this.$store.state.users.currentUser
},
- funcArg () {
+ funcArg() {
return {
status: this.status,
replying: this.replying,
@@ -63,25 +60,33 @@ const StatusActionButtons = {
getters: this.$store.getters,
router: this.$router,
currentUser: this.currentUser,
- loggedIn: !!this.currentUser
+ loggedIn: !!this.currentUser,
}
},
- triggerAttrs () {
+ triggerAttrs() {
return {
title: this.$t('status.more_actions'),
'aria-controls': `popup-menu-${this.randomSeed}`,
- 'aria-haspopup': 'menu'
+ 'aria-haspopup': 'menu',
}
- }
+ },
},
methods: {
- doAction (button) {
+ doAction(button) {
if (button.confirm?.(this.funcArg)) {
// TODO move to action_button
- this.currentConfirmTitle = this.$t(button.confirmStrings(this.funcArg).title)
- this.currentConfirmOkText = this.$t(button.confirmStrings(this.funcArg).confirm)
- this.currentConfirmCancelText = this.$t(button.confirmStrings(this.funcArg).cancel)
- this.currentConfirmBody = this.$t(button.confirmStrings(this.funcArg).body)
+ this.currentConfirmTitle = this.$t(
+ button.confirmStrings(this.funcArg).title,
+ )
+ this.currentConfirmOkText = this.$t(
+ button.confirmStrings(this.funcArg).confirm,
+ )
+ this.currentConfirmCancelText = this.$t(
+ button.confirmStrings(this.funcArg).cancel,
+ )
+ this.currentConfirmBody = this.$t(
+ button.confirmStrings(this.funcArg).body,
+ )
this.currentConfirmAction = () => {
this.showingConfirmDialog = false
this.doActionReal(button)
@@ -91,26 +96,33 @@ const StatusActionButtons = {
this.doActionReal(button)
}
},
- doActionReal (button) {
- button.action(this.funcArg)
+ doActionReal(button) {
+ button
+ .action?.(this.funcArg)
.then(() => this.$emit('onSuccess'))
- .catch(err => this.$emit('onError', err.error.error))
+ .catch((err) => this.$emit('onError', err.error.error))
},
- onExtraClose () {
+ onExtraClose() {
this.showPin = false
},
- isPinned (button) {
+ isPinned(button) {
return this.pinnedItems.has(button.name)
},
- unpin (button) {
- useServerSideStorageStore().removeCollectionPreference({ path: 'collections.pinnedStatusActions', value: button.name })
+ unpin(button) {
+ useServerSideStorageStore().removeCollectionPreference({
+ path: 'collections.pinnedStatusActions',
+ value: button.name,
+ })
useServerSideStorageStore().pushServerSideStorage()
},
- pin (button) {
- useServerSideStorageStore().addCollectionPreference({ path: 'collections.pinnedStatusActions', value: button.name })
+ pin(button) {
+ useServerSideStorageStore().addCollectionPreference({
+ path: 'collections.pinnedStatusActions',
+ value: button.name,
+ })
useServerSideStorageStore().pushServerSideStorage()
},
- getComponent (button) {
+ getComponent(button) {
if (!this.$store.state.users.currentUser && button.anonLink) {
return 'a'
} else if (button.action == null && button.link != null) {
@@ -119,16 +131,18 @@ const StatusActionButtons = {
return 'button'
}
},
- getClass (button) {
+ getClass(button) {
return {
[button.name + '-button']: true,
- disabled: button.interactive ? !button.interactive(this.funcArg) : false,
+ disabled: button.interactive
+ ? !button.interactive(this.funcArg)
+ : false,
'-pin-edit': this.showPin,
'-dropdown': button.dropdown?.(),
- '-active': button.active?.(this.funcArg)
+ '-active': button.active?.(this.funcArg),
}
- }
- }
+ },
+ },
}
export default StatusActionButtons
diff --git a/src/components/status_action_buttons/status_action_buttons.vue b/src/components/status_action_buttons/status_action_buttons.vue
index 40884425c..c1d0d9571 100644
--- a/src/components/status_action_buttons/status_action_buttons.vue
+++ b/src/components/status_action_buttons/status_action_buttons.vue
@@ -15,7 +15,7 @@
:func-arg="funcArg"
:get-class="getClass"
:get-component="getComponent"
- :close="() => {}"
+ :close="() => { /* no-op */ }"
:do-action="doAction"
@interacted="e => $emit('interacted')"
/>
diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js
index 9a56060e8..80f8400b6 100644
--- a/src/components/status_body/status_body.js
+++ b/src/components/status_body/status_body.js
@@ -1,22 +1,18 @@
-import fileType from 'src/services/file_type/file_type.service'
-import RichContent from 'src/components/rich_content/rich_content.jsx'
import { mapGetters } from 'vuex'
+
+import RichContent from 'src/components/rich_content/rich_content.jsx'
+import fileType from 'src/services/file_type/file_type.service'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faFile,
- faMusic,
faImage,
faLink,
- faPollH
+ faMusic,
+ faPollH,
} from '@fortawesome/free-solid-svg-icons'
-library.add(
- faFile,
- faMusic,
- faImage,
- faLink,
- faPollH
-)
+library.add(faFile, faMusic, faImage, faLink, faPollH)
const StatusBody = {
name: 'StatusBody',
@@ -33,17 +29,17 @@ const StatusBody = {
'showingLongSubject',
'toggleShowingTall',
'toggleExpandingSubject',
- 'toggleShowingLongSubject'
+ 'toggleShowingLongSubject',
],
- data () {
+ data() {
return {
postLength: this.status.text.length,
- parseReadyDone: false
+ parseReadyDone: false,
}
},
emits: ['parseReady'],
computed: {
- localCollapseSubjectDefault () {
+ localCollapseSubjectDefault() {
return this.mergedConfig.collapseMessageWithSubject
},
// This is a bit hacky, but we want to approximate post height before rendering
@@ -53,73 +49,87 @@ const StatusBody = {
//
// Using max-height + overflow: auto for status components resulted in false positives
// very often with japanese characters, and it was very annoying.
- tallStatus () {
+ tallStatus() {
if (this.singleLine || this.compact) return false
- const lengthScore = this.status.raw_html.split(/
20
},
- longSubject () {
+ longSubject() {
return this.status.summary.length > 240
},
// When a status has a subject and is also tall, we should only have one show more/less button. If the default is to collapse statuses with subjects, we just treat it like a status with a subject; otherwise, we just treat it like a tall status.
- mightHideBecauseSubject () {
+ mightHideBecauseSubject() {
return !!this.status.summary && this.localCollapseSubjectDefault
},
- mightHideBecauseTall () {
- return this.tallStatus && !(this.status.summary && this.localCollapseSubjectDefault)
+ mightHideBecauseTall() {
+ return (
+ this.tallStatus &&
+ !(this.status.summary && this.localCollapseSubjectDefault)
+ )
},
- hideSubjectStatus () {
+ hideSubjectStatus() {
return this.mightHideBecauseSubject && !this.expandingSubject
},
- hideTallStatus () {
+ hideTallStatus() {
return this.mightHideBecauseTall && !this.showingTall
},
- shouldShowToggle () {
+ shouldShowToggle() {
return this.mightHideBecauseSubject || this.mightHideBecauseTall
},
- toggleButtonClasses () {
+ toggleButtonClasses() {
return {
'cw-status-hider': !this.showingMore && this.mightHideBecauseSubject,
'tall-status-hider': !this.showingMore && this.mightHideBecauseTall,
'status-unhider': this.showingMore,
}
},
- toggleText () {
+ toggleText() {
if (this.showingMore) {
- return this.mightHideBecauseSubject ? this.$t('status.hide_content') : this.$t('general.show_less')
+ return this.mightHideBecauseSubject
+ ? this.$t('status.hide_content')
+ : this.$t('general.show_less')
} else {
- return this.mightHideBecauseSubject ? this.$t('status.show_content') : this.$t('general.show_more')
+ return this.mightHideBecauseSubject
+ ? this.$t('status.show_content')
+ : this.$t('general.show_more')
}
},
- showingMore () {
- return (this.mightHideBecauseTall && this.showingTall) || (this.mightHideBecauseSubject && this.expandingSubject)
+ showingMore() {
+ return (
+ (this.mightHideBecauseTall && this.showingTall) ||
+ (this.mightHideBecauseSubject && this.expandingSubject)
+ )
},
- attachmentTypes () {
- return this.status.attachments.map(file => fileType.fileType(file.mimetype))
+ attachmentTypes() {
+ return this.status.attachments.map((file) =>
+ fileType.fileType(file.mimetype),
+ )
},
- collapsedStatus () {
+ collapsedStatus() {
return this.status.raw_html.replace(/(\n|
)/g, ' ')
},
- ...mapGetters(['mergedConfig'])
+ ...mapGetters(['mergedConfig']),
},
components: {
- RichContent
+ RichContent,
},
- mounted () {
- this.status.attentions && this.status.attentions.forEach(attn => {
- const { id } = attn
- this.$store.dispatch('fetchUserIfMissing', id)
- })
+ mounted() {
+ this.status.attentions &&
+ this.status.attentions.forEach((attn) => {
+ const { id } = attn
+ this.$store.dispatch('fetchUserIfMissing', id)
+ })
},
methods: {
- onParseReady (event) {
+ onParseReady(event) {
if (this.parseReadyDone) return
this.parseReadyDone = true
this.$emit('parseReady', event)
const { writtenMentions, invisibleMentions } = event
writtenMentions
- .filter(mention => !mention.notifying)
- .forEach(mention => {
+ .filter((mention) => !mention.notifying)
+ .forEach((mention) => {
const { content, url } = mention
const cleanedString = content.replace(/<[^>]+?>/gi, '') // remove all tags
if (!cleanedString.startsWith('@')) return
@@ -137,17 +147,17 @@ const StatusBody = {
return acc - mention.textContent.length - 1
}, this.postLength)
},
- toggleShowMore () {
+ toggleShowMore() {
if (this.mightHideBecauseTall) {
this.toggleShowingTall()
} else if (this.mightHideBecauseSubject) {
this.toggleExpandingSubject()
}
},
- generateTagLink (tag) {
+ generateTagLink(tag) {
return `/tag/${tag}`
- }
- }
+ },
+ },
}
export default StatusBody
diff --git a/src/components/status_bookmark_folder_menu/status_bookmark_folder_menu.js b/src/components/status_bookmark_folder_menu/status_bookmark_folder_menu.js
index 72d4f6fda..4aa617832 100644
--- a/src/components/status_bookmark_folder_menu/status_bookmark_folder_menu.js
+++ b/src/components/status_bookmark_folder_menu/status_bookmark_folder_menu.js
@@ -1,42 +1,41 @@
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { faChevronRight, faFolder } from '@fortawesome/free-solid-svg-icons'
import { mapState } from 'pinia'
-import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
import Popover from 'src/components/popover/popover.vue'
import StillImage from 'src/components/still-image/still-image.vue'
+import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faChevronRight, faFolder } from '@fortawesome/free-solid-svg-icons'
library.add(faChevronRight, faFolder)
const StatusBookmarkFolderMenu = {
- props: [
- 'status',
- 'close'
- ],
- data () {
+ props: ['status', 'close'],
+ data() {
return {}
},
components: {
Popover,
- StillImage
+ StillImage,
},
computed: {
...mapState(useBookmarkFoldersStore, {
- folders: store => store.allFolders
+ folders: (store) => store.allFolders,
}),
- folderId () {
+ folderId() {
return this.status.bookmark_folder_id
- }
+ },
},
methods: {
- toggleFolder (id) {
+ toggleFolder(id) {
const value = id === this.folderId ? null : id
- this.$store.dispatch('bookmark', { id: this.status.id, bookmark_folder_id: value })
+ this.$store
+ .dispatch('bookmark', { id: this.status.id, bookmark_folder_id: value })
.then(() => this.$emit('onSuccess'))
- .catch(err => this.$emit('onError', err.error.error))
- }
- }
+ .catch((err) => this.$emit('onError', err.error.error))
+ },
+ },
}
export default StatusBookmarkFolderMenu
diff --git a/src/components/status_content/status_content.js b/src/components/status_content/status_content.js
index 364123f49..51bfe6f1e 100644
--- a/src/components/status_content/status_content.js
+++ b/src/components/status_content/status_content.js
@@ -1,41 +1,41 @@
-import Attachment from '../attachment/attachment.vue'
-import Poll from '../poll/poll.vue'
-import Gallery from '../gallery/gallery.vue'
-import StatusBody from 'src/components/status_body/status_body.vue'
-import LinkPreview from '../link-preview/link-preview.vue'
import { mapGetters, mapState } from 'vuex'
+
+import StatusBody from 'src/components/status_body/status_body.vue'
+import { useMediaViewerStore } from 'src/stores/media_viewer'
+import Attachment from '../attachment/attachment.vue'
+import Gallery from '../gallery/gallery.vue'
+import LinkPreview from '../link-preview/link-preview.vue'
+import Poll from '../poll/poll.vue'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faCircleNotch,
faFile,
- faMusic,
faImage,
faLink,
- faPollH
+ faMusic,
+ faPollH,
} from '@fortawesome/free-solid-svg-icons'
-import { useMediaViewerStore } from 'src/stores/media_viewer'
-library.add(
- faCircleNotch,
- faFile,
- faMusic,
- faImage,
- faLink,
- faPollH
-)
+library.add(faCircleNotch, faFile, faMusic, faImage, faLink, faPollH)
-const camelCase = name => name.charAt(0).toUpperCase() + name.slice(1)
+const camelCase = (name) => name.charAt(0).toUpperCase() + name.slice(1)
-const controlledOrUncontrolledGetters = list => list.reduce((res, name) => {
- const camelized = camelCase(name)
- const toggle = `controlledToggle${camelized}`
- const controlledName = `controlled${camelized}`
- const uncontrolledName = `uncontrolled${camelized}`
- res[name] = function () {
- return ((this.$data[toggle] !== undefined || this.$props[toggle] !== undefined) && this[toggle]) ? this[controlledName] : this[uncontrolledName]
- }
- return res
-}, {})
+const controlledOrUncontrolledGetters = (list) =>
+ list.reduce((res, name) => {
+ const camelized = camelCase(name)
+ const toggle = `controlledToggle${camelized}`
+ const controlledName = `controlled${camelized}`
+ const uncontrolledName = `uncontrolled${camelized}`
+ res[name] = function () {
+ return (this.$data[toggle] !== undefined ||
+ this.$props[toggle] !== undefined) &&
+ this[toggle]
+ ? this[controlledName]
+ : this[uncontrolledName]
+ }
+ return res
+ }, {})
const controlledOrUncontrolledToggle = (obj, name) => {
const camelized = camelCase(name)
@@ -63,28 +63,38 @@ const StatusContent = {
'controlledToggleShowingTall',
'controlledToggleExpandingSubject',
'controlledShowingLongSubject',
- 'controlledToggleShowingLongSubject'
+ 'controlledToggleShowingLongSubject',
],
emits: ['parseReady', 'mediaplay', 'mediapause'],
- data () {
+ data() {
return {
- uncontrolledShowingTall: this.fullContent || (this.inConversation && this.focused),
+ uncontrolledShowingTall:
+ this.fullContent || (this.inConversation && this.focused),
uncontrolledShowingLongSubject: false,
// not as computed because it sets the initial state which will be changed later
- uncontrolledExpandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject
+ uncontrolledExpandingSubject:
+ !this.$store.getters.mergedConfig.collapseMessageWithSubject,
}
},
computed: {
- ...controlledOrUncontrolledGetters(['showingTall', 'expandingSubject', 'showingLongSubject']),
- statusCard () {
+ ...controlledOrUncontrolledGetters([
+ 'showingTall',
+ 'expandingSubject',
+ 'showingLongSubject',
+ ]),
+ statusCard() {
if (!this.status.card) return null
- return this.status.card.url === this.status.quote_url ? null : this.status.card
+ return this.status.card.url === this.status.quote_url
+ ? null
+ : this.status.card
},
- hideAttachments () {
- return (this.mergedConfig.hideAttachments && !this.inConversation) ||
+ hideAttachments() {
+ return (
+ (this.mergedConfig.hideAttachments && !this.inConversation) ||
(this.mergedConfig.hideAttachmentsInConv && this.inConversation)
+ )
},
- nsfwClickthrough () {
+ nsfwClickthrough() {
if (!this.status.nsfw) {
return false
}
@@ -93,49 +103,54 @@ const StatusContent = {
}
return true
},
- localCollapseSubjectDefault () {
+ localCollapseSubjectDefault() {
return this.mergedConfig.collapseMessageWithSubject
},
- attachmentSize () {
+ attachmentSize() {
if (this.compact) {
return 'small'
- } else if ((this.mergedConfig.hideAttachments && !this.inConversation) ||
+ } else if (
+ (this.mergedConfig.hideAttachments && !this.inConversation) ||
(this.mergedConfig.hideAttachmentsInConv && this.inConversation) ||
- (this.status.attachments.length > this.maxThumbnails)) {
+ this.status.attachments.length > this.maxThumbnails
+ ) {
return 'hide'
}
return 'normal'
},
- maxThumbnails () {
+ maxThumbnails() {
return this.mergedConfig.maxThumbnails
},
...mapGetters(['mergedConfig']),
...mapState({
- currentUser: state => state.users.currentUser
- })
+ currentUser: (state) => state.users.currentUser,
+ }),
},
components: {
Attachment,
Poll,
Gallery,
LinkPreview,
- StatusBody
+ StatusBody,
},
methods: {
- toggleShowingTall () {
+ toggleShowingTall() {
controlledOrUncontrolledToggle(this, 'showingTall')
},
- toggleExpandingSubject () {
+ toggleExpandingSubject() {
controlledOrUncontrolledToggle(this, 'expandingSubject')
},
- toggleShowingLongSubject () {
+ toggleShowingLongSubject() {
controlledOrUncontrolledToggle(this, 'showingLongSubject')
},
- setMedia () {
- const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments
+ setMedia() {
+ const attachments =
+ this.attachmentSize === 'hide'
+ ? this.status.attachments
+ : this.galleryAttachments
return () => useMediaViewerStore().setMedia(attachments)
- }
- }
+ },
+ },
}
export default StatusContent
diff --git a/src/components/status_history_modal/status_history_modal.js b/src/components/status_history_modal/status_history_modal.js
index 215f8152e..1ad48ace3 100644
--- a/src/components/status_history_modal/status_history_modal.js
+++ b/src/components/status_history_modal/status_history_modal.js
@@ -1,61 +1,64 @@
import { get } from 'lodash'
+
+import { useStatusHistoryStore } from 'src/stores/statusHistory'
import Modal from '../modal/modal.vue'
import Status from '../status/status.vue'
-import { useStatusHistoryStore } from 'src/stores/statusHistory'
const StatusHistoryModal = {
components: {
Modal,
- Status
+ Status,
},
- data () {
+ data() {
return {
- statuses: []
+ statuses: [],
}
},
computed: {
- modalActivated () {
+ modalActivated() {
return useStatusHistoryStore().modalActivated
},
- params () {
+ params() {
return useStatusHistoryStore().params
},
- statusId () {
+ statusId() {
return this.params.id
},
- historyCount () {
+ historyCount() {
return this.statuses.length
},
- history () {
+ history() {
return this.statuses
- }
+ },
},
watch: {
- params (newVal, oldVal) {
+ params(newVal, oldVal) {
const newStatusId = get(newVal, 'id') !== get(oldVal, 'id')
if (newStatusId) {
this.resetHistory()
}
- if (newStatusId || get(newVal, 'edited_at') !== get(oldVal, 'edited_at')) {
+ if (
+ newStatusId ||
+ get(newVal, 'edited_at') !== get(oldVal, 'edited_at')
+ ) {
this.fetchStatusHistory()
}
- }
+ },
},
methods: {
- resetHistory () {
+ resetHistory() {
this.statuses = []
},
- fetchStatusHistory () {
- this.$store.dispatch('fetchStatusHistory', this.params)
- .then(data => {
- this.statuses = data
- })
+ fetchStatusHistory() {
+ this.$store.dispatch('fetchStatusHistory', this.params).then((data) => {
+ this.statuses = data
+ })
},
- closeModal () {
+ closeModal() {
useStatusHistoryStore().closeStatusHistoryModal()
- }
- }
+ },
+ },
}
export default StatusHistoryModal
diff --git a/src/components/status_popover/status_popover.js b/src/components/status_popover/status_popover.js
index 2615208d2..9ad12356e 100644
--- a/src/components/status_popover/status_popover.js
+++ b/src/components/status_popover/status_popover.js
@@ -1,51 +1,49 @@
import { find } from 'lodash'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
import { defineAsyncComponent } from 'vue'
-library.add(
- faCircleNotch
-)
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
+
+library.add(faCircleNotch)
const StatusPopover = {
name: 'StatusPopover',
- props: [
- 'statusId'
- ],
- data () {
+ props: ['statusId'],
+ data() {
return {
- error: false
+ error: false,
}
},
computed: {
- status () {
+ status() {
return find(this.$store.state.statuses.allStatuses, { id: this.statusId })
- }
+ },
},
components: {
Status: defineAsyncComponent(() => import('../status/status.vue')),
- Popover: defineAsyncComponent(() => import('../popover/popover.vue'))
+ Popover: defineAsyncComponent(() => import('../popover/popover.vue')),
},
methods: {
- enter () {
+ enter() {
if (!this.status) {
if (!this.statusId) {
this.error = true
return
}
- this.$store.dispatch('fetchStatus', this.statusId)
+ this.$store
+ .dispatch('fetchStatus', this.statusId)
.then(() => (this.error = false))
.catch(() => (this.error = true))
}
- }
+ },
},
watch: {
- status (newStatus, oldStatus) {
+ status(newStatus, oldStatus) {
if (newStatus !== oldStatus) {
this.$nextTick(() => this.$refs.popover.updateStyles())
}
- }
- }
+ },
+ },
}
export default StatusPopover
diff --git a/src/components/sticker_picker/sticker_picker.js b/src/components/sticker_picker/sticker_picker.js
index b06384e5f..6a6aed862 100644
--- a/src/components/sticker_picker/sticker_picker.js
+++ b/src/components/sticker_picker/sticker_picker.js
@@ -4,49 +4,50 @@ import TabSwitcher from '../tab_switcher/tab_switcher.jsx'
const StickerPicker = {
components: {
- TabSwitcher
+ TabSwitcher,
},
- data () {
+ data() {
return {
meta: {
- stickers: []
+ stickers: [],
},
- path: ''
+ path: '',
}
},
computed: {
- pack () {
+ pack() {
return this.$store.state.instance.stickers || []
- }
+ },
},
methods: {
- clear () {
+ clear() {
this.meta = {
- stickers: []
+ stickers: [],
}
},
- pick (sticker, name) {
+ pick(sticker, name) {
const store = this.$store
// TODO remove this workaround by finding a way to bypass reuploads
- fetch(sticker)
- .then((res) => {
- res.blob().then((blob) => {
- const file = new File([blob], name, { mimetype: 'image/png' })
- const formData = new FormData()
- formData.append('file', file)
- statusPosterService.uploadMedia({ store, formData })
- .then((fileData) => {
- this.$emit('uploaded', fileData)
- this.clear()
- }, (error) => {
- console.warn("Can't attach sticker")
- console.warn(error)
- this.$emit('upload-failed', 'default')
- })
- })
+ fetch(sticker).then((res) => {
+ res.blob().then((blob) => {
+ const file = new File([blob], name, { mimetype: 'image/png' })
+ const formData = new FormData()
+ formData.append('file', file)
+ statusPosterService.uploadMedia({ store, formData }).then(
+ (fileData) => {
+ this.$emit('uploaded', fileData)
+ this.clear()
+ },
+ (error) => {
+ console.warn("Can't attach sticker")
+ console.warn(error)
+ this.$emit('upload-failed', 'default')
+ },
+ )
})
- }
- }
+ })
+ },
+ },
}
export default StickerPicker
diff --git a/src/components/still-image/still-image-emoji-popover.vue b/src/components/still-image/still-image-emoji-popover.vue
index 8317c6a0c..f8ff89a6f 100644
--- a/src/components/still-image/still-image-emoji-popover.vue
+++ b/src/components/still-image/still-image-emoji-popover.vue
@@ -56,51 +56,54 @@