Comparing version 2.0.0-beta.32 to 2.0.0-beta.33
import * as React from "react"; | ||
import type { Ctx } from "../lib"; | ||
export declare type UpdateConditionOrDeps = boolean | readonly any[]; | ||
export declare function useElementEvt<T extends HTMLElement = any>(effect: (params: { | ||
ctx: Ctx; | ||
element: T; | ||
}) => void, deps: React.DependencyList): { | ||
}) => void, updateConditionOrDeps: boolean | readonly any[]): { | ||
ref: React.RefObject<T>; | ||
@@ -12,2 +13,2 @@ }; | ||
element: T; | ||
}) => void, ref: React.RefObject<T>, deps: React.DependencyList): void; | ||
}) => void, ref: React.RefObject<T>, updateConditionOrDeps: boolean | readonly any[]): void; |
@@ -28,8 +28,8 @@ "use strict"; | ||
var useEvt_1 = require("./useEvt"); | ||
function useElementEvt(effect, depsOrRef, depsOrUndefined) { | ||
function useElementEvt(effect, updateConditionOrDepsOrRef, updateConditionOrDepsOrUndefined) { | ||
var _a; | ||
var isRefProvided = depsOrUndefined !== undefined; | ||
var deps = depsOrUndefined !== null && depsOrUndefined !== void 0 ? depsOrUndefined : depsOrRef; | ||
var isRefProvided = updateConditionOrDepsOrUndefined !== undefined; | ||
var updateConditionOrDeps = updateConditionOrDepsOrUndefined !== null && updateConditionOrDepsOrUndefined !== void 0 ? updateConditionOrDepsOrUndefined : updateConditionOrDepsOrRef; | ||
var refInternallyCreated = useRef(null); | ||
var ref = isRefProvided ? depsOrRef : refInternallyCreated; | ||
var ref = isRefProvided ? updateConditionOrDepsOrRef : refInternallyCreated; | ||
var _b = __read(useState(null), 2), element = _b[0], setElement = _b[1]; | ||
@@ -42,3 +42,4 @@ useEffect(function () { setElement(ref.current); }, [(_a = ref.current) !== null && _a !== void 0 ? _a : Object]); | ||
effect({ ctx: ctx, element: element, registerSideEffect: registerSideEffect }); | ||
}, __spreadArray([element !== null && element !== void 0 ? element : Object], __read(deps))); | ||
}, typeof updateConditionOrDeps === "boolean" ? | ||
updateConditionOrDeps : __spreadArray([element !== null && element !== void 0 ? element : Object], __read(updateConditionOrDeps))); | ||
return { ref: ref }; | ||
@@ -45,0 +46,0 @@ } |
import type { Ctx } from "../lib"; | ||
import * as React from "react"; | ||
/** | ||
@@ -31,2 +30,3 @@ * https://docs.evt.land/api/react-hooks | ||
*/ | ||
export declare function useEvt<T>(factoryOrEffect: (ctx: Ctx, registerSideEffect: (sideEffect: () => void) => void) => T, deps: React.DependencyList): T; | ||
export declare function useEvt<T>(factoryOrEffect: (ctx: Ctx, registerSideEffect: (sideEffect: () => void) => void) => T, deps: readonly any[]): T; | ||
export declare function useEvt<T>(factoryOrEffect: (ctx: Ctx, registerSideEffect: (sideEffect: () => void) => void) => T, updateConditionOrDeps: boolean | readonly any[]): T | undefined; |
@@ -29,2 +29,3 @@ "use strict"; | ||
var useEffectIf_1 = require("../tools/hooks/useEffectIf"); | ||
var useUpdateConditionOrDeps_1 = require("../tools/hooks/useUpdateConditionOrDeps"); | ||
var React = require("react"); | ||
@@ -36,84 +37,71 @@ var useEffect = React.useEffect, useState = React.useState, useReducer = React.useReducer, useRef = React.useRef; | ||
((_b = (_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.NODE_ENV) !== null && _b !== void 0 ? _b : "production") !== "production"; | ||
/** | ||
* https://docs.evt.land/api/react-hooks | ||
* | ||
* Provide a Ctx to attach handlers. | ||
* You should list in deps all the Evt that are | ||
* susceptible to change ( Evt passed as props | ||
* or Evt that are react states ) that you use in the | ||
* factoryOrEffect callback. | ||
* As for useEffect you should also list every other | ||
* value that you use. | ||
* Whenever any value in deps is changed factoryOrEffect | ||
* is invoked again with the new Evt and the previous handler | ||
* get detached. | ||
* All handler are also detached when the component unmount. | ||
* | ||
* factoryOrEffect can be used for attaching handler to event | ||
* or to generate a new event that is a merge/pipe of other | ||
* Evts. | ||
* c | ||
* BE AWARE: Unlike useEffect factoryOrEffect is called | ||
* on render ( like useMemo's callback ). | ||
* Remember that you shouldn't update state in a component | ||
* render tick (in the useMemo for example). If you you need to | ||
* perform an effect on first render (attaching a stateful evt | ||
* for example) use registerSideEffect(()=>{ ... }) | ||
* | ||
* Demo: https://stackblitz.com/edit/evt-useevt?file=index.tsx | ||
*/ | ||
function useEvt(factoryOrEffect, deps) { | ||
var ctxRef = useRef(null); | ||
var _a = __read(useState([]), 1), registeredSideEffects = _a[0]; | ||
var _b = __read(useReducer(function (n) { return n + 1; }, 0), 2), forceUpdate = _b[1]; | ||
useEffectIf_1.useEffectIf(function callee() { | ||
var registeredSideEffectsCopy = __spreadArray([], __read(registeredSideEffects)); | ||
registeredSideEffectsCopy.forEach(function (sideEffect) { return sideEffect(); }); | ||
registeredSideEffects.splice(0, registeredSideEffectsCopy.length); | ||
if (registeredSideEffects.length !== 0) { | ||
callee(); | ||
return; | ||
function useEvt(factoryOrEffect, updateConditionOrDeps) { | ||
var deps = useUpdateConditionOrDeps_1.useUpdateConditionOrDeps({ | ||
updateConditionOrDeps: updateConditionOrDeps, | ||
"hookName": useEvt.name | ||
}).deps; | ||
return useEvtWithOnlyDependencyArray(function (ctx, registerSideEffect) { | ||
if (updateConditionOrDeps === false) { | ||
return undefined; | ||
} | ||
}, registeredSideEffects.length !== 0); | ||
var out = useSemanticGuaranteeMemo_1.useSemanticGuaranteeMemo(function () { | ||
var _a; | ||
(_a = ctxRef.current) === null || _a === void 0 ? void 0 : _a.done(); | ||
ctxRef.current = Evt_2.Evt.newCtx(); | ||
return factoryOrEffect(ctxRef.current, function (sideEffect) { | ||
registeredSideEffects.push(sideEffect); | ||
forceUpdate(); | ||
}); | ||
return factoryOrEffect(ctx, registerSideEffect); | ||
}, deps); | ||
useEffect(function () { return function () { ctxRef.current.done(); }; }, []); | ||
useClearCtxIfReactStrictModeInspectRun(isDevStrictMode, ctxRef); | ||
return out; | ||
} | ||
exports.useEvt = useEvt; | ||
/** | ||
* When <React.StrictMode> is used in development | ||
* useState and useMemo get triggered a first time on a | ||
* separate component instance but useEffect is not invoked. | ||
* | ||
* To prevent leaving handlers that we attached inside the useMemo | ||
* callback we clear the context if useEffect(f,[]) | ||
* is not invoked right after useState(f). | ||
*/ | ||
function useClearCtxIfReactStrictModeInspectRun(isDevStrictMode, ctxRef) { | ||
var timerRef = useRef(null); | ||
useSemanticGuaranteeMemo_1.useSemanticGuaranteeMemo(function () { | ||
if (!isDevStrictMode) { | ||
return; | ||
} | ||
timerRef.current = setTimeout(function () { return ctxRef.current.done(); }, 700); | ||
}, []); | ||
useEffect(function () { | ||
if (!isDevStrictMode) { | ||
return; | ||
} | ||
if (timerRef.current === null) { | ||
return; | ||
} | ||
clearTimeout(timerRef.current); | ||
}, []); | ||
} | ||
var useEvtWithOnlyDependencyArray = (function () { | ||
/** | ||
* When <React.StrictMode> is used in development | ||
* useState and useMemo get triggered a first time on a | ||
* separate component instance but useEffect is not invoked. | ||
* | ||
* To prevent leaving handlers that we attached inside the useMemo | ||
* callback we clear the context if useEffect(f,[]) | ||
* is not invoked right after useState(f). | ||
*/ | ||
function useClearCtxIfReactStrictModeInspectRun(isDevStrictMode, ctxRef) { | ||
var timerRef = useRef(null); | ||
useSemanticGuaranteeMemo_1.useSemanticGuaranteeMemo(function () { | ||
if (!isDevStrictMode) { | ||
return; | ||
} | ||
timerRef.current = setTimeout(function () { return ctxRef.current.done(); }, 700); | ||
}, []); | ||
useEffect(function () { | ||
if (!isDevStrictMode) { | ||
return; | ||
} | ||
if (timerRef.current === null) { | ||
return; | ||
} | ||
clearTimeout(timerRef.current); | ||
}, []); | ||
} | ||
function useEvtWithOnlyDependencyArray(factoryOrEffect, deps) { | ||
var ctxRef = useRef(null); | ||
var _a = __read(useState([]), 1), registeredSideEffects = _a[0]; | ||
var _b = __read(useReducer(function (n) { return n + 1; }, 0), 2), forceUpdate = _b[1]; | ||
useEffectIf_1.useEffectIf(function callee() { | ||
var registeredSideEffectsCopy = __spreadArray([], __read(registeredSideEffects)); | ||
registeredSideEffectsCopy.forEach(function (sideEffect) { return sideEffect(); }); | ||
registeredSideEffects.splice(0, registeredSideEffectsCopy.length); | ||
if (registeredSideEffects.length !== 0) { | ||
callee(); | ||
return; | ||
} | ||
}, registeredSideEffects.length !== 0); | ||
var out = useSemanticGuaranteeMemo_1.useSemanticGuaranteeMemo(function () { | ||
var _a; | ||
(_a = ctxRef.current) === null || _a === void 0 ? void 0 : _a.done(); | ||
ctxRef.current = Evt_2.Evt.newCtx(); | ||
return factoryOrEffect(ctxRef.current, function (sideEffect) { | ||
registeredSideEffects.push(sideEffect); | ||
forceUpdate(); | ||
}); | ||
}, deps); | ||
useEffect(function () { return function () { ctxRef.current.done(); }; }, []); | ||
useClearCtxIfReactStrictModeInspectRun(isDevStrictMode, ctxRef); | ||
return out; | ||
} | ||
return { useEvtWithOnlyDependencyArray: useEvtWithOnlyDependencyArray }; | ||
})().useEvtWithOnlyDependencyArray; | ||
//# sourceMappingURL=useEvt.js.map |
{ | ||
"name": "evt", | ||
"version": "2.0.0-beta.32", | ||
"version": "2.0.0-beta.33", | ||
"description": "Type safe replacement for node's EventEmitter", | ||
@@ -202,2 +202,5 @@ "repository": { | ||
"tools/hooks/useSemanticGuaranteeMemo.js.map", | ||
"tools/hooks/useUpdateConditionOrDeps.d.ts", | ||
"tools/hooks/useUpdateConditionOrDeps.js", | ||
"tools/hooks/useUpdateConditionOrDeps.js.map", | ||
"tools/inDepth/copy.d.ts", | ||
@@ -342,2 +345,3 @@ "tools/inDepth/copy.js", | ||
"src/tools/hooks/useSemanticGuaranteeMemo.ts", | ||
"src/tools/hooks/useUpdateConditionOrDeps.ts", | ||
"src/tools/inDepth/copy.ts", | ||
@@ -344,0 +348,0 @@ "src/tools/inDepth/getPrototypeChain.ts", |
@@ -6,5 +6,7 @@ import * as React from "react"; | ||
export type UpdateConditionOrDeps = boolean | readonly any[]; | ||
export function useElementEvt<T extends HTMLElement = any>( | ||
effect: (params: { ctx: Ctx; element: T }) => void, | ||
deps: React.DependencyList | ||
updateConditionOrDeps: boolean | readonly any[], | ||
): { ref: React.RefObject<T>; }; | ||
@@ -14,3 +16,3 @@ export function useElementEvt<T extends HTMLElement = any>( | ||
ref: React.RefObject<T>, | ||
deps: React.DependencyList | ||
updateConditionOrDeps: boolean | readonly any[], | ||
): void; | ||
@@ -23,13 +25,13 @@ export function useElementEvt<T extends HTMLElement = any>( | ||
}) => void, | ||
depsOrRef: React.DependencyList | React.RefObject<T>, | ||
depsOrUndefined?: React.DependencyList | ||
updateConditionOrDepsOrRef: UpdateConditionOrDeps | React.RefObject<T>, | ||
updateConditionOrDepsOrUndefined?: boolean | readonly any[], | ||
): { ref: React.RefObject<T>; } | void { | ||
const isRefProvided = depsOrUndefined !== undefined; | ||
const isRefProvided = updateConditionOrDepsOrUndefined !== undefined; | ||
const deps = depsOrUndefined ?? depsOrRef as React.DependencyList; | ||
const updateConditionOrDeps = updateConditionOrDepsOrUndefined ?? updateConditionOrDepsOrRef as UpdateConditionOrDeps; | ||
const refInternallyCreated = useRef<T>(null); | ||
const ref = isRefProvided ? depsOrRef as React.RefObject<T> : refInternallyCreated; | ||
const ref = isRefProvided ? updateConditionOrDepsOrRef as React.RefObject<T> : refInternallyCreated; | ||
@@ -53,3 +55,5 @@ const [element, setElement] = useState<T | null>(null); | ||
}, | ||
[element ?? Object, ...deps] | ||
typeof updateConditionOrDeps === "boolean" ? | ||
updateConditionOrDeps : | ||
[element ?? Object, ...updateConditionOrDeps] | ||
); | ||
@@ -56,0 +60,0 @@ |
@@ -5,2 +5,3 @@ import { Evt } from "../lib/Evt"; | ||
import { useEffectIf } from "../tools/hooks/useEffectIf"; | ||
import { useUpdateConditionOrDeps } from "../tools/hooks/useUpdateConditionOrDeps"; | ||
import * as React from "react"; | ||
@@ -48,99 +49,145 @@ const { useEffect, useState, useReducer, useRef } = React; | ||
) => T, | ||
deps: React.DependencyList | ||
): T { | ||
deps: readonly any[] | ||
): T; | ||
export function useEvt<T>( | ||
factoryOrEffect: ( | ||
ctx: Ctx, | ||
registerSideEffect: (sideEffect: () => void) => void | ||
) => T, | ||
updateConditionOrDeps: boolean | readonly any[] | ||
): T | undefined; | ||
export function useEvt<T>( | ||
factoryOrEffect: ( | ||
ctx: Ctx, | ||
registerSideEffect: (sideEffect: () => void) => void | ||
) => T, | ||
updateConditionOrDeps: boolean | readonly any[] | ||
): T | undefined { | ||
const ctxRef = useRef<Ctx>(null as any); | ||
const { deps } = useUpdateConditionOrDeps({ | ||
updateConditionOrDeps, | ||
"hookName": useEvt.name | ||
}); | ||
const [registeredSideEffects] = useState<(() => void)[]>([]); | ||
return useEvtWithOnlyDependencyArray( | ||
(ctx, registerSideEffect) => { | ||
if (updateConditionOrDeps === false) { | ||
return undefined; | ||
} | ||
const [, forceUpdate] = useReducer(n => n + 1, 0); | ||
return factoryOrEffect(ctx, registerSideEffect) | ||
}, | ||
deps | ||
); | ||
useEffectIf( | ||
function callee() { | ||
} | ||
const registeredSideEffectsCopy = [...registeredSideEffects]; | ||
const { useEvtWithOnlyDependencyArray } = (() => { | ||
registeredSideEffectsCopy.forEach(sideEffect => sideEffect()); | ||
/** | ||
* When <React.StrictMode> is used in development | ||
* useState and useMemo get triggered a first time on a | ||
* separate component instance but useEffect is not invoked. | ||
* | ||
* To prevent leaving handlers that we attached inside the useMemo | ||
* callback we clear the context if useEffect(f,[]) | ||
* is not invoked right after useState(f). | ||
*/ | ||
function useClearCtxIfReactStrictModeInspectRun( | ||
isDevStrictMode: boolean, | ||
ctxRef: React.MutableRefObject<Ctx> | ||
) { | ||
registeredSideEffects.splice(0, registeredSideEffectsCopy.length); | ||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null); | ||
if (registeredSideEffects.length !== 0) { | ||
useSemanticGuaranteeMemo(() => { | ||
callee(); | ||
if (!isDevStrictMode) { | ||
return; | ||
} | ||
timerRef.current = setTimeout( | ||
() => ctxRef.current.done(), | ||
700 | ||
); | ||
}, []); | ||
useEffect(() => { | ||
if (!isDevStrictMode) { | ||
return; | ||
} | ||
if (timerRef.current === null) { | ||
return; | ||
} | ||
}, | ||
registeredSideEffects.length !== 0 | ||
); | ||
clearTimeout(timerRef.current); | ||
const out = useSemanticGuaranteeMemo(() => { | ||
}, []); | ||
ctxRef.current?.done(); | ||
} | ||
ctxRef.current = Evt.newCtx(); | ||
function useEvtWithOnlyDependencyArray<T>( | ||
factoryOrEffect: ( | ||
ctx: Ctx, | ||
registerSideEffect: (sideEffect: () => void) => void | ||
) => T, | ||
deps: readonly any[] | ||
): T { | ||
return factoryOrEffect( | ||
ctxRef.current, | ||
sideEffect => { | ||
registeredSideEffects.push(sideEffect); | ||
forceUpdate(); | ||
} | ||
); | ||
const ctxRef = useRef<Ctx>(null as any); | ||
}, deps); | ||
const [registeredSideEffects] = useState<(() => void)[]>([]); | ||
useEffect(() => () => { ctxRef.current.done(); }, []); | ||
const [, forceUpdate] = useReducer(n => n + 1, 0); | ||
useClearCtxIfReactStrictModeInspectRun(isDevStrictMode, ctxRef); | ||
useEffectIf( | ||
function callee() { | ||
return out; | ||
const registeredSideEffectsCopy = [...registeredSideEffects]; | ||
} | ||
registeredSideEffectsCopy.forEach(sideEffect => sideEffect()); | ||
/** | ||
* When <React.StrictMode> is used in development | ||
* useState and useMemo get triggered a first time on a | ||
* separate component instance but useEffect is not invoked. | ||
* | ||
* To prevent leaving handlers that we attached inside the useMemo | ||
* callback we clear the context if useEffect(f,[]) | ||
* is not invoked right after useState(f). | ||
*/ | ||
function useClearCtxIfReactStrictModeInspectRun( | ||
isDevStrictMode: boolean, | ||
ctxRef: React.MutableRefObject<Ctx> | ||
) { | ||
registeredSideEffects.splice(0, registeredSideEffectsCopy.length); | ||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null); | ||
if (registeredSideEffects.length !== 0) { | ||
useSemanticGuaranteeMemo(() => { | ||
callee(); | ||
if (!isDevStrictMode) { | ||
return; | ||
} | ||
return; | ||
timerRef.current = setTimeout( | ||
() => ctxRef.current.done(), | ||
700 | ||
} | ||
}, | ||
registeredSideEffects.length !== 0 | ||
); | ||
}, []); | ||
const out = useSemanticGuaranteeMemo(() => { | ||
useEffect(() => { | ||
ctxRef.current?.done(); | ||
if (!isDevStrictMode) { | ||
return; | ||
} | ||
ctxRef.current = Evt.newCtx(); | ||
if (timerRef.current === null) { | ||
return; | ||
} | ||
return factoryOrEffect( | ||
ctxRef.current, | ||
sideEffect => { | ||
registeredSideEffects.push(sideEffect); | ||
forceUpdate(); | ||
} | ||
); | ||
clearTimeout(timerRef.current); | ||
}, deps); | ||
}, []); | ||
useEffect(() => () => { ctxRef.current.done(); }, []); | ||
} | ||
useClearCtxIfReactStrictModeInspectRun(isDevStrictMode, ctxRef); | ||
return out; | ||
} | ||
return { useEvtWithOnlyDependencyArray }; | ||
})(); |
@@ -1,9 +0,8 @@ | ||
import { assert } from "tsafe/assert"; | ||
import { useUpdateConditionOrDeps } from "./useUpdateConditionOrDeps"; | ||
import * as React from "react"; | ||
const { useEffect, useRef } = React; | ||
const { useEffect } = React; | ||
export type Destructor = () => void; | ||
const depsMaxLength = 7; | ||
export function useEffectIf( | ||
@@ -14,20 +13,7 @@ effect: () => (void | Destructor), | ||
const depsRef = useRef<readonly any[]>(new Array(depsMaxLength).fill(Object)); | ||
const { deps } = useUpdateConditionOrDeps({ | ||
updateConditionOrDeps, | ||
"hookName": useEffectIf.name | ||
}); | ||
depsRef.current = typeof updateConditionOrDeps === "boolean" ? | ||
updateConditionOrDeps ? | ||
[{}, ...new Array(depsMaxLength - 1).fill(Object)] : | ||
depsRef.current | ||
: | ||
( | ||
assert( | ||
updateConditionOrDeps.length <= depsMaxLength, | ||
`dependency array passed to ${useEffectIf.name} can only contain at most ${depsMaxLength} elements` | ||
), | ||
[ | ||
...updateConditionOrDeps, | ||
...new Array(depsMaxLength - updateConditionOrDeps.length).fill(Object) | ||
] | ||
); | ||
useEffect( | ||
@@ -44,3 +30,3 @@ () => { | ||
}, | ||
depsRef.current | ||
deps | ||
); | ||
@@ -47,0 +33,0 @@ |
"use strict"; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.useEffectIf = void 0; | ||
var assert_1 = require("tsafe/assert"); | ||
var useUpdateConditionOrDeps_1 = require("./useUpdateConditionOrDeps"); | ||
var React = require("react"); | ||
var useEffect = React.useEffect, useRef = React.useRef; | ||
var depsMaxLength = 7; | ||
var useEffect = React.useEffect; | ||
function useEffectIf(effect, updateConditionOrDeps) { | ||
var depsRef = useRef(new Array(depsMaxLength).fill(Object)); | ||
depsRef.current = typeof updateConditionOrDeps === "boolean" ? | ||
updateConditionOrDeps ? __spreadArray([{}], __read(new Array(depsMaxLength - 1).fill(Object))) : | ||
depsRef.current | ||
: | ||
(assert_1.assert(updateConditionOrDeps.length <= depsMaxLength, "dependency array passed to " + useEffectIf.name + " can only contain at most " + depsMaxLength + " elements"), __spreadArray(__spreadArray([], __read(updateConditionOrDeps)), __read(new Array(depsMaxLength - updateConditionOrDeps.length).fill(Object)))); | ||
var deps = useUpdateConditionOrDeps_1.useUpdateConditionOrDeps({ | ||
updateConditionOrDeps: updateConditionOrDeps, | ||
"hookName": useEffectIf.name | ||
}).deps; | ||
useEffect(function () { | ||
@@ -42,5 +18,5 @@ //Only necessary for fist render. | ||
return effect(); | ||
}, depsRef.current); | ||
}, deps); | ||
} | ||
exports.useEffectIf = useEffectIf; | ||
//# sourceMappingURL=useEffectIf.js.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
2485265
356
43746