Support redirects from t.me (websync) (#1383)
This commit is contained in:
parent
6fa2fae909
commit
ae0ad36478
@ -73,6 +73,7 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet {
|
|||||||
thumbs,
|
thumbs,
|
||||||
count,
|
count,
|
||||||
hash,
|
hash,
|
||||||
|
shortName,
|
||||||
} = set;
|
} = set;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -85,6 +86,7 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet {
|
|||||||
hasThumbnail: Boolean(thumbs && thumbs.length),
|
hasThumbnail: Boolean(thumbs && thumbs.length),
|
||||||
count,
|
count,
|
||||||
hash,
|
hash,
|
||||||
|
shortName,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -113,6 +113,12 @@ export function buildInputStickerSet(id: string, accessHash: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildInputStickerSetShortName(shortName: string) {
|
||||||
|
return new GramJs.InputStickerSetShortName({
|
||||||
|
shortName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function buildInputDocument(media: ApiSticker | ApiVideo) {
|
export function buildInputDocument(media: ApiSticker | ApiVideo) {
|
||||||
const document = localDb.documents[media.id];
|
const document = localDb.documents[media.id];
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { ApiSticker, ApiVideo, OnApiUpdate } from '../../types';
|
|||||||
|
|
||||||
import { invokeRequest } from './client';
|
import { invokeRequest } from './client';
|
||||||
import { buildStickerFromDocument, buildStickerSet, buildStickerSetCovered } from '../apiBuilders/symbols';
|
import { buildStickerFromDocument, buildStickerSet, buildStickerSetCovered } from '../apiBuilders/symbols';
|
||||||
import { buildInputStickerSet, buildInputDocument } from '../gramjsBuilders';
|
import { buildInputStickerSet, buildInputDocument, buildInputStickerSetShortName } from '../gramjsBuilders';
|
||||||
import { buildVideoFromDocument } from '../apiBuilders/messages';
|
import { buildVideoFromDocument } from '../apiBuilders/messages';
|
||||||
import { RECENT_STICKERS_LIMIT } from '../../../config';
|
import { RECENT_STICKERS_LIMIT } from '../../../config';
|
||||||
|
|
||||||
@ -93,9 +93,12 @@ export async function faveSticker({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchStickers({ stickerSetId, accessHash }: { stickerSetId: string; accessHash: string }) {
|
export async function fetchStickers({ stickerSetShortName, stickerSetId, accessHash }:
|
||||||
|
{ stickerSetShortName?: string; stickerSetId?: string; accessHash: string }) {
|
||||||
const result = await invokeRequest(new GramJs.messages.GetStickerSet({
|
const result = await invokeRequest(new GramJs.messages.GetStickerSet({
|
||||||
stickerset: buildInputStickerSet(stickerSetId, accessHash),
|
stickerset: stickerSetId
|
||||||
|
? buildInputStickerSet(stickerSetId, accessHash)
|
||||||
|
: buildInputStickerSetShortName(stickerSetShortName!),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
|||||||
@ -43,6 +43,7 @@ export interface ApiStickerSet {
|
|||||||
stickers?: ApiSticker[];
|
stickers?: ApiSticker[];
|
||||||
packs?: Record<string, ApiSticker[]>;
|
packs?: Record<string, ApiSticker[]>;
|
||||||
covers?: ApiSticker[];
|
covers?: ApiSticker[];
|
||||||
|
shortName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiVideo {
|
export interface ApiVideo {
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { GlobalActions } from '../../global/types';
|
|||||||
|
|
||||||
import { STICKER_SIZE_MODAL } from '../../config';
|
import { STICKER_SIZE_MODAL } from '../../config';
|
||||||
import { pick } from '../../util/iteratees';
|
import { pick } from '../../util/iteratees';
|
||||||
import { selectStickerSet } from '../../modules/selectors';
|
import { selectStickerSet, selectStickerSetByShortName } from '../../modules/selectors';
|
||||||
import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
|
import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
|
||||||
import useLang from '../../hooks/useLang';
|
import useLang from '../../hooks/useLang';
|
||||||
import renderText from './helpers/renderText';
|
import renderText from './helpers/renderText';
|
||||||
@ -22,7 +22,8 @@ import './StickerSetModal.scss';
|
|||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
fromSticker: ApiSticker;
|
fromSticker?: ApiSticker;
|
||||||
|
stickerSetShortName?: string;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ const INTERSECTION_THROTTLE = 200;
|
|||||||
const StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({
|
const StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
fromSticker,
|
fromSticker,
|
||||||
|
stickerSetShortName,
|
||||||
stickerSet,
|
stickerSet,
|
||||||
onClose,
|
onClose,
|
||||||
loadStickers,
|
loadStickers,
|
||||||
@ -53,10 +55,19 @@ const StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
const { stickerSetId, stickerSetAccessHash } = fromSticker;
|
if (fromSticker) {
|
||||||
loadStickers({ stickerSetId, stickerSetAccessHash });
|
const { stickerSetId, stickerSetAccessHash } = fromSticker;
|
||||||
|
loadStickers({
|
||||||
|
stickerSetId,
|
||||||
|
stickerSetAccessHash,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
loadStickers({
|
||||||
|
stickerSetShortName,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [isOpen, fromSticker, loadStickers]);
|
}, [isOpen, fromSticker, loadStickers, stickerSetShortName]);
|
||||||
|
|
||||||
const handleSelect = useCallback((sticker: ApiSticker) => {
|
const handleSelect = useCallback((sticker: ApiSticker) => {
|
||||||
sticker = {
|
sticker = {
|
||||||
@ -69,9 +80,11 @@ const StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
}, [onClose, sendMessage]);
|
}, [onClose, sendMessage]);
|
||||||
|
|
||||||
const handleButtonClick = useCallback(() => {
|
const handleButtonClick = useCallback(() => {
|
||||||
toggleStickerSet({ stickerSetId: fromSticker.stickerSetId });
|
if (stickerSet) {
|
||||||
onClose();
|
toggleStickerSet({ stickerSetId: stickerSet.id });
|
||||||
}, [fromSticker.stickerSetId, onClose, toggleStickerSet]);
|
onClose();
|
||||||
|
}
|
||||||
|
}, [onClose, stickerSet, toggleStickerSet]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -117,8 +130,12 @@ const StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default memo(withGlobal(
|
export default memo(withGlobal(
|
||||||
(global, { fromSticker }: OwnProps) => {
|
(global, { fromSticker, stickerSetShortName }: OwnProps) => {
|
||||||
return { stickerSet: selectStickerSet(global, fromSticker.stickerSetId) };
|
return {
|
||||||
|
stickerSet: fromSticker
|
||||||
|
? selectStickerSet(global, fromSticker.stickerSetId)
|
||||||
|
: selectStickerSetByShortName(global, stickerSetShortName!),
|
||||||
|
};
|
||||||
},
|
},
|
||||||
(setGlobal, actions): DispatchProps => pick(actions, [
|
(setGlobal, actions): DispatchProps => pick(actions, [
|
||||||
'loadStickers',
|
'loadStickers',
|
||||||
|
|||||||
@ -27,6 +27,8 @@ import useShowTransition from '../../hooks/useShowTransition';
|
|||||||
import useBackgroundMode from '../../hooks/useBackgroundMode';
|
import useBackgroundMode from '../../hooks/useBackgroundMode';
|
||||||
import useBeforeUnload from '../../hooks/useBeforeUnload';
|
import useBeforeUnload from '../../hooks/useBeforeUnload';
|
||||||
import useOnChange from '../../hooks/useOnChange';
|
import useOnChange from '../../hooks/useOnChange';
|
||||||
|
import { processDeepLink } from '../../util/deeplink';
|
||||||
|
import { LOCATION_HASH } from '../../hooks/useHistoryBack';
|
||||||
|
|
||||||
import LeftColumn from '../left/LeftColumn';
|
import LeftColumn from '../left/LeftColumn';
|
||||||
import MiddleColumn from '../middle/MiddleColumn';
|
import MiddleColumn from '../middle/MiddleColumn';
|
||||||
@ -38,6 +40,7 @@ import Dialogs from './Dialogs.async';
|
|||||||
import ForwardPicker from './ForwardPicker.async';
|
import ForwardPicker from './ForwardPicker.async';
|
||||||
import SafeLinkModal from './SafeLinkModal.async';
|
import SafeLinkModal from './SafeLinkModal.async';
|
||||||
import HistoryCalendar from './HistoryCalendar.async';
|
import HistoryCalendar from './HistoryCalendar.async';
|
||||||
|
import StickerSetModal from '../common/StickerSetModal.async';
|
||||||
|
|
||||||
import './Main.scss';
|
import './Main.scss';
|
||||||
|
|
||||||
@ -55,11 +58,12 @@ type StateProps = {
|
|||||||
isHistoryCalendarOpen: boolean;
|
isHistoryCalendarOpen: boolean;
|
||||||
shouldSkipHistoryAnimations?: boolean;
|
shouldSkipHistoryAnimations?: boolean;
|
||||||
language?: LangCode;
|
language?: LangCode;
|
||||||
|
openedStickerSetShortName?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, (
|
type DispatchProps = Pick<GlobalActions, (
|
||||||
'loadAnimatedEmojis' | 'loadNotificationSettings' | 'loadNotificationExceptions' | 'updateIsOnline' |
|
'loadAnimatedEmojis' | 'loadNotificationSettings' | 'loadNotificationExceptions' | 'updateIsOnline' |
|
||||||
'loadTopInlineBots' | 'loadEmojiKeywords'
|
'loadTopInlineBots' | 'loadEmojiKeywords' | 'openStickerSetShortName'
|
||||||
)>;
|
)>;
|
||||||
|
|
||||||
const NOTIFICATION_INTERVAL = 1000;
|
const NOTIFICATION_INTERVAL = 1000;
|
||||||
@ -82,12 +86,14 @@ const Main: FC<StateProps & DispatchProps> = ({
|
|||||||
isHistoryCalendarOpen,
|
isHistoryCalendarOpen,
|
||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
language,
|
language,
|
||||||
|
openedStickerSetShortName,
|
||||||
loadAnimatedEmojis,
|
loadAnimatedEmojis,
|
||||||
loadNotificationSettings,
|
loadNotificationSettings,
|
||||||
loadNotificationExceptions,
|
loadNotificationExceptions,
|
||||||
updateIsOnline,
|
updateIsOnline,
|
||||||
loadTopInlineBots,
|
loadTopInlineBots,
|
||||||
loadEmojiKeywords,
|
loadEmojiKeywords,
|
||||||
|
openStickerSetShortName,
|
||||||
}) => {
|
}) => {
|
||||||
if (DEBUG && !DEBUG_isLogged) {
|
if (DEBUG && !DEBUG_isLogged) {
|
||||||
DEBUG_isLogged = true;
|
DEBUG_isLogged = true;
|
||||||
@ -114,6 +120,12 @@ const Main: FC<StateProps & DispatchProps> = ({
|
|||||||
loadTopInlineBots, loadEmojiKeywords, language,
|
loadTopInlineBots, loadEmojiKeywords, language,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (lastSyncTime && LOCATION_HASH.startsWith('#?tgaddr=')) {
|
||||||
|
processDeepLink(decodeURIComponent(LOCATION_HASH.substr('#?tgaddr='.length)));
|
||||||
|
}
|
||||||
|
}, [lastSyncTime]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
transitionClassNames: middleColumnTransitionClassNames,
|
transitionClassNames: middleColumnTransitionClassNames,
|
||||||
} = useShowTransition(!isLeftColumnShown, undefined, true, undefined, shouldSkipHistoryAnimations);
|
} = useShowTransition(!isLeftColumnShown, undefined, true, undefined, shouldSkipHistoryAnimations);
|
||||||
@ -223,6 +235,11 @@ const Main: FC<StateProps & DispatchProps> = ({
|
|||||||
{audioMessage && <AudioPlayer key={audioMessage.id} message={audioMessage} noUi />}
|
{audioMessage && <AudioPlayer key={audioMessage.id} message={audioMessage} noUi />}
|
||||||
<SafeLinkModal url={safeLinkModalUrl} />
|
<SafeLinkModal url={safeLinkModalUrl} />
|
||||||
<HistoryCalendar isOpen={isHistoryCalendarOpen} />
|
<HistoryCalendar isOpen={isHistoryCalendarOpen} />
|
||||||
|
<StickerSetModal
|
||||||
|
isOpen={!!openedStickerSetShortName}
|
||||||
|
onClose={() => openStickerSetShortName({ stickerSetShortName: undefined })}
|
||||||
|
stickerSetShortName={openedStickerSetShortName}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -269,10 +286,11 @@ export default memo(withGlobal(
|
|||||||
isHistoryCalendarOpen: Boolean(global.historyCalendarSelectedAt),
|
isHistoryCalendarOpen: Boolean(global.historyCalendarSelectedAt),
|
||||||
shouldSkipHistoryAnimations: global.shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations: global.shouldSkipHistoryAnimations,
|
||||||
language: global.settings.byKey.language,
|
language: global.settings.byKey.language,
|
||||||
|
openedStickerSetShortName: global.openedStickerSetShortName,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
(setGlobal, actions): DispatchProps => pick(actions, [
|
(setGlobal, actions): DispatchProps => pick(actions, [
|
||||||
'loadAnimatedEmojis', 'loadNotificationSettings', 'loadNotificationExceptions', 'updateIsOnline',
|
'loadAnimatedEmojis', 'loadNotificationSettings', 'loadNotificationExceptions', 'updateIsOnline',
|
||||||
'loadTopInlineBots', 'loadEmojiKeywords',
|
'loadTopInlineBots', 'loadEmojiKeywords', 'openStickerSetShortName',
|
||||||
]),
|
]),
|
||||||
)(Main));
|
)(Main));
|
||||||
|
|||||||
@ -421,6 +421,7 @@ export type GlobalState = {
|
|||||||
|
|
||||||
safeLinkModalUrl?: string;
|
safeLinkModalUrl?: string;
|
||||||
historyCalendarSelectedAt?: number;
|
historyCalendarSelectedAt?: number;
|
||||||
|
openedStickerSetShortName?: string;
|
||||||
|
|
||||||
// TODO To be removed in August 2021
|
// TODO To be removed in August 2021
|
||||||
shouldShowContextMenuHint?: boolean;
|
shouldShowContextMenuHint?: boolean;
|
||||||
@ -491,6 +492,7 @@ export type ActionTypes = (
|
|||||||
'loadStickers' | 'setStickerSearchQuery' | 'loadSavedGifs' | 'setGifSearchQuery' | 'searchMoreGifs' |
|
'loadStickers' | 'setStickerSearchQuery' | 'loadSavedGifs' | 'setGifSearchQuery' | 'searchMoreGifs' |
|
||||||
'faveSticker' | 'unfaveSticker' | 'toggleStickerSet' | 'loadAnimatedEmojis' |
|
'faveSticker' | 'unfaveSticker' | 'toggleStickerSet' | 'loadAnimatedEmojis' |
|
||||||
'loadStickersForEmoji' | 'clearStickersForEmoji' | 'loadEmojiKeywords' | 'loadGreetingStickers' |
|
'loadStickersForEmoji' | 'clearStickersForEmoji' | 'loadEmojiKeywords' | 'loadGreetingStickers' |
|
||||||
|
'openStickerSetShortName' |
|
||||||
// bots
|
// bots
|
||||||
'clickInlineButton' | 'sendBotCommand' | 'loadTopInlineBots' | 'queryInlineBot' | 'sendInlineBotResult' |
|
'clickInlineButton' | 'sendBotCommand' | 'loadTopInlineBots' | 'queryInlineBot' | 'sendInlineBotResult' |
|
||||||
'resetInlineBot' | 'restartBot' |
|
'resetInlineBot' | 'restartBot' |
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { areSortedArraysEqual } from '../util/iteratees';
|
|||||||
// TODO: may be different on other devices such as iPad, maybe take dpi into account?
|
// TODO: may be different on other devices such as iPad, maybe take dpi into account?
|
||||||
const SAFARI_EDGE_BACK_GESTURE_LIMIT = 300;
|
const SAFARI_EDGE_BACK_GESTURE_LIMIT = 300;
|
||||||
const SAFARI_EDGE_BACK_GESTURE_DURATION = 350;
|
const SAFARI_EDGE_BACK_GESTURE_DURATION = 350;
|
||||||
|
export const LOCATION_HASH = window.location.hash;
|
||||||
|
|
||||||
type HistoryState = {
|
type HistoryState = {
|
||||||
currentIndex: number;
|
currentIndex: number;
|
||||||
@ -54,7 +55,7 @@ if (IS_IOS) {
|
|||||||
window.addEventListener('popstate', handleTouchEnd);
|
window.addEventListener('popstate', handleTouchEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.history.replaceState({ index: historyState.currentIndex }, '');
|
window.history.replaceState({ index: historyState.currentIndex }, '', window.location.pathname);
|
||||||
|
|
||||||
export default function useHistoryBack(
|
export default function useHistoryBack(
|
||||||
isActive: boolean | undefined,
|
isActive: boolean | undefined,
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import {
|
|||||||
importLegacySession,
|
importLegacySession,
|
||||||
clearLegacySessions,
|
clearLegacySessions,
|
||||||
} from '../../../util/sessions';
|
} from '../../../util/sessions';
|
||||||
|
import { forceWebsync } from '../../../util/websync';
|
||||||
|
|
||||||
addReducer('initApi', (global: GlobalState, actions) => {
|
addReducer('initApi', (global: GlobalState, actions) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@ -128,6 +129,7 @@ addReducer('signOut', () => {
|
|||||||
try {
|
try {
|
||||||
await unsubscribe();
|
await unsubscribe();
|
||||||
await callApi('destroy');
|
await callApi('destroy');
|
||||||
|
await forceWebsync(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,10 +83,10 @@ addReducer('loadFeaturedStickers', (global) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
addReducer('loadStickers', (global, actions, payload) => {
|
addReducer('loadStickers', (global, actions, payload) => {
|
||||||
const { stickerSetId } = payload!;
|
const { stickerSetId, stickerSetShortName } = payload!;
|
||||||
let { stickerSetAccessHash } = payload!;
|
let { stickerSetAccessHash } = payload!;
|
||||||
|
|
||||||
if (!stickerSetAccessHash) {
|
if (!stickerSetAccessHash && !stickerSetShortName) {
|
||||||
const stickerSet = selectStickerSet(global, stickerSetId);
|
const stickerSet = selectStickerSet(global, stickerSetId);
|
||||||
if (!stickerSet) {
|
if (!stickerSet) {
|
||||||
return;
|
return;
|
||||||
@ -95,7 +95,7 @@ addReducer('loadStickers', (global, actions, payload) => {
|
|||||||
stickerSetAccessHash = stickerSet.accessHash;
|
stickerSetAccessHash = stickerSet.accessHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadStickers(stickerSetId, stickerSetAccessHash);
|
void loadStickers(stickerSetId, stickerSetAccessHash, stickerSetShortName);
|
||||||
});
|
});
|
||||||
|
|
||||||
addReducer('loadAnimatedEmojis', () => {
|
addReducer('loadAnimatedEmojis', () => {
|
||||||
@ -257,8 +257,9 @@ async function loadFeaturedStickers(hash = 0) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadStickers(stickerSetId: string, accessHash: string) {
|
async function loadStickers(stickerSetId: string, accessHash: string, stickerSetShortName?: string) {
|
||||||
const stickerSet = await callApi('fetchStickers', { stickerSetId, accessHash });
|
const stickerSet = await callApi('fetchStickers',
|
||||||
|
{ stickerSetShortName, stickerSetId, accessHash });
|
||||||
if (!stickerSet) {
|
if (!stickerSet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -356,6 +357,14 @@ addReducer('clearStickersForEmoji', (global) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addReducer('openStickerSetShortName', (global, actions, payload) => {
|
||||||
|
const { stickerSetShortName } = payload!;
|
||||||
|
return {
|
||||||
|
...global,
|
||||||
|
openedStickerSetShortName: stickerSetShortName,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
async function searchStickers(query: string, hash = 0) {
|
async function searchStickers(query: string, hash = 0) {
|
||||||
const result = await callApi('searchStickers', { query, hash });
|
const result = await callApi('searchStickers', { query, hash });
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import { subscribe } from '../../../util/notifications';
|
|||||||
import { updateUser } from '../../reducers';
|
import { updateUser } from '../../reducers';
|
||||||
import { setLanguage } from '../../../util/langProvider';
|
import { setLanguage } from '../../../util/langProvider';
|
||||||
import { selectNotifySettings } from '../../selectors';
|
import { selectNotifySettings } from '../../selectors';
|
||||||
|
import { forceWebsync } from '../../../util/websync';
|
||||||
|
|
||||||
addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@ -90,6 +91,8 @@ function onUpdateAuthorizationState(update: ApiUpdateAuthorizationState) {
|
|||||||
|
|
||||||
switch (authState) {
|
switch (authState) {
|
||||||
case 'authorizationStateLoggingOut':
|
case 'authorizationStateLoggingOut':
|
||||||
|
void forceWebsync(false);
|
||||||
|
|
||||||
setGlobal({
|
setGlobal({
|
||||||
...global,
|
...global,
|
||||||
isLoggingOut: true,
|
isLoggingOut: true,
|
||||||
@ -119,6 +122,8 @@ function onUpdateAuthorizationState(update: ApiUpdateAuthorizationState) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void forceWebsync(true);
|
||||||
|
|
||||||
setGlobal({
|
setGlobal({
|
||||||
...global,
|
...global,
|
||||||
isLoggingOut: false,
|
isLoggingOut: false,
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
import { setLanguage } from '../../../util/langProvider';
|
import { setLanguage } from '../../../util/langProvider';
|
||||||
import switchTheme from '../../../util/switchTheme';
|
import switchTheme from '../../../util/switchTheme';
|
||||||
import { selectTheme } from '../../selectors';
|
import { selectTheme } from '../../selectors';
|
||||||
|
import { startWebsync } from '../../../util/websync';
|
||||||
|
|
||||||
const HISTORY_ANIMATION_DURATION = 450;
|
const HISTORY_ANIMATION_DURATION = 450;
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ addReducer('init', (global) => {
|
|||||||
document.body.classList.add(`animation-level-${animationLevel}`);
|
document.body.classList.add(`animation-level-${animationLevel}`);
|
||||||
document.body.classList.add(IS_TOUCH_ENV ? 'is-touch-env' : 'is-pointer-env');
|
document.body.classList.add(IS_TOUCH_ENV ? 'is-touch-env' : 'is-pointer-env');
|
||||||
switchTheme(theme, animationLevel === ANIMATION_LEVEL_MAX);
|
switchTheme(theme, animationLevel === ANIMATION_LEVEL_MAX);
|
||||||
|
startWebsync();
|
||||||
|
|
||||||
if (IS_SAFARI) {
|
if (IS_SAFARI) {
|
||||||
document.body.classList.add('is-safari');
|
document.body.classList.add('is-safari');
|
||||||
|
|||||||
@ -18,6 +18,10 @@ export function selectStickerSet(global: GlobalState, id: string) {
|
|||||||
return global.stickers.setsById[id];
|
return global.stickers.setsById[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectStickerSetByShortName(global: GlobalState, shortName: string) {
|
||||||
|
return Object.values(global.stickers.setsById).find((l) => l.shortName.toLowerCase() === shortName.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
export function selectStickersForEmoji(global: GlobalState, emoji: string) {
|
export function selectStickersForEmoji(global: GlobalState, emoji: string) {
|
||||||
const stickerSets = Object.values(global.stickers.setsById);
|
const stickerSets = Object.values(global.stickers.setsById);
|
||||||
let stickersForEmoji: ApiSticker[] = [];
|
let stickersForEmoji: ApiSticker[] = [];
|
||||||
|
|||||||
@ -30,9 +30,13 @@ self.addEventListener('activate', (e) => {
|
|||||||
|
|
||||||
// eslint-disable-next-line no-restricted-globals
|
// eslint-disable-next-line no-restricted-globals
|
||||||
self.addEventListener('fetch', (e: FetchEvent) => {
|
self.addEventListener('fetch', (e: FetchEvent) => {
|
||||||
e.respondWith((() => {
|
const { url } = e.request;
|
||||||
const { url } = e.request;
|
|
||||||
|
|
||||||
|
if (url.includes('_websync_')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.respondWith((() => {
|
||||||
if (url.includes('/progressive/')) {
|
if (url.includes('/progressive/')) {
|
||||||
return respondForProgressive(e);
|
return respondForProgressive(e);
|
||||||
}
|
}
|
||||||
@ -43,6 +47,8 @@ self.addEventListener('fetch', (e: FetchEvent) => {
|
|||||||
|
|
||||||
return fetch(e.request);
|
return fetch(e.request);
|
||||||
})());
|
})());
|
||||||
|
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('push', handlePush);
|
self.addEventListener('push', handlePush);
|
||||||
|
|||||||
54
src/util/deeplink.ts
Normal file
54
src/util/deeplink.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { getDispatch } from '../lib/teact/teactn';
|
||||||
|
|
||||||
|
export const processDeepLink = (url: string) => {
|
||||||
|
const { protocol, searchParams, pathname } = new URL(url);
|
||||||
|
|
||||||
|
if (protocol !== 'tg:') return;
|
||||||
|
|
||||||
|
const { openChatByUsername, openStickerSetShortName } = getDispatch();
|
||||||
|
|
||||||
|
const method = pathname.replace(/^\/\//, '');
|
||||||
|
const params: Record<string, string> = {};
|
||||||
|
searchParams.forEach((value, key) => {
|
||||||
|
params[key] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
case 'resolve': {
|
||||||
|
const {
|
||||||
|
domain,
|
||||||
|
} = params;
|
||||||
|
|
||||||
|
if (domain !== 'telegrampassport') {
|
||||||
|
openChatByUsername({
|
||||||
|
username: domain,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'privatepost':
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'bg':
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'join':
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'addstickers': {
|
||||||
|
const { set } = params;
|
||||||
|
|
||||||
|
openStickerSetShortName({
|
||||||
|
stickerSetShortName: set,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'msg':
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unsupported deeplink
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
82
src/util/websync.ts
Normal file
82
src/util/websync.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { APP_VERSION } from '../config';
|
||||||
|
import { getGlobal } from '../lib/teact/teactn';
|
||||||
|
import { hasStoredSession } from './sessions';
|
||||||
|
|
||||||
|
const WEBSYNC_URLS = [
|
||||||
|
't.me',
|
||||||
|
'telegram.me',
|
||||||
|
].map((domain) => `//${domain}/_websync_?`);
|
||||||
|
const WEBSYNC_VERSION = `${APP_VERSION} Z`;
|
||||||
|
const WEBSYNC_KEY = 'tgme_sync';
|
||||||
|
const WEBSYNC_TIMEOUT = 86400;
|
||||||
|
|
||||||
|
const getTs = () => {
|
||||||
|
return Math.floor(Number(new Date()) / 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveSync = (authed: boolean) => {
|
||||||
|
const ts = getTs();
|
||||||
|
localStorage.setItem(WEBSYNC_KEY, JSON.stringify({
|
||||||
|
canRedirect: authed,
|
||||||
|
ts,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
let lastTimeout: NodeJS.Timeout | undefined;
|
||||||
|
|
||||||
|
export const forceWebsync = (authed: boolean) => {
|
||||||
|
const currentTs = getTs();
|
||||||
|
|
||||||
|
const { canRedirect, ts } = JSON.parse(localStorage.getItem(WEBSYNC_KEY) || '{}');
|
||||||
|
|
||||||
|
if (canRedirect !== authed || ts + WEBSYNC_TIMEOUT <= currentTs) {
|
||||||
|
return Promise.all(WEBSYNC_URLS.map((url) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
|
||||||
|
const removeElement = () => !!document.body.removeChild(script);
|
||||||
|
|
||||||
|
script.src = url + new URLSearchParams({
|
||||||
|
authed: Number(authed).toString(),
|
||||||
|
version: WEBSYNC_VERSION,
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.appendChild(script);
|
||||||
|
|
||||||
|
script.onload = () => {
|
||||||
|
saveSync(authed);
|
||||||
|
removeElement();
|
||||||
|
if (lastTimeout) {
|
||||||
|
clearTimeout(lastTimeout);
|
||||||
|
lastTimeout = undefined;
|
||||||
|
}
|
||||||
|
startWebsync();
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
script.onerror = () => {
|
||||||
|
removeElement();
|
||||||
|
reject();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function startWebsync() {
|
||||||
|
if (lastTimeout !== undefined) return;
|
||||||
|
const currentTs = getTs();
|
||||||
|
|
||||||
|
const { ts } = JSON.parse(localStorage.getItem(WEBSYNC_KEY) || '{}');
|
||||||
|
|
||||||
|
const timeout = WEBSYNC_TIMEOUT - (currentTs - ts);
|
||||||
|
|
||||||
|
lastTimeout = setTimeout(() => {
|
||||||
|
const { authState } = getGlobal();
|
||||||
|
|
||||||
|
const authed = authState === 'authorizationStateReady' || hasStoredSession(true);
|
||||||
|
forceWebsync(authed);
|
||||||
|
}, Math.max(0, timeout * 1000));
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user