Mini App: Fix geolocation check (#6898)

This commit is contained in:
zubiden 2026-04-27 14:29:21 +02:00 committed by Alexander Zinchuk
parent fa6224abb7
commit e30555d3b3
5 changed files with 123 additions and 45 deletions

View File

@ -36,7 +36,7 @@ const LocationAccessModal: FC<OwnProps & StateProps> = ({
currentUser, currentUser,
}) => { }) => {
const { const {
closeLocationAccessModal, toggleUserLocationPermission, sendWebAppEvent, closeLocationAccessModal, toggleUserLocationPermission, sendWebAppEvent, showNotification,
} = getActions(); } = getActions();
const isOpen = Boolean(modal); const isOpen = Boolean(modal);
@ -47,28 +47,48 @@ const LocationAccessModal: FC<OwnProps & StateProps> = ({
const containerRef = useRef<HTMLDivElement>(); const containerRef = useRef<HTMLDivElement>();
const confirmHandler = useLastCallback(async () => { const confirmHandler = useLastCallback(async () => {
const geolocationData = await getGeolocationStatus();
const { geolocation } = geolocationData;
if (!modal?.bot?.id) return; if (!modal?.bot?.id) return;
const geolocationData = await getGeolocationStatus();
const { accessRequested, accessGranted, geolocation } = geolocationData;
const isAccessGranted = accessRequested && accessGranted && Boolean(geolocation);
closeLocationAccessModal(); closeLocationAccessModal();
if (modal?.webAppKey) { if (modal?.webAppKey) {
toggleUserLocationPermission({ toggleUserLocationPermission({
botId: modal.bot.id, botId: modal.bot.id,
isAccessGranted: true, isAccessGranted,
}); });
if (!isAccessGranted || !geolocation) {
sendWebAppEvent({
webAppKey: modal.webAppKey,
event: {
eventType: 'location_requested',
eventData: {
available: false,
},
},
});
showNotification({ message: oldLang('PermissionNoLocationPosition') });
return;
}
sendWebAppEvent({ sendWebAppEvent({
webAppKey: modal.webAppKey, webAppKey: modal.webAppKey,
event: { event: {
eventType: 'location_requested', eventType: 'location_requested',
eventData: { eventData: {
available: true, available: true,
latitude: geolocation?.latitude, latitude: geolocation.latitude,
longitude: geolocation?.longitude, longitude: geolocation.longitude,
altitude: geolocation?.altitude, altitude: geolocation.altitude,
course: geolocation?.heading, course: geolocation.heading,
speed: geolocation?.speed, speed: geolocation.speed,
horizontal_accuracy: geolocation?.accuracy, horizontal_accuracy: geolocation.accuracy,
vertical_accuracy: geolocation?.accuracy, vertical_accuracy: geolocation.altitudeAccuracy,
// eslint-disable-next-line no-null/no-null
course_accuracy: null,
// eslint-disable-next-line no-null/no-null
speed_accuracy: null,
}, },
}, },
}); });

View File

@ -321,6 +321,35 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
}); });
}); });
const sendLocationUnavailable = useLastCallback(() => {
sendEvent({
eventType: 'location_requested',
eventData: {
available: false,
},
});
});
const sendLocation = useLastCallback((geolocation: GeolocationCoordinates) => {
sendEvent({
eventType: 'location_requested',
eventData: {
available: true,
latitude: geolocation.latitude,
longitude: geolocation.longitude,
altitude: geolocation.altitude,
course: geolocation.heading,
speed: geolocation.speed,
horizontal_accuracy: geolocation.accuracy,
vertical_accuracy: geolocation.altitudeAccuracy,
// eslint-disable-next-line no-null/no-null
course_accuracy: null,
// eslint-disable-next-line no-null/no-null
speed_accuracy: null,
},
});
});
const handleAppPopupModalClose = useLastCallback(() => { const handleAppPopupModalClose = useLastCallback(() => {
handleAppPopupClose(); handleAppPopupClose();
}); });
@ -773,10 +802,20 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
if (eventType === 'web_app_check_location') { if (eventType === 'web_app_check_location') {
const handleGeolocationCheck = () => { const handleGeolocationCheck = () => {
if (!isAvailable) {
sendEvent({
eventType: 'location_checked',
eventData: {
available: false,
},
});
return;
}
sendEvent({ sendEvent({
eventType: 'location_checked', eventType: 'location_checked',
eventData: { eventData: {
available: isAvailable, available: true,
access_requested: isAccessRequested, access_requested: isAccessRequested,
access_granted: isAccessGranted, access_granted: isAccessGranted,
}, },
@ -788,43 +827,38 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
if (eventType === 'web_app_request_location') { if (eventType === 'web_app_request_location') {
const handleRequestLocation = async () => { const handleRequestLocation = async () => {
const geolocationData = await getGeolocationStatus(); if (!isAvailable) {
const { accessRequested, accessGranted, geolocation } = geolocationData; sendLocationUnavailable();
if (!accessGranted || !accessRequested) {
sendEvent({
eventType: 'location_requested',
eventData: {
available: false,
},
});
showNotification({ message: oldLang('PermissionNoLocationPosition') }); showNotification({ message: oldLang('PermissionNoLocationPosition') });
handleAppPopupClose(undefined); handleAppPopupClose(undefined);
return; return;
} }
if (isAvailable) { if (!isAccessRequested) {
if (isAccessRequested) { if (bot && webAppKey) {
sendEvent({
eventType: 'location_requested',
eventData: {
available: Boolean(botAppPermissions?.geolocation),
latitude: geolocation?.latitude,
longitude: geolocation?.longitude,
altitude: geolocation?.altitude,
course: geolocation?.heading,
speed: geolocation?.speed,
horizontal_accuracy: geolocation?.accuracy,
vertical_accuracy: geolocation?.altitudeAccuracy,
},
});
} else {
openLocationAccessModal({ bot, webAppKey }); openLocationAccessModal({ bot, webAppKey });
} else {
sendLocationUnavailable();
} }
} else { return;
}
if (!isAccessGranted) {
sendLocationUnavailable();
return;
}
const geolocationData = await getGeolocationStatus();
const { accessRequested, accessGranted, geolocation } = geolocationData;
if (!accessGranted || !accessRequested || !geolocation) {
sendLocationUnavailable();
showNotification({ message: oldLang('PermissionNoLocationPosition') }); showNotification({ message: oldLang('PermissionNoLocationPosition') });
handleAppPopupClose(undefined); handleAppPopupClose(undefined);
return;
} }
sendLocation(geolocation);
}; };
handleRequestLocation(); handleRequestLocation();

View File

@ -61,7 +61,7 @@ export const MEDIA_PROGRESSIVE_CACHE_DISABLED = false;
export const MEDIA_PROGRESSIVE_CACHE_NAME = 'tt-media-progressive'; export const MEDIA_PROGRESSIVE_CACHE_NAME = 'tt-media-progressive';
export const MEDIA_CACHE_MAX_BYTES = 512 * 1024; // 512 KB export const MEDIA_CACHE_MAX_BYTES = 512 * 1024; // 512 KB
export const CUSTOM_BG_CACHE_NAME = 'tt-custom-bg'; export const CUSTOM_BG_CACHE_NAME = 'tt-custom-bg';
export const LANG_CACHE_NAME = 'tt-lang-packs-v51'; export const LANG_CACHE_NAME = 'tt-lang-packs-v52';
export const ASSET_CACHE_NAME = 'tt-assets'; export const ASSET_CACHE_NAME = 'tt-assets';
export const AUTODOWNLOAD_FILESIZE_MB_LIMITS = [1, 5, 10, 50, 100, 500]; export const AUTODOWNLOAD_FILESIZE_MB_LIMITS = [1, 5, 10, 50, 100, 500];
export const DATA_BROADCAST_CHANNEL_PREFIX = 'tt-global'; export const DATA_BROADCAST_CHANNEL_PREFIX = 'tt-global';

View File

@ -55,6 +55,31 @@ import {
} from '../../selectors'; } from '../../selectors';
const LOCAL_BOOST_COOLDOWN = 86400; // 24 hours const LOCAL_BOOST_COOLDOWN = 86400; // 24 hours
const SMART_GLOCAL_DOMAIN = 'smart-glocal.com';
const SMART_GLOCAL_TOKENIZE_PATH = '/cds/v1/tokenize/card';
function isValidSmartGlocalTokenizeUrl(tokenizeUrl: string) {
if (tokenizeUrl !== tokenizeUrl.trim()) {
return false;
}
let parsedUrl: URL;
try {
parsedUrl = new URL(tokenizeUrl);
} catch {
return false;
}
const { protocol, hostname, pathname, port, username, password } = parsedUrl;
const isSmartGlocalHost = hostname === SMART_GLOCAL_DOMAIN || hostname.endsWith(`.${SMART_GLOCAL_DOMAIN}`);
return protocol === 'https:'
&& isSmartGlocalHost
&& pathname === SMART_GLOCAL_TOKENIZE_PATH
&& !port
&& !username
&& !password;
}
addActionHandler('validateRequestedInfo', (global, actions, payload): ActionReturnType => { addActionHandler('validateRequestedInfo', (global, actions, payload): ActionReturnType => {
const { requestInfo, saveInfo, tabId = getCurrentTabId() } = payload; const { requestInfo, saveInfo, tabId = getCurrentTabId() } = payload;
@ -429,8 +454,7 @@ async function sendSmartGlocalCredentials<T extends GlobalState>(
url = 'https://tgb.smart-glocal.com/cds/v1/tokenize/card'; url = 'https://tgb.smart-glocal.com/cds/v1/tokenize/card';
} }
if (tokenizeUrl?.startsWith('https://') if (tokenizeUrl && isValidSmartGlocalTokenizeUrl(tokenizeUrl)) {
&& tokenizeUrl.endsWith('.smart-glocal.com/cds/v1/tokenize/card')) {
url = tokenizeUrl; url = tokenizeUrl;
} }

View File

@ -239,14 +239,14 @@ interface WebAppOutboundEventMap {
location_checked: location_checked:
| { available: false } | { available: false }
| { | {
available: boolean; available: true;
access_requested: boolean; access_requested: boolean;
access_granted?: boolean; access_granted?: boolean;
}; };
location_requested: location_requested:
| { available: boolean } | { available: false }
| { | {
available: boolean; available: true;
latitude: number; latitude: number;
longitude: number; longitude: number;
altitude: number | null; altitude: number | null;