optional chaining

This commit is contained in:
Henry Jameson 2026-08-04 15:59:52 +03:00
commit cf85b00c0a
26 changed files with 34 additions and 34 deletions

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

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

@ -411,7 +411,7 @@ const Popover = {
if (!scrollable) scrollable = window
this.scrollable = scrollable
let parent = this.$parent
while (parent && parent.$.type.name !== 'Popover') {
while (parent?.$.type.name !== 'Popover') {
parent = parent.$parent
}
this.parentPopover = parent

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

@ -343,7 +343,7 @@
<li>
<div class="meta-buttons">
<button
v-if="pack && pack.remote === undefined"
v-if="pack?.remote === undefined"
class="button button-default btn"
type="button"
@click="savePackMetadata"
@ -351,7 +351,7 @@
{{ $t('admin_dash.emoji.save_meta') }}
</button>
<button
v-if="pack && pack.remote === undefined"
v-if="pack?.remote === undefined"
class="button button-default btn"
type="button"
@click="savePackMetadata"
@ -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

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

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

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

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

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

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

@ -231,7 +231,7 @@ export const SLOT_ORDERED = topoSort(
Object.entries(SLOT_INHERITANCE)
.sort(
([, aV], [, bV]) =>
((aV && aV.priority) || 0) - ((bV && bV.priority) || 0),
((aV?.priority) || 0) - ((bV && bV.priority) || 0),
)
.reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}),
)
@ -408,7 +408,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 {

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

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

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

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