Merge remote-tracking branch 'origin/develop' into 2-11-3-fixes
This commit is contained in:
commit
a125a9af6c
117 changed files with 591 additions and 557 deletions
|
|
@ -12,10 +12,7 @@ export const maybeShowChatNotification = (chat) => {
|
|||
body: chat.lastMessage.content,
|
||||
}
|
||||
|
||||
if (
|
||||
chat.lastMessage.attachment &&
|
||||
chat.lastMessage.attachment.type === 'image'
|
||||
) {
|
||||
if (chat.lastMessage.attachment?.type === 'image') {
|
||||
opts.image = chat.lastMessage.attachment.preview_url
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { contrastRatio, convert, invertLightness } from 'chromatism'
|
|||
* @param {Number} [b] - Blue component
|
||||
*/
|
||||
export const rgb2hex = (r, g, b) => {
|
||||
if (r === null || typeof r === 'undefined') {
|
||||
if (r === null || r === undefined) {
|
||||
return undefined
|
||||
}
|
||||
// TODO: clean up this mess
|
||||
|
|
@ -130,7 +130,7 @@ export const arithmeticBlend = (origin, value, operator) => {
|
|||
* @returns {Object} sRGB of resulting color
|
||||
*/
|
||||
export const alphaBlend = (fg, fga, bg) => {
|
||||
if (fga === 1 || typeof fga === 'undefined') {
|
||||
if (fga === 1 || fga === undefined) {
|
||||
return fg
|
||||
}
|
||||
|
||||
|
|
@ -210,16 +210,16 @@ export const rgba2css = function (rgba) {
|
|||
}
|
||||
|
||||
if (rgba !== null) {
|
||||
if (rgba.r !== undefined && !isNaN(rgba.r)) {
|
||||
if (rgba.r !== undefined && !Number.isNaN(rgba.r)) {
|
||||
base.r = rgba.r
|
||||
}
|
||||
if (rgba.g !== undefined && !isNaN(rgba.g)) {
|
||||
if (rgba.g !== undefined && !Number.isNaN(rgba.g)) {
|
||||
base.g = rgba.g
|
||||
}
|
||||
if (rgba.b !== undefined && !isNaN(rgba.b)) {
|
||||
if (rgba.b !== undefined && !Number.isNaN(rgba.b)) {
|
||||
base.b = rgba.b
|
||||
}
|
||||
if (rgba.a !== undefined && !isNaN(rgba.a)) {
|
||||
if (rgba.a !== undefined && !Number.isNaN(rgba.a)) {
|
||||
base.a = rgba.a
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ export const parseUser = (data) => {
|
|||
})
|
||||
output.fields_text = data.fields.map((field) => {
|
||||
return {
|
||||
name: unescape(field.name.replace(/<[^>]*>/g, '')),
|
||||
value: unescape(field.value.replace(/<[^>]*>/g, '')),
|
||||
name: unescape(field.name.replaceAll(/<[^>]*>/g, '')),
|
||||
value: unescape(field.value.replaceAll(/<[^>]*>/g, '')),
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ export const parseUser = (data) => {
|
|||
|
||||
// Convert punycode to unicode for UI
|
||||
output.screen_name_ui = output.screen_name
|
||||
if (output.screen_name && output.screen_name.includes('@')) {
|
||||
if (output.screen_name?.includes('@')) {
|
||||
const parts = output.screen_name.split('@')
|
||||
const unicodeDomain = punycode.toUnicode(parts[1])
|
||||
if (unicodeDomain !== parts[1]) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { capitalize } from 'lodash'
|
|||
function humanizeErrors(errors) {
|
||||
return Object.entries(errors).reduce((errs, [k, val]) => {
|
||||
const message = val.reduce((acc, message) => {
|
||||
const key = capitalize(k.replace(/_/g, ' '))
|
||||
const key = capitalize(k.replaceAll('_', ' '))
|
||||
return acc + [key, message].join(' ') + '. '
|
||||
}, '')
|
||||
return [...errs, message]
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export const fileTypeExt = (url) => {
|
|||
}
|
||||
|
||||
export const fileMatchesSomeType = (types, file) =>
|
||||
types.some((type) => fileType(file.mimetype) === type)
|
||||
types.includes(fileType(file.mimetype))
|
||||
|
||||
const fileTypeService = {
|
||||
fileType,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const visibleTypes = (notificationVisibility) => {
|
|||
notificationVisibility.emojiReactions && 'pleroma:emoji_reaction',
|
||||
notificationVisibility.reports && 'pleroma:report',
|
||||
notificationVisibility.polls && 'poll',
|
||||
].filter((_) => _)
|
||||
].filter(Boolean)
|
||||
}
|
||||
|
||||
const statusNotifications = new Set([
|
||||
|
|
@ -95,9 +95,7 @@ export const filteredNotificationsFromStore = (
|
|||
types,
|
||||
) => {
|
||||
// map is just to clone the array since sort mutates it and it causes some issues
|
||||
const sortedNotifications = notificationsFromStore(store)
|
||||
.map((_) => _)
|
||||
.sort(sortById)
|
||||
const sortedNotifications = notificationsFromStore(store).sort(sortById)
|
||||
// TODO implement sorting elsewhere and make it optional
|
||||
return sortedNotifications.filter((notification) =>
|
||||
(types || visibleTypes(notificationVisibility)).includes(notification.type),
|
||||
|
|
@ -175,13 +173,7 @@ export const prepareNotificationObject = (notification, i18n) => {
|
|||
}
|
||||
|
||||
// Shows first attached non-nsfw image, if any. Should add configuration for this somehow...
|
||||
if (
|
||||
status &&
|
||||
status.attachments &&
|
||||
status.attachments.length > 0 &&
|
||||
!status.nsfw &&
|
||||
status.attachments[0].mimetype.startsWith('image/')
|
||||
) {
|
||||
if (!status.nsfw && status?.attachments?.[0]?.mimetype.startsWith('image/')) {
|
||||
notifObj.image = status.attachments[0].url
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ const createRuffleService = () => {
|
|||
script.src = '/static/ruffle/ruffle.js'
|
||||
script.type = 'text/javascript'
|
||||
script.onerror = (e) => {
|
||||
reject(e)
|
||||
reject(new Error('Ruffle script errorred', e))
|
||||
}
|
||||
script.onabort = (e) => {
|
||||
reject(e)
|
||||
reject(new Error('Ruffle script aborted', e))
|
||||
}
|
||||
script.oncancel = (e) => {
|
||||
reject(e)
|
||||
reject(new Error('Ruffle script cancelled', e))
|
||||
}
|
||||
script.onload = () => {
|
||||
ruffleInstance = window.RufflePlayer
|
||||
|
|
|
|||
|
|
@ -88,5 +88,5 @@ export const muteFilterHits = (muteFilters, status) => {
|
|||
}
|
||||
}
|
||||
})
|
||||
.filter((_) => _)
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export const createStyleSheet = (id, priority = 1000) => {
|
|||
addRule(rule) {
|
||||
let newRule = rule
|
||||
if (!CSS.supports?.('backdrop-filter', 'blur()')) {
|
||||
newRule = newRule.replace(/backdrop-filter:[^;]+;/g, '') // Remove backdrop-filter
|
||||
newRule = newRule.replaceAll(/backdrop-filter:[^;]+;/g, '') // Remove backdrop-filter
|
||||
}
|
||||
|
||||
if (newRule.startsWith('::-webkit')) {
|
||||
|
|
@ -44,7 +44,7 @@ export const createStyleSheet = (id, priority = 1000) => {
|
|||
}
|
||||
|
||||
this.rules.push(
|
||||
newRule.replace(/var\(--shadowFilter\)[^;]*;/g, ''), // Remove shadowFilter references
|
||||
newRule.replaceAll(/var\(--shadowFilter\)[^;]*;/g, ''), // Remove shadowFilter references
|
||||
)
|
||||
},
|
||||
}
|
||||
|
|
@ -92,6 +92,11 @@ export const adoptStyleSheets = throttle(() => {
|
|||
const EAGER_STYLE_ID = 'pleroma-eager-styles'
|
||||
const LAZY_STYLE_ID = 'pleroma-lazy-styles'
|
||||
|
||||
export const hasInvalidCachedThemeRules = (data) =>
|
||||
data
|
||||
.flat()
|
||||
.some((rule) => /--(?:mono)?font:\s*\[object Object\](?:;|$)/i.test(rule))
|
||||
|
||||
const generateTheme = (inputRuleset, callbacks, debug) => {
|
||||
const {
|
||||
onNewRule = () => {
|
||||
|
|
@ -151,7 +156,8 @@ export const tryLoadCache = async () => {
|
|||
if (
|
||||
cache.engineChecksum === getEngineChecksum() &&
|
||||
cache.checksum !== undefined &&
|
||||
cache.checksum === useMergedConfigStore().mergedConfig.themeChecksum
|
||||
cache.checksum === useMergedConfigStore().mergedConfig.themeChecksum &&
|
||||
!hasInvalidCachedThemeRules(cache.data)
|
||||
) {
|
||||
const eagerStyles = createStyleSheet(EAGER_STYLE_ID, 10)
|
||||
const lazyStyles = createStyleSheet(LAZY_STYLE_ID, 20)
|
||||
|
|
@ -318,7 +324,7 @@ export const getResourcesIndex = async (url, parser = noop) => {
|
|||
const resourceTransform = (resources) => {
|
||||
return Object.entries(resources).map(([k, v]) => {
|
||||
if (typeof v === 'object') {
|
||||
return [k, () => Promise.resolve(v)]
|
||||
return [k, () => v]
|
||||
} else if (typeof v === 'string') {
|
||||
return [
|
||||
k,
|
||||
|
|
@ -362,11 +368,9 @@ export const getResourcesIndex = async (url, parser = noop) => {
|
|||
|
||||
const total = [...custom, ...builtin]
|
||||
if (total.length === 0) {
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
`Resource at ${url} and ${customUrl} completely unavailable. Panicking`,
|
||||
),
|
||||
throw new Error(
|
||||
`Resource at ${url} and ${customUrl} completely unavailable. Panicking`,
|
||||
)
|
||||
}
|
||||
return Promise.resolve(Object.fromEntries(total))
|
||||
return Object.fromEntries(total)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/* global process */
|
||||
function urlBase64ToUint8Array(base64String) {
|
||||
const padding = '='.repeat((4 - (base64String.length % 4)) % 4)
|
||||
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/')
|
||||
const base64 = (base64String + padding)
|
||||
.replaceAll('-', '+')
|
||||
.replaceAll('_', '/')
|
||||
|
||||
const rawData = window.atob(base64)
|
||||
return Uint8Array.from([...rawData].map((char) => char.codePointAt(0)))
|
||||
|
|
@ -26,10 +28,8 @@ function getOrCreateServiceWorker() {
|
|||
}
|
||||
|
||||
function subscribePush(registration, isEnabled, vapidPublicKey) {
|
||||
if (!isEnabled)
|
||||
return Promise.reject(new Error('Web Push is disabled in config'))
|
||||
if (!vapidPublicKey)
|
||||
return Promise.reject(new Error('VAPID public key is not found'))
|
||||
if (!isEnabled) throw new Error('Web Push is disabled in config')
|
||||
if (!vapidPublicKey) throw new Error('VAPID public key is not found')
|
||||
|
||||
const subscribeOptions = {
|
||||
userVisibleOnly: false,
|
||||
|
|
@ -38,10 +38,10 @@ function subscribePush(registration, isEnabled, vapidPublicKey) {
|
|||
return registration.pushManager.subscribe(subscribeOptions)
|
||||
}
|
||||
|
||||
function unsubscribePush(registration) {
|
||||
async function unsubscribePush(registration) {
|
||||
return registration.pushManager.getSubscription().then((subscription) => {
|
||||
if (subscription === null) {
|
||||
return Promise.resolve('No subscription')
|
||||
return 'No subscription'
|
||||
}
|
||||
return subscription.unsubscribe()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export const getCssRules = (rules, debug) =>
|
|||
header,
|
||||
directives,
|
||||
rule.component === 'Text' &&
|
||||
rule.state.indexOf('faint') < 0 &&
|
||||
!rule.state.includes('faint') &&
|
||||
rule.directives.textNoCssColor !== 'yes'
|
||||
? ' color: var(--text);'
|
||||
: '',
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export const getAllPossibleCombinations = (array) => {
|
|||
const nonSelf = array.filter((x) => !selfSet.has(x))
|
||||
return nonSelf.map((x) => [...self, x])
|
||||
})
|
||||
const flatCombos = newCombos.reduce((acc, x) => [...acc, ...x], [])
|
||||
const flatCombos = newCombos.flat()
|
||||
const uniqueComboStrings = new Set()
|
||||
const uniqueCombos = flatCombos.map(sortBy).filter((x) => {
|
||||
if (uniqueComboStrings.has(x.join())) {
|
||||
|
|
@ -36,7 +36,7 @@ export const getAllPossibleCombinations = (array) => {
|
|||
})
|
||||
combos.push(uniqueCombos)
|
||||
}
|
||||
return combos.reduce((acc, x) => [...acc, ...x], [])
|
||||
return combos.flat()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -110,13 +110,6 @@ export const genericRuleToSelector =
|
|||
let arraySelector = Array.isArray(selector) ? selector : [selector]
|
||||
if (ignoreOutOfTreeSelector || liteMode)
|
||||
arraySelector = [arraySelector[0]]
|
||||
arraySelector
|
||||
.sort((a) => {
|
||||
if (a.startsWith(':')) return 1
|
||||
if (/^[a-z]/.exec(a)) return -1
|
||||
else return 0
|
||||
})
|
||||
.join('')
|
||||
return arraySelector
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -191,14 +191,16 @@ export const convertTheme2To3 = (data) => {
|
|||
newRules.push(rule)
|
||||
|
||||
if (rule.component === 'Button') {
|
||||
newRules.push({ ...rule, component: 'ScrollbarElement' })
|
||||
newRules.push({ ...rule, component: 'Tab' })
|
||||
newRules.push({
|
||||
...rule,
|
||||
component: 'Tab',
|
||||
state: ['active'],
|
||||
directives: { opacity: 0 },
|
||||
})
|
||||
newRules.push(
|
||||
{ ...rule, component: 'ScrollbarElement' },
|
||||
{ ...rule, component: 'Tab' },
|
||||
{
|
||||
...rule,
|
||||
component: 'Tab',
|
||||
state: ['active'],
|
||||
directives: { opacity: 0 },
|
||||
},
|
||||
)
|
||||
}
|
||||
if (rule.component === 'Panel') {
|
||||
newRules.push({ ...rule, component: 'Post' })
|
||||
|
|
@ -250,8 +252,10 @@ export const convertTheme2To3 = (data) => {
|
|||
}
|
||||
newRules.push(rule)
|
||||
if (rule.component === 'Button') {
|
||||
newRules.push({ ...rule, component: 'ScrollbarElement' })
|
||||
newRules.push({ ...rule, component: 'Tab' })
|
||||
newRules.push(
|
||||
{ ...rule, component: 'ScrollbarElement' },
|
||||
{ ...rule, component: 'Tab' },
|
||||
)
|
||||
}
|
||||
})
|
||||
return newRules
|
||||
|
|
@ -349,16 +353,20 @@ export const convertTheme2To3 = (data) => {
|
|||
newRules.push({ ...rule, parent: { component: 'Notification' } })
|
||||
}
|
||||
if (key === 'buttonPressed') {
|
||||
newRules.push({ ...rule, state: ['toggled'] })
|
||||
newRules.push({ ...rule, state: ['toggled', 'focus'] })
|
||||
newRules.push({ ...rule, state: ['pressed', 'focus'] })
|
||||
newRules.push({ ...rule, state: ['toggled', 'focus', 'hover'] })
|
||||
newRules.push({ ...rule, state: ['pressed', 'focus', 'hover'] })
|
||||
newRules.push(
|
||||
{ ...rule, state: ['toggled'] },
|
||||
{ ...rule, state: ['toggled', 'focus'] },
|
||||
{ ...rule, state: ['pressed', 'focus'] },
|
||||
{ ...rule, state: ['toggled', 'focus', 'hover'] },
|
||||
{ ...rule, state: ['pressed', 'focus', 'hover'] },
|
||||
)
|
||||
}
|
||||
|
||||
if (rule.component === 'Button') {
|
||||
newRules.push({ ...rule, component: 'ScrollbarElement' })
|
||||
newRules.push({ ...rule, component: 'Tab' })
|
||||
newRules.push(
|
||||
{ ...rule, component: 'ScrollbarElement' },
|
||||
{ ...rule, component: 'Tab' },
|
||||
)
|
||||
}
|
||||
})
|
||||
return newRules
|
||||
|
|
@ -512,15 +520,17 @@ export const convertTheme2To3 = (data) => {
|
|||
{ ...newRule, component: 'Tab' },
|
||||
{ ...newRule, component: 'ScrollbarElement' },
|
||||
]
|
||||
if (newRule.state?.indexOf('toggled') >= 0) {
|
||||
rules.push({ ...newRule, state: [...newRule.state, 'focused'] })
|
||||
rules.push({ ...newRule, state: [...newRule.state, 'hover'] })
|
||||
rules.push({
|
||||
...newRule,
|
||||
state: [...newRule.state, 'hover', 'focused'],
|
||||
})
|
||||
if (newRule.state?.includes('toggled')) {
|
||||
rules.push(
|
||||
{ ...newRule, state: [...newRule.state, 'focused'] },
|
||||
{ ...newRule, state: [...newRule.state, 'hover'] },
|
||||
{
|
||||
...newRule,
|
||||
state: [...newRule.state, 'hover', 'focused'],
|
||||
},
|
||||
)
|
||||
}
|
||||
if (newRule.state?.indexOf('hover') >= 0) {
|
||||
if (newRule.state?.includes('hover')) {
|
||||
rules.push({ ...newRule, state: [...newRule.state, 'focused'] })
|
||||
}
|
||||
return rules
|
||||
|
|
@ -559,9 +569,9 @@ export const convertTheme2To3 = (data) => {
|
|||
|
||||
const flatExtRules = extendedRules
|
||||
.filter(Boolean)
|
||||
.reduce((acc, x) => [...acc, ...x], [])
|
||||
.flat()
|
||||
.filter(Boolean)
|
||||
.reduce((acc, x) => [...acc, ...x], [])
|
||||
.flat()
|
||||
|
||||
return [
|
||||
generateRoot(),
|
||||
|
|
|
|||
|
|
@ -244,10 +244,7 @@ export const OPACITIES = Object.entries(SLOT_INHERITANCE).reduce((acc, [k]) => {
|
|||
...acc,
|
||||
[opacity]: {
|
||||
defaultValue: DEFAULT_OPACITY[opacity] || 1,
|
||||
affectedSlots: [
|
||||
...((acc[opacity] && acc[opacity].affectedSlots) || []),
|
||||
k,
|
||||
],
|
||||
affectedSlots: [...(acc[opacity]?.affectedSlots || []), k],
|
||||
},
|
||||
}
|
||||
} else {
|
||||
|
|
@ -413,7 +410,7 @@ export const getColors = (sourceColors, sourceOpacity) =>
|
|||
outputColor.a = Number(
|
||||
opacityOverriden
|
||||
? sourceOpacity[opacitySlot]
|
||||
: (OPACITIES[opacitySlot] || {}).defaultValue,
|
||||
: OPACITIES[opacitySlot]?.defaultValue,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -460,7 +457,7 @@ export const generatePreset = (input) => {
|
|||
return composePreset(
|
||||
colors,
|
||||
generateRadii(input),
|
||||
generateShadows(input, colors.theme.colors, colors.mod),
|
||||
generateShadows(input, colors.theme.colors),
|
||||
generateFonts(input),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ export const init = ({
|
|||
...r,
|
||||
})),
|
||||
)
|
||||
.reduce((acc, arr) => [...acc, ...arr], []),
|
||||
.flat(),
|
||||
...inputRuleset,
|
||||
].map((rule) => {
|
||||
normalizeCombination(rule)
|
||||
|
|
@ -690,11 +690,11 @@ export const init = ({
|
|||
.map((combination) => ['normal', ...combination])
|
||||
.filter((combo) => {
|
||||
// Optimization: filter out some hard-coded combinations that don't make sense
|
||||
if (combo.indexOf('disabled') >= 0) {
|
||||
if (combo.includes('disabled')) {
|
||||
return !(
|
||||
combo.indexOf('hover') >= 0 ||
|
||||
combo.indexOf('focused') >= 0 ||
|
||||
combo.indexOf('pressed') >= 0
|
||||
combo.includes('hover') ||
|
||||
combo.includes('focused') ||
|
||||
combo.includes('pressed')
|
||||
)
|
||||
}
|
||||
return true
|
||||
|
|
@ -705,13 +705,13 @@ export const init = ({
|
|||
.map((variant) => {
|
||||
return stateCombinations.map((state) => ({ variant, state }))
|
||||
})
|
||||
.reduce((acc, x) => [...acc, ...x], [])
|
||||
.flat()
|
||||
|
||||
stateVariantCombination.forEach((combination) => {
|
||||
combination.component = component.name
|
||||
combination.lazy = component.lazy || parent?.lazy
|
||||
combination.parent = parent
|
||||
if (!liteMode && combination.state.indexOf('hover') >= 0) {
|
||||
if (!liteMode && combination.state.includes('hover')) {
|
||||
combination.lazy = true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ const highlightStyle = (prefs) => {
|
|||
|
||||
const highlightClass = (user) => {
|
||||
return (
|
||||
'USER____' + user.screen_name?.replace(/\./g, '_').replace(/@/g, '_AT_')
|
||||
'USER____' + user.screen_name?.replaceAll('.', '_').replaceAll('@', '_AT_')
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue