Files
photoview/ui/src/components/messages/Messages.js
viktorstrate 8e8abe7d37 Replace all gorm .Scan() calls with .Find()
if the argument is a model. This ensures that the proper gorm hooks are
called which was causing the full screen view on the Places page to
crash.

Also fixed a bug in Messages.js that caused a crash.
2021-04-15 16:27:26 +02:00

141 lines
3.3 KiB
JavaScript

import React, { useState } from 'react'
import { animated, useTransition } from 'react-spring'
import { Message } from 'semantic-ui-react'
import styled from 'styled-components'
import { authToken } from '../../helpers/authentication'
import MessageProgress from './MessageProgress'
import SubscriptionsHook from './SubscriptionsHook'
const Container = styled.div`
position: fixed;
bottom: 20px;
right: 20px;
width: 500px;
@media (max-width: 1000px) {
display: none;
}
`
export const MessageState = {
set: fn => {
console.warn('set function is not defined yet, called with', fn)
},
get: [],
add: message => {
MessageState.set(messages => {
const newMessages = messages.filter(msg => msg.key != message.key)
newMessages.push(message)
return newMessages
})
},
removeKey: key => {
MessageState.set(messages => {
const newMessages = messages.filter(msg => msg.key != key)
return newMessages
})
},
}
const Messages = () => {
const [messages, setMessages] = useState([])
MessageState.set = setMessages
MessageState.get = messages
const [refMap] = useState(() => new WeakMap())
const getMessageElement = (message, ref) => {
const dismissMessage = message => {
message.onDismiss && message.onDismiss()
setMessages(messages => messages.filter(msg => msg.key != message.key))
}
const RefDiv = props => <div {...props} ref={x => x && ref(x)} />
switch (message.type) {
case 'Message':
return props => (
<Message
as={RefDiv}
onDismiss={() => {
dismissMessage(message)
}}
floating
{...message.props}
{...props}
/>
)
case 'Progress':
return props => (
<MessageProgress
as={RefDiv}
onDismiss={() => {
dismissMessage(message)
}}
{...message.props}
{...props}
/>
)
}
}
let refHooks = new Map()
messages.forEach(message => {
let resolveFunc = null
const waitPromise = new Promise(resolve => {
resolveFunc = resolve
})
refHooks.set(message.key, {
done: resolveFunc,
promise: waitPromise,
})
})
const transitions = useTransition(messages.slice().reverse(), x => x.key, {
from: {
opacity: 0,
height: '0px',
},
enter: item => async next => {
const refPromise = refHooks.get(item.key).promise
await refPromise
await next({
opacity: 1,
height: `${refMap.get(item).offsetHeight + 10}px`,
})
},
leave: { opacity: 0, height: '0px' },
})
return (
<Container>
{transitions.map(({ item, props: style, key }) => {
const getRef = ref => {
refMap.set(item, ref)
if (refHooks.has(item.key)) {
refHooks.get(item.key).done()
}
}
const MessageElement = getMessageElement(item, getRef)
style.padding = 0
return (
<animated.div key={key} style={style}>
<MessageElement />
</animated.div>
)
})}
{authToken() && (
<SubscriptionsHook messages={messages} setMessages={setMessages} />
)}
</Container>
)
}
export default Messages