71 lines
2.0 KiB
TypeScript
71 lines
2.0 KiB
TypeScript
|
import PropTypes from 'prop-types';
|
||
|
import { createContext, useContext } from 'react';
|
||
|
|
||
|
import hoistStatics from 'hoist-non-react-statics';
|
||
|
|
||
|
import type { InitialState } from 'mastodon/initial_state';
|
||
|
|
||
|
export interface IdentityContextType {
|
||
|
signedIn: boolean;
|
||
|
accountId: string | undefined;
|
||
|
disabledAccountId: string | undefined;
|
||
|
permissions: number;
|
||
|
}
|
||
|
|
||
|
export const identityContextPropShape = PropTypes.shape({
|
||
|
signedIn: PropTypes.bool.isRequired,
|
||
|
accountId: PropTypes.string,
|
||
|
disabledAccountId: PropTypes.string,
|
||
|
}).isRequired;
|
||
|
|
||
|
export const createIdentityContext = (state: InitialState) => ({
|
||
|
signedIn: !!state.meta.me,
|
||
|
accountId: state.meta.me,
|
||
|
disabledAccountId: state.meta.disabled_account_id,
|
||
|
permissions: state.role?.permissions ?? 0,
|
||
|
});
|
||
|
|
||
|
export const IdentityContext = createContext<IdentityContextType>({
|
||
|
signedIn: false,
|
||
|
permissions: 0,
|
||
|
accountId: undefined,
|
||
|
disabledAccountId: undefined,
|
||
|
});
|
||
|
|
||
|
export const useIdentity = () => useContext(IdentityContext);
|
||
|
|
||
|
export interface IdentityProps {
|
||
|
ref?: unknown;
|
||
|
wrappedComponentRef?: unknown;
|
||
|
}
|
||
|
|
||
|
/* Injects an `identity` props into the wrapped component to be able to use the new context in class components */
|
||
|
export function withIdentity<
|
||
|
ComponentType extends React.ComponentType<IdentityProps>,
|
||
|
>(Component: ComponentType) {
|
||
|
const displayName = `withIdentity(${Component.displayName ?? Component.name})`;
|
||
|
const C = (props: React.ComponentProps<ComponentType>) => {
|
||
|
const { wrappedComponentRef, ...remainingProps } = props;
|
||
|
|
||
|
return (
|
||
|
<IdentityContext.Consumer>
|
||
|
{(context) => {
|
||
|
return (
|
||
|
// @ts-expect-error - Dynamic covariant generic components are tough to type.
|
||
|
<Component
|
||
|
{...remainingProps}
|
||
|
identity={context}
|
||
|
ref={wrappedComponentRef}
|
||
|
/>
|
||
|
);
|
||
|
}}
|
||
|
</IdentityContext.Consumer>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
C.displayName = displayName;
|
||
|
C.WrappedComponent = Component;
|
||
|
|
||
|
return hoistStatics(C, Component);
|
||
|
}
|