Merge pull request 'Synchronized Settings' (#3473) from setttingssync into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma-fe/pulls/3473
This commit is contained in:
commit
9f3c0ec60b
150 changed files with 3942 additions and 1810 deletions
|
|
@ -1,8 +1,8 @@
|
|||
import { parseLinkHeader } from '@web3-storage/parse-link-header'
|
||||
import escapeHtml from 'escape-html'
|
||||
import fileTypeService from '../file_type/file_type.service.js'
|
||||
import punycode from 'punycode.js'
|
||||
|
||||
import fileTypeService from '../file_type/file_type.service.js'
|
||||
import { isStatusNotification } from '../notification_utils/notification_utils.js'
|
||||
|
||||
/** NOTICE! **
|
||||
|
|
@ -117,6 +117,7 @@ export const parseUser = (data) => {
|
|||
if (data.pleroma) {
|
||||
if (data.pleroma.settings_store) {
|
||||
output.storage = data.pleroma.settings_store['pleroma-fe']
|
||||
output.user_highlight = data.pleroma.settings_store['user_highlight']
|
||||
}
|
||||
const relationship = data.pleroma.relationship
|
||||
|
||||
|
|
@ -371,8 +372,8 @@ export const parseStatus = (data) => {
|
|||
const quoteData = quoteRaw ? parseStatus(quoteRaw) : undefined
|
||||
output.quote = quoteData
|
||||
output.quote_id =
|
||||
data.quote?.id ?? data.quote_id ?? quoteData?.id ?? pleroma.quote_id
|
||||
output.quote_url = data.quote?.url ?? quoteData?.url ?? pleroma.quote_url
|
||||
data.quote?.id ?? data.quote_id ?? quoteData?.id ?? pleroma?.quote_id
|
||||
output.quote_url = data.quote?.url ?? quoteData?.url ?? pleroma?.quote_url
|
||||
|
||||
output.in_reply_to_status_id = data.in_reply_to_id
|
||||
output.in_reply_to_user_id = data.in_reply_to_account_id
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ export const getAttrs = (tag, filter) => {
|
|||
.replace(/\/?$/, '')
|
||||
.trim()
|
||||
const attrs = Array.from(
|
||||
innertag.matchAll(/([a-z]+[a-z0-9-]*)(?:=((?:"(?:\\.|[^"\\])*")|(?:'(?:\\.|[^'\\])*')))?/gi),
|
||||
innertag.matchAll(
|
||||
/([a-z]+[a-z0-9-]*)(?:=((?:"(?:\\.|[^"\\])*")|(?:'(?:\\.|[^'\\])*')))?/gi,
|
||||
),
|
||||
)
|
||||
.map(([, key, value]) => [key, value])
|
||||
.map(([k, v]) => {
|
||||
|
|
|
|||
|
|
@ -20,10 +20,8 @@ export const getJsonOrError = async (response) => {
|
|||
}
|
||||
|
||||
export const createApp = (instance) => {
|
||||
console.log('NAP', instance)
|
||||
const url = `${instance}/api/v1/apps`
|
||||
const form = new window.FormData()
|
||||
console.log(url)
|
||||
|
||||
form.append('client_name', 'PleromaFE')
|
||||
form.append('website', 'https://pleroma.social')
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { showDesktopNotification } from '../desktop_notification_utils/desktop_notification_utils.js'
|
||||
import { muteFilterHits } from '../status_parser/status_parser.js'
|
||||
|
||||
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
||||
import { useI18nStore } from 'src/stores/i18n.js'
|
||||
|
||||
import FaviconService from 'src/services/favicon_service/favicon_service.js'
|
||||
|
|
@ -16,12 +16,7 @@ let cachedBadgeUrl = null
|
|||
|
||||
export const notificationsFromStore = (store) => store.state.notifications.data
|
||||
|
||||
export const visibleTypes = (store) => {
|
||||
// When called from within a module we need rootGetters to access wider scope
|
||||
// however when called from a component (i.e. this.$store) we already have wider scope
|
||||
const rootGetters = store.rootGetters || store.getters
|
||||
const { notificationVisibility } = rootGetters.mergedConfig
|
||||
|
||||
const visibleTypes = (notificationVisibility) => {
|
||||
return [
|
||||
notificationVisibility.likes && 'like',
|
||||
notificationVisibility.mentions && 'mention',
|
||||
|
|
@ -70,18 +65,23 @@ const sortById = (a, b) => {
|
|||
}
|
||||
}
|
||||
|
||||
const isMutedNotification = (notification) => {
|
||||
const isMutedNotification = (muteFilters, notification) => {
|
||||
if (!notification.status) return false
|
||||
if (notification.status.muted) return true
|
||||
return muteFilterHits(notification.status).length > 0
|
||||
return muteFilterHits(muteFilters, notification.status).length > 0
|
||||
}
|
||||
|
||||
export const maybeShowNotification = (store, notification) => {
|
||||
export const maybeShowNotification = (
|
||||
store,
|
||||
notificationVisibility,
|
||||
muteFilters,
|
||||
notification,
|
||||
) => {
|
||||
const rootState = store.rootState || store.state
|
||||
|
||||
if (notification.seen) return
|
||||
if (!visibleTypes(store).includes(notification.type)) return
|
||||
if (notification.type === 'mention' && isMutedNotification(notification))
|
||||
if (!visibleTypes(notificationVisibility).includes(notification.type)) return
|
||||
if (notification.type === 'mention' && isMutedNotification(muteFilters, notification))
|
||||
return
|
||||
|
||||
const notificationObject = prepareNotificationObject(
|
||||
|
|
@ -91,26 +91,33 @@ export const maybeShowNotification = (store, notification) => {
|
|||
showDesktopNotification(rootState, notificationObject)
|
||||
}
|
||||
|
||||
export const filteredNotificationsFromStore = (store, types) => {
|
||||
export const filteredNotificationsFromStore = (
|
||||
store,
|
||||
notificationVisibility,
|
||||
types,
|
||||
) => {
|
||||
// map is just to clone the array since sort mutates it and it causes some issues
|
||||
const sortedNotifications = notificationsFromStore(store)
|
||||
.map((_) => _)
|
||||
.sort(sortById)
|
||||
// TODO implement sorting elsewhere and make it optional
|
||||
return sortedNotifications.filter((notification) =>
|
||||
(types || visibleTypes(store)).includes(notification.type),
|
||||
(types || visibleTypes(notificationVisibility)).includes(notification.type),
|
||||
)
|
||||
}
|
||||
|
||||
export const unseenNotificationsFromStore = (store) => {
|
||||
const rootGetters = store.rootGetters || store.getters
|
||||
const ignoreInactionableSeen = rootGetters.mergedConfig.ignoreInactionableSeen
|
||||
|
||||
return filteredNotificationsFromStore(store).filter(({ seen, type }) => {
|
||||
if (!ignoreInactionableSeen) return !seen
|
||||
if (seen) return false
|
||||
return ACTIONABLE_NOTIFICATION_TYPES.has(type)
|
||||
})
|
||||
export const unseenNotificationsFromStore = (
|
||||
store,
|
||||
notificationVisibility,
|
||||
ignoreInactionableSeen,
|
||||
) => {
|
||||
return filteredNotificationsFromStore(store, notificationVisibility).filter(
|
||||
({ seen, type }) => {
|
||||
if (!ignoreInactionableSeen) return !seen
|
||||
if (seen) return false
|
||||
return ACTIONABLE_NOTIFICATION_TYPES.has(type)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export const prepareNotificationObject = (notification, i18n) => {
|
||||
|
|
@ -183,9 +190,8 @@ export const prepareNotificationObject = (notification, i18n) => {
|
|||
return notifObj
|
||||
}
|
||||
|
||||
export const countExtraNotifications = (store) => {
|
||||
export const countExtraNotifications = (store, mergedConfig) => {
|
||||
const rootGetters = store.rootGetters || store.getters
|
||||
const mergedConfig = rootGetters.mergedConfig
|
||||
|
||||
if (!mergedConfig.showExtraNotifications) {
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { promiseInterval } from '../promise_interval/promise_interval.js'
|
|||
import { useInstanceStore } from 'src/stores/instance.js'
|
||||
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
||||
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||
|
||||
const update = ({ store, notifications, older }) => {
|
||||
store.dispatch('addNewNotifications', { notifications, older })
|
||||
|
|
@ -26,10 +27,9 @@ const mastoApiNotificationTypes = new Set([
|
|||
|
||||
const fetchAndUpdate = ({ store, credentials, older = false, since }) => {
|
||||
const args = { credentials }
|
||||
const { getters } = store
|
||||
const rootState = store.rootState || store.state
|
||||
const timelineData = rootState.notifications
|
||||
const hideMutedPosts = getters.mergedConfig.hideMutedPosts
|
||||
const hideMutedPosts = useMergedConfigStore().mergedConfig.hideMutedPosts
|
||||
|
||||
if (useInstanceCapabilitiesStore().pleromaChatMessagesAvailable) {
|
||||
mastoApiNotificationTypes.add('pleroma:chat_mention')
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
import sum from 'hash-sum'
|
||||
import localforage from 'localforage'
|
||||
import { chunk, throttle } from 'lodash'
|
||||
|
||||
import { getCssRules } from '../theme_data/css_utils.js'
|
||||
import { getEngineChecksum, init } from '../theme_data/theme_data_3.service.js'
|
||||
|
||||
import { defaultState } from 'src/modules/default_config_state.js'
|
||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||
import { useSyncConfigStore } from 'src/stores/sync_config.js'
|
||||
|
||||
import { ROOT_CONFIG } from 'src/modules/default_config_state.js'
|
||||
|
||||
// On platforms where this is not supported, it will return undefined
|
||||
// Otherwise it will return an array
|
||||
|
|
@ -77,7 +81,7 @@ export const adoptStyleSheets = throttle(() => {
|
|||
const EAGER_STYLE_ID = 'pleroma-eager-styles'
|
||||
const LAZY_STYLE_ID = 'pleroma-lazy-styles'
|
||||
|
||||
export const generateTheme = (inputRuleset, callbacks, debug) => {
|
||||
const generateTheme = (inputRuleset, callbacks, debug) => {
|
||||
const {
|
||||
onNewRule = () => {
|
||||
/* no-op */
|
||||
|
|
@ -136,7 +140,11 @@ export const tryLoadCache = async () => {
|
|||
const cache = await localforage.getItem('pleromafe-theme-cache')
|
||||
if (!cache) return null
|
||||
try {
|
||||
if (cache.engineChecksum === getEngineChecksum()) {
|
||||
if (
|
||||
cache.engineChecksum === getEngineChecksum() &&
|
||||
cache.checksum !== undefined &&
|
||||
cache.checksum === useMergedConfigStore().mergedConfig.themeChecksum
|
||||
) {
|
||||
const eagerStyles = createStyleSheet(EAGER_STYLE_ID, 10)
|
||||
const lazyStyles = createStyleSheet(LAZY_STYLE_ID, 20)
|
||||
|
||||
|
|
@ -149,7 +157,7 @@ export const tryLoadCache = async () => {
|
|||
console.info(`Loaded theme from cache`)
|
||||
return true
|
||||
} else {
|
||||
console.warn("Engine checksum doesn't match, cache not usable, clearing")
|
||||
console.warn("Checksums don't match, cache not usable, clearing")
|
||||
localStorage.removeItem('pleroma-fe-theme-cache')
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -195,10 +203,17 @@ export const applyTheme = (
|
|||
onLazyFinished() {
|
||||
lazyStyles.ready = true
|
||||
adoptStyleSheets()
|
||||
const data = [eagerStyles.rules, lazyStyles.rules]
|
||||
const checksum = sum(data)
|
||||
const cache = {
|
||||
checksum,
|
||||
engineChecksum: getEngineChecksum(),
|
||||
data: [eagerStyles.rules, lazyStyles.rules],
|
||||
data,
|
||||
}
|
||||
useSyncConfigStore().setSimplePrefAndSave({
|
||||
path: 'themeChecksum',
|
||||
value: checksum,
|
||||
})
|
||||
onFinish(cache)
|
||||
localforage.setItem('pleromafe-theme-cache', cache)
|
||||
console.info('Theme cache stored')
|
||||
|
|
@ -253,7 +268,7 @@ const extractStyleConfig = ({
|
|||
return result
|
||||
}
|
||||
|
||||
const defaultStyleConfig = extractStyleConfig(defaultState)
|
||||
const defaultStyleConfig = extractStyleConfig(ROOT_CONFIG)
|
||||
|
||||
export const applyStyleConfig = (input) => {
|
||||
const config = extractStyleConfig(input)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ function subscribePush(registration, isEnabled, vapidPublicKey) {
|
|||
function unsubscribePush(registration) {
|
||||
return registration.pushManager.getSubscription().then((subscription) => {
|
||||
if (subscription === null) {
|
||||
return
|
||||
return Promise.resolve('No subscription')
|
||||
}
|
||||
return subscription.unsubscribe()
|
||||
})
|
||||
|
|
@ -158,23 +158,23 @@ export function registerPushNotifications(
|
|||
|
||||
export function unregisterPushNotifications(token) {
|
||||
if (isPushSupported()) {
|
||||
Promise.all([
|
||||
deleteSubscriptionFromBackEnd(token),
|
||||
getOrCreateServiceWorker()
|
||||
.then((registration) => {
|
||||
return unsubscribePush(registration).then((result) => [
|
||||
registration,
|
||||
result,
|
||||
])
|
||||
})
|
||||
.then(([, unsubResult]) => {
|
||||
if (!unsubResult) {
|
||||
console.warn("Push subscription cancellation wasn't successful")
|
||||
}
|
||||
}),
|
||||
]).catch((e) =>
|
||||
console.warn(`Failed to disable Web Push Notifications: ${e.message}`),
|
||||
)
|
||||
getOrCreateServiceWorker()
|
||||
.then((registration) => {
|
||||
return unsubscribePush(registration).then((result) => [
|
||||
registration,
|
||||
result,
|
||||
])
|
||||
})
|
||||
.then(([, unsubResult]) => {
|
||||
if (unsubResult === 'No subscription') return
|
||||
if (!unsubResult) {
|
||||
console.warn("Push subscription cancellation wasn't successful")
|
||||
}
|
||||
return deleteSubscriptionFromBackEnd(token)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.warn(`Failed to disable Web Push Notifications: ${e.message}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { promiseInterval } from '../promise_interval/promise_interval.js'
|
|||
import { useInstanceStore } from 'src/stores/instance.js'
|
||||
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
||||
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||
|
||||
const update = ({
|
||||
store,
|
||||
|
|
@ -44,9 +45,9 @@ const fetchAndUpdate = ({
|
|||
}) => {
|
||||
const args = { timeline, credentials }
|
||||
const rootState = store.rootState || store.state
|
||||
const { getters } = store
|
||||
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
|
||||
const { hideMutedPosts, replyVisibility } = getters.mergedConfig
|
||||
const { hideMutedPosts, replyVisibility } =
|
||||
useMergedConfigStore().mergedConfig
|
||||
const loggedIn = !!rootState.users.currentUser
|
||||
|
||||
if (older) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { hex2rgb } from '../color_convert/color_convert.js'
|
|||
|
||||
const highlightStyle = (prefs) => {
|
||||
if (prefs === undefined) return
|
||||
const { color, type } = prefs
|
||||
const { color = '#FFFFFF', type } = prefs
|
||||
if (typeof color !== 'string') return
|
||||
const rgb = hex2rgb(color)
|
||||
if (rgb == null) return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue