fix problems after update
This commit is contained in:
@@ -7,11 +7,7 @@ import './styles';
|
||||
|
||||
import { h, FunctionComponent } from 'preact';
|
||||
|
||||
import { Comment as CommentType } from 'common/types';
|
||||
|
||||
import { useStore } from 'react-redux';
|
||||
|
||||
import { StoreState } from 'store';
|
||||
import { useAppSelector } from 'store';
|
||||
import { addComment, removeComment, updateComment, setPinState, setCommentMode } from 'store/comments/actions';
|
||||
import { blockUser, unblockUser, hideUser, setVerifiedStatus } from 'store/user/actions';
|
||||
|
||||
@@ -36,21 +32,6 @@ type ProvidedProps = Pick<
|
||||
| 'uploadImage'
|
||||
>;
|
||||
|
||||
const mapStateToProps = (state: StoreState, cprops: { data: CommentType }) => {
|
||||
const props: ProvidedProps = {
|
||||
editMode: getCommentMode(cprops.data.id)(state),
|
||||
user: state.user,
|
||||
isUserBanned: cprops.data.user.block || state.bannedUsers.find((u) => u.id === cprops.data.user.id) !== undefined,
|
||||
post_info: state.info,
|
||||
isCommentsDisabled: state.info.read_only || false,
|
||||
theme: state.theme,
|
||||
collapsed: getThreadIsCollapsed(cprops.data)(state),
|
||||
getPreview,
|
||||
uploadImage,
|
||||
};
|
||||
return props;
|
||||
};
|
||||
|
||||
export const boundActions = bindActions({
|
||||
addComment,
|
||||
updateComment,
|
||||
@@ -66,7 +47,19 @@ export const boundActions = bindActions({
|
||||
export const ConnectedComment: FunctionComponent<Omit<CommentProps, keyof (ProvidedProps & typeof bindActions)>> = (
|
||||
props
|
||||
) => {
|
||||
const providedProps = mapStateToProps(useStore().getState(), props);
|
||||
const providedProps = useAppSelector((state): ProvidedProps => {
|
||||
return {
|
||||
editMode: getCommentMode(props.data.id)(state),
|
||||
user: state.user,
|
||||
isUserBanned: props.data.user.block || state.bannedUsers.find((u) => u.id === props.data.user.id) !== undefined,
|
||||
post_info: state.info,
|
||||
isCommentsDisabled: state.info.read_only || false,
|
||||
theme: state.theme,
|
||||
collapsed: getThreadIsCollapsed(props.data)(state),
|
||||
getPreview,
|
||||
uploadImage,
|
||||
};
|
||||
});
|
||||
const actions = useActions(boundActions);
|
||||
const intl = useIntl();
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import clsx from 'clsx';
|
||||
import styles from './input.module.css';
|
||||
|
||||
type Props = JSX.HTMLAttributes<HTMLInputElement> & {
|
||||
invalid?: boolean;
|
||||
invalid?: boolean;
|
||||
};
|
||||
|
||||
export function Input({ className, type, invalid, ...props }: Props) {
|
||||
return (
|
||||
<input className={clsx(className, styles.input, { [styles.invalid]: invalid })} type={type ?? 'text'} {...props}/>
|
||||
<input className={clsx(className, styles.input, { [styles.invalid]: invalid })} type={type ?? 'text'} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@ export function Profile() {
|
||||
function handleClickClose() {
|
||||
const rootElement = rootRef.current;
|
||||
|
||||
if (!rootElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
rootElement.classList.remove(styles.rootAppear);
|
||||
rootElement.classList.add(styles.rootDisappear);
|
||||
// No need to unsubscribe because iframe will be destroyed
|
||||
@@ -114,7 +118,9 @@ export function Profile() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
rootRef.current.classList.add(styles.rootAppear);
|
||||
if (rootRef.current) {
|
||||
rootRef.current.classList.add(styles.rootAppear);
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!user.id) {
|
||||
|
||||
@@ -36,7 +36,7 @@ export function InView({ children }: Props) {
|
||||
const element = ref.current;
|
||||
const { observer, instanceMap } = getObserver();
|
||||
|
||||
if (!(element.base instanceof Element)) {
|
||||
if (!(element?.base instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -323,6 +323,9 @@ export function ConnectedRoot() {
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!rootRef.current) {
|
||||
return;
|
||||
}
|
||||
// TODO: throttle updates
|
||||
const observer = new MutationObserver(() => {
|
||||
postMessageToParent({ height: document.body.offsetHeight });
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { h } from 'preact';
|
||||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||
import { useMemo } from 'preact/hooks';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
|
||||
import { StoreState } from 'store';
|
||||
import { StoreState, useAppDispatch, useAppSelector } from 'store';
|
||||
import { Select } from 'components/select';
|
||||
import { updateSorting } from 'store/comments/actions';
|
||||
import type { Sorting } from 'common/types';
|
||||
|
||||
export function SortPicker() {
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
const [items, itemsById] = useMemo(() => {
|
||||
const sortOptions = {
|
||||
@@ -31,7 +30,7 @@ export function SortPicker() {
|
||||
|
||||
return [sortItems, sortById];
|
||||
}, [intl]);
|
||||
const sort = useSelector((s: StoreState) => s.comments.sort) || items[0].value;
|
||||
const sort = useAppSelector((s: StoreState) => s.comments.sort) || items[0].value;
|
||||
const selected = itemsById[sort];
|
||||
|
||||
function handleSortChange(evt: Event) {
|
||||
|
||||
@@ -7,22 +7,30 @@ function autoResize(textarea: HTMLTextAreaElement) {
|
||||
textarea.style.height = `${textarea.scrollHeight}px`;
|
||||
}
|
||||
|
||||
type Props = JSX.HTMLAttributes<HTMLTextAreaElement>;
|
||||
type Props = Omit<JSX.HTMLAttributes<HTMLTextAreaElement>, 'onInput'> & {
|
||||
onInput?: (evt: JSX.TargetedEvent<HTMLTextAreaElement, Event>) => void;
|
||||
};
|
||||
|
||||
export const TextareaAutosize = forwardRef<HTMLTextAreaElement, Props>(({ onInput, value, ...props }, externalRef) => {
|
||||
const localRef = useRef<HTMLTextAreaElement>();
|
||||
const localRef = useRef<HTMLTextAreaElement>(null);
|
||||
const ref = externalRef || localRef;
|
||||
|
||||
const handleInput: JSX.GenericEventHandler<HTMLTextAreaElement> = (evt) => {
|
||||
if (!ref.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (onInput) {
|
||||
return onInput.call(ref.current, evt);
|
||||
return onInput(evt);
|
||||
}
|
||||
|
||||
autoResize(ref.current);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
autoResize(ref.current);
|
||||
if (ref.current) {
|
||||
autoResize(ref.current);
|
||||
}
|
||||
}, [value, ref]);
|
||||
|
||||
return <textarea {...props} data-testid={props.id} onInput={handleInput} value={value} ref={ref} />;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { h, FunctionComponent } from 'preact';
|
||||
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
||||
import { shallowEqual } from 'react-redux';
|
||||
import { useCallback } from 'preact/hooks';
|
||||
import b from 'bem-react-helper';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import { Comment as CommentInterface } from 'common/types';
|
||||
import { getHandleClickProps } from 'common/accessibility';
|
||||
import { StoreState } from 'store';
|
||||
import { StoreState, useAppDispatch, useAppSelector } from 'store';
|
||||
import { setCollapse } from 'store/thread/actions';
|
||||
import { getThreadIsCollapsed } from 'store/thread/getters';
|
||||
import { InView } from 'components/root/in-view/in-view';
|
||||
@@ -33,9 +33,9 @@ const commentSelector = (id: string) => (state: StoreState) => {
|
||||
};
|
||||
|
||||
export const Thread: FunctionComponent<Props> = ({ id, level, mix, getPreview }) => {
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
const { collapsed, comment, childs, theme } = useSelector(commentSelector(id), shallowEqual);
|
||||
const { collapsed, comment, childs, theme } = useAppSelector(commentSelector(id), shallowEqual);
|
||||
const collapse = useCallback(() => {
|
||||
dispatch(setCollapse(id, !collapsed));
|
||||
}, [id, collapsed, dispatch]);
|
||||
|
||||
@@ -22,7 +22,7 @@ import { LS_SORT_KEY } from 'common/constants';
|
||||
|
||||
/** sets comments, and put pinned comments in cache */
|
||||
export const setComments =
|
||||
(comments: Node[]): StoreAction<void> =>
|
||||
(comments: Node[]): StoreAction =>
|
||||
(dispatch) => {
|
||||
dispatch({
|
||||
type: COMMENTS_SET,
|
||||
@@ -105,7 +105,7 @@ export const fetchComments =
|
||||
|
||||
/** sets mode for comment, either reply or edit */
|
||||
export const setCommentMode =
|
||||
(mode: StoreState['comments']['activeComment']): StoreAction<void> =>
|
||||
(mode: StoreState['comments']['activeComment']): StoreAction =>
|
||||
(dispatch) => {
|
||||
if (mode !== null && mode.state === CommentMode.None) {
|
||||
mode = null;
|
||||
@@ -121,7 +121,7 @@ export function unsetCommentMode(mode: StoreState['comments']['activeComment'] =
|
||||
} as COMMENT_MODE_SET_ACTION;
|
||||
}
|
||||
|
||||
export function updateSorting(sort: Sorting): StoreAction<void> {
|
||||
export function updateSorting(sort: Sorting): StoreAction {
|
||||
return async (dispatch, getState) => {
|
||||
const { sort: prevSort } = getState().comments;
|
||||
dispatch({ type: COMMENTS_SET_SORT, payload: sort });
|
||||
|
||||
@@ -1,33 +1,20 @@
|
||||
import { createStore, applyMiddleware, AnyAction, compose, combineReducers } from 'redux';
|
||||
import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux';
|
||||
import thunk, { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||
import { rootProvider } from './reducers';
|
||||
import { ACTIONS } from './actions';
|
||||
|
||||
const reducers = combineReducers(rootProvider);
|
||||
|
||||
export type StoreState = ReturnType<typeof reducers>;
|
||||
|
||||
const middleware = applyMiddleware(thunk);
|
||||
export const store = createStore(reducers, compose(middleware));
|
||||
|
||||
/**
|
||||
* Thunk Action shortcut
|
||||
*/
|
||||
export type StoreAction<R, A extends AnyAction = ACTIONS> = ThunkAction<R, StoreState, undefined, A>;
|
||||
|
||||
/**
|
||||
* Thunk Dispatch shortcut
|
||||
*/
|
||||
export type StoreState = ReturnType<typeof store.getState>;
|
||||
export type StoreDispatch = ThunkDispatch<StoreState, undefined, ACTIONS>;
|
||||
export type StoreAction<ReturnType = void> = ThunkAction<ReturnType, StoreState, unknown, AnyAction>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
||||
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
||||
: compose;
|
||||
|
||||
export const store = createStore(reducers, composeEnhancers(middleware));
|
||||
export const useAppDispatch: () => StoreDispatch = useDispatch;
|
||||
export const useAppSelector: TypedUseSelectorHook<StoreState> = useSelector;
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).ReduxStore = store;
|
||||
window.ReduxStore = store;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { StoreAction } from '../';
|
||||
import { THEME_SET } from './types';
|
||||
|
||||
export const setTheme =
|
||||
(theme: Theme): StoreAction<void> =>
|
||||
(theme: Theme): StoreAction =>
|
||||
(dispatch) =>
|
||||
dispatch({
|
||||
type: THEME_SET,
|
||||
|
||||
@@ -11,13 +11,14 @@ export const restoreCollapsedThreads = (): THREAD_RESTORE_COLLAPSE_ACTION => ({
|
||||
});
|
||||
|
||||
export const setCollapse =
|
||||
(id: Comment['id'], value: boolean): StoreAction<void> =>
|
||||
(id: Comment['id'], value: boolean): StoreAction =>
|
||||
(dispatch, getState) => {
|
||||
dispatch({
|
||||
type: THREAD_SET_COLLAPSE,
|
||||
id,
|
||||
collapsed: value,
|
||||
});
|
||||
|
||||
saveCollapsedComments(
|
||||
siteId!,
|
||||
url!,
|
||||
|
||||
@@ -93,14 +93,14 @@ export const unblockUser =
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchHiddenUsers = (): StoreAction<void> => (dispatch) => {
|
||||
export const fetchHiddenUsers = (): StoreAction => (dispatch) => {
|
||||
const hiddenUsers = getHiddenUsers();
|
||||
|
||||
dispatch({ type: USER_HIDELIST_SET, payload: hiddenUsers });
|
||||
};
|
||||
|
||||
export const hideUser =
|
||||
(user: User): StoreAction<void> =>
|
||||
(user: User): StoreAction =>
|
||||
(dispatch, getState) => {
|
||||
const hiddenUsers = getHiddenUsers();
|
||||
|
||||
@@ -116,7 +116,7 @@ export const hideUser =
|
||||
};
|
||||
|
||||
export const unhideUser =
|
||||
(userId: string): StoreAction<void> =>
|
||||
(userId: string): StoreAction =>
|
||||
(dispatch, _getState) => {
|
||||
const hiddenUsers = getHiddenUsers();
|
||||
|
||||
|
||||
Vendored
+3
@@ -17,6 +17,9 @@ type RemarkConfig = {
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
|
||||
/** only for dev env */
|
||||
ReduxStore: typeof store;
|
||||
remark_config: RemarkConfig;
|
||||
REMARK42: {
|
||||
changeTheme?: (theme: Theme) => void;
|
||||
|
||||
@@ -23,7 +23,7 @@ const config: Config = {
|
||||
},
|
||||
],
|
||||
},
|
||||
transformIgnorePatterns: ['node_modules/(?!(@testing-library/preact|preact|@github))'],
|
||||
transformIgnorePatterns: ['node_modules/(?!(@testing-library/preact|preact|@github|lodash-es))'],
|
||||
moduleDirectories: ['node_modules', 'app'],
|
||||
moduleNameMapper: {
|
||||
'\\.css': 'identity-obj-proxy',
|
||||
|
||||
Reference in New Issue
Block a user