Manage Group Permissions: Implement paid messages settings for groups (#5845)
This commit is contained in:
parent
752c6f4fab
commit
888e740b39
@ -623,6 +623,7 @@ async function getFullChannelInfo(
|
|||||||
hasScheduled,
|
hasScheduled,
|
||||||
stargiftsCount,
|
stargiftsCount,
|
||||||
stargiftsAvailable,
|
stargiftsAvailable,
|
||||||
|
paidMessagesAvailable,
|
||||||
} = result.fullChat;
|
} = result.fullChat;
|
||||||
|
|
||||||
if (chatPhoto) {
|
if (chatPhoto) {
|
||||||
@ -717,6 +718,7 @@ async function getFullChannelInfo(
|
|||||||
hasScheduledMessages: hasScheduled,
|
hasScheduledMessages: hasScheduled,
|
||||||
starGiftCount: stargiftsCount,
|
starGiftCount: stargiftsCount,
|
||||||
areStarGiftsAvailable: Boolean(stargiftsAvailable),
|
areStarGiftsAvailable: Boolean(stargiftsAvailable),
|
||||||
|
arePaidMessagesAvailable: paidMessagesAvailable,
|
||||||
},
|
},
|
||||||
chats,
|
chats,
|
||||||
userStatusesById: statusesById,
|
userStatusesById: statusesById,
|
||||||
@ -2022,6 +2024,19 @@ export async function fetchChannelRecommendations({ chat }: { chat?: ApiChat })
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function updatePaidMessagesPrice({
|
||||||
|
chat, paidMessagesStars,
|
||||||
|
}: {
|
||||||
|
chat?: ApiChat; paidMessagesStars: number;
|
||||||
|
}) {
|
||||||
|
return invokeRequest(new GramJs.channels.UpdatePaidMessagesPrice({
|
||||||
|
channel: chat && buildInputEntity(chat.id, chat.accessHash) as GramJs.InputChannel,
|
||||||
|
sendPaidMessagesStars: BigInt(paidMessagesStars),
|
||||||
|
}), {
|
||||||
|
shouldReturnTrue: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchSponsoredPeer({ query }: { query: string }) {
|
export async function fetchSponsoredPeer({ query }: { query: string }) {
|
||||||
const result = await invokeRequest(new GramJs.contacts.GetSponsoredPeers({ q: query }));
|
const result = await invokeRequest(new GramJs.contacts.GetSponsoredPeers({ q: query }));
|
||||||
if (!result || result instanceof GramJs.contacts.SponsoredPeersEmpty) return undefined;
|
if (!result || result instanceof GramJs.contacts.SponsoredPeersEmpty) return undefined;
|
||||||
|
|||||||
@ -142,6 +142,7 @@ export interface ApiChatFullInfo {
|
|||||||
hasScheduledMessages?: boolean;
|
hasScheduledMessages?: boolean;
|
||||||
starGiftCount?: number;
|
starGiftCount?: number;
|
||||||
areStarGiftsAvailable?: boolean;
|
areStarGiftsAvailable?: boolean;
|
||||||
|
arePaidMessagesAvailable?: true;
|
||||||
|
|
||||||
boostsApplied?: number;
|
boostsApplied?: number;
|
||||||
boostsToUnrestrict?: number;
|
boostsToUnrestrict?: number;
|
||||||
|
|||||||
@ -1894,7 +1894,7 @@
|
|||||||
"ExceptionTitlePrivacyChargeForMessages" = "Remove fee";
|
"ExceptionTitlePrivacyChargeForMessages" = "Remove fee";
|
||||||
"ExceptionDescriptionPrivacyChargeForMessages" = "Add users or entire groups who won't be charged for sending messages to you.";
|
"ExceptionDescriptionPrivacyChargeForMessages" = "Add users or entire groups who won't be charged for sending messages to you.";
|
||||||
"SectionTitleStarsForForMessages" = "Set your price per message";
|
"SectionTitleStarsForForMessages" = "Set your price per message";
|
||||||
"SectionDescriptionStarsForForMessages" = "You will receive {percent}% of the selected fee (~{amount}) for each incoming message.";
|
"SectionDescriptionStarsForForMessages" = "You will receive {percent} of the selected fee (~{amount}) for each incoming message.";
|
||||||
"SubtitlePrivacyAddUsers" = "Add Users";
|
"SubtitlePrivacyAddUsers" = "Add Users";
|
||||||
"PrivacyPaidMessagesValue" = "Paid";
|
"PrivacyPaidMessagesValue" = "Paid";
|
||||||
"FirstMessageInPaidMessagesChat" = "**{user}** charges {amount} for each message.";
|
"FirstMessageInPaidMessagesChat" = "**{user}** charges {amount} for each message.";
|
||||||
@ -1931,6 +1931,9 @@
|
|||||||
"DescriptionRestrictedMedia" = "Posting media content is not allowed in this group.";
|
"DescriptionRestrictedMedia" = "Posting media content is not allowed in this group.";
|
||||||
"DescriptionScheduledPaidMediaNotAllowed" = "Posting scheduled paid media content is not allowed";
|
"DescriptionScheduledPaidMediaNotAllowed" = "Posting scheduled paid media content is not allowed";
|
||||||
"DescriptionScheduledPaidMessagesNotAllowed" = "Scheduled paid messages is not allowed";
|
"DescriptionScheduledPaidMessagesNotAllowed" = "Scheduled paid messages is not allowed";
|
||||||
|
"GroupMessagesChargePrice" = "Charge Stars for Messages";
|
||||||
|
"RightsChargeStarsAbout" = "If you turn this on, regular members of the group will have to pay Stars to send messages.";
|
||||||
|
"SetPriceGroupDescription" = "Your group will receive {percent} of the selected fee (~{amount}) for each incoming messages.";
|
||||||
"UnlockButtonTitle" = "Unlock with Telegram Premium";
|
"UnlockButtonTitle" = "Unlock with Telegram Premium";
|
||||||
"FrozenAccountModalTitle" = "Your Account is Frozen";
|
"FrozenAccountModalTitle" = "Your Account is Frozen";
|
||||||
"FrozenAccountViolationTitle" = "Violation of Terms";
|
"FrozenAccountViolationTitle" = "Violation of Terms";
|
||||||
|
|||||||
115
src/components/common/paidMessage/PaidMessagePrice.tsx
Normal file
115
src/components/common/paidMessage/PaidMessagePrice.tsx
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import React, {
|
||||||
|
memo,
|
||||||
|
} from '../../../lib/teact/teact';
|
||||||
|
import { getActions, withGlobal } from '../../../global';
|
||||||
|
|
||||||
|
import {
|
||||||
|
DEFAULT_MAXIMUM_CHARGE_FOR_MESSAGES,
|
||||||
|
MINIMUM_CHARGE_FOR_MESSAGES,
|
||||||
|
} from '../../../config';
|
||||||
|
import { formatCurrencyAsString } from '../../../util/formatCurrency';
|
||||||
|
import { formatPercent } from '../../../util/textFormat';
|
||||||
|
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
|
||||||
|
import Button from '../../ui/Button';
|
||||||
|
import Icon from '../icons/Icon';
|
||||||
|
import PaidMessageSlider from './PaidMessageSlider';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
chargeForMessages: number;
|
||||||
|
canChangeChargeForMessages?: boolean;
|
||||||
|
isGroupChat?: boolean;
|
||||||
|
onChange: (value: number) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StateProps = {
|
||||||
|
starsUsdWithdrawRate: number;
|
||||||
|
starsPaidMessageAmountMax: number;
|
||||||
|
starsPaidMessageCommissionPermille: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
function PaidMessagePrice({
|
||||||
|
starsUsdWithdrawRate,
|
||||||
|
starsPaidMessageAmountMax,
|
||||||
|
starsPaidMessageCommissionPermille,
|
||||||
|
canChangeChargeForMessages,
|
||||||
|
isGroupChat,
|
||||||
|
chargeForMessages,
|
||||||
|
onChange,
|
||||||
|
}: OwnProps & StateProps) {
|
||||||
|
const { openPremiumModal } = getActions();
|
||||||
|
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
|
const handleChargeForMessagesChange = useLastCallback((value: number) => {
|
||||||
|
onChange?.(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleUnlockWithPremium = useLastCallback(() => {
|
||||||
|
openPremiumModal({ initialSection: 'message_privacy' });
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||||
|
{lang('SectionTitleStarsForForMessages')}
|
||||||
|
</h4>
|
||||||
|
<PaidMessageSlider
|
||||||
|
defaultValue={chargeForMessages}
|
||||||
|
min={MINIMUM_CHARGE_FOR_MESSAGES}
|
||||||
|
max={starsPaidMessageAmountMax}
|
||||||
|
value={chargeForMessages}
|
||||||
|
onChange={handleChargeForMessagesChange}
|
||||||
|
canChangeChargeForMessages={canChangeChargeForMessages}
|
||||||
|
readOnly={!canChangeChargeForMessages}
|
||||||
|
/>
|
||||||
|
{!canChangeChargeForMessages && (
|
||||||
|
<Button
|
||||||
|
color="primary"
|
||||||
|
fluid
|
||||||
|
size="smaller"
|
||||||
|
noForcedUpperCase
|
||||||
|
className="settings-unlock-button"
|
||||||
|
onClick={handleUnlockWithPremium}
|
||||||
|
>
|
||||||
|
<span className="settings-unlock-button-title">
|
||||||
|
{lang('UnlockButtonTitle')}
|
||||||
|
<Icon name="lock-badge" className="settings-unlock-button-icon" />
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{canChangeChargeForMessages && (
|
||||||
|
<p className="settings-item-description-larger" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||||
|
{lang(isGroupChat ? 'SetPriceGroupDescription' : 'SectionDescriptionStarsForForMessages', {
|
||||||
|
percent: formatPercent(starsPaidMessageCommissionPermille * 100),
|
||||||
|
amount: formatCurrencyAsString(
|
||||||
|
chargeForMessages * starsUsdWithdrawRate * starsPaidMessageCommissionPermille,
|
||||||
|
'USD',
|
||||||
|
lang.code,
|
||||||
|
),
|
||||||
|
}, {
|
||||||
|
withNodes: true,
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(withGlobal<OwnProps>(
|
||||||
|
(global): StateProps => {
|
||||||
|
const starsUsdWithdrawRateX1000 = global.appConfig?.starsUsdWithdrawRateX1000;
|
||||||
|
const starsUsdWithdrawRate = starsUsdWithdrawRateX1000 ? starsUsdWithdrawRateX1000 / 1000 : 1;
|
||||||
|
const configStarsPaidMessageCommissionPermille = global.appConfig?.starsPaidMessageCommissionPermille;
|
||||||
|
const starsPaidMessageCommissionPermille = configStarsPaidMessageCommissionPermille
|
||||||
|
? configStarsPaidMessageCommissionPermille / 1000 : 100;
|
||||||
|
|
||||||
|
return {
|
||||||
|
starsPaidMessageCommissionPermille,
|
||||||
|
starsUsdWithdrawRate,
|
||||||
|
starsPaidMessageAmountMax: global.appConfig?.starsPaidMessageAmountMax || DEFAULT_MAXIMUM_CHARGE_FOR_MESSAGES,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
)(PaidMessagePrice));
|
||||||
121
src/components/common/paidMessage/PaidMessageSlider.tsx
Normal file
121
src/components/common/paidMessage/PaidMessageSlider.tsx
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
|
import React, { memo, useMemo } from '../../../lib/teact/teact';
|
||||||
|
|
||||||
|
import buildClassName from '../../../util/buildClassName';
|
||||||
|
import { formatStarsAsText } from '../../../util/localization/format';
|
||||||
|
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
|
||||||
|
import Icon from '../icons/Icon';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
min?: number;
|
||||||
|
max: number;
|
||||||
|
value: number;
|
||||||
|
disabled?: boolean;
|
||||||
|
readOnly?: boolean;
|
||||||
|
bold?: boolean;
|
||||||
|
className?: string;
|
||||||
|
defaultValue: number;
|
||||||
|
onChange: (value: number) => void;
|
||||||
|
canChangeChargeForMessages?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_POINTS = [50, 100, 500, 1000, 2000, 5000, 10000];
|
||||||
|
|
||||||
|
const PaidMessageSlider: FC<OwnProps> = ({
|
||||||
|
min = 0,
|
||||||
|
max,
|
||||||
|
value,
|
||||||
|
disabled,
|
||||||
|
readOnly,
|
||||||
|
bold,
|
||||||
|
className,
|
||||||
|
defaultValue,
|
||||||
|
onChange,
|
||||||
|
canChangeChargeForMessages,
|
||||||
|
}) => {
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
|
const points = useMemo(() => {
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < DEFAULT_POINTS.length; i++) {
|
||||||
|
if (DEFAULT_POINTS[i] < max) {
|
||||||
|
result.push(DEFAULT_POINTS[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEFAULT_POINTS[i] >= max) {
|
||||||
|
result.push(max);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}, [max]);
|
||||||
|
|
||||||
|
const handleChange = useLastCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newValue = Number(event.currentTarget.value);
|
||||||
|
onChange(getValue(points, newValue));
|
||||||
|
});
|
||||||
|
|
||||||
|
const mainClassName = buildClassName(
|
||||||
|
className,
|
||||||
|
'RangeSlider',
|
||||||
|
disabled && 'disabled',
|
||||||
|
readOnly && 'readOnly',
|
||||||
|
bold && 'bold',
|
||||||
|
);
|
||||||
|
|
||||||
|
function renderTopRow() {
|
||||||
|
return (
|
||||||
|
<div className="slider-top-row" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||||
|
<span className="value-min" dir="auto">{lang.number(min)}</span>
|
||||||
|
<span className="settings-range-value">
|
||||||
|
{!canChangeChargeForMessages && (<Icon name="lock-badge" />)}
|
||||||
|
{formatStarsAsText(lang, getValue(points, getProgress(points, value)))}
|
||||||
|
</span>
|
||||||
|
<span className="value-max" dir="auto">{lang.number(max)}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={mainClassName}>
|
||||||
|
{renderTopRow()}
|
||||||
|
<div className="slider-main">
|
||||||
|
<div
|
||||||
|
className="slider-fill-track"
|
||||||
|
style={`width: ${(getProgress(points, value) / points.length) * 100}%`}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
min={0}
|
||||||
|
max={points.length}
|
||||||
|
defaultValue={getProgress(points, defaultValue)}
|
||||||
|
step="any"
|
||||||
|
type="range"
|
||||||
|
className="RangeSlider__input"
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function getProgress(points: number[], value: number) {
|
||||||
|
const pointIndex = points.findIndex((point) => value <= point);
|
||||||
|
const prevPoint = points[pointIndex - 1] || 1;
|
||||||
|
const nextPoint = points[pointIndex] || points[points.length - 1];
|
||||||
|
const progress = (value - prevPoint) / (nextPoint - prevPoint);
|
||||||
|
return pointIndex + progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getValue(points: number[], progress: number) {
|
||||||
|
const pointIndex = Math.floor(progress);
|
||||||
|
const prevPoint = points[pointIndex - 1] || 1;
|
||||||
|
const nextPoint = points[pointIndex] || points[points.length - 1];
|
||||||
|
const pointValue = prevPoint + (nextPoint - prevPoint) * (progress - pointIndex);
|
||||||
|
return pointValue < 100 ? Math.round(pointValue) : Math.round(pointValue / 10) * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(PaidMessageSlider);
|
||||||
@ -7,16 +7,12 @@ import { SettingsScreens } from '../../../types';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
DEFAULT_CHARGE_FOR_MESSAGES,
|
DEFAULT_CHARGE_FOR_MESSAGES,
|
||||||
DEFAULT_MAXIMUM_CHARGE_FOR_MESSAGES,
|
|
||||||
MINIMUM_CHARGE_FOR_MESSAGES,
|
|
||||||
} from '../../../config';
|
} from '../../../config';
|
||||||
import {
|
import {
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
selectNewNoncontactPeersRequirePremium,
|
selectNewNoncontactPeersRequirePremium,
|
||||||
selectNonContactPeersPaidStars,
|
selectNonContactPeersPaidStars,
|
||||||
} from '../../../global/selectors';
|
} from '../../../global/selectors';
|
||||||
import { formatCurrencyAsString } from '../../../util/formatCurrency';
|
|
||||||
import { formatStarsAsText } from '../../../util/localization/format';
|
|
||||||
|
|
||||||
import useDebouncedCallback from '../../../hooks/useDebouncedCallback';
|
import useDebouncedCallback from '../../../hooks/useDebouncedCallback';
|
||||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||||
@ -24,11 +20,9 @@ import useLang from '../../../hooks/useLang';
|
|||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useOldLang from '../../../hooks/useOldLang';
|
import useOldLang from '../../../hooks/useOldLang';
|
||||||
|
|
||||||
import Icon from '../../common/icons/Icon';
|
import PaidMessagePrice from '../../common/paidMessage/PaidMessagePrice';
|
||||||
import Button from '../../ui/Button';
|
|
||||||
import ListItem from '../../ui/ListItem';
|
import ListItem from '../../ui/ListItem';
|
||||||
import RadioGroup from '../../ui/RadioGroup';
|
import RadioGroup from '../../ui/RadioGroup';
|
||||||
import RangeSlider from '../../ui/RangeSlider';
|
|
||||||
import PremiumStatusItem from './PremiumStatusItem';
|
import PremiumStatusItem from './PremiumStatusItem';
|
||||||
import PrivacyLockedOption from './PrivacyLockedOption';
|
import PrivacyLockedOption from './PrivacyLockedOption';
|
||||||
|
|
||||||
@ -44,9 +38,6 @@ type StateProps = {
|
|||||||
canLimitNewMessagesWithoutPremium?: boolean;
|
canLimitNewMessagesWithoutPremium?: boolean;
|
||||||
canChargeForMessages?: boolean;
|
canChargeForMessages?: boolean;
|
||||||
isCurrentUserPremium?: boolean;
|
isCurrentUserPremium?: boolean;
|
||||||
starsUsdWithdrawRate: number;
|
|
||||||
starsPaidMessageCommissionPermille: number;
|
|
||||||
starsPaidMessageAmountMax?: number;
|
|
||||||
nonContactPeersPaidStars: number;
|
nonContactPeersPaidStars: number;
|
||||||
noPaidReactionsForUsersCount: number;
|
noPaidReactionsForUsersCount: number;
|
||||||
};
|
};
|
||||||
@ -59,14 +50,11 @@ function PrivacyMessages({
|
|||||||
shouldChargeForMessages,
|
shouldChargeForMessages,
|
||||||
nonContactPeersPaidStars,
|
nonContactPeersPaidStars,
|
||||||
isCurrentUserPremium,
|
isCurrentUserPremium,
|
||||||
starsPaidMessageCommissionPermille,
|
|
||||||
starsPaidMessageAmountMax,
|
|
||||||
starsUsdWithdrawRate,
|
|
||||||
noPaidReactionsForUsersCount,
|
noPaidReactionsForUsersCount,
|
||||||
onReset,
|
onReset,
|
||||||
onScreenSelect,
|
onScreenSelect,
|
||||||
}: OwnProps & StateProps) {
|
}: OwnProps & StateProps) {
|
||||||
const { updateGlobalPrivacySettings, openPremiumModal } = getActions();
|
const { updateGlobalPrivacySettings } = getActions();
|
||||||
const oldLang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
|
||||||
@ -131,68 +119,6 @@ function PrivacyMessages({
|
|||||||
updateGlobalPrivacySettingsWithDebounced(value);
|
updateGlobalPrivacySettingsWithDebounced(value);
|
||||||
}, [setChargeForMessages, updateGlobalPrivacySettingsWithDebounced]);
|
}, [setChargeForMessages, updateGlobalPrivacySettingsWithDebounced]);
|
||||||
|
|
||||||
const renderValueForStarsRange = useCallback((value: number) => {
|
|
||||||
return (
|
|
||||||
<span className="settings-range-value">
|
|
||||||
{!canChangeChargeForMessages && (<Icon name="lock-badge" />)}
|
|
||||||
{formatStarsAsText(lang, value)}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}, [lang, canChangeChargeForMessages]);
|
|
||||||
|
|
||||||
const handleUnlockWithPremium = useLastCallback(() => {
|
|
||||||
openPremiumModal({ initialSection: 'message_privacy' });
|
|
||||||
});
|
|
||||||
|
|
||||||
function renderSectionStarsAmountForPaidMessages() {
|
|
||||||
return (
|
|
||||||
<div className="settings-item fluid-container">
|
|
||||||
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
|
||||||
{lang('SectionTitleStarsForForMessages')}
|
|
||||||
</h4>
|
|
||||||
<RangeSlider
|
|
||||||
isCenteredLayout
|
|
||||||
min={MINIMUM_CHARGE_FOR_MESSAGES}
|
|
||||||
max={starsPaidMessageAmountMax}
|
|
||||||
value={chargeForMessages}
|
|
||||||
onChange={handleChargeForMessagesChange}
|
|
||||||
renderValue={renderValueForStarsRange}
|
|
||||||
readOnly={!canChangeChargeForMessages}
|
|
||||||
/>
|
|
||||||
{!isCurrentUserPremium && (
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
fluid
|
|
||||||
size="smaller"
|
|
||||||
noForcedUpperCase
|
|
||||||
className="settings-unlock-button"
|
|
||||||
onClick={handleUnlockWithPremium}
|
|
||||||
>
|
|
||||||
|
|
||||||
<span className="settings-unlock-button-title">
|
|
||||||
{lang('UnlockButtonTitle')}
|
|
||||||
<Icon name="lock-badge" className="settings-unlock-button-icon" />
|
|
||||||
</span>
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{isCurrentUserPremium && (
|
|
||||||
<p className="settings-item-description-larger" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
|
||||||
{lang('SectionDescriptionStarsForForMessages', {
|
|
||||||
percent: starsPaidMessageCommissionPermille * 100,
|
|
||||||
amount: formatCurrencyAsString(
|
|
||||||
chargeForMessages * starsUsdWithdrawRate * starsPaidMessageCommissionPermille,
|
|
||||||
'USD',
|
|
||||||
lang.code,
|
|
||||||
),
|
|
||||||
}, {
|
|
||||||
withNodes: true,
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderSectionNoPaidMessagesForUsers() {
|
function renderSectionNoPaidMessagesForUsers() {
|
||||||
const itemSubtitle = !noPaidReactionsForUsersCount ? lang('SubtitlePrivacyAddUsers')
|
const itemSubtitle = !noPaidReactionsForUsersCount ? lang('SubtitlePrivacyAddUsers')
|
||||||
: oldLang('Users', noPaidReactionsForUsersCount, 'i');
|
: oldLang('Users', noPaidReactionsForUsersCount, 'i');
|
||||||
@ -248,7 +174,15 @@ function PrivacyMessages({
|
|||||||
{privacyDescription}
|
{privacyDescription}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{selectedValue === 'charge_for_messages' && renderSectionStarsAmountForPaidMessages()}
|
{selectedValue === 'charge_for_messages' && (
|
||||||
|
<div className="settings-item fluid-container">
|
||||||
|
<PaidMessagePrice
|
||||||
|
canChangeChargeForMessages={canChangeChargeForMessages}
|
||||||
|
chargeForMessages={chargeForMessages}
|
||||||
|
onChange={handleChargeForMessagesChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{canChangeChargeForMessages && selectedValue === 'charge_for_messages' && renderSectionNoPaidMessagesForUsers()}
|
{canChangeChargeForMessages && selectedValue === 'charge_for_messages' && renderSectionNoPaidMessagesForUsers()}
|
||||||
{!isCurrentUserPremium && selectedValue !== 'charge_for_messages'
|
{!isCurrentUserPremium && selectedValue !== 'charge_for_messages'
|
||||||
&& <PremiumStatusItem premiumSection="message_privacy" />}
|
&& <PremiumStatusItem premiumSection="message_privacy" />}
|
||||||
@ -259,12 +193,6 @@ function PrivacyMessages({
|
|||||||
export default memo(withGlobal<OwnProps>((global): StateProps => {
|
export default memo(withGlobal<OwnProps>((global): StateProps => {
|
||||||
const nonContactPeersPaidStars = selectNonContactPeersPaidStars(global);
|
const nonContactPeersPaidStars = selectNonContactPeersPaidStars(global);
|
||||||
|
|
||||||
const starsUsdWithdrawRateX1000 = global.appConfig?.starsUsdWithdrawRateX1000;
|
|
||||||
const starsUsdWithdrawRate = starsUsdWithdrawRateX1000 ? starsUsdWithdrawRateX1000 / 1000 : 1;
|
|
||||||
const configStarsPaidMessageCommissionPermille = global.appConfig?.starsPaidMessageCommissionPermille;
|
|
||||||
const starsPaidMessageCommissionPermille = configStarsPaidMessageCommissionPermille
|
|
||||||
? configStarsPaidMessageCommissionPermille / 1000 : 100;
|
|
||||||
|
|
||||||
const noPaidReactionsForUsersCount = global.settings.privacy.noPaidMessages?.allowUserIds.length || 0;
|
const noPaidReactionsForUsersCount = global.settings.privacy.noPaidMessages?.allowUserIds.length || 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -274,9 +202,6 @@ export default memo(withGlobal<OwnProps>((global): StateProps => {
|
|||||||
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||||
canLimitNewMessagesWithoutPremium: global.appConfig?.canLimitNewMessagesWithoutPremium,
|
canLimitNewMessagesWithoutPremium: global.appConfig?.canLimitNewMessagesWithoutPremium,
|
||||||
canChargeForMessages: global.appConfig?.starsPaidMessagesAvailable,
|
canChargeForMessages: global.appConfig?.starsPaidMessagesAvailable,
|
||||||
starsPaidMessageAmountMax: global.appConfig?.starsPaidMessageAmountMax || DEFAULT_MAXIMUM_CHARGE_FOR_MESSAGES,
|
|
||||||
starsPaidMessageCommissionPermille,
|
|
||||||
starsUsdWithdrawRate,
|
|
||||||
noPaidReactionsForUsersCount,
|
noPaidReactionsForUsersCount,
|
||||||
};
|
};
|
||||||
})(PrivacyMessages));
|
})(PrivacyMessages));
|
||||||
|
|||||||
@ -125,6 +125,7 @@
|
|||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin-inline-start: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-item-simple,
|
.settings-item-simple,
|
||||||
@ -283,11 +284,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.RangeSlider {
|
|
||||||
margin-bottom: 1.0625rem;
|
|
||||||
padding-inline: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.radio-group {
|
.radio-group {
|
||||||
.Radio:last-child {
|
.Radio:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|||||||
@ -3,7 +3,11 @@ import { getActions, getGlobal, withGlobal } from '../../../global';
|
|||||||
|
|
||||||
import type { ApiChat, ApiMessage, ApiPeer } from '../../../api/types';
|
import type { ApiChat, ApiMessage, ApiPeer } from '../../../api/types';
|
||||||
|
|
||||||
import { GENERAL_TOPIC_ID, SERVICE_NOTIFICATIONS_USER_ID, TME_LINK_PREFIX } from '../../../config';
|
import {
|
||||||
|
GENERAL_TOPIC_ID,
|
||||||
|
SERVICE_NOTIFICATIONS_USER_ID,
|
||||||
|
TME_LINK_PREFIX,
|
||||||
|
} from '../../../config';
|
||||||
import {
|
import {
|
||||||
getMessageInvoice, getMessageText, isChatChannel,
|
getMessageInvoice, getMessageText, isChatChannel,
|
||||||
} from '../../../global/helpers';
|
} from '../../../global/helpers';
|
||||||
|
|||||||
@ -96,7 +96,7 @@
|
|||||||
box-shadow: 0 1px 2px var(--color-default-shadow);
|
box-shadow: 0 1px 2px var(--color-default-shadow);
|
||||||
|
|
||||||
.RangeSlider {
|
.RangeSlider {
|
||||||
margin-bottom: 0;
|
margin: 0;
|
||||||
input[type="range"] {
|
input[type="range"] {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,25 +1,38 @@
|
|||||||
import type { FC } from '../../../lib/teact/teact';
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
import React, {
|
import React, {
|
||||||
memo, useCallback, useMemo, useState,
|
memo, useCallback, useEffect,
|
||||||
|
useMemo, useState,
|
||||||
} from '../../../lib/teact/teact';
|
} from '../../../lib/teact/teact';
|
||||||
import { getActions, withGlobal } from '../../../global';
|
import { getActions, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiChat, ApiChatBannedRights, ApiChatMember } from '../../../api/types';
|
import type { ApiChat, ApiChatBannedRights, ApiChatMember } from '../../../api/types';
|
||||||
import { ManagementScreens } from '../../../types';
|
import { ManagementProgress, ManagementScreens } from '../../../types';
|
||||||
|
|
||||||
import { selectChat, selectChatFullInfo } from '../../../global/selectors';
|
import {
|
||||||
|
DEFAULT_CHARGE_FOR_MESSAGES,
|
||||||
|
} from '../../../config';
|
||||||
|
import {
|
||||||
|
selectChat,
|
||||||
|
selectChatFullInfo,
|
||||||
|
selectTabState,
|
||||||
|
} from '../../../global/selectors';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
|
|
||||||
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useOldLang from '../../../hooks/useOldLang';
|
import useOldLang from '../../../hooks/useOldLang';
|
||||||
import useManagePermissions from '../hooks/useManagePermissions';
|
import useManagePermissions from '../hooks/useManagePermissions';
|
||||||
|
|
||||||
import Icon from '../../common/icons/Icon';
|
import Icon from '../../common/icons/Icon';
|
||||||
|
import PaidMessagePrice from '../../common/paidMessage/PaidMessagePrice';
|
||||||
import PrivateChatInfo from '../../common/PrivateChatInfo';
|
import PrivateChatInfo from '../../common/PrivateChatInfo';
|
||||||
import PermissionCheckboxList from '../../main/PermissionCheckboxList';
|
import PermissionCheckboxList from '../../main/PermissionCheckboxList';
|
||||||
import FloatingActionButton from '../../ui/FloatingActionButton';
|
import FloatingActionButton from '../../ui/FloatingActionButton';
|
||||||
import ListItem from '../../ui/ListItem';
|
import ListItem from '../../ui/ListItem';
|
||||||
import Spinner from '../../ui/Spinner';
|
import Spinner from '../../ui/Spinner';
|
||||||
|
import Switcher from '../../ui/Switcher';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
@ -31,9 +44,13 @@ type OwnProps = {
|
|||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
chat?: ApiChat;
|
chat?: ApiChat;
|
||||||
|
progress?: ManagementProgress;
|
||||||
currentUserId?: string;
|
currentUserId?: string;
|
||||||
removedUsersCount: number;
|
removedUsersCount: number;
|
||||||
members?: ApiChatMember[];
|
members?: ApiChatMember[];
|
||||||
|
arePaidMessagesAvailable?: boolean;
|
||||||
|
groupPeersPaidStars: number;
|
||||||
|
canChargeForMessages?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ITEM_HEIGHT = 48;
|
const ITEM_HEIGHT = 48;
|
||||||
@ -83,18 +100,23 @@ const ManageGroupPermissions: FC<OwnProps & StateProps> = ({
|
|||||||
onScreenSelect,
|
onScreenSelect,
|
||||||
onChatMemberSelect,
|
onChatMemberSelect,
|
||||||
chat,
|
chat,
|
||||||
|
progress,
|
||||||
currentUserId,
|
currentUserId,
|
||||||
removedUsersCount,
|
removedUsersCount,
|
||||||
members,
|
members,
|
||||||
onClose,
|
onClose,
|
||||||
isActive,
|
isActive,
|
||||||
|
arePaidMessagesAvailable,
|
||||||
|
canChargeForMessages,
|
||||||
|
groupPeersPaidStars,
|
||||||
}) => {
|
}) => {
|
||||||
const { updateChatDefaultBannedRights } = getActions();
|
const { updateChatDefaultBannedRights, updatePaidMessagesPrice } = getActions();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
permissions, havePermissionChanged, isLoading, handlePermissionChange, setIsLoading,
|
permissions, havePermissionChanged, isLoading, handlePermissionChange, setIsLoading,
|
||||||
} = useManagePermissions(chat?.defaultBannedRights);
|
} = useManagePermissions(chat?.defaultBannedRights);
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
useHistoryBack({
|
useHistoryBack({
|
||||||
isActive,
|
isActive,
|
||||||
@ -116,14 +138,41 @@ const ManageGroupPermissions: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const [isMediaDropdownOpen, setIsMediaDropdownOpen] = useState(false);
|
const [isMediaDropdownOpen, setIsMediaDropdownOpen] = useState(false);
|
||||||
|
|
||||||
const handleSavePermissions = useCallback(() => {
|
const [isPriceForMessagesChanged, markPriceForMessagesChanged, unmarkPriceForMessagesChanged] = useFlag();
|
||||||
|
const [isPriceForMessagesOpen, setIsPriceForMessagesOpen] = useState(canChargeForMessages);
|
||||||
|
const [chargeForMessages, setChargeForMessages] = useState<number>(groupPeersPaidStars);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (progress === ManagementProgress.Complete) {
|
||||||
|
unmarkPriceForMessagesChanged();
|
||||||
|
}
|
||||||
|
}, [progress]);
|
||||||
|
|
||||||
|
const handleSavePermissions = useLastCallback(() => {
|
||||||
if (!chat) {
|
if (!chat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
updateChatDefaultBannedRights({ chatId: chat.id, bannedRights: permissions });
|
updateChatDefaultBannedRights({ chatId: chat.id, bannedRights: permissions });
|
||||||
}, [chat, permissions, setIsLoading, updateChatDefaultBannedRights]);
|
});
|
||||||
|
|
||||||
|
const handleUpdatePaidMessagesPrice = useLastCallback(() => {
|
||||||
|
if (!chat) return;
|
||||||
|
updatePaidMessagesPrice({
|
||||||
|
chatId: chat?.id,
|
||||||
|
paidMessagesStars: isPriceForMessagesOpen ? chargeForMessages : 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleUpdatePermissions = useLastCallback(() => {
|
||||||
|
if (isPriceForMessagesChanged) {
|
||||||
|
handleUpdatePaidMessagesPrice();
|
||||||
|
}
|
||||||
|
if (havePermissionChanged) {
|
||||||
|
handleSavePermissions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const exceptionMembers = useMemo(() => {
|
const exceptionMembers = useMemo(() => {
|
||||||
if (!members) {
|
if (!members) {
|
||||||
@ -157,11 +206,24 @@ const ManageGroupPermissions: FC<OwnProps & StateProps> = ({
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const translatedString = lang(langKey);
|
const translatedString = oldLang(langKey);
|
||||||
|
|
||||||
return `${result}${!result.length ? translatedString : `, ${translatedString}`}`;
|
return `${result}${!result.length ? translatedString : `, ${translatedString}`}`;
|
||||||
}, '');
|
}, '');
|
||||||
}, [chat, lang]);
|
}, [chat, oldLang]);
|
||||||
|
|
||||||
|
const handleChargeStarsForMessages = useLastCallback(() => {
|
||||||
|
setIsPriceForMessagesOpen(!isPriceForMessagesOpen);
|
||||||
|
markPriceForMessagesChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleChargeForMessagesChange = useLastCallback((value: number) => {
|
||||||
|
setChargeForMessages(value);
|
||||||
|
markPriceForMessagesChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
const arePermissionsChanged = isPriceForMessagesChanged || havePermissionChanged;
|
||||||
|
const arePermissionsLoading = progress === ManagementProgress.InProgress || isLoading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -187,6 +249,43 @@ const ManageGroupPermissions: FC<OwnProps & StateProps> = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{arePaidMessagesAvailable && (
|
||||||
|
<div
|
||||||
|
className={buildClassName(
|
||||||
|
'section',
|
||||||
|
isMediaDropdownOpen && 'shifted',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ListItem onClick={handleChargeStarsForMessages}>
|
||||||
|
<span>{lang('GroupMessagesChargePrice')}</span>
|
||||||
|
<Switcher
|
||||||
|
id="charge_for_messages"
|
||||||
|
label={lang('GroupMessagesChargePrice')}
|
||||||
|
checked={isPriceForMessagesOpen}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
<p className="settings-item-description-larger" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||||
|
{lang('RightsChargeStarsAbout')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isPriceForMessagesOpen && (
|
||||||
|
<div
|
||||||
|
className={buildClassName(
|
||||||
|
'section',
|
||||||
|
isMediaDropdownOpen && 'shifted',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<PaidMessagePrice
|
||||||
|
canChangeChargeForMessages
|
||||||
|
isGroupChat
|
||||||
|
chargeForMessages={chargeForMessages}
|
||||||
|
onChange={handleChargeForMessagesChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={buildClassName(
|
className={buildClassName(
|
||||||
'section',
|
'section',
|
||||||
@ -237,12 +336,12 @@ const ManageGroupPermissions: FC<OwnProps & StateProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FloatingActionButton
|
<FloatingActionButton
|
||||||
isShown={havePermissionChanged}
|
isShown={arePermissionsChanged}
|
||||||
onClick={handleSavePermissions}
|
onClick={handleUpdatePermissions}
|
||||||
ariaLabel={lang('Save')}
|
ariaLabel={lang('Save')}
|
||||||
disabled={isLoading}
|
disabled={arePermissionsLoading}
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{arePermissionsLoading ? (
|
||||||
<Spinner color="white" />
|
<Spinner color="white" />
|
||||||
) : (
|
) : (
|
||||||
<Icon name="check" />
|
<Icon name="check" />
|
||||||
@ -256,12 +355,20 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
(global, { chatId }): StateProps => {
|
(global, { chatId }): StateProps => {
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
const fullInfo = selectChatFullInfo(global, chatId);
|
const fullInfo = selectChatFullInfo(global, chatId);
|
||||||
|
const { progress } = selectTabState(global).management;
|
||||||
|
|
||||||
|
const paidMessagesStars = chat?.paidMessagesStars;
|
||||||
|
const configStarsPaidMessageCommissionPermille = global.appConfig?.starsPaidMessageCommissionPermille;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
chat,
|
chat,
|
||||||
|
progress,
|
||||||
currentUserId: global.currentUserId,
|
currentUserId: global.currentUserId,
|
||||||
removedUsersCount: fullInfo?.kickedMembers?.length || 0,
|
removedUsersCount: fullInfo?.kickedMembers?.length || 0,
|
||||||
members: fullInfo?.members,
|
members: fullInfo?.members,
|
||||||
|
arePaidMessagesAvailable: Boolean(fullInfo?.arePaidMessagesAvailable && configStarsPaidMessageCommissionPermille),
|
||||||
|
canChargeForMessages: Boolean(paidMessagesStars && configStarsPaidMessageCommissionPermille),
|
||||||
|
groupPeersPaidStars: paidMessagesStars || DEFAULT_CHARGE_FOR_MESSAGES,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(ManageGroupPermissions));
|
)(ManageGroupPermissions));
|
||||||
|
|||||||
@ -126,9 +126,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.RangeSlider {
|
.RangeSlider {
|
||||||
margin-top: 2rem;
|
margin-top: 1rem;
|
||||||
margin-inline-start: 1rem;
|
|
||||||
margin-inline-end: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-position {
|
.button-position {
|
||||||
|
|||||||
@ -18,7 +18,9 @@
|
|||||||
.RangeSlider {
|
.RangeSlider {
|
||||||
--slider-color: var(--color-primary);
|
--slider-color: var(--color-primary);
|
||||||
|
|
||||||
margin-bottom: 1rem;
|
margin: 0.5rem 0 0;
|
||||||
|
margin-inline-start: 1rem;
|
||||||
|
margin-inline-end: 1rem;
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|||||||
@ -2896,6 +2896,27 @@ addActionHandler('toggleChannelRecommendations', (global, actions, payload): Act
|
|||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addActionHandler('updatePaidMessagesPrice', async (global, actions, payload): Promise<void> => {
|
||||||
|
const { chatId, paidMessagesStars, tabId = getCurrentTabId() } = payload;
|
||||||
|
const chat = chatId ? selectChat(global, chatId) : undefined;
|
||||||
|
if (!chat) return;
|
||||||
|
|
||||||
|
global = updateManagementProgress(global, ManagementProgress.InProgress, tabId);
|
||||||
|
setGlobal(global);
|
||||||
|
|
||||||
|
const result = await callApi('updatePaidMessagesPrice', {
|
||||||
|
chat,
|
||||||
|
paidMessagesStars,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result) return;
|
||||||
|
|
||||||
|
global = getGlobal();
|
||||||
|
global = updateManagementProgress(global, ManagementProgress.Complete, tabId);
|
||||||
|
global = updateChat(global, chatId, { paidMessagesStars });
|
||||||
|
setGlobal(global);
|
||||||
|
});
|
||||||
|
|
||||||
addActionHandler('resolveBusinessChatLink', async (global, actions, payload): Promise<void> => {
|
addActionHandler('resolveBusinessChatLink', async (global, actions, payload): Promise<void> => {
|
||||||
const { slug, tabId = getCurrentTabId() } = payload;
|
const { slug, tabId = getCurrentTabId() } = payload;
|
||||||
const result = await callApi('resolveBusinessChatLink', { slug });
|
const result = await callApi('resolveBusinessChatLink', { slug });
|
||||||
|
|||||||
@ -1058,6 +1058,10 @@ export interface ActionPayloads {
|
|||||||
chatId: string;
|
chatId: string;
|
||||||
isEnabled: boolean;
|
isEnabled: boolean;
|
||||||
};
|
};
|
||||||
|
updatePaidMessagesPrice: {
|
||||||
|
chatId: string;
|
||||||
|
paidMessagesStars: number;
|
||||||
|
} & WithTabId;
|
||||||
|
|
||||||
updateChat: {
|
updateChat: {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
|
|||||||
@ -1709,6 +1709,7 @@ channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = U
|
|||||||
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.getChannelRecommendations#25a71742 flags:# channel:flags.0?InputChannel = messages.Chats;
|
channels.getChannelRecommendations#25a71742 flags:# channel:flags.0?InputChannel = messages.Chats;
|
||||||
channels.searchPosts#d19f987b hashtag:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
channels.searchPosts#d19f987b hashtag:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||||
|
channels.updatePaidMessagesPrice#fc84653f channel:InputChannel send_paid_messages_stars:long = Updates;
|
||||||
bots.setBotInfo#10cf3123 flags:# bot:flags.2?InputUser lang_code:string name:flags.3?string about:flags.0?string description:flags.1?string = Bool;
|
bots.setBotInfo#10cf3123 flags:# bot:flags.2?InputUser lang_code:string name:flags.3?string about:flags.0?string description:flags.1?string = Bool;
|
||||||
bots.canSendMessage#1359f4e6 bot:InputUser = Bool;
|
bots.canSendMessage#1359f4e6 bot:InputUser = Bool;
|
||||||
bots.allowSendMessage#f132e3ef bot:InputUser = Updates;
|
bots.allowSendMessage#f132e3ef bot:InputUser = Updates;
|
||||||
|
|||||||
@ -277,6 +277,7 @@
|
|||||||
"channels.getChannelRecommendations",
|
"channels.getChannelRecommendations",
|
||||||
"channels.searchPosts",
|
"channels.searchPosts",
|
||||||
"channels.reportSpam",
|
"channels.reportSpam",
|
||||||
|
"channels.updatePaidMessagesPrice",
|
||||||
"bots.getBotRecommendations",
|
"bots.getBotRecommendations",
|
||||||
"bots.canSendMessage",
|
"bots.canSendMessage",
|
||||||
"bots.allowSendMessage",
|
"bots.allowSendMessage",
|
||||||
|
|||||||
6
src/types/language.d.ts
vendored
6
src/types/language.d.ts
vendored
@ -1475,6 +1475,8 @@ export interface LangPair {
|
|||||||
'DescriptionRestrictedMedia': undefined;
|
'DescriptionRestrictedMedia': undefined;
|
||||||
'DescriptionScheduledPaidMediaNotAllowed': undefined;
|
'DescriptionScheduledPaidMediaNotAllowed': undefined;
|
||||||
'DescriptionScheduledPaidMessagesNotAllowed': undefined;
|
'DescriptionScheduledPaidMessagesNotAllowed': undefined;
|
||||||
|
'GroupMessagesChargePrice': undefined;
|
||||||
|
'RightsChargeStarsAbout': undefined;
|
||||||
'UnlockButtonTitle': undefined;
|
'UnlockButtonTitle': undefined;
|
||||||
'PrivacySubscribeToTelegramPremium': undefined;
|
'PrivacySubscribeToTelegramPremium': undefined;
|
||||||
'PrivacyDisableLimitedEditionStarGifts': undefined;
|
'PrivacyDisableLimitedEditionStarGifts': undefined;
|
||||||
@ -2387,6 +2389,10 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
|||||||
'PaidMessageTransactionDescription': {
|
'PaidMessageTransactionDescription': {
|
||||||
'percent': V;
|
'percent': V;
|
||||||
};
|
};
|
||||||
|
'SetPriceGroupDescription': {
|
||||||
|
'percent': V;
|
||||||
|
'amount': V;
|
||||||
|
};
|
||||||
'FrozenAccountAppealSubtitle': {
|
'FrozenAccountAppealSubtitle': {
|
||||||
'botLink': V;
|
'botLink': V;
|
||||||
'date': V;
|
'date': V;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user