pull/1852/head
filip mertens 3 years ago
parent 66126a4d15
commit eb11ba7842
  1. 30
      libs/remix-ui/app/src/lib/remix-app/actions/modals.ts
  2. 0
      libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.css
  3. 0
      libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.tsx
  4. 27
      libs/remix-ui/app/src/lib/remix-app/components/modals/dialogs.tsx
  5. 2
      libs/remix-ui/app/src/lib/remix-app/components/modals/matomo.tsx
  6. 54
      libs/remix-ui/app/src/lib/remix-app/components/modals/modal-wrapper.tsx
  7. 4
      libs/remix-ui/app/src/lib/remix-app/components/modals/origin-warning.tsx
  8. 0
      libs/remix-ui/app/src/lib/remix-app/components/splashscreen.tsx
  9. 14
      libs/remix-ui/app/src/lib/remix-app/context/context.tsx
  10. 62
      libs/remix-ui/app/src/lib/remix-app/context/provider.tsx
  11. 21
      libs/remix-ui/app/src/lib/remix-app/interface/index.ts
  12. 79
      libs/remix-ui/app/src/lib/remix-app/reducer/modals.ts
  13. 68
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  14. 60
      libs/remix-ui/app/src/lib/remix-app/state/modals.ts
  15. 18
      libs/remix-ui/app/src/lib/remix-app/types/index.ts
  16. 2
      libs/remix-ui/modal-dialog/src/lib/types/index.ts

@ -0,0 +1,30 @@
import { AppModal } from '../interface'
export type ActionMap<M extends { [index: string]: any }> = {
[Key in keyof M]: M[Key] extends undefined
? {
type: Key;
}
: {
type: Key;
payload: M[Key];
}
}
export const enum actionTypes {
setModal = 'SET_MODAL',
setToast = 'SET_TOAST',
handleHideModal = 'HANDLE_HIDE_MODAL',
handleToaster = 'HANDLE_HIDE_TOAST'
}
type ModalPayload = {
[actionTypes.setModal]: AppModal
[actionTypes.handleHideModal]: any
[actionTypes.setToast]: string
[actionTypes.handleToaster]: any
}
export type ModalAction = ActionMap<ModalPayload>[keyof ActionMap<
ModalPayload
>]

@ -0,0 +1,27 @@
import React, { useEffect } from 'react'
import { useDialogDispatchers, useDialogs } from '../../context/provider'
import { Toaster } from '@remix-ui/toaster'
import ModalWrapper from './modal-wrapper'
import { ModalTypes } from '../../types'
const AppDialogs = () => {
const { modal, toast, alert, handleHideModal, handleToaster } = useDialogDispatchers()
const { focusModal, focusToaster } = useDialogs()
const ok = (returnedValue) => {
console.log('ok', returnedValue)
}
useEffect(() => {
modal('test', 'Enter gist url', 'yes', ok, 'cancel', () => { }, ModalTypes.prompt, 'wss://remix.ethereum.org:8545')
toast('test toast')
// alert('fat error')
}, [])
return (
<>
<ModalWrapper {...focusModal } handleHide={handleHideModal}></ModalWrapper>
<Toaster message={focusToaster} handleHide={handleToaster} />
</>)
}
export default AppDialogs

@ -1,6 +1,6 @@
import React, { useContext, useEffect, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
import AppContext from '../context/context'
import { AppContext } from '../../context/context'
const _paq = window._paq = window._paq || []
const MatomoDialog = (props) => {

@ -0,0 +1,54 @@
import React, { useEffect, useRef, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
import { ModalDialogProps } from 'libs/remix-ui/modal-dialog/src/lib/types'
import { ModalTypes } from '../../types'
interface ModalWrapperProps extends ModalDialogProps {
modalType?: ModalTypes
defaultValue?: string
}
const ModalWrapper = (props: ModalWrapperProps) => {
const [state, setState] = useState<ModalDialogProps>()
const ref = useRef()
const onFinishPrompt = async () => {
if (ref.current === undefined) {
props.okFn()
} else {
// @ts-ignore: Object is possibly 'null'.
props.okFn(ref.current.value)
}
}
const createModalMessage = () => {
return (
<>
{props.message}
<input type={props.modalType === ModalTypes.password ? 'password' : 'text'} value={props.defaultValue} data-id="modalDialogCustomPromp" ref={ref} className="form-control" /></>
)
}
useEffect(() => {
console.log(props)
if (props.modalType) {
switch (props.modalType) {
case ModalTypes.prompt:
case ModalTypes.password:
setState({
...props,
okFn: onFinishPrompt,
message: createModalMessage()
})
break
default:
setState({ ...props })
break
}
}
}, [props])
return (
<ModalDialog id='appDialog' {...state} handleHide={props.handleHide} />)
}
export default ModalWrapper

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
const AlertModal = () => {
const OriginWarning = () => {
const [visible, setVisible] = useState<boolean>(true)
const [content, setContent] = useState<string>('')
@ -40,4 +40,4 @@ const AlertModal = () => {
cancelFn={closeModal}>{content}</ModalDialog>)
}
export default AlertModal
export default OriginWarning

@ -1,5 +1,15 @@
import React from 'react'
import { ModalInitialState } from '../state/modals'
import { ModalTypes } from '../types'
const AppContext = React.createContext(null)
export const AppContext = React.createContext(null)
export default AppContext
export const dispatchModalContext = React.createContext({
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: (value?:any) => void, cancelLabel?: string, cancelFn?: () => void, modalType?: ModalTypes, defaultValue?: string) => { },
toast: (message: string) => {},
alert: (title: string, message?: string | JSX.Element) => {},
handleHideModal: () => { },
handleToaster: () => {}
})
export const modalContext = React.createContext(ModalInitialState)

@ -0,0 +1,62 @@
import React, { useReducer } from 'react'
import { actionTypes } from '../actions/modals'
import { modalReducer } from '../reducer/modals'
import { ModalInitialState } from '../state/modals'
import { ModalTypes } from '../types'
import { AppContext, dispatchModalContext, modalContext } from './context'
export const ModalProvider = ({ children = [], reducer = modalReducer, initialState = ModalInitialState } = {}) => {
const [{ modals, toasters, focusModal, focusToaster }, dispatch] = useReducer(reducer, initialState)
const modal = (title: string, message: string | JSX.Element, okLabel: string, okFn: (value?:any) => void, cancelLabel?: string, cancelFn?: () => void, modalType?: ModalTypes, defaultValue?: string) => {
dispatch({
type: actionTypes.setModal,
payload: { title, message, okLabel, okFn, cancelLabel, cancelFn, modalType: modalType || ModalTypes.default, defaultValue: defaultValue }
})
}
const alert = (title: string, message?: string | JSX.Element) => {
modal(message ? title : 'Alert', message || title, 'OK', null, null, null)
}
const handleHideModal = () => {
dispatch({
type: actionTypes.handleHideModal,
payload: null
})
}
const toast = (message: string) => {
dispatch({
type: actionTypes.setToast,
payload: message
})
}
const handleToaster = () => {
dispatch({
type: actionTypes.handleToaster,
payload: null
})
}
return (<dispatchModalContext.Provider value={{ modal, toast, alert, handleHideModal, handleToaster }}>
<modalContext.Provider value={{ modals, toasters, focusModal, focusToaster }}>
{children}
</modalContext.Provider>
</dispatchModalContext.Provider>)
}
export const AppProvider = ({ children = [], value = {} } = {}) => {
return <AppContext.Provider value={value}>
<ModalProvider>{children}</ModalProvider>
</AppContext.Provider>
}
export const useDialogs = () => {
return React.useContext(modalContext)
}
export const useDialogDispatchers = () => {
return React.useContext(dispatchModalContext)
}

@ -0,0 +1,21 @@
import { ModalTypes } from '../types'
export interface AppModal {
hide?: boolean
title: string
// eslint-disable-next-line no-undef
message: string | JSX.Element
okLabel: string
okFn: (value?:any) => void
cancelLabel: string
cancelFn: () => void,
modalType?: ModalTypes,
defaultValue?: string
}
export interface ModalState {
modals: AppModal[],
toasters: string[],
focusModal: AppModal,
focusToaster: string
}

@ -1,43 +1,48 @@
import { actionTypes } from '../state/modals'
import { Modal } from '../types'
import { actionTypes, ModalAction } from '../actions/modals'
import { ModalInitialState } from '../state/modals'
import { AppModal, ModalState } from '../interface'
interface Action {
type: string
payload: any
}
export interface ModalState {
modals: Modal[],
toasters: string[],
focusModal: Modal,
focusToaster: string
}
export const modalReducer = (state: ModalState = ModalInitialState, action: ModalAction) => {
console.log(action)
switch (action.type) {
case actionTypes.setModal: {
console.log('set modal', action, Date.now())
let modalList:AppModal[] = state.modals
modalList.push(action.payload)
if (state.modals.length === 1 && state.focusModal.hide === true) { // if it's the first one show it
const focusModal: AppModal = {
hide: false,
title: modalList[0].title,
message: modalList[0].message,
okLabel: modalList[0].okLabel,
okFn: modalList[0].okFn,
cancelLabel: modalList[0].cancelLabel,
cancelFn: modalList[0].cancelFn,
modalType: modalList[0].modalType,
defaultValue: modalList[0].defaultValue
}
const ModalInitialState: ModalState = {
modals: [],
toasters: [],
focusModal: {
hide: true,
title: '',
message: '',
okLabel: '',
okFn: () => {},
cancelLabel: '',
cancelFn: () => {}
},
focusToaster: ''
}
modalList = modalList.slice()
modalList.shift()
return { ...state, modals: modalList, focusModal: focusModal }
}
return { ...state, modals: modalList }
}
case actionTypes.handleHideModal:
console.log('handle hid', JSON.stringify(state.modals))
state.focusModal = { ...state.focusModal, hide: true, message: null }
return { ...state }
export const modalReducer = (state: ModalState = ModalInitialState, action: Action) => {
switch (action.type) {
case actionTypes.setModal:
state.modals.push(action.payload)
case actionTypes.setToast:
state.toasters.push(action.payload)
if (state.toasters.length > 0) {
const focus = state.toasters[0]
state.toasters.shift()
return { ...state, focusToaster: focus }
}
return { ...state }
}
return {
modals: state.modals,
toasters: state.toasters,
focusModal: state.focusModal,
focusToaster: state.focusToaster
case actionTypes.handleToaster:
return { ...state, focusToaster: '' }
}
}

@ -1,13 +1,12 @@
import React, { useContext, useEffect, useRef, useState } from 'react'
import React, { useEffect, useRef, useState } from 'react'
import './style/remix-app.css'
import RemixSplashScreen from './modals/splashscreen'
import MatomoDialog from './modals/matomo'
import AlertModal from './modals/alert'
import AppContext from './context/context'
import DragBar from './dragbar/dragbar'
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
import { Modal } from './types'
import RemixSplashScreen from './components/splashscreen'
import MatomoDialog from './components/modals/matomo'
import OriginWarning from './components/modals/origin-warning'
import DragBar from './components/dragbar/dragbar'
import { AppProvider } from './context/provider'
import AppDialogs from './components/modals/dialogs'
interface IRemixAppUi {
app: any
}
@ -19,19 +18,6 @@ const RemixApp = (props: IRemixAppUi) => {
const mainPanelRef = useRef(null)
const iconPanelRef = useRef(null)
const hiddenPanelRef = useRef(null)
// modals
const [focusModal, setFocusModal] = useState<Modal>({
hide: true,
title: '',
message: '',
okLabel: '',
okFn: () => {},
cancelLabel: '',
cancelFn: () => {}
})
const [modals, setModals] = useState<Modal[]>([])
const [focusToaster, setFocusToaster] = useState<string>('')
const [toasters, setToasters] = useState<string[]>([])
useEffect(() => {
if (sidePanelRef.current) {
@ -77,36 +63,6 @@ const RemixApp = (props: IRemixAppUi) => {
})
}
const handleHideModal = () => {
setFocusModal(modal => {
return { ...modal, hide: true, message: null }
})
}
// eslint-disable-next-line no-undef
const modal = (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => {
setModals(modals => {
modals.push({ message, title, okLabel, okFn, cancelLabel, cancelFn })
return [...modals]
})
}
export const clearPopUp = async () => {
dispatch(hidePopUp())
}
const handleToaster = () => {
setFocusToaster('')
clearPopUp()
}
const toast = (toasterMsg: string) => {
setToasters(messages => {
messages.push(toasterMsg)
return [...messages]
})
}
const components = {
iconPanel: <div ref={iconPanelRef} id="icon-panel" data-id="remixIdeIconPanel" className="iconpanel bg-light"></div>,
sidePanel: <div ref={sidePanelRef} id="side-panel" data-id="remixIdeSidePanel" className={`sidepanel border-right border-left ${hideSidePanel ? 'd-none' : ''}`}></div>,
@ -121,9 +77,9 @@ const RemixApp = (props: IRemixAppUi) => {
}
return (
<AppContext.Provider value={value}>
<AppProvider value={value}>
<RemixSplashScreen hide={appReady}></RemixSplashScreen>
<AlertModal></AlertModal>
<OriginWarning></OriginWarning>
<MatomoDialog hide={!appReady}></MatomoDialog>
<div className={`remixIDE ${appReady ? '' : 'd-none'}`} data-id="remixIDE">
@ -134,8 +90,8 @@ const RemixApp = (props: IRemixAppUi) => {
</div>
{components.hiddenPanel}
</AppContext.Provider>
<AppDialogs></AppDialogs>
</AppProvider>
)
}

@ -1,48 +1,16 @@
import { useReducer } from 'react'
import { modalReducer } from '../reducer/modals'
import { ModalState } from '../interface'
export const actionTypes = {
setModal: 'SET_MODAL',
setToast: 'SET_TOAST'
}
export const setModal = (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => {
return {
type: actionTypes.setModal,
payload: { message, title, okLabel, okFn, cancelLabel, cancelFn }
}
}
export const setToast = (toasterMsg: string) => {
return {
type: actionTypes.setToast,
payload: toasterMsg
}
}
function useModals ({ reducer = modalReducer } = {}) {
const [{ modals, toasters, focusModal, focusToaster }, dispatch] = useReducer(reducer, {
modals: [],
toasters: [],
focusModal: {
hide: true,
title: '',
message: '',
okLabel: '',
okFn: () => {},
cancelLabel: '',
cancelFn: () => {}
},
focusToaster: ''
})
const modal = (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => {
dispatch(setModal(title, message, okLabel, okFn, cancelLabel, cancelFn))
}
const toast = (toasterMsg: string) => {
dispatch(setToast(toasterMsg))
}
return { focusModal, modals, focusToaster, toasters, modal, toast }
export const ModalInitialState: ModalState = {
modals: [],
toasters: [],
focusModal: {
hide: true,
title: '',
message: '',
okLabel: '',
okFn: () => { },
cancelLabel: '',
cancelFn: () => { }
},
focusToaster: ''
}

@ -1,11 +1,7 @@
export interface Modal {
hide?: boolean
title: string
// eslint-disable-next-line no-undef
message: string | JSX.Element
okLabel: string
okFn: () => void
cancelLabel: string
cancelFn: () => void
}
export const enum ModalTypes {
alert = 'alert',
confirm = 'confirm',
prompt = 'prompt',
password = 'password',
default = 'default',
}

@ -4,7 +4,7 @@ export interface ModalDialogProps {
title?: string,
message?: string | JSX.Element,
okLabel?: string,
okFn?: () => void,
okFn?: (value?:any) => void,
cancelLabel?: string,
cancelFn?: () => void,
modalClass?: string,

Loading…
Cancel
Save