Skip to content

Commit

Permalink
fix(sdk,main-button): rework the mount function, making it not to set…
Browse files Browse the repository at this point in the history
… properties from theme
  • Loading branch information
heyqbnk committed Oct 1, 2024
1 parent 5e63671 commit 82cd37c
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 55 deletions.
29 changes: 19 additions & 10 deletions packages/sdk/src/scopes/components/main-button/methods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import {
isEnabled,
isLoaderVisible,
isVisible,
state,
internalState,
backgroundColor,
hasShineEffect,
state,
} from './signals.js';
import { onClick, offClick, setParams, mount, unmount } from './methods.js';

Expand All @@ -40,8 +41,16 @@ beforeEach(() => {
themeParams.isCssVarsBound,
themeParams.isMounted,
themeParams.state,
state,
text,
textColor,
isMounted,
isEnabled,
isLoaderVisible,
isVisible,
internalState,
backgroundColor,
hasShineEffect,
state,
].forEach(resetSignal);
mockPostEvent();
});
Expand All @@ -56,7 +65,7 @@ describe.each([
{ signal: textColor, name: 'textColor' },
] as const)('$name property', ({ signal, name }) => {
beforeEach(() => {
state.set({
internalState.set({
backgroundColor: '#123456',
hasShineEffect: true,
isEnabled: true,
Expand All @@ -68,7 +77,7 @@ describe.each([
});

it(`should use "${name}" property from state`, () => {
expect(signal()).toBe(state()[name]);
expect(signal()).toBe(internalState()[name]);
});
});

Expand All @@ -78,7 +87,7 @@ describe('mounted', () => {

describe('setParams', () => {
it('should save the state in storage key tapps/mainButton', () => {
state.set({
internalState.set({
backgroundColor: '#123456',
hasShineEffect: true,
isEnabled: true,
Expand All @@ -99,7 +108,7 @@ describe('mounted', () => {

it('should call "web_app_setup_main_button" only if text is not empty', () => {
const spy = mockPostEvent();
state.set({
internalState.set({
backgroundColor: '#123456',
hasShineEffect: false,
isEnabled: true,
Expand Down Expand Up @@ -232,7 +241,7 @@ describe('offClick', () => {

describe('setParams', () => {
it('should merge passed object with the state', () => {
state.set({
internalState.set({
backgroundColor: '#123456',
hasShineEffect: true,
isEnabled: true,
Expand All @@ -250,7 +259,7 @@ describe('setParams', () => {
textColor: '#000000',
});

expect(state()).toStrictEqual({
expect(internalState()).toStrictEqual({
backgroundColor: '#111111',
hasShineEffect: true,
isEnabled: false,
Expand All @@ -268,15 +277,15 @@ describe('unmount', () => {
it('should stop calling postEvent function and session storage updates when something changes', () => {
const postEventSpy = mockPostEvent();
const storageSpy = mockSessionStorageSetItem();
state.set({ ...state(), text: 'Hello!' });
internalState.set({ ...internalState(), text: 'Hello!' });
expect(postEventSpy).toHaveBeenCalledTimes(1);
expect(storageSpy).toHaveBeenCalledTimes(1);

postEventSpy.mockClear();
storageSpy.mockClear();

unmount();
state.set({ ...state() });
internalState.set({ ...internalState() });

expect(postEventSpy).toHaveBeenCalledTimes(0);
expect(storageSpy).toHaveBeenCalledTimes(0);
Expand Down
81 changes: 36 additions & 45 deletions packages/sdk/src/scopes/components/main-button/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,33 @@ import {
import { isPageReload } from '@telegram-apps/navigation';

import { postEvent } from '@/scopes/globals.js';
import {
mount as tpMount,
buttonColor as tpButtonColor,
buttonTextColor as tpButtonTextColor,
} from '@/scopes/components/theme-params/instance.js';

import { state, isMounted } from './signals.js';
import { internalState, isMounted, state } from './signals.js';
import type { State } from './types.js';

type StorageValue = State;

const MINI_APPS_METHOD = 'web_app_setup_main_button';
const CLICK_EVENT = 'main_button_pressed';
const STORAGE_KEY = 'mainButton';

/**
* Mounts the component.
*
* This function restores the component state and is automatically saving it in the local storage
* if it changed.
*/
export function mount(): void {
if (!isMounted()) {
const prev = isPageReload() && getStorageValue<StorageValue>(STORAGE_KEY);
prev && internalState.set(prev);

internalState.sub(onInternalStateChanged);
state.sub(onStateChanged);
isMounted.set(true);
}
}

/**
* Adds a new main button click listener.
* @param fn - event listener.
Expand All @@ -39,54 +52,31 @@ export function offClick(fn: EventListener<'main_button_pressed'>): void {
off(CLICK_EVENT, fn);
}

/**
* Mounts the component.
*
* This function restores the component state and is automatically saving it in the local storage
* if it changed.
*/
export function mount(): void {
if (!isMounted()) {
const prev = isPageReload() && getStorageValue<StorageValue>(STORAGE_KEY);
if (prev) {
state.set(prev);
} else {
tpMount();
setParams({
backgroundColor: tpButtonColor(),
textColor: tpButtonTextColor(),
});
}

state.sub(onStateChanged);
isMounted.set(true);
}
function onInternalStateChanged(state: State): void {
setStorageValue<StorageValue>(STORAGE_KEY, state);
}

function onStateChanged(s: State): void {
// We should not commit changes until the payload is correct. Some version of Telegram will
// crash due to the empty value of the text.
if (s.text) {
postEvent('web_app_setup_main_button', {
has_shine_effect: s.hasShineEffect,
is_visible: s.isVisible,
is_active: s.isEnabled,
is_progress_visible: s.isLoaderVisible,
text: s.text,
color: s.backgroundColor,
text_color: s.textColor,
});
}
setStorageValue<StorageValue>(STORAGE_KEY, s);
function onStateChanged(s: Required<State>) {
// We should not commit changes until the payload is correct.
// Some version of Telegram will crash due to the empty value of the text.
s.text && postEvent(MINI_APPS_METHOD, {
has_shine_effect: s.hasShineEffect,
is_visible: s.isVisible,
is_active: s.isEnabled,
is_progress_visible: s.isLoaderVisible,
text: s.text,
color: s.backgroundColor,
text_color: s.textColor,
});
}

/**
* Updates the main button state.
* @param updates - state changes to perform.
*/
export function setParams(updates: Partial<State>): void {
state.set({
...state(),
internalState.set({
...internalState(),
...Object.fromEntries(
Object.entries(updates).filter(([, v]) => v !== undefined),
),
Expand All @@ -100,6 +90,7 @@ export function setParams(updates: Partial<State>): void {
* @see onClick
*/
export function unmount(): void {
internalState.unsub(onInternalStateChanged);
state.unsub(onStateChanged);
isMounted.set(false);
}

0 comments on commit 82cd37c

Please sign in to comment.