More fixes for muted chats; PWA badge (#1133)
This commit is contained in:
parent
9af2ce7d0b
commit
ffe756414c
5
src/@types/global.d.ts
vendored
5
src/@types/global.d.ts
vendored
@ -100,3 +100,8 @@ interface HTMLElement {
|
|||||||
webkitEnterFullscreen?: () => Promise<void>;
|
webkitEnterFullscreen?: () => Promise<void>;
|
||||||
webkitRequestFullscreen?: () => Promise<void>;
|
webkitRequestFullscreen?: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Navigator {
|
||||||
|
// PWA badging extensions https://w3c.github.io/badging/
|
||||||
|
setAppBadge?(count: number): Promise<void>;
|
||||||
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {
|
|||||||
ApiTypingStatus,
|
ApiTypingStatus,
|
||||||
MAIN_THREAD_ID, ApiUser,
|
MAIN_THREAD_ID, ApiUser,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
|
import { NotifyException, NotifySettings } from '../../types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN,
|
MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN,
|
||||||
@ -27,6 +28,7 @@ import {
|
|||||||
getMessageKey,
|
getMessageKey,
|
||||||
getChatTitle,
|
getChatTitle,
|
||||||
getSenderTitle,
|
getSenderTitle,
|
||||||
|
selectIsChatMuted,
|
||||||
} from '../../modules/helpers';
|
} from '../../modules/helpers';
|
||||||
import {
|
import {
|
||||||
selectChat,
|
selectChat,
|
||||||
@ -43,6 +45,8 @@ import {
|
|||||||
selectScheduledIds,
|
selectScheduledIds,
|
||||||
selectIsInSelectMode,
|
selectIsInSelectMode,
|
||||||
selectIsChatWithBot,
|
selectIsChatWithBot,
|
||||||
|
selectNotifySettings,
|
||||||
|
selectNotifyExceptions,
|
||||||
} from '../../modules/selectors';
|
} from '../../modules/selectors';
|
||||||
import useEnsureMessage from '../../hooks/useEnsureMessage';
|
import useEnsureMessage from '../../hooks/useEnsureMessage';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/useWindowSize';
|
||||||
@ -88,6 +92,8 @@ type StateProps = {
|
|||||||
isChatWithSelf?: boolean;
|
isChatWithSelf?: boolean;
|
||||||
isChatWithBot?: boolean;
|
isChatWithBot?: boolean;
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
|
notifySettings: NotifySettings;
|
||||||
|
notifyExceptions?: Record<number, NotifyException>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, (
|
type DispatchProps = Pick<GlobalActions, (
|
||||||
@ -115,6 +121,8 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
isChatWithSelf,
|
isChatWithSelf,
|
||||||
isChatWithBot,
|
isChatWithBot,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
|
notifySettings,
|
||||||
|
notifyExceptions,
|
||||||
openChatWithInfo,
|
openChatWithInfo,
|
||||||
pinMessage,
|
pinMessage,
|
||||||
focusMessage,
|
focusMessage,
|
||||||
@ -211,7 +219,9 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const count = currentChat.unreadCount || 0;
|
const count = currentChat.unreadCount || 0;
|
||||||
if (count && (!currentChat.isMuted || currentChat.unreadMentionsCount)) {
|
if (
|
||||||
|
count && (!selectIsChatMuted(currentChat, notifySettings, notifyExceptions) || currentChat.unreadMentionsCount)
|
||||||
|
) {
|
||||||
isActive = true;
|
isActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +236,7 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
isActive,
|
isActive,
|
||||||
totalCount,
|
totalCount,
|
||||||
};
|
};
|
||||||
}, [isLeftColumnHideable, chatsById]);
|
}, [isLeftColumnHideable, chatsById, notifySettings, notifyExceptions]);
|
||||||
|
|
||||||
const canToolsCollideWithChatInfo = (
|
const canToolsCollideWithChatInfo = (
|
||||||
windowWidth >= MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN
|
windowWidth >= MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN
|
||||||
@ -444,6 +454,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
isChatWithSelf: selectIsChatWithSelf(global, chatId),
|
isChatWithSelf: selectIsChatWithSelf(global, chatId),
|
||||||
isChatWithBot: chat && selectIsChatWithBot(global, chat),
|
isChatWithBot: chat && selectIsChatWithBot(global, chat),
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
|
notifySettings: selectNotifySettings(global),
|
||||||
|
notifyExceptions: selectNotifyExceptions(global),
|
||||||
};
|
};
|
||||||
|
|
||||||
const messagesById = selectChatMessages(global, chatId);
|
const messagesById = selectChatMessages(global, chatId);
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import {
|
|||||||
import { initApi, callApi } from '../../../api/gramjs';
|
import { initApi, callApi } from '../../../api/gramjs';
|
||||||
import { unsubscribe } from '../../../util/notifications';
|
import { unsubscribe } from '../../../util/notifications';
|
||||||
import * as cacheApi from '../../../util/cacheApi';
|
import * as cacheApi from '../../../util/cacheApi';
|
||||||
|
import { updateAppBadge } from '../../../util/appBadge';
|
||||||
|
|
||||||
addReducer('initApi', (global: GlobalState, actions) => {
|
addReducer('initApi', (global: GlobalState, actions) => {
|
||||||
const sessionId = localStorage.getItem(GRAMJS_SESSION_ID_KEY) || undefined;
|
const sessionId = localStorage.getItem(GRAMJS_SESSION_ID_KEY) || undefined;
|
||||||
@ -111,6 +112,7 @@ addReducer('signOut', () => {
|
|||||||
|
|
||||||
addReducer('reset', () => {
|
addReducer('reset', () => {
|
||||||
localStorage.removeItem(GRAMJS_SESSION_ID_KEY);
|
localStorage.removeItem(GRAMJS_SESSION_ID_KEY);
|
||||||
|
updateAppBadge(0);
|
||||||
|
|
||||||
cacheApi.clear(MEDIA_CACHE_NAME);
|
cacheApi.clear(MEDIA_CACHE_NAME);
|
||||||
cacheApi.clear(MEDIA_CACHE_NAME_AVATARS);
|
cacheApi.clear(MEDIA_CACHE_NAME_AVATARS);
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { ApiUpdate, MAIN_THREAD_ID } from '../../../api/types';
|
|||||||
import { ARCHIVED_FOLDER_ID, MAX_ACTIVE_PINNED_CHATS } from '../../../config';
|
import { ARCHIVED_FOLDER_ID, MAX_ACTIVE_PINNED_CHATS } from '../../../config';
|
||||||
import { pick } from '../../../util/iteratees';
|
import { pick } from '../../../util/iteratees';
|
||||||
import { showNewMessageNotification } from '../../../util/notifications';
|
import { showNewMessageNotification } from '../../../util/notifications';
|
||||||
|
import { updateAppBadge } from '../../../util/appBadge';
|
||||||
import {
|
import {
|
||||||
updateChat,
|
updateChat,
|
||||||
replaceChatListIds,
|
replaceChatListIds,
|
||||||
@ -17,12 +18,15 @@ import {
|
|||||||
selectIsChatListed,
|
selectIsChatListed,
|
||||||
selectChatListType,
|
selectChatListType,
|
||||||
selectCurrentMessageList,
|
selectCurrentMessageList,
|
||||||
|
selectCountNotMutedUnread,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
|
import { throttle } from '../../../util/schedulers';
|
||||||
|
|
||||||
const TYPING_STATUS_CLEAR_DELAY = 6000; // 6 seconds
|
const TYPING_STATUS_CLEAR_DELAY = 6000; // 6 seconds
|
||||||
|
|
||||||
// Enough to animate and mark as read in Message List
|
// Enough to animate and mark as read in Message List
|
||||||
const CURRENT_CHAT_UNREAD_DELAY = 1000;
|
const CURRENT_CHAT_UNREAD_DELAY = 1000;
|
||||||
|
const runThrottledForUpdateAppBadge = throttle((cb) => cb(), CURRENT_CHAT_UNREAD_DELAY, true);
|
||||||
|
|
||||||
addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
||||||
switch (update['@type']) {
|
switch (update['@type']) {
|
||||||
@ -32,8 +36,11 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
|||||||
actions.loadTopChats();
|
actions.loadTopChats();
|
||||||
}
|
}
|
||||||
|
|
||||||
setGlobal(updateChat(global, update.id, update.chat, update.newProfilePhoto));
|
const newGlobal = updateChat(global, update.id, update.chat, update.newProfilePhoto);
|
||||||
|
setGlobal(newGlobal);
|
||||||
|
|
||||||
|
const unreadCount = selectCountNotMutedUnread(newGlobal);
|
||||||
|
runThrottledForUpdateAppBadge(() => updateAppBadge(unreadCount));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +132,8 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unreadCount = selectCountNotMutedUnread(getGlobal());
|
||||||
|
updateAppBadge(unreadCount);
|
||||||
showNewMessageNotification({ chat, message, isActiveChat });
|
showNewMessageNotification({ chat, message, isActiveChat });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -377,7 +377,7 @@ export function getFolderUnreadDialogs(
|
|||||||
|
|
||||||
const hasActiveDialogs = listedChats.some((chat) => (
|
const hasActiveDialogs = listedChats.some((chat) => (
|
||||||
chat.unreadMentionsCount
|
chat.unreadMentionsCount
|
||||||
|| (!chat.isMuted && (chat.unreadCount || chat.hasUnreadMark))
|
|| (!selectIsChatMuted(chat, notifySettings, notifyExceptions) && (chat.unreadCount || chat.hasUnreadMark))
|
||||||
));
|
));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -2,10 +2,11 @@ import { ApiChat, MAIN_THREAD_ID } from '../../api/types';
|
|||||||
import { GlobalState } from '../../global/types';
|
import { GlobalState } from '../../global/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getPrivateChatUserId, isChatChannel, isChatPrivate, isHistoryClearMessage, isUserBot, isUserOnline,
|
getPrivateChatUserId, isChatChannel, isChatPrivate, isHistoryClearMessage, isUserBot, isUserOnline, selectIsChatMuted,
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import { selectUser } from './users';
|
import { selectUser } from './users';
|
||||||
import { ALL_FOLDER_ID, ARCHIVED_FOLDER_ID, MEMBERS_LOAD_SLICE } from '../../config';
|
import { ALL_FOLDER_ID, ARCHIVED_FOLDER_ID, MEMBERS_LOAD_SLICE } from '../../config';
|
||||||
|
import { selectNotifyExceptions, selectNotifySettings } from './settings';
|
||||||
|
|
||||||
export function selectChat(global: GlobalState, chatId: number): ApiChat | undefined {
|
export function selectChat(global: GlobalState, chatId: number): ApiChat | undefined {
|
||||||
return global.chats.byId[chatId];
|
return global.chats.byId[chatId];
|
||||||
@ -157,7 +158,11 @@ export function selectCountNotMutedUnread(global: GlobalState) {
|
|||||||
return activeChatIds.reduce((acc, chatId) => {
|
return activeChatIds.reduce((acc, chatId) => {
|
||||||
const chat = chats[chatId];
|
const chat = chats[chatId];
|
||||||
|
|
||||||
if (chat && chat.unreadCount && !chat.isMuted) {
|
if (
|
||||||
|
chat
|
||||||
|
&& chat.unreadCount
|
||||||
|
&& !selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global))
|
||||||
|
) {
|
||||||
return acc + chat.unreadCount;
|
return acc + chat.unreadCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
src/util/appBadge.ts
Normal file
14
src/util/appBadge.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { DEBUG } from '../config';
|
||||||
|
|
||||||
|
export function updateAppBadge(unreadCount: number) {
|
||||||
|
if (typeof window.navigator.setAppBadge !== 'function') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.navigator.setAppBadge(unreadCount).catch((err) => {
|
||||||
|
if (DEBUG) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -11,10 +11,13 @@ import {
|
|||||||
getPrivateChatUserId,
|
getPrivateChatUserId,
|
||||||
isActionMessage,
|
isActionMessage,
|
||||||
isChatChannel,
|
isChatChannel,
|
||||||
|
selectIsChatMuted,
|
||||||
} from '../modules/helpers';
|
} from '../modules/helpers';
|
||||||
import { getTranslation } from './langProvider';
|
import { getTranslation } from './langProvider';
|
||||||
import { replaceSettings } from '../modules/reducers';
|
import { replaceSettings } from '../modules/reducers';
|
||||||
import { selectChatMessage, selectUser } from '../modules/selectors';
|
import {
|
||||||
|
selectChatMessage, selectNotifyExceptions, selectNotifySettings, selectUser,
|
||||||
|
} from '../modules/selectors';
|
||||||
import { IS_SERVICE_WORKER_SUPPORTED } from './environment';
|
import { IS_SERVICE_WORKER_SUPPORTED } from './environment';
|
||||||
|
|
||||||
function getDeviceToken(subscription: PushSubscription) {
|
function getDeviceToken(subscription: PushSubscription) {
|
||||||
@ -187,12 +190,15 @@ export async function subscribe() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkIfShouldNotify(chat: ApiChat, isActive: boolean) {
|
function checkIfShouldNotify(chat: ApiChat, isActive: boolean) {
|
||||||
if (chat.isMuted || chat.isNotJoined) return false;
|
const global = getGlobal();
|
||||||
|
|
||||||
|
if (selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global)) || chat.isNotJoined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Dont show notification for active chat if client has focus
|
// Dont show notification for active chat if client has focus
|
||||||
if (isActive && document.hasFocus()) return false;
|
if (isActive && document.hasFocus()) return false;
|
||||||
|
|
||||||
const global = getGlobal();
|
|
||||||
switch (chat.type) {
|
switch (chat.type) {
|
||||||
case 'chatTypePrivate':
|
case 'chatTypePrivate':
|
||||||
case 'chatTypeSecret':
|
case 'chatTypeSecret':
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user