Multitab: Follow-up
This commit is contained in:
parent
847139e7ce
commit
cdad1bc867
@ -186,7 +186,7 @@ export default withGlobal<OwnProps>(
|
|||||||
shouldSkipHistoryAnimations: tabState.shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations: tabState.shouldSkipHistoryAnimations,
|
||||||
uiReadyState: tabState.uiReadyState,
|
uiReadyState: tabState.uiReadyState,
|
||||||
isRightColumnShown: selectIsRightColumnShown(global, isMobile),
|
isRightColumnShown: selectIsRightColumnShown(global, isMobile),
|
||||||
leftColumnWidth: tabState.leftColumnWidth,
|
leftColumnWidth: global.leftColumnWidth,
|
||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@ -488,11 +488,11 @@ export default memo(withGlobal(
|
|||||||
date,
|
date,
|
||||||
},
|
},
|
||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
leftColumnWidth,
|
|
||||||
activeChatFolder,
|
activeChatFolder,
|
||||||
nextSettingsScreen,
|
nextSettingsScreen,
|
||||||
} = tabState;
|
} = tabState;
|
||||||
const {
|
const {
|
||||||
|
leftColumnWidth,
|
||||||
currentUserId,
|
currentUserId,
|
||||||
passcode: {
|
passcode: {
|
||||||
hasPasscode,
|
hasPasscode,
|
||||||
|
|||||||
@ -152,7 +152,7 @@ const ChatList: FC<OwnProps> = ({
|
|||||||
const expendedOffsetTop = currentChatListHeight;
|
const expendedOffsetTop = currentChatListHeight;
|
||||||
const collapsedOffsetTop = (viewportOffset + i) * CHAT_HEIGHT_PX;
|
const collapsedOffsetTop = (viewportOffset + i) * CHAT_HEIGHT_PX;
|
||||||
|
|
||||||
currentChatListHeight += (selectChat(global, id)!.isForum ? CHAT_HEIGHT_FORUM_PX : CHAT_HEIGHT_PX);
|
currentChatListHeight += (selectChat(global, id)?.isForum ? CHAT_HEIGHT_FORUM_PX : CHAT_HEIGHT_PX);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Chat
|
<Chat
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import {
|
|||||||
selectTabState,
|
selectTabState,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { init as initFolderManager } from '../../../util/folderManager';
|
import { init as initFolderManager } from '../../../util/folderManager';
|
||||||
|
import { updateTabState } from '../../reducers/tabs';
|
||||||
|
|
||||||
const RELEASE_STATUS_TIMEOUT = 15000; // 15 sec;
|
const RELEASE_STATUS_TIMEOUT = 15000; // 15 sec;
|
||||||
|
|
||||||
@ -96,6 +97,8 @@ async function loadAndReplaceMessages<T extends GlobalState>(global: T, actions:
|
|||||||
|
|
||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
|
|
||||||
|
let wasReset = false;
|
||||||
|
|
||||||
for (const { id: tabId } of Object.values(global.byTabId)) {
|
for (const { id: tabId } of Object.values(global.byTabId)) {
|
||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
const { chatId: currentChatId, threadId: currentThreadId } = selectCurrentMessageList(global, tabId) || {};
|
const { chatId: currentChatId, threadId: currentThreadId } = selectCurrentMessageList(global, tabId) || {};
|
||||||
@ -137,9 +140,32 @@ async function loadAndReplaceMessages<T extends GlobalState>(global: T, actions:
|
|||||||
const byId = buildCollectionByKey(allMessages, 'id');
|
const byId = buildCollectionByKey(allMessages, 'id');
|
||||||
const listedIds = Object.keys(byId).map(Number);
|
const listedIds = Object.keys(byId).map(Number);
|
||||||
|
|
||||||
|
if (!wasReset) {
|
||||||
|
global = {
|
||||||
|
...global,
|
||||||
|
messages: {
|
||||||
|
...global.messages,
|
||||||
|
byChatId: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
||||||
|
Object.values(global.byTabId).forEach(({ id: otherTabId }) => {
|
||||||
|
global = updateTabState(global, {
|
||||||
|
tabThreads: {},
|
||||||
|
}, otherTabId);
|
||||||
|
});
|
||||||
|
wasReset = true;
|
||||||
|
}
|
||||||
|
|
||||||
global = addChatMessagesById(global, activeCurrentChatId, byId);
|
global = addChatMessagesById(global, activeCurrentChatId, byId);
|
||||||
global = updateListedIds(global, activeCurrentChatId, activeThreadId, listedIds);
|
global = updateListedIds(global, activeCurrentChatId, activeThreadId, listedIds);
|
||||||
global = safeReplaceViewportIds(global, activeCurrentChatId, activeThreadId, listedIds, tabId);
|
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
||||||
|
Object.values(global.byTabId).forEach(({ id: otherTabId }) => {
|
||||||
|
const { chatId: otherChatId, threadId: otherThreadId } = selectCurrentMessageList(global, otherTabId) || {};
|
||||||
|
if (otherChatId === activeCurrentChatId && otherThreadId === activeThreadId) {
|
||||||
|
global = safeReplaceViewportIds(global, activeCurrentChatId, activeThreadId, listedIds, otherTabId);
|
||||||
|
}
|
||||||
|
});
|
||||||
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
|
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
|
||||||
global = updateUsers(global, buildCollectionByKey(result.users, 'id'));
|
global = updateUsers(global, buildCollectionByKey(result.users, 'id'));
|
||||||
global = updateThreadInfos(global, activeCurrentChatId, result.repliesThreadInfos);
|
global = updateThreadInfos(global, activeCurrentChatId, result.repliesThreadInfos);
|
||||||
@ -176,6 +202,14 @@ async function loadAndReplaceMessages<T extends GlobalState>(global: T, actions:
|
|||||||
byChatId: {},
|
byChatId: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
||||||
|
Object.values(global.byTabId).forEach(({ id: otherTabId }) => {
|
||||||
|
global = updateTabState(global, {
|
||||||
|
tabThreads: {},
|
||||||
|
}, otherTabId);
|
||||||
|
});
|
||||||
|
|
||||||
|
setGlobal(global);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.values(global.byTabId).forEach(({ id: tabId }) => {
|
Object.values(global.byTabId).forEach(({ id: tabId }) => {
|
||||||
|
|||||||
@ -749,7 +749,7 @@ addActionHandler('openReactorListModal', (global, actions, payload): ActionRetur
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('closeReactorListModal', (global, actions, payload): ActionReturnType => {
|
addActionHandler('closeReactorListModal', (global, actions, payload): ActionReturnType => {
|
||||||
const { tabId = getCurrentTabId() } = payload;
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
|
|
||||||
return updateTabState(global, {
|
return updateTabState(global, {
|
||||||
reactorModal: undefined,
|
reactorModal: undefined,
|
||||||
@ -765,7 +765,7 @@ addActionHandler('openSeenByModal', (global, actions, payload): ActionReturnType
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('closeSeenByModal', (global, actions, payload): ActionReturnType => {
|
addActionHandler('closeSeenByModal', (global, actions, payload): ActionReturnType => {
|
||||||
const { tabId = getCurrentTabId() } = payload;
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
|
|
||||||
return updateTabState(global, {
|
return updateTabState(global, {
|
||||||
seenByModal: undefined,
|
seenByModal: undefined,
|
||||||
|
|||||||
@ -32,18 +32,19 @@ addActionHandler('toggleChatInfo', (global, actions, payload): ActionReturnType
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('setLeftColumnWidth', (global, actions, payload): ActionReturnType => {
|
addActionHandler('setLeftColumnWidth', (global, actions, payload): ActionReturnType => {
|
||||||
const { leftColumnWidth, tabId = getCurrentTabId() } = payload;
|
const { leftColumnWidth } = payload;
|
||||||
|
|
||||||
return updateTabState(global, {
|
return {
|
||||||
|
...global,
|
||||||
leftColumnWidth,
|
leftColumnWidth,
|
||||||
}, tabId);
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('resetLeftColumnWidth', (global, actions, payload): ActionReturnType => {
|
addActionHandler('resetLeftColumnWidth', (global): ActionReturnType => {
|
||||||
const { tabId = getCurrentTabId() } = payload || {};
|
return {
|
||||||
return updateTabState(global, {
|
...global,
|
||||||
leftColumnWidth: undefined,
|
leftColumnWidth: undefined,
|
||||||
}, tabId);
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('toggleManagement', (global, actions, payload): ActionReturnType => {
|
addActionHandler('toggleManagement', (global, actions, payload): ActionReturnType => {
|
||||||
|
|||||||
@ -383,6 +383,7 @@ export function serializeGlobal<T extends GlobalState>(global: T) {
|
|||||||
'push',
|
'push',
|
||||||
'serviceNotifications',
|
'serviceNotifications',
|
||||||
'attachmentSettings',
|
'attachmentSettings',
|
||||||
|
'leftColumnWidth',
|
||||||
]),
|
]),
|
||||||
customEmojis: reduceCustomEmojis(global),
|
customEmojis: reduceCustomEmojis(global),
|
||||||
users: reduceUsers(global),
|
users: reduceUsers(global),
|
||||||
@ -510,12 +511,21 @@ function reduceMessages<T extends GlobalState>(global: T): GlobalState['messages
|
|||||||
}
|
}
|
||||||
|
|
||||||
const viewportIdsToSave = unique(Object.values(threadsToSave).flatMap((thread) => thread.lastViewportIds || []));
|
const viewportIdsToSave = unique(Object.values(threadsToSave).flatMap((thread) => thread.lastViewportIds || []));
|
||||||
const lastMessagesToSave = chat?.topics
|
const lastMessageIdsToSave = chat?.topics
|
||||||
? Object.values(chat.topics).map(({ lastMessageId }) => lastMessageId) : [];
|
? Object.values(chat.topics).map(({ lastMessageId }) => lastMessageId) : [];
|
||||||
|
const byId = pick(current.byId, viewportIdsToSave.concat(lastMessageIdsToSave));
|
||||||
|
const threadsById = Object.keys(threadsToSave).reduce((acc, key) => {
|
||||||
|
const t = threadsToSave[Number(key)];
|
||||||
|
acc[Number(key)] = {
|
||||||
|
...t,
|
||||||
|
listedIds: t.lastViewportIds,
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {} as GlobalState['messages']['byChatId'][string]['threadsById']);
|
||||||
|
|
||||||
byChatId[chatId] = {
|
byChatId[chatId] = {
|
||||||
byId: pick(current.byId, viewportIdsToSave.concat(lastMessagesToSave)),
|
byId,
|
||||||
threadsById: threadsToSave,
|
threadsById,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { INITIAL_GLOBAL_STATE, INITIAL_TAB_STATE } from './initialState';
|
|||||||
import { IS_MOCKED_CLIENT } from '../config';
|
import { IS_MOCKED_CLIENT } from '../config';
|
||||||
import { initCache, loadCache } from './cache';
|
import { initCache, loadCache } from './cache';
|
||||||
import { cloneDeep } from '../util/iteratees';
|
import { cloneDeep } from '../util/iteratees';
|
||||||
import { replaceTabThreadParam, updatePasscodeSettings } from './reducers';
|
import { replaceTabThreadParam, replaceThreadParam, updatePasscodeSettings } from './reducers';
|
||||||
import { clearStoredSession } from '../util/sessions';
|
import { clearStoredSession } from '../util/sessions';
|
||||||
import { parseLocationHash } from '../util/routing';
|
import { parseLocationHash } from '../util/routing';
|
||||||
import { MAIN_THREAD_ID } from '../api/types';
|
import { MAIN_THREAD_ID } from '../api/types';
|
||||||
@ -14,7 +14,7 @@ import { selectTabState, selectThreadParam } from './selectors';
|
|||||||
import { Bundles, loadBundle } from '../util/moduleLoader';
|
import { Bundles, loadBundle } from '../util/moduleLoader';
|
||||||
import { getCurrentTabId, reestablishMasterToSelf } from '../util/establishMultitabRole';
|
import { getCurrentTabId, reestablishMasterToSelf } from '../util/establishMultitabRole';
|
||||||
import { updateTabState } from './reducers/tabs';
|
import { updateTabState } from './reducers/tabs';
|
||||||
import type { ActionReturnType } from './types';
|
import type { ActionReturnType, GlobalState } from './types';
|
||||||
import { getIsMobile } from '../hooks/useAppLayout';
|
import { getIsMobile } from '../hooks/useAppLayout';
|
||||||
|
|
||||||
initCache();
|
initCache();
|
||||||
@ -61,15 +61,49 @@ addActionHandler('init', (global, actions, payload): ActionReturnType => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(global.messages.byChatId).forEach((chatId) => {
|
Object.keys(global.messages.byChatId).forEach((chatId) => {
|
||||||
|
const lastViewportIds = selectThreadParam(global, chatId, MAIN_THREAD_ID, 'lastViewportIds');
|
||||||
|
// Check if migration from previous version is faulty
|
||||||
|
if (!lastViewportIds?.every((id) => global.messages.byChatId[chatId]?.byId[id])) {
|
||||||
|
global = replaceThreadParam(global, chatId, MAIN_THREAD_ID, 'lastViewportIds', undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
global = replaceTabThreadParam(
|
global = replaceTabThreadParam(
|
||||||
global,
|
global,
|
||||||
chatId,
|
chatId,
|
||||||
MAIN_THREAD_ID,
|
MAIN_THREAD_ID,
|
||||||
'viewportIds',
|
'viewportIds',
|
||||||
selectThreadParam(global, chatId, MAIN_THREAD_ID, 'lastViewportIds'),
|
lastViewportIds,
|
||||||
tabId,
|
tabId,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Temporary state fix
|
||||||
|
Object.keys(global.messages.byChatId).forEach((chatId) => {
|
||||||
|
const threadsById = global.messages.byChatId[chatId].threadsById;
|
||||||
|
const fixedThreadsById = Object.keys(threadsById).reduce((acc, key) => {
|
||||||
|
const t = threadsById[Number(key)];
|
||||||
|
acc[Number(key)] = {
|
||||||
|
...t,
|
||||||
|
listedIds: t.lastViewportIds,
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {} as GlobalState['messages']['byChatId'][string]['threadsById']);
|
||||||
|
|
||||||
|
global = {
|
||||||
|
...global,
|
||||||
|
messages: {
|
||||||
|
...global.messages,
|
||||||
|
byChatId: {
|
||||||
|
...global.messages.byChatId,
|
||||||
|
[chatId]: {
|
||||||
|
...global.messages.byChatId[chatId],
|
||||||
|
threadsById: fixedThreadsById,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const parsedMessageList = !getIsMobile() ? parseLocationHash() : undefined;
|
const parsedMessageList = !getIsMobile() ? parseLocationHash() : undefined;
|
||||||
|
|
||||||
if (global.authState !== 'authorizationStateReady'
|
if (global.authState !== 'authorizationStateReady'
|
||||||
@ -101,8 +135,8 @@ addActionHandler('requestMasterAndCallAction', async (
|
|||||||
|
|
||||||
if (global.phoneCall || global.groupCalls.activeGroupCallId) {
|
if (global.phoneCall || global.groupCalls.activeGroupCallId) {
|
||||||
await loadBundle(Bundles.Calls);
|
await loadBundle(Bundles.Calls);
|
||||||
actions.hangUp({ tabId });
|
if ('hangUp' in actions) actions.hangUp({ tabId });
|
||||||
actions.leaveGroupCall({ tabId });
|
if ('leaveGroupCall' in actions) actions.leaveGroupCall({ tabId });
|
||||||
} else {
|
} else {
|
||||||
reestablishMasterToSelf();
|
reestablishMasterToSelf();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ function getLeftColumnWidth(windowWidth: number) {
|
|||||||
export function subtractXForEmojiInteraction(global: GlobalState, x: number) {
|
export function subtractXForEmojiInteraction(global: GlobalState, x: number) {
|
||||||
const tabState = selectTabState(global);
|
const tabState = selectTabState(global);
|
||||||
return x - ((tabState.isLeftColumnShown && !getIsMobile())
|
return x - ((tabState.isLeftColumnShown && !getIsMobile())
|
||||||
? tabState.leftColumnWidth || getLeftColumnWidth(windowSize.get().width)
|
? global.leftColumnWidth || getLeftColumnWidth(windowSize.get().width)
|
||||||
: 0);
|
: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -173,7 +173,6 @@ export type TabState = {
|
|||||||
uiReadyState: 0 | 1 | 2;
|
uiReadyState: 0 | 1 | 2;
|
||||||
shouldInit: boolean;
|
shouldInit: boolean;
|
||||||
shouldSkipHistoryAnimations?: boolean;
|
shouldSkipHistoryAnimations?: boolean;
|
||||||
leftColumnWidth?: number;
|
|
||||||
|
|
||||||
gifSearch: {
|
gifSearch: {
|
||||||
query?: string;
|
query?: string;
|
||||||
@ -534,6 +533,7 @@ export type GlobalState = {
|
|||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
serverTimeOffset: number;
|
serverTimeOffset: number;
|
||||||
blurredTabTokens: number[];
|
blurredTabTokens: number[];
|
||||||
|
leftColumnWidth?: number;
|
||||||
initialUnreadNotifications?: number;
|
initialUnreadNotifications?: number;
|
||||||
notificationIndex?: number;
|
notificationIndex?: number;
|
||||||
allNotificationsCount?: number;
|
allNotificationsCount?: number;
|
||||||
@ -1315,8 +1315,8 @@ export interface ActionPayloads {
|
|||||||
disableHistoryAnimations: WithTabId | undefined;
|
disableHistoryAnimations: WithTabId | undefined;
|
||||||
setLeftColumnWidth: {
|
setLeftColumnWidth: {
|
||||||
leftColumnWidth: number;
|
leftColumnWidth: number;
|
||||||
} & WithTabId;
|
};
|
||||||
resetLeftColumnWidth: WithTabId | undefined;
|
resetLeftColumnWidth: undefined;
|
||||||
|
|
||||||
copySelectedMessages: WithTabId;
|
copySelectedMessages: WithTabId;
|
||||||
copyMessagesByIds: {
|
copyMessagesByIds: {
|
||||||
@ -1326,8 +1326,8 @@ export interface ActionPayloads {
|
|||||||
chatId: string;
|
chatId: string;
|
||||||
messageId: number;
|
messageId: number;
|
||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
closeSeenByModal: WithTabId;
|
closeSeenByModal: WithTabId | undefined;
|
||||||
closeReactorListModal: WithTabId;
|
closeReactorListModal: WithTabId | undefined;
|
||||||
openReactorListModal: {
|
openReactorListModal: {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
messageId: number;
|
messageId: number;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user