Skip to content

Commit

Permalink
Merge pull request #96 from gravity-ui/promo-manager-hooks
Browse files Browse the repository at this point in the history
Promo manager hooks
  • Loading branch information
vanilla-wave authored Sep 2, 2024
2 parents b1151ad + 7d58011 commit d1160b8
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 59 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,14 +328,14 @@ export const { controller, usePromoManager, useActivePromo } = createPromoManage

import { usePromoManager } from './promo-manager';

const { status, requestStart, cancelStart } = usePromoManager('issuePoll');
const { status, requestStart, skipPromo } = usePromoManager('issuePoll');

useMount(() => {
requestStart();
});

useUnmount(() => {
cancelStart();
skipPromo();
});

if(status === 'active') {
Expand Down
30 changes: 6 additions & 24 deletions src/promo-manager/core/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import type {
InitPromoManagerOptions,
Nullable,
ProgressInfoConfig,
Promo,
PromoBaseState as BaseState,
PromoGroup,
PromoGroupSlug,
PromoManagerStatus,
PromoOptions,
Expand Down Expand Up @@ -219,7 +217,7 @@ export class Controller {
this.updateProgressInfo(slug);
};

cancelStart = (slug: Nullable<PromoSlug>) => {
skipPromo = (slug: Nullable<PromoSlug>) => {
this.logger.debug('Skip promo run', slug);
if (!slug) {
return;
Expand Down Expand Up @@ -260,28 +258,12 @@ export class Controller {
return 'canRun';
};

getFirstAvailablePromoByType = (slug: PromoGroupSlug): Nullable<PromoSlug> => {
const promoGroup = Object.values(this.options.config.promoGroups).find(
(currentPromoGroup: PromoGroup<unknown>) => currentPromoGroup.slug === slug,
);

if (!promoGroup) {
return null;
}

return (
promoGroup.promos.find(
(promo: Promo) => this.isAbleToRun(promo.slug) || this.isPending(promo.slug),
)?.slug ?? null
);
};

getActivePromo = (promoType?: PromoGroupSlug): Nullable<PromoSlug> => {
getActivePromo = (promoGroup?: PromoGroupSlug): Nullable<PromoSlug> => {
const activePromo = this.state.base.activePromo;

if (!promoType) return activePromo;
if (!promoGroup) return activePromo;

return this.getGroupBySlug(activePromo) === promoType ? activePromo : null;
return this.getGroupBySlug(activePromo) === promoGroup ? activePromo : null;
};

subscribe = (listener: Listener) => {
Expand Down Expand Up @@ -490,7 +472,7 @@ export class Controller {

const result = await this.requestStart(stepData.preset);
if (!result) {
this.cancelStart(stepData.preset);
this.skipPromo(stepData.preset);
}
return result;
},
Expand All @@ -507,7 +489,7 @@ export class Controller {

instance.events.subscribe('closeHint', async ({hint}: OnboardingEventsMap['closeHint']) => {
if (this.promoPresets.has(hint.preset)) {
this.cancelStart(hint.preset);
this.skipPromo(hint.preset);
}
});

Expand Down
53 changes: 24 additions & 29 deletions src/promo-manager/core/getHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,67 @@ import type {Controller} from './controller';
import type {PromoGroupSlug, PromoSlug} from './types';

export function getHooks(controller: Controller) {
const usePromoManager = (promo: PromoSlug) => {
const status = useSyncExternalStore(controller.subscribe, () =>
controller.getPromoStatus(promo),
const usePromoManager = () => {
const activePromo = useSyncExternalStore(
controller.subscribe,
() => controller.state.base.activePromo,
);

return useMemo(
() => ({
status,
requestStart: () => {
controller.requestStart(promo).catch((error) => {
controller.logger.error(error);
});
},
finish: (closeActiveTimeout?: number) =>
controller.finishPromo(promo, closeActiveTimeout),
cancel: (closeActiveTimeout?: number) =>
controller.cancelPromo(promo, closeActiveTimeout),
cancelStart: () => controller.cancelStart(promo),
updateProgressInfo: () => controller.updateProgressInfo(promo),
activePromo,
requestStartPromo: controller.requestStart,
finisPromo: controller.finishPromo,
cancelPromo: controller.cancelPromo,
skipPromo: controller.skipPromo,
}),
[promo, status],
[activePromo],
);
};

const useActivePromo = (promoGroupSlug?: PromoGroupSlug) => {
const promo = useSyncExternalStore(controller.subscribe, () =>
controller.getActivePromo(promoGroupSlug),
const usePromo = (promo: PromoSlug) => {
const status = useSyncExternalStore(controller.subscribe, () =>
controller.getPromoStatus(promo),
);

return useMemo(
() => ({
promo,
promoGroup: controller.getGroupBySlug(promo),
metaInfo: controller.getPromoMeta(promo),
status,
requestStart: () => controller.requestStart(promo),
finish: (closeActiveTimeout?: number) =>
controller.finishPromo(promo, closeActiveTimeout),
cancel: (closeActiveTimeout?: number) =>
controller.cancelPromo(promo, closeActiveTimeout),
cancelStart: () => controller.cancelStart(promo),
updateProgressInfo: () => controller.updateProgressInfo(promo),
skip: () => controller.skipPromo(promo),
}),
[promo],
[status],
);
};

const useAvailablePromo = (type: PromoGroupSlug) => {
const useActivePromo = (promoGroupSlug?: PromoGroupSlug) => {
const promo = useSyncExternalStore(controller.subscribe, () =>
controller.getFirstAvailablePromoByType(type),
controller.getActivePromo(promoGroupSlug),
);

return useMemo(
() => ({
promo,
requestStart: () => controller.requestStart(promo),
promoGroup: controller.getGroupBySlug(promo),
metaInfo: controller.getPromoMeta(promo),
finish: (closeActiveTimeout?: number) =>
controller.finishPromo(promo, closeActiveTimeout),
cancel: (closeActiveTimeout?: number) =>
controller.cancelPromo(promo, closeActiveTimeout),
skipPromo: () => controller.skipPromo(promo),
updateProgressInfo: () => controller.updateProgressInfo(promo),
}),
[promo],
);
};

return {
usePromoManager,
useAvailablePromo,
usePromo,
useActivePromo,
};
}
4 changes: 2 additions & 2 deletions src/promo-manager/setups/survey-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ export const createSurveyManager = ({
const surveySlug = surveyGroup?.slug;

const useActiveSurvey = () => {
const {promo, promoGroup, metaInfo, finish, cancel, cancelStart, updateProgressInfo} =
const {promo, promoGroup, metaInfo, finish, cancel, skipPromo, updateProgressInfo} =
useActivePromo();

return {
active: promoGroup === surveySlug ? promo : null,
config: metaInfo,
finish,
cancel,
cancelStart,
skipPromo,
updateProgressInfo,
};
};
Expand Down
4 changes: 2 additions & 2 deletions src/promo-manager/tests/controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,13 @@ describe('trigger subscribe', () => {
expect(callback).toHaveBeenCalledTimes(1);
});

it('cancelStart -> 1 update', async () => {
it('skipPromo -> 1 update', async () => {
await controller.requestStart('boardPoll');

const callback = jest.fn();
controller.subscribe(callback);

await controller.cancelStart('boardPoll');
await controller.skipPromo('boardPoll');

expect(callback).toHaveBeenCalledTimes(1);
});
Expand Down

0 comments on commit d1160b8

Please sign in to comment.