Merge pull request 'Cleanup issues found by SonarQube' (#3527) from sonarqube-cleanup into develop

Reviewed-on: https://git.pleroma.social/pleroma/pleroma-fe/pulls/3527
This commit is contained in:
HJ 2026-08-04 13:48:16 +00:00
commit 4f82709bf2
66 changed files with 275 additions and 343 deletions

View file

@ -1,41 +0,0 @@
import chalk from 'chalk'
import semver from 'semver'
import packageConfig from '../package.json' with { type: 'json' }
var versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node,
},
]
export default function () {
const warnings = []
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),
)
}
}
if (warnings.length) {
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)
}
process.exit(1)
}
}

View file

@ -1,8 +1,8 @@
import childProcess from 'child_process'
import childProcess from 'node:child_process'
export const getCommitHash = () => {
const subst = '$Format:%h$'
if (!subst.match(/Format:/)) {
if (!/Format:/.exec(subst)) {
return subst
} else {
try {

View file

@ -31,7 +31,6 @@ export const buildSwPlugin = ({ swSrc, swDest }) => {
name: 'build-sw-plugin',
enforce: 'post',
configResolved(resolvedConfig) {
resolvedConfig
config = {
define: resolvedConfig.define,
resolve: resolvedConfig.resolve,
@ -60,7 +59,7 @@ export const buildSwPlugin = ({ swSrc, swDest }) => {
sequential: true,
async handler(_, bundle) {
const assets = Object.keys(bundle)
.filter((name) => !/\.map$/.test(name))
.filter((name) => !name.endsWith('.map'))
.map((name) => '/' + name)
config.plugins.push({

View file

@ -1,10 +1,10 @@
import fs from 'node:fs'
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) => {
emojis[k].forEach((e) => {
delete e.unicode_version
delete e.emoji_version
delete e.skin_tone_support_unicode_version
@ -12,11 +12,15 @@ Object.keys(emojis).map((k) => {
})
const res = {}
Object.keys(emojis).map((k) => {
const groupId = k.replace('&', 'and').replace(/ /g, '-').toLowerCase()
Object.keys(emojis).forEach((k) => {
const groupId = k.replace('&', 'and').replaceAll(' ', '-').toLowerCase()
res[groupId] = emojis[k]
})
console.info('Updating emojis...')
fs.writeFileSync('src/assets/emoji.json', JSON.stringify(res))
console.info('Done.')
try {
fs.writeFileSync('src/assets/emoji.json', JSON.stringify(res))
console.info('Done.')
} catch (e) {
console.error('Failed updating emoji', e)
}

View file

@ -1,15 +1,19 @@
FROM mcr.microsoft.com/playwright:v1.61.0-jammy
RUN npm install -g yarn@1.22.22
RUN adduser --system playwright --group --shell=/bin/bash
USER playwright
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 . .
COPY --chown=playwright ./build ./src ./test ./public ./static ./yarn.lock ./package.json .
ENV CI=1

View file

@ -31,7 +31,7 @@
<div class="chunk" id="chunk-E">
</div>
</div>
<img id="mascot" src="/static/pleromatan_apology_small.webp">
<img id="mascot" alt="A cute mascot" src="/static/pleromatan_apology_small.webp">
</div>
<div id="status" class="css-ok">
<!-- (。><) -->

View file

@ -6,4 +6,4 @@
Pleroma install containing the real ToS for your instance.</p>
<p>See the <a href='https://docs.pleroma.social/backend/configuration/static_dir/'>Pleroma documentation</a> for more information.</p>
<br>
<img src="/static/logo.svg" style="display: block; margin: auto; max-width: 100%; height: 50px; object-fit: contain;" />
<img src="/static/logo.svg" alt="Pleroma Logo" style="display: block; margin: auto; max-width: 100%; height: 50px; object-fit: contain;" />

View file

@ -1,10 +1,11 @@
// stylelint-disable rscss/class-format
/* stylelint-disable no-descending-specificity */
@use "panel";
@import '@fortawesome/fontawesome-svg-core/styles.css';
@import '@kazvmoe-infra/pinch-zoom-element/dist/pinch-zoom.css';
// stylelint-disable rscss/class-format
/* stylelint-disable no-descending-specificity */
:root {
--status-margin: 0.75em;
--post-line-height: 1.4;
@ -934,7 +935,6 @@ option {
#splash {
pointer-events: none;
// transition: opacity 0.5s;
#status {
&.css-ok {

View file

@ -39,7 +39,7 @@ const USERS_URL_LIST = ({
isAdmin && 'is_admin',
isModerator && 'is_moderator',
]
.filter((x) => x)
.filter(Boolean)
.join(',')
return `/api/v1/pleroma/admin/users?page=${page}&page_size=${pageSize}&filters=${filters_str}&query=${query}&name=${name}&email=${email}`
}
@ -236,7 +236,7 @@ export const changeStatusScope = ({
opts: { id, sensitive, visibility },
credentials,
}) => {
var payload = {}
const payload = {}
if (typeof sensitive !== 'undefined') {
payload['sensitive'] = sensitive
}

View file

@ -6,12 +6,12 @@ export const paramsString = (params = {}) => {
if (params == null || params === undefined) return ''
if (typeof params !== 'object' || Array.isArray(params)) {
throw new Error('Params are not an object!')
throw new TypeError('Params are not an object!')
}
const entries = (() => {
if (params instanceof Map) {
return params.entries()
return [...params.entries()]
} else {
return Object.entries(params)
}
@ -26,7 +26,7 @@ export const paramsString = (params = {}) => {
(typeof v === 'object' && !Array.isArray(v)) ||
typeof v === 'function'
) {
throw new Error('Param cannot be non-primitive!')
throw new TypeError('Param cannot be non-primitive!')
}
if (Array.isArray(v)) {
arrays.push([k, v])
@ -42,7 +42,7 @@ export const paramsString = (params = {}) => {
typeof v === 'function' ||
typeof v === 'undefined'
)
throw new Error('Array param cannot contain non-primitives!')
throw new TypeError('Array param cannot contain non-primitives!')
})
})
@ -109,7 +109,9 @@ export const promisedRequest = async ({
.get('content-type')
.split(';')
.map((x) => x.toLowerCase().trim())
const contentLength = parseInt(response.headers.get('content-length'))
const contentLength = Number.parseInt(
response.headers.get('content-length'),
)
if (contentLength === 0) return null
switch (contentType) {

View file

@ -105,7 +105,7 @@ export const fetchUserByName = ({ name, credentials }) =>
})
.then(({ data }) => data.id)
.catch((error) => {
if (error && error.statusCode === 404) {
if (error?.statusCode === 404) {
// Either the backend does not support lookup endpoint,
// or there is no user with such name. Fallback and treat name as id.
return name

View file

@ -1,4 +1,4 @@
import { concat, last } from 'lodash'
import { last } from 'lodash'
import { paramsString, promisedRequest } from './helpers.js'
import { fetchFriends, MASTODON_STATUS_URL } from './public.js'
@ -220,7 +220,7 @@ export const postStatus = ({
})
if (pollOptions.some((option) => option !== '')) {
const normalizedPoll = {
expires_in: parseInt(poll.expiresIn, 10),
expires_in: Number.parseInt(poll.expiresIn, 10),
multiple: poll.multiple,
}
Object.keys(normalizedPoll).forEach((key) => {
@ -278,7 +278,7 @@ export const editStatus = ({
if (pollOptions.some((option) => option !== '')) {
const normalizedPoll = {
expires_in: parseInt(poll.expiresIn, 10),
expires_in: Number.parseInt(poll.expiresIn, 10),
multiple: poll.multiple,
}
Object.keys(normalizedPoll).forEach((key) => {
@ -412,7 +412,7 @@ export const exportFriends = ({ id, credentials }) => {
credentials,
withRelationships: true,
})
friends = concat(friends, users)
friends = [...friends, ...users]
if (users.length === 0) {
more = false
}
@ -613,7 +613,7 @@ export const listAliases = ({ credentials }) =>
method: 'GET',
credentials,
params: {
_cacheBooster: new Date().getTime(),
_cacheBooster: Date.now(),
},
})
@ -799,7 +799,7 @@ export const listBackups = ({ credentials }) =>
method: 'GET',
credentials,
params: {
_cacheBooster: new Date().getTime(),
_cacheBooster: Date.now(),
},
})

View file

@ -141,13 +141,11 @@ export const handleMastoWS = (
if (data.result === 'success') {
console.debug('[WS] Successfully authenticated')
onAuthenticated()
} else if (data.error === 'already_authenticated') {
onAuthenticated()
} else {
if (data.error === 'already_authenticated') {
onAuthenticated()
} else {
console.error('[WS] Unable to authenticate:', data.error)
wsEvent.target.close()
}
console.error('[WS] Unable to authenticate:', data.error)
wsEvent.target.close()
}
}
return null

View file

@ -63,14 +63,14 @@ const parsedInitialResults = () => {
const decodeUTF8Base64 = (data) => {
const rawData = atob(data)
const array = Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)))
const array = Uint8Array.from([...rawData].map((char) => char.codePointAt(0)))
const text = new TextDecoder().decode(array)
return text
}
const preloadFetch = async (request) => {
const data = parsedInitialResults()
if (!data || !data[request]) {
if (!data?.[request]) {
return window.fetch(request)
}
const decoded = decodeUTF8Base64(data[request])
@ -170,9 +170,9 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
let config = {}
if (overrides.staticConfigPreference && env === 'development') {
console.warn('OVERRIDING API CONFIG WITH STATIC CONFIG')
config = Object.assign({}, apiConfig, staticConfig)
config = { ...apiConfig, ...staticConfig }
} else {
config = Object.assign({}, staticConfig, apiConfig)
config = { ...staticConfig, ...apiConfig }
}
Object.keys(INSTANCE_IDENTITY_DEFAULT_DEFINITIONS).forEach((source) => {
@ -353,19 +353,19 @@ const getNodeInfo = async ({ store }) => {
const uploadLimits = metadata.uploadLimits
useInstanceStore().set({
path: 'limits.uploadlimit',
value: parseInt(uploadLimits.general),
value: Number.parseInt(uploadLimits.general),
})
useInstanceStore().set({
path: 'limits.avatarlimit',
value: parseInt(uploadLimits.avatar),
value: Number.parseInt(uploadLimits.avatar),
})
useInstanceStore().set({
path: 'limits.backgroundlimit',
value: parseInt(uploadLimits.background),
value: Number.parseInt(uploadLimits.background),
})
useInstanceStore().set({
path: 'limits.bannerlimit',
value: parseInt(uploadLimits.banner),
value: Number.parseInt(uploadLimits.banner),
})
useInstanceStore().set({
path: 'limits.fieldsLimits',
@ -409,7 +409,7 @@ const getNodeInfo = async ({ store }) => {
useInstanceCapabilitiesStore().set(
'tagPolicyAvailable',
typeof federation.mrf_policies === 'undefined'
federation.mrf_policies === undefined
? false
: metadata.federation.mrf_policies.includes('TagPolicy'),
)
@ -420,8 +420,7 @@ const getNodeInfo = async ({ store }) => {
})
useInstanceStore().set({
path: 'federating',
value:
typeof federation.enabled === 'undefined' ? true : federation.enabled,
value: federation.enabled === undefined ? true : federation.enabled,
})
const accountActivationRequired = metadata.accountActivationRequired
@ -443,7 +442,7 @@ const getNodeInfo = async ({ store }) => {
const setConfig = async ({ store }) => {
// apiConfig, staticConfig
const configInfos = await Promise.all([
getBackendProvidedConfig({ store }),
getBackendProvidedConfig(),
getStaticConfig(),
])
const apiConfig = configInfos[0]
@ -457,7 +456,7 @@ const checkOAuthToken = async ({ store }) => {
if (oauth.userToken) {
return store.dispatch('loginUser', oauth.userToken)
}
return Promise.resolve()
return
}
const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
@ -485,7 +484,7 @@ 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(
throw new TypeError(
'No stores are available. Check the code in src/boot/after_store.js',
)
}
@ -495,7 +494,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
const isStoreName = (name) => name.startsWith('use')
if (process.env.NODE_ENV === 'development') {
if (Object.keys(mod).filter(isStoreName).length !== 1) {
throw new Error(
throw new TypeError(
'Each store file must export exactly one store as a named export. Check your code in src/stores/',
)
}
@ -504,13 +503,13 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
if (storeFuncName && typeof mod[storeFuncName] === 'function') {
const p = mod[storeFuncName]().$persistLoaded
if (!(p instanceof Promise)) {
throw new Error(
throw new TypeError(
`${name} store's $persistLoaded is not a Promise. The persist plugin is not applied.`,
)
}
await p
} else {
throw new Error(
throw new TypeError(
`Store module ${name} does not export a 'use...' function`,
)
}
@ -518,14 +517,15 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
)
}
let newStorageError
try {
await waitForAllStoresToLoad()
} catch (e) {
console.error('Cannot load stores:', e)
storageError = e
newStorageError = e
}
if (storageError) {
if (storageError || newStorageError) {
useInterfaceStore().pushGlobalNotice({
messageKey: 'errors.storage_unavailable',
level: 'error',
@ -547,9 +547,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
const overrides = window.___pleromafe_dev_overrides || {}
const server =
typeof overrides.target !== 'undefined'
? overrides.target
: window.location.origin
overrides.target !== undefined ? overrides.target : window.location.origin
useInstanceStore().set({ path: 'server', value: server })
await setConfig({ store })
@ -561,7 +559,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
})
} catch (e) {
window.splashError(e)
return Promise.reject(e)
throw e
}
applyStyleConfig(useMergedConfigStore().mergedConfig, i18n.global)
@ -573,7 +571,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
getInstancePanel({ store }),
getNodeInfo({ store }),
getInstanceConfig({ store }),
]).catch((e) => Promise.reject(e))
])
getTOS({ store })
getStickers({ store })
@ -583,7 +581,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
routes: routes(store),
scrollBehavior: (to, _from, savedPosition) => {
if (to.matched.some((m) => m.meta.dontScroll)) {
return false
return {}
}
return savedPosition || { left: 0, top: 0 }
},

View file

@ -39,7 +39,7 @@ const ChatListItem = {
messageForStatusContent() {
const message = this.chat.lastMessage
const messageEmojis = message ? message.emojis : []
const isYou = message && message.account_id === this.currentUser.id
const isYou = message?.account_id === this.currentUser.id
const content = message ? this.attachmentInfo || message.content : ''
const messagePreview = isYou
? `<i>${this.$t('chats.you')}</i> ${content}`

View file

@ -111,7 +111,7 @@ const ChatMessage = {
const user = this.$store.getters.findUser(
this.message.in_reply_to_user_id,
)
return user && user.screen_name_ui
return user?.screen_name_ui
}
},
replyProfileLink() {

View file

@ -53,7 +53,7 @@
:user-screen-name="message.in_reply_to_screen_name"
/>
<!-- v-if is there because status might not be loaded yet -->
<template v-if="customReplyTo && customReplyTo.text.trim().length > 0">
<template v-if="customReplyTo?.text.trim().length > 0">
:
<StatusBody
class="reply-body faint"

View file

@ -16,7 +16,7 @@
<RichContent
v-if="user"
class="username"
:title="'@'+(user && user.screen_name_ui)"
:title="'@'+(user?.screen_name_ui)"
:html="htmlTitle"
:emoji="user.emoji || []"
:allow-non-square-emoji="allowNonSquareEmoji"

View file

@ -134,7 +134,7 @@ export default {
emits: ['update:modelValue'],
computed: {
present() {
return typeof this.modelValue !== 'undefined'
return this.modelValue !== undefined
},
validColor() {
return hex2rgb(this.modelValue || this.fallback)

View file

@ -73,17 +73,15 @@ export default {
}
},
logoBgStyle() {
return Object.assign(
{
margin: `${this.logoMargin} 0`,
opacity: this.searchBarHidden ? 1 : 0,
},
this.enableMask
? {}
: {
'background-color': this.enableMask ? '' : 'transparent',
},
)
const mask = this.enableMask
? {}
: { 'background-color': this.enableMask ? '' : 'transparent' }
return {
margin: `${this.logoMargin} 0`,
opacity: this.searchBarHidden ? 1 : 0,
...mask,
}
},
...mapState(useInstanceStore, ['privateMode']),
...mapState(useInstanceStore, {

View file

@ -50,7 +50,7 @@
/>
</button>
<button
v-if="currentUser && currentUser.role === 'admin'"
v-if="currentUser?.role === 'admin'"
class="button-unstyled nav-icon"
target="_blank"
:title="$t('nav.administration')"

View file

@ -29,7 +29,7 @@ const FollowRequestCard = {
notif.from_profile.id === this.user.id &&
notif.type === 'follow_request',
)
return notif && notif.id
return notif?.id
},
showApproveConfirmDialog() {
this.showingApproveConfirmDialog = true

View file

@ -42,7 +42,7 @@ export default {
emits: ['update:modelValue'],
computed: {
present() {
return typeof this.modelValue !== 'undefined'
return this.modelValue !== undefined
},
},
}

View file

@ -89,7 +89,7 @@ export default {
this.error = false
const notice = this.noticeRegex.exec(value)
if (notice && notice.length === 4) {
if (notice?.length === 4) {
this.$emit('update:id', notice[3])
} else if (value) {
this.loading = true
@ -102,7 +102,7 @@ export default {
type: 'statuses',
})
.then((data) => {
if (data && data.statuses && data.statuses.length === 1) {
if (data?.statuses && data.statuses.length === 1) {
this.$emit('update:id', data.statuses[0].id)
} else {
this.handleError(true)

View file

@ -68,7 +68,7 @@ export default {
emits: ['update:modelValue'],
computed: {
present() {
return typeof this.modelValue !== 'undefined'
return this.modelValue !== undefined
},
},
}

View file

@ -335,7 +335,7 @@ export default {
this.pauseMfm ? '-pause' : '',
this.scaleMfm ? '-scale' : '',
]
.filter((x) => x)
.filter(Boolean)
.join(' ')
newAttrs['data-mfm-operator'] = mfmOperator
switch (mfmOperator) {

View file

@ -42,7 +42,7 @@ export default {
emits: ['update:modelValue'],
computed: {
present() {
return typeof this.modelValue !== 'undefined'
return this.modelValue !== undefined
},
},
}

View file

@ -374,7 +374,7 @@
class="emoji-list setting-list"
>
<EmojiEditingPopover
v-if="pack && pack.remote === undefined"
v-if="pack?.remote === undefined"
class="emoji-item"
placement="bottom"
new-upload

View file

@ -29,7 +29,7 @@ export default {
...Setting.methods,
getValue(e) {
if (!this.truncate === 1) {
return parseInt(e.target.value)
return Number.parseInt(e.target.value)
} else if (this.truncate > 1) {
return Math.trunc(e.target.value / this.truncate) * this.truncate
}

View file

@ -159,7 +159,7 @@ export default {
return this.source || this.defaultSource
},
realDraftMode() {
return typeof this.draftMode === 'undefined'
return this.draftMode === undefined
? this.defaultDraftMode
: this.draftMode
},

View file

@ -47,7 +47,7 @@ export default {
// In case of controlled component
if (this.activeTab) {
return this.slots().findIndex(
(slot) => slot && slot.props && this.activeTab === slot.props.key,
(slot) => slot?.props && this.activeTab === slot.props.key,
)
} else {
return this.active

View file

@ -236,7 +236,7 @@ const AppearanceTab = {
},
stylePalettes() {
const ruleset = useInterfaceStore().styleDataUsed || []
if (!ruleset && ruleset.length === 0) return
if (!ruleset?.length === 0) return
const meta = ruleset.find((x) => x.component === '@meta')
const result = ruleset
.filter((x) => x.component.startsWith('@palette'))
@ -401,7 +401,7 @@ const AppearanceTab = {
}
theme3 = init({
inputRuleset: [...input, paletteRule].filter((x) => x),
inputRuleset: [...input, paletteRule].filter(Boolean),
ultimateBackgroundColor: '#000000',
liteMode: true,
onlyNormalState: true,

View file

@ -95,7 +95,7 @@ const DataImportExportTab = {
return users
.map((user) => {
// check is it's a local user
if (user && user.is_local) {
if (user?.is_local) {
// append the instance address
return user.screen_name + '@' + location.hostname
}

View file

@ -81,7 +81,7 @@ const MutesAndBlocks = {
return users
.map((user) => {
// check is it's a local user
if (user && user.is_local) {
if (user?.is_local) {
// append the instance address
return user.screen_name + '@' + location.hostname
}

View file

@ -147,7 +147,7 @@ export default {
})
},
mounted() {
if (typeof this.shadowSelected === 'undefined') {
if (this.shadowSelected === undefined) {
this.shadowSelected = this.shadowsAvailable[0]
}
},
@ -633,17 +633,11 @@ 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 (colors.text === undefined && colors.fg !== undefined) {
version = 1
}
// New v2 naming: text is text, fg is foreground
if (
typeof colors.text !== 'undefined' &&
typeof colors.fg !== 'undefined'
) {
if (colors.text !== undefined && colors.fg !== undefined) {
version = 2
}
}
@ -679,7 +673,7 @@ export default {
if (opacity && !this.keepOpacity) {
this.clearOpacity()
Object.entries(opacity).forEach(([k, v]) => {
if (typeof v === 'undefined' || v === null || Number.isNaN(v)) return
if (v === undefined || v === null || Number.isNaN(v)) return
this[k + 'OpacityLocal'] = v
})
}

View file

@ -602,7 +602,7 @@ export default {
.map((x) => Object.entries(x.directives))
.flat()
})
.filter((x) => x)
.filter(Boolean)
.flat()
.map(([name, value]) => {
const [valType, valVal] = value.split('|')

View file

@ -220,7 +220,7 @@
</router-link>
</li>
<li
v-if="currentUser && currentUser.role === 'admin'"
v-if="currentUser?.role === 'admin'"
@click="toggleDrawer"
>
<button

View file

@ -316,11 +316,11 @@ const Status = {
return (
(status.muted && !status.thread_muted) ||
// Reprööt of a muted post according to BE
(reblog && reblog.muted && !reblog.thread_muted) ||
(reblog?.muted && !reblog.thread_muted) ||
// Muted user
relationship.muting ||
// Muted user of a reprööt
(relationshipReblog && relationshipReblog.muting)
relationshipReblog?.muting
)
},
shouldNotMute() {
@ -333,7 +333,7 @@ const Status = {
// 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))) ||
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
@ -374,7 +374,7 @@ const Status = {
const user = this.$store.getters.findUser(
this.status.in_reply_to_user_id,
)
return user && user.screen_name_ui
return user?.screen_name_ui
}
},
combinedFavsAndRepeatsUsers() {

View file

@ -225,7 +225,7 @@
/>
</button>
<button
v-if="inThreadForest && replies && replies.length && !simpleTree"
v-if="inThreadForest && replies?.length && !simpleTree"
class="button-unstyled"
:title="threadShowing ? $t('status.thread_hide') : $t('status.thread_show')"
:aria-expanded="threadShowing ? 'true' : 'false'"
@ -426,7 +426,7 @@
/>
<div
v-if="inConversation && !isPreview && replies && replies.length"
v-if="inConversation && !isPreview && replies?.length"
class="replies"
>
<button

View file

@ -138,7 +138,7 @@ export default {
const existingReaction = this.status.emoji_reactions.find(
(r) => r.name === emoji,
)
if (existingReaction && existingReaction.me) {
if (existingReaction?.me) {
this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })
} else {
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })

View file

@ -47,7 +47,7 @@ export default {
// In case of controlled component
if (this.activeTab) {
return this.slots().findIndex(
(slot) => slot && slot.props && this.activeTab === slot.props.key,
(slot) => slot?.props && this.activeTab === slot.props.key,
)
} else {
return this.active

View file

@ -154,7 +154,7 @@ const Timeline = {
})
},
mounted() {
if (typeof document.hidden !== 'undefined') {
if (document.hidden !== undefined) {
document.addEventListener(
'visibilitychange',
this.handleVisibilityChange,
@ -168,7 +168,7 @@ const Timeline = {
unmounted() {
window.removeEventListener('scroll', this.handleScroll)
window.removeEventListener('keydown', this.handleShortKey)
if (typeof document.hidden !== 'undefined')
if (document.hidden !== undefined)
document.removeEventListener(
'visibilitychange',
this.handleVisibilityChange,
@ -231,7 +231,7 @@ const Timeline = {
tag: this.tag,
})
.then(({ statuses }) => {
if (statuses && statuses.length === 0) {
if (statuses?.length === 0) {
this.bottomedOut = true
}
})

View file

@ -1,6 +1,6 @@
<template>
<FAIcon
v-if="user && user.screen_name_ui_contains_non_ascii"
v-if="user?.screen_name_ui_contains_non_ascii"
icon="code"
:title="$t('unicode_domain_indicator.tooltip')"
/>

View file

@ -68,7 +68,7 @@
>
<button
v-if="editable"
:disabled="newName && newName.length === 0"
:disabled="newName?.length === 0"
class="btn button-unstyled edit-banner-button"
@click="changeBanner"
>

View file

@ -34,15 +34,15 @@ const VideoAttachment = {
// If hasAudio is false, we've already marked this video to not have audio,
// a video can't gain audio out of nowhere so don't bother checking again.
if (!this.hasAudio) return
if (typeof target.webkitAudioDecodedByteCount !== 'undefined') {
if (target.webkitAudioDecodedByteCount !== undefined) {
// non-zero if video has audio track
if (target.webkitAudioDecodedByteCount > 0) return
}
if (typeof target.mozHasAudio !== 'undefined') {
if (target.mozHasAudio !== undefined) {
// true if video has audio track
if (target.mozHasAudio) return
}
if (typeof target.audioTracks !== 'undefined') {
if (target.audioTracks !== undefined) {
if (target.audioTracks.length > 0) return
}
this.hasAudio = false

View file

@ -3,14 +3,12 @@ import {
find,
findIndex,
first,
isArray,
last,
maxBy,
merge,
minBy,
omitBy,
remove,
slice,
} from 'lodash'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
@ -206,7 +204,7 @@ const addNewStatuses = (
},
) => {
// Sanity check
if (!isArray(statuses)) {
if (!Array.isArray(statuses)) {
return false
}
@ -410,7 +408,7 @@ export const mutations = {
const oldTimeline = state.timelines[timeline]
oldTimeline.newStatusCount = 0
oldTimeline.visibleStatuses = slice(oldTimeline.statuses, 0, 50)
oldTimeline.visibleStatuses = oldTimeline.statuses.slice(0, 50)
oldTimeline.minVisibleId = last(oldTimeline.visibleStatuses).id
oldTimeline.minId = oldTimeline.minVisibleId
oldTimeline.visibleStatusesObject = {}

View file

@ -1,14 +1,5 @@
import Cookies from 'js-cookie'
import {
compact,
concat,
each,
isArray,
last,
map,
mergeWith,
uniq,
} from 'lodash'
import { compact, each, last, map, mergeWith } from 'lodash'
import {
registerPushNotifications,
@ -76,7 +67,7 @@ export const mergeOrAdd = (arr, obj, item) => {
}
const mergeArrayLength = (oldValue, newValue) => {
if (isArray(oldValue) && isArray(newValue)) {
if (Array.isArray(oldValue) && Array.isArray(newValue)) {
oldValue.length = newValue.length
return mergeWith(oldValue, newValue, mergeArrayLength)
}
@ -234,11 +225,11 @@ export const mutations = {
},
saveFriendIds(state, { id, friendIds }) {
const user = state.usersObject[id]
user.friendIds = uniq(concat(user.friendIds || [], friendIds))
user.friendIds = [...new Set([...(user.friendIds || []), ...friendIds])]
},
saveFollowerIds(state, { id, followerIds }) {
const user = state.usersObject[id]
user.followerIds = uniq(concat(user.followerIds || [], followerIds))
user.followerIds = [...new Set([user.followerIds || [], ...followerIds])]
},
// Because frontend doesn't have a reason to keep these stuff in memory
// outside of viewing someones user profile.

View file

@ -173,9 +173,9 @@ export const hex2rgb = (hex) => {
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
r: Number.parseInt(result[1], 16),
g: Number.parseInt(result[2], 16),
b: Number.parseInt(result[3], 16),
}
: null
}
@ -271,7 +271,7 @@ export const getTextColor = function (bg, text, preserve) {
contrast = getContrastRatio(bg, convert(result).rgb)
}
const base = typeof text.a !== 'undefined' ? { a: text.a } : {}
const base = text.a !== undefined ? { a: text.a } : {}
return Object.assign(convert(result).rgb, base)
}

View file

@ -177,7 +177,7 @@ export const parseUser = (data) => {
// deactivated was changed to is_active in Pleroma 2.3.0
// so check if is_active is present
output.deactivated =
typeof data.pleroma.is_active !== 'undefined'
data.pleroma.is_active !== undefined
? !data.pleroma.is_active // new backend
: data.pleroma.deactivated // old backend
@ -372,7 +372,7 @@ export const parseNotification = (data) => {
}
output.created_at = new Date(data.created_at)
output.id = parseInt(data.id)
output.id = Number.parseInt(data.id)
return output
}
@ -385,8 +385,8 @@ export const parseLinkHeaderPagination = (linkHeader, opts = {}) => {
const minId = parsedLinkHeader.prev?.min_id
return {
maxId: flakeId ? maxId : parseInt(maxId, 10),
minId: flakeId ? minId : parseInt(minId, 10),
maxId: flakeId ? maxId : Number.parseInt(maxId, 10),
minId: flakeId ? minId : Number.parseInt(minId, 10),
}
}

View file

@ -14,7 +14,7 @@ export function StatusCodeError(statusCode, body, options, response) {
this.name = 'StatusCodeError'
this.statusCode = statusCode
this.statusText = body.error || body.errors || body
this.details = JSON && JSON.stringify ? JSON.stringify(body) : body
this.details = JSON.stringify(body)
this.errorData = body.error || body.errors
this.message = this.statusCode + ' - ' + this.statusText
this.error = body // legacy attribute

View file

@ -1,5 +1,3 @@
import { uniq } from 'lodash'
import * as DateUtils from 'src/services/date_utils/date_utils.js'
const pollFallbackValues = {
@ -19,9 +17,9 @@ export const pollFormToMasto = (poll) => {
pollFallback(poll, 'expiryAmount'),
)
const options = uniq(
pollFallback(poll, 'options').filter((option) => option !== ''),
)
const options = [
...new Set(pollFallback(poll, 'options').filter((option) => option !== '')),
]
if (options.length < 2) {
return { errorKey: 'polls.not_enough_options' }
}

View file

@ -125,10 +125,7 @@ const generateTheme = (inputRuleset, callbacks, debug) => {
const processChunk = () => {
const chunk = chunks[counter]
Promise.all(chunk.map((x) => x())).then((result) => {
getCssRules(
result.filter((x) => x),
debug,
).forEach((rule) => {
getCssRules(result.filter(Boolean), debug).forEach((rule) => {
onNewRule(rule, true)
})
// const t1 = performance.now()
@ -253,7 +250,9 @@ const extractStyleConfig = ({
contentColumnWidth,
notifsColumnWidth,
themeEditorMinWidth:
parseInt(themeEditorMinWidth) === 0 ? 'fit-content' : themeEditorMinWidth,
Number.parseInt(themeEditorMinWidth) === 0
? 'fit-content'
: themeEditorMinWidth,
emojiReactionsScale,
emojiSize,
navbarSize,

View file

@ -4,7 +4,7 @@ function urlBase64ToUint8Array(base64String) {
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/')
const rawData = window.atob(base64)
return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)))
return Uint8Array.from([...rawData].map((char) => char.codePointAt(0)))
}
export function isSWSupported() {

View file

@ -104,7 +104,7 @@ export const getCssRules = (rules, debug) =>
: '',
' --background: ' + v,
]
.filter((x) => x)
.filter(Boolean)
.join(';\n')
}
const color = getCssColorString(
@ -115,7 +115,7 @@ export const getCssRules = (rules, debug) =>
if (rule.directives.backgroundNoCssColor !== 'yes') {
cssDirectives.push('background-color: ' + color)
}
return cssDirectives.filter((x) => x).join(';\n')
return cssDirectives.filter(Boolean).join(';\n')
}
case 'blur': {
const cssDirectives = []
@ -157,7 +157,7 @@ export const getCssRules = (rules, debug) =>
return null
}
})
.filter((x) => x)
.filter(Boolean)
.map((x) => ' ' + x + ';')
.join('\n')
@ -172,10 +172,10 @@ export const getCssRules = (rules, debug) =>
virtualDirectives,
footer,
]
.filter((x) => x)
.filter(Boolean)
.join('\n')
})
.filter((x) => x)
.filter(Boolean)
export const getScopedVersion = (rules, newScope) => {
return rules.map((x) => {

View file

@ -62,6 +62,6 @@ export const serialize = (ruleset) => {
return `${header} {\n${content.join(';\n')}\n}`
})
.filter((x) => x)
.filter(Boolean)
.join('\n\n')
}

View file

@ -558,9 +558,9 @@ export const convertTheme2To3 = (data) => {
)
const flatExtRules = extendedRules
.filter((x) => x)
.filter(Boolean)
.reduce((acc, x) => [...acc, ...x], [])
.filter((x) => x)
.filter(Boolean)
.reduce((acc, x) => [...acc, ...x], [])
return [

View file

@ -229,10 +229,7 @@ export const getLayerSlot = (
*/
export const SLOT_ORDERED = topoSort(
Object.entries(SLOT_INHERITANCE)
.sort(
([, aV], [, bV]) =>
((aV && aV.priority) || 0) - ((bV && bV.priority) || 0),
)
.sort(([, aV], [, bV]) => (aV?.priority || 0) - (bV?.priority || 0))
.reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}),
)
@ -408,7 +405,7 @@ export const getColors = (sourceColors, sourceOpacity) =>
delete outputColor.a
} else {
// Otherwise try to assign opacity
if (dependencyColor && dependencyColor.a === 0) {
if (dependencyColor?.a === 0) {
// transparent dependency shall make dependents transparent too
outputColor.a = 0
} else {
@ -523,7 +520,7 @@ export const generateColors = (themeData) => {
(acc, [k, v]) => {
if (!v) return acc
acc.solid[k] = rgb2hex(v)
acc.complete[k] = typeof v.a === 'undefined' ? rgb2hex(v) : rgba2css(v)
acc.complete[k] = v.a === undefined ? rgb2hex(v) : rgba2css(v)
return acc
},
{ complete: {}, solid: {} },
@ -545,7 +542,7 @@ export const generateColors = (themeData) => {
export const generateRadii = (input) => {
let inputRadii = input.radii || {}
// v1 -> v2
if (typeof input.btnRadius !== 'undefined') {
if (input.btnRadius !== undefined) {
inputRadii = Object.entries(input)
.filter(([k]) => k.endsWith('Radius'))
.reduce((acc, e) => {

View file

@ -338,10 +338,10 @@ export const init = ({
const relevantRules = ruleset.filter((r) => r.component === component.name)
const backgrounds = relevantRules
.map((r) => r.directives.background)
.filter((x) => x)
.filter(Boolean)
const opacities = relevantRules
.map((r) => r.directives.opacity)
.filter((x) => x)
.filter(Boolean)
if (
backgrounds.some((x) => x.match(/--parent/)) ||
opacities.some((x) => x != null && x < 1)
@ -596,7 +596,7 @@ export const init = ({
const shadow = value
.split(/,/g)
.map((s) => s.trim())
.filter((x) => x)
.filter(Boolean)
dynamicVars[k] = shadow
if (combination.component === rootComponentName) {
staticVars[k.substring(2)] = shadow
@ -752,7 +752,7 @@ export const init = ({
return processCombination(combination)
}
})
.filter((x) => x)
.filter(Boolean)
const t2 = performance.now()
if (debug) {
console.debug('Eager processing took ' + (t2 - t1) + ' ms')

View file

@ -11,6 +11,6 @@ const generateProfileLink = (id, screenName, restrictedNicknames) => {
}
}
const isExternal = (screenName) => screenName && screenName.includes('@')
const isExternal = (screenName) => screenName?.includes('@')
export default generateProfileLink

View file

@ -1,4 +1,4 @@
import { cloneDeep, differenceWith, flatten, get, isEqual, set } from 'lodash'
import { cloneDeep, differenceWith, get, isEqual, set } from 'lodash'
import { defineStore } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
@ -209,11 +209,11 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
}
// Getting all group-keys used in config
const allGroupKeys = flatten(
Object.entries(this.config).map(([group, lv1data]) =>
const allGroupKeys = Object.entries(this.config)
.map(([group, lv1data]) =>
Object.keys(lv1data).map((key) => ({ group, key })),
),
)
)
.flat()
// Only using group-keys where there are changes detected
const changedGroupKeys = allGroupKeys.filter(({ group, key }) => {

View file

@ -74,7 +74,7 @@ export const useAnnouncementsStore = defineStore('announcements', {
} catch (error) {
// If and only if backend does not support announcements, it would return 404.
// In this case, silently ignores it.
if (error && error.statusCode === 404) {
if (error?.statusCode === 404) {
this.supportsAnnouncements = false
} else {
throw error

View file

@ -747,7 +747,7 @@ export const useInterfaceStore = defineStore('interface', {
this.styleDataUsed,
paletteIss,
hacks,
].filter((x) => x)
].filter(Boolean)
return applyTheme(
rulesetArray.flat(),
@ -790,7 +790,7 @@ export const normalizeThemeData = (input) => {
// New theme presets don't have 'theme' property, they use 'source'
let out // shout, shout let it all out
if (themeSource && themeSource.themeEngineVersion === CURRENT_VERSION) {
if (themeSource?.themeEngineVersion === CURRENT_VERSION) {
// There are some themes in wild that have completely broken source
out = { ...(themeData || {}), ...themeSource }
} else {

View file

@ -4,13 +4,12 @@ import {
clamp,
cloneDeep,
findLastIndex,
flatten,
get,
groupBy,
isEqual,
last,
set,
take,
takeRight,
uniqWith,
unset,
} from 'lodash'
@ -222,15 +221,16 @@ export const _mergeFlags = (recent, stale, allFlagKeys) => {
export const _mergeJournal = (...journals) => {
// Ignore invalid journal entries
const allJournals = flatten(
journals.map((j) => (Array.isArray(j) ? j : [])),
).filter(
(entry) =>
Object.hasOwn(entry, 'path') &&
Object.hasOwn(entry, 'operation') &&
Object.hasOwn(entry, 'args') &&
Object.hasOwn(entry, 'timestamp'),
)
const allJournals = journals
.map((j) => (Array.isArray(j) ? j : []))
.flat()
.filter(
(entry) =>
Object.hasOwn(entry, 'path') &&
Object.hasOwn(entry, 'operation') &&
Object.hasOwn(entry, 'args') &&
Object.hasOwn(entry, 'timestamp'),
)
const grouped = groupBy(allJournals, 'path')
const trimmedGrouped = Object.entries(grouped).map(([path, rawJournal]) => {
const journal = rawJournal
@ -271,13 +271,14 @@ export const _mergeJournal = (...journals) => {
})
} else if (path.startsWith('simple')) {
// Only the last record is important
return takeRight(journal)
return [last(journal)]
} else {
return journal
}
})
const flat = flatten(trimmedGrouped)
const flat = trimmedGrouped
.flat()
.map((data, index) => ({ data, index }))
.toSorted(({ data: a, index: ai }, { data: b, index: bi }) => {
if (a.timestamp === b.timestamp) {

View file

@ -2,10 +2,9 @@ import {
merge as _merge,
clone,
cloneDeep,
flatten,
groupBy,
isEqual,
takeRight,
last,
} from 'lodash'
import { defineStore } from 'pinia'
import { toRaw } from 'vue'
@ -117,25 +116,26 @@ export const _getRecentData = (cache, live, isTest) => {
const _mergeJournal = (...journals) => {
// Ignore invalid journal entries
const allJournals = flatten(
journals.map((j) => (Array.isArray(j) ? j : [])),
).filter(
(entry) =>
Object.hasOwn(entry, 'user') &&
Object.hasOwn(entry, 'operation') &&
Object.hasOwn(entry, 'args') &&
Object.hasOwn(entry, 'timestamp'),
)
const allJournals = journals
.map((j) => (Array.isArray(j) ? j : []))
.flat()
.filter(
(entry) =>
Object.hasOwn(entry, 'user') &&
Object.hasOwn(entry, 'operation') &&
Object.hasOwn(entry, 'args') &&
Object.hasOwn(entry, 'timestamp'),
)
const grouped = groupBy(allJournals, 'user')
const trimmedGrouped = Object.entries(grouped).map(([user, journal]) => {
// side effect
journal.sort((a, b) => (a.timestamp > b.timestamp ? 1 : -1))
return takeRight(journal)
return [last(journal)]
})
return flatten(trimmedGrouped).sort((a, b) =>
a.timestamp > b.timestamp ? 1 : -1,
)
return trimmedGrouped
.flat()
.sort((a, b) => (a.timestamp > b.timestamp ? 1 : -1))
}
export const _mergeHighlights = (recent, stale) => {

View file

@ -132,7 +132,7 @@ export const waitForEvent = (
return vi.waitFor(
() => {
const e = wrapper.emitted(event)
if (e && e.length >= timesEmitted) {
if (e?.length >= timesEmitted) {
return
}
throw new Error('event is not emitted')

View file

@ -7,100 +7,92 @@ import {
} from 'src/services/entity_normalizer/entity_normalizer.service.js'
const makeMockUserMasto = (overrides = {}) => {
return Object.assign(
{
acct: 'hj',
avatar:
'https://shigusegubu.club/media/1657b945-8d5b-4ce6-aafb-4c3fc5772120/8ce851029af84d55de9164e30cc7f46d60cbf12eee7e96c5c0d35d9038ddade1.png',
avatar_static:
'https://shigusegubu.club/media/1657b945-8d5b-4ce6-aafb-4c3fc5772120/8ce851029af84d55de9164e30cc7f46d60cbf12eee7e96c5c0d35d9038ddade1.png',
bot: false,
created_at: '2017-12-17T21:54:14.000Z',
display_name: 'whatever whatever whatever witch',
emojis: [],
fields: [],
followers_count: 705,
following_count: 326,
header:
'https://shigusegubu.club/media/7ab024d9-2a8a-4fbc-9ce8-da06756ae2db/6aadefe4e264133bc377ab450e6b045b6f5458542a5c59e6c741f86107f0388b.png',
header_static:
'https://shigusegubu.club/media/7ab024d9-2a8a-4fbc-9ce8-da06756ae2db/6aadefe4e264133bc377ab450e6b045b6f5458542a5c59e6c741f86107f0388b.png',
id: '1',
locked: false,
note: 'Volatile Internet Weirdo. Name pronounced as Hee Jay. JS and Java dark arts mage, Elixir trainee. I love sampo and lain. Matrix is <span><a data-user="1" href="https://shigusegubu.club/users/hj">@<span>hj</span></a></span>:matrix.heldscal.la Pronouns are whatever. Do not DM me unless it\'s truly private matter and you\'re instance\'s admin or you risk your DM to be reposted publicly.Wish i was Finnish girl.',
pleroma: { confirmation_pending: false, tags: null },
source: { note: '', privacy: 'public', sensitive: false },
statuses_count: 41775,
url: 'https://shigusegubu.club/users/hj',
username: 'hj',
},
overrides,
)
return {
acct: 'hj',
avatar:
'https://shigusegubu.club/media/1657b945-8d5b-4ce6-aafb-4c3fc5772120/8ce851029af84d55de9164e30cc7f46d60cbf12eee7e96c5c0d35d9038ddade1.png',
avatar_static:
'https://shigusegubu.club/media/1657b945-8d5b-4ce6-aafb-4c3fc5772120/8ce851029af84d55de9164e30cc7f46d60cbf12eee7e96c5c0d35d9038ddade1.png',
bot: false,
created_at: '2017-12-17T21:54:14.000Z',
display_name: 'whatever whatever whatever witch',
emojis: [],
fields: [],
followers_count: 705,
following_count: 326,
header:
'https://shigusegubu.club/media/7ab024d9-2a8a-4fbc-9ce8-da06756ae2db/6aadefe4e264133bc377ab450e6b045b6f5458542a5c59e6c741f86107f0388b.png',
header_static:
'https://shigusegubu.club/media/7ab024d9-2a8a-4fbc-9ce8-da06756ae2db/6aadefe4e264133bc377ab450e6b045b6f5458542a5c59e6c741f86107f0388b.png',
id: '1',
locked: false,
note: 'Volatile Internet Weirdo. Name pronounced as Hee Jay. JS and Java dark arts mage, Elixir trainee. I love sampo and lain. Matrix is <span><a data-user="1" href="https://shigusegubu.club/users/hj">@<span>hj</span></a></span>:matrix.heldscal.la Pronouns are whatever. Do not DM me unless it\'s truly private matter and you\'re instance\'s admin or you risk your DM to be reposted publicly.Wish i was Finnish girl.',
pleroma: { confirmation_pending: false, tags: null },
source: { note: '', privacy: 'public', sensitive: false },
statuses_count: 41775,
url: 'https://shigusegubu.club/users/hj',
username: 'hj',
...overrides,
}
}
const makeMockStatusMasto = (overrides = {}) => {
return Object.assign(
{
account: makeMockUserMasto(),
application: { name: 'Web', website: null },
content:
'<span><a data-user="14660" href="https://pleroma.soykaf.com/users/sampo">@<span>sampo</span></a></span> god i wish i was there',
created_at: '2019-01-17T16:29:23.000Z',
emojis: [],
favourited: false,
favourites_count: 1,
id: '10423476',
in_reply_to_account_id: '14660',
in_reply_to_id: '10423197',
language: null,
media_attachments: [],
mentions: [
{
acct: 'sampo@pleroma.soykaf.com',
id: '14660',
url: 'https://pleroma.soykaf.com/users/sampo',
username: 'sampo',
},
],
muted: false,
reblog: null,
reblogged: false,
reblogs_count: 0,
replies_count: 0,
sensitive: false,
spoiler_text: '',
tags: [],
uri: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639',
url: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639',
visibility: 'public',
pleroma: {
local: true,
return {
account: makeMockUserMasto(),
application: { name: 'Web', website: null },
content:
'<span><a data-user="14660" href="https://pleroma.soykaf.com/users/sampo">@<span>sampo</span></a></span> god i wish i was there',
created_at: '2019-01-17T16:29:23.000Z',
emojis: [],
favourited: false,
favourites_count: 1,
id: '10423476',
in_reply_to_account_id: '14660',
in_reply_to_id: '10423197',
language: null,
media_attachments: [],
mentions: [
{
acct: 'sampo@pleroma.soykaf.com',
id: '14660',
url: 'https://pleroma.soykaf.com/users/sampo',
username: 'sampo',
},
],
muted: false,
reblog: null,
reblogged: false,
reblogs_count: 0,
replies_count: 0,
sensitive: false,
spoiler_text: '',
tags: [],
uri: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639',
url: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639',
visibility: 'public',
pleroma: {
local: true,
},
overrides,
)
...overrides,
}
}
const makeMockEmojiMasto = (overrides = [{}]) => {
return [
Object.assign(
{
shortcode: 'image',
static_url: 'https://example.com/image.png',
url: 'https://example.com/image.png',
visible_in_picker: false,
},
overrides[0],
),
Object.assign(
{
shortcode: 'thinking',
static_url: 'https://example.com/think.png',
url: 'https://example.com/think.png',
visible_in_picker: false,
},
overrides[1],
),
{
shortcode: 'image',
static_url: 'https://example.com/image.png',
url: 'https://example.com/image.png',
visible_in_picker: false,
...overrides[0],
},
{
shortcode: 'thinking',
static_url: 'https://example.com/think.png',
url: 'https://example.com/think.png',
visible_in_picker: false,
...overrides[1],
},
]
}