Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop
This commit is contained in:
commit
66c44b4260
62 changed files with 1206 additions and 595 deletions
|
@ -632,7 +632,8 @@ const postStatus = ({
|
|||
mediaIds = [],
|
||||
inReplyToStatusId,
|
||||
contentType,
|
||||
preview
|
||||
preview,
|
||||
idempotencyKey
|
||||
}) => {
|
||||
const form = new FormData()
|
||||
const pollOptions = poll.options || []
|
||||
|
@ -666,10 +667,15 @@ const postStatus = ({
|
|||
form.append('preview', 'true')
|
||||
}
|
||||
|
||||
let postHeaders = authHeaders(credentials)
|
||||
if (idempotencyKey) {
|
||||
postHeaders['idempotency-key'] = idempotencyKey
|
||||
}
|
||||
|
||||
return fetch(MASTODON_POST_STATUS_URL, {
|
||||
body: form,
|
||||
method: 'POST',
|
||||
headers: authHeaders(credentials)
|
||||
headers: postHeaders
|
||||
})
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
|
|
19
src/services/chat_utils/chat_utils.js
Normal file
19
src/services/chat_utils/chat_utils.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { showDesktopNotification } from '../desktop_notification_utils/desktop_notification_utils.js'
|
||||
|
||||
export const maybeShowChatNotification = (store, chat) => {
|
||||
if (!chat.lastMessage) return
|
||||
if (store.rootState.chats.currentChatId === chat.id && !document.hidden) return
|
||||
|
||||
const opts = {
|
||||
tag: chat.lastMessage.id,
|
||||
title: chat.account.name,
|
||||
icon: chat.account.profile_image_url,
|
||||
body: chat.lastMessage.content
|
||||
}
|
||||
|
||||
if (chat.lastMessage.attachment && chat.lastMessage.attachment.type === 'image') {
|
||||
opts.image = chat.lastMessage.attachment.preview_url
|
||||
}
|
||||
|
||||
showDesktopNotification(store.rootState, opts)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export const showDesktopNotification = (rootState, desktopNotificationOpts) => {
|
||||
if (!('Notification' in window && window.Notification.permission === 'granted')) return
|
||||
if (rootState.statuses.notifications.desktopNotificationSilence) { return }
|
||||
|
||||
const desktopNotification = new window.Notification(desktopNotificationOpts.title, desktopNotificationOpts)
|
||||
// Chrome is known for not closing notifications automatically
|
||||
// according to MDN, anyway.
|
||||
setTimeout(desktopNotification.close.bind(desktopNotification), 5000)
|
||||
}
|
|
@ -79,6 +79,7 @@ export const parseUser = (data) => {
|
|||
const relationship = data.pleroma.relationship
|
||||
|
||||
output.background_image = data.pleroma.background_image
|
||||
output.favicon = data.pleroma.favicon
|
||||
output.token = data.pleroma.chat_token
|
||||
|
||||
if (relationship) {
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
import { filter, sortBy, includes } from 'lodash'
|
||||
import { muteWordHits } from '../status_parser/status_parser.js'
|
||||
import { showDesktopNotification } from '../desktop_notification_utils/desktop_notification_utils.js'
|
||||
|
||||
export const notificationsFromStore = store => store.state.statuses.notifications.data
|
||||
|
||||
export const visibleTypes = store => ([
|
||||
store.state.config.notificationVisibility.likes && 'like',
|
||||
store.state.config.notificationVisibility.mentions && 'mention',
|
||||
store.state.config.notificationVisibility.repeats && 'repeat',
|
||||
store.state.config.notificationVisibility.follows && 'follow',
|
||||
store.state.config.notificationVisibility.followRequest && 'follow_request',
|
||||
store.state.config.notificationVisibility.moves && 'move',
|
||||
store.state.config.notificationVisibility.emojiReactions && 'pleroma:emoji_reaction'
|
||||
].filter(_ => _))
|
||||
export const visibleTypes = store => {
|
||||
const rootState = store.rootState || store.state
|
||||
|
||||
return ([
|
||||
rootState.config.notificationVisibility.likes && 'like',
|
||||
rootState.config.notificationVisibility.mentions && 'mention',
|
||||
rootState.config.notificationVisibility.repeats && 'repeat',
|
||||
rootState.config.notificationVisibility.follows && 'follow',
|
||||
rootState.config.notificationVisibility.followRequest && 'follow_request',
|
||||
rootState.config.notificationVisibility.moves && 'move',
|
||||
rootState.config.notificationVisibility.emojiReactions && 'pleroma:emoji_reaction'
|
||||
].filter(_ => _))
|
||||
}
|
||||
|
||||
const statusNotifications = ['like', 'mention', 'repeat', 'pleroma:emoji_reaction']
|
||||
|
||||
|
@ -32,6 +38,22 @@ const sortById = (a, b) => {
|
|||
}
|
||||
}
|
||||
|
||||
const isMutedNotification = (store, notification) => {
|
||||
if (!notification.status) return
|
||||
return notification.status.muted || muteWordHits(notification.status, store.rootGetters.mergedConfig.muteWords).length > 0
|
||||
}
|
||||
|
||||
export const maybeShowNotification = (store, notification) => {
|
||||
const rootState = store.rootState || store.state
|
||||
|
||||
if (notification.seen) return
|
||||
if (!visibleTypes(store).includes(notification.type)) return
|
||||
if (notification.type === 'mention' && isMutedNotification(store, notification)) return
|
||||
|
||||
const notificationObject = prepareNotificationObject(notification, store.rootGetters.i18n)
|
||||
showDesktopNotification(rootState, notificationObject)
|
||||
}
|
||||
|
||||
export const filteredNotificationsFromStore = (store, types) => {
|
||||
// map is just to clone the array since sort mutates it and it causes some issues
|
||||
let sortedNotifications = notificationsFromStore(store).map(_ => _).sort(sortById)
|
||||
|
|
|
@ -35,7 +35,7 @@ const fetchAndUpdate = ({ store, credentials, older = false }) => {
|
|||
const notifications = timelineData.data
|
||||
const readNotifsIds = notifications.filter(n => n.seen).map(n => n.id)
|
||||
const numUnseenNotifs = notifications.length - readNotifsIds.length
|
||||
if (numUnseenNotifs > 0) {
|
||||
if (numUnseenNotifs > 0 && readNotifsIds.length > 0) {
|
||||
args['since'] = Math.max(...readNotifsIds)
|
||||
fetchNotifications({ store, args, older })
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ const postStatus = ({
|
|||
media = [],
|
||||
inReplyToStatusId = undefined,
|
||||
contentType = 'text/plain',
|
||||
preview = false
|
||||
preview = false,
|
||||
idempotencyKey = ''
|
||||
}) => {
|
||||
const mediaIds = map(media, 'id')
|
||||
|
||||
|
@ -25,7 +26,8 @@ const postStatus = ({
|
|||
inReplyToStatusId,
|
||||
contentType,
|
||||
poll,
|
||||
preview
|
||||
preview,
|
||||
idempotencyKey
|
||||
})
|
||||
.then((data) => {
|
||||
if (!data.error && !preview) {
|
||||
|
|
|
@ -675,23 +675,22 @@ export const SLOT_INHERITANCE = {
|
|||
depends: ['bg']
|
||||
},
|
||||
|
||||
chatMessage: {
|
||||
depends: ['chatBg']
|
||||
},
|
||||
|
||||
chatMessageIncomingBg: {
|
||||
depends: ['chatMessage'],
|
||||
layer: 'chatMessage'
|
||||
depends: ['chatBg']
|
||||
},
|
||||
|
||||
chatMessageIncomingText: {
|
||||
depends: ['text'],
|
||||
layer: 'text'
|
||||
layer: 'chatMessage',
|
||||
variant: 'chatMessageIncomingBg',
|
||||
textColor: true
|
||||
},
|
||||
|
||||
chatMessageIncomingLink: {
|
||||
depends: ['link'],
|
||||
layer: 'link'
|
||||
layer: 'chatMessage',
|
||||
variant: 'chatMessageIncomingBg',
|
||||
textColor: 'preserve'
|
||||
},
|
||||
|
||||
chatMessageIncomingBorder: {
|
||||
|
@ -701,22 +700,27 @@ export const SLOT_INHERITANCE = {
|
|||
},
|
||||
|
||||
chatMessageOutgoingBg: {
|
||||
depends: ['chatMessage'],
|
||||
depends: ['chatMessageIncomingBg'],
|
||||
color: (mod, chatMessage) => brightness(5 * mod, chatMessage).rgb
|
||||
},
|
||||
|
||||
chatMessageOutgoingText: {
|
||||
depends: ['text'],
|
||||
layer: 'text'
|
||||
layer: 'chatMessage',
|
||||
variant: 'chatMessageOutgoingBg',
|
||||
textColor: true
|
||||
},
|
||||
|
||||
chatMessageOutgoingLink: {
|
||||
depends: ['link'],
|
||||
layer: 'link'
|
||||
layer: 'chatMessage',
|
||||
variant: 'chatMessageOutgoingBg',
|
||||
textColor: 'preserve'
|
||||
},
|
||||
|
||||
chatMessageOutgoingBorder: {
|
||||
depends: ['chatMessage'],
|
||||
opacity: 'chatMessage'
|
||||
depends: ['chatMessageOutgoingBg'],
|
||||
opacity: 'border',
|
||||
color: (mod, border) => brightness(2 * mod, border).rgb
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,14 +128,17 @@ export const topoSort = (
|
|||
while (unprocessed.length > 0) {
|
||||
step(unprocessed.pop())
|
||||
}
|
||||
return output.sort((a, b) => {
|
||||
|
||||
// The index thing is to make sorting stable on browsers
|
||||
// where Array.sort() isn't stable
|
||||
return output.map((data, index) => ({ data, index })).sort(({ data: a, index: ai }, { data: b, index: bi }) => {
|
||||
const depsA = getDeps(a, inheritance).length
|
||||
const depsB = getDeps(b, inheritance).length
|
||||
|
||||
if (depsA === depsB || (depsB !== 0 && depsA !== 0)) return 0
|
||||
if (depsA === depsB || (depsB !== 0 && depsA !== 0)) return ai - bi
|
||||
if (depsA === 0 && depsB !== 0) return -1
|
||||
if (depsB === 0 && depsA !== 0) return 1
|
||||
})
|
||||
}).map(({ data }) => data)
|
||||
}
|
||||
|
||||
const expandSlotValue = (value) => {
|
||||
|
|
|
@ -43,7 +43,9 @@ const fetchAndUpdate = ({
|
|||
args['userId'] = userId
|
||||
args['tag'] = tag
|
||||
args['withMuted'] = !hideMutedPosts
|
||||
if (loggedIn) args['replyVisibility'] = replyVisibility
|
||||
if (loggedIn && ['friends', 'public', 'publicAndExternal'].includes(timeline)) {
|
||||
args['replyVisibility'] = replyVisibility
|
||||
}
|
||||
|
||||
const numStatusesBeforeFetch = timelineData.statuses.length
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue