diff --git a/src/components/sidebarLeft/index.ts b/src/components/sidebarLeft/index.ts
index 862c0356..d89d021e 100644
--- a/src/components/sidebarLeft/index.ts
+++ b/src/components/sidebarLeft/index.ts
@@ -310,7 +310,7 @@ export class AppSidebarLeft extends SidebarSlider {
rootScope.addEventListener('folder_unread', (folder) => {
if(folder.id === 1) {
// const count = folder.unreadMessagesCount;
- const count = folder.unreadDialogsCount;
+ const count = folder.unreadPeerIds.size;
this.archivedCount.innerText = '' + formatNumber(count, 1);
this.archivedCount.classList.toggle('hide', !count);
}
diff --git a/src/index.hbs b/src/index.hbs
index 9f415faf..dbf6be10 100644
--- a/src/index.hbs
+++ b/src/index.hbs
@@ -3,26 +3,45 @@
- Telegram Web
-
+ {{htmlWebpackPlugin.options.title}}
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{#each htmlWebpackPlugin.files.css}}
{{/each}}
diff --git a/src/index.ts b/src/index.ts
index 770caf66..79150f8c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -32,6 +32,9 @@ document.addEventListener('DOMContentLoaded', async() => {
rootScope.managers = getProxiedManagers();
+ const manifest = document.getElementById('manifest') as HTMLLinkElement;
+ manifest.href = `site${IS_APPLE && !IS_APPLE_MOBILE ? '_apple' : ''}.webmanifest?v=jw3mK7G9Aq`;
+
singleInstance.start();
// We listen to the resize event (https://css-tricks.com/the-trick-to-viewport-units-on-mobile/)
diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts
index 199b8528..c0957828 100644
--- a/src/lib/appManagers/appDialogsManager.ts
+++ b/src/lib/appManagers/appDialogsManager.ts
@@ -205,7 +205,6 @@ export class AppDialogsManager {
}
} = {};
private showFiltersPromise: Promise;
- private allUnreadCount: HTMLElement;
private sliceTimeout: number;
@@ -236,8 +235,6 @@ export class AppDialogsManager {
this.contextMenu = new DialogsContextMenu(managers);
- this.allUnreadCount = this.folders.menu.querySelector('.badge');
-
this.folders.menuScrollContainer = this.folders.menu.parentElement;
this.onListLengthChange = debounce(this._onListLengthChange, 100, false, true);
@@ -524,7 +521,6 @@ export class AppDialogsManager {
rootScope.addEventListener('dialog_notify_settings', (dialog) => {
this.validateDialogForFilter(dialog);
this.setUnreadMessagesN({dialog}); // возможно это не нужно, но нужно менять is-muted
- this.setFiltersUnreadCount();
});
rootScope.addEventListener('dialog_draft', ({dialog, drop, peerId}) => {
@@ -667,20 +663,6 @@ export class AppDialogsManager {
}
}
- if(state.notifySettings) {
- const promises: Promise[] = [];
- for(const key in state.notifySettings) {
- assumeType>(key);
- const promise = this.managers.appNotificationsManager.savePeerSettings({
- key,
- settings: state.notifySettings[key]
- });
- promises.push(promise);
- }
-
- await Promise.all(promises);
- }
-
this.managers.appNotificationsManager.getNotifyPeerTypeSettings();
await (await loadDialogsPromise).renderPromise;
@@ -755,13 +737,17 @@ export class AppDialogsManager {
};
private async setFilterUnreadCount(filterId: number) {
- const unreadSpan = filterId === 0 ? this.allUnreadCount : this.filtersRendered[filterId]?.unread;
+ if(filterId === 0) {
+ return;
+ }
+
+ const unreadSpan = this.filtersRendered[filterId]?.unread;
if(!unreadSpan) {
return;
}
- const {foundUnmuted, unreadCount} = await this.managers.dialogsStorage.getFolderUnreadCount(filterId);
- unreadSpan.classList.toggle('badge-gray', !foundUnmuted);
+ const {unreadUnmutedCount, unreadCount} = await this.managers.dialogsStorage.getFolderUnreadCount(filterId);
+ unreadSpan.classList.toggle('badge-gray', !unreadUnmutedCount);
unreadSpan.innerText = unreadCount ? '' + unreadCount : '';
}
diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts
index 3dba9d0b..47762baf 100644
--- a/src/lib/appManagers/appMessagesManager.ts
+++ b/src/lib/appManagers/appMessagesManager.ts
@@ -3113,18 +3113,14 @@ export class AppMessagesManager extends AppManager {
if(!this.migratedFromTo[migrateFrom] &&
!this.migratedToFrom[migrateTo] &&
this.appChatsManager.hasChat(migrateTo.toChatId())) {
- const fromChat = this.appChatsManager.getChat(migrateFrom.toChatId());
- if(fromChat &&
- fromChat.migrated_to &&
- fromChat.migrated_to.channel_id === migrateTo.toChatId()) {
- this.migratedFromTo[migrateFrom] = migrateTo;
- this.migratedToFrom[migrateTo] = migrateFrom;
+ const fromChat: Chat.chat = this.appChatsManager.getChat(migrateFrom.toChatId());
+ if(fromChat?.migrated_to && (fromChat.migrated_to as InputChannel.inputChannel).channel_id === migrateTo.toChatId()) {
+ this.migratedFromTo[migrateFrom] = migrateTo;
+ this.migratedToFrom[migrateTo] = migrateFrom;
- //setTimeout(() => {
- this.rootScope.dispatchEvent('dialog_migrate', {migrateFrom, migrateTo});
+ this.rootScope.dispatchEvent('dialog_migrate', {migrateFrom, migrateTo});
- this.dialogsStorage.dropDialogWithEvent(migrateFrom);
- //}, 100);
+ this.dialogsStorage.dropDialogWithEvent(migrateFrom);
}
}
}
diff --git a/src/lib/appManagers/appNotificationsManager.ts b/src/lib/appManagers/appNotificationsManager.ts
index 5d79717b..31df2959 100644
--- a/src/lib/appManagers/appNotificationsManager.ts
+++ b/src/lib/appManagers/appNotificationsManager.ts
@@ -17,6 +17,7 @@ import convertInputKeyToKey from "../../helpers/string/convertInputKeyToKey";
import { AppManager } from "./manager";
import getPeerId from "./utils/peers/getPeerId";
import ctx from "../../environment/ctx";
+import assumeType from "../../helpers/assumeType";
type ImSadAboutIt = Promise | PeerNotifySettings;
export class AppNotificationsManager extends AppManager {
@@ -50,6 +51,18 @@ export class AppNotificationsManager extends AppManager {
this.rootScope.dispatchEvent('notify_settings', update);
}
});
+
+ return this.appStateManager.getState().then((state) => {
+ if(state.notifySettings) {
+ for(const key in state.notifySettings) {
+ assumeType>(key);
+ this.savePeerSettings({
+ key,
+ settings: state.notifySettings[key]
+ });
+ }
+ }
+ });
}
public getNotifySettings(peer: InputNotifyPeer): ImSadAboutIt {
diff --git a/src/lib/appManagers/createManagers.ts b/src/lib/appManagers/createManagers.ts
index b485c610..79e7704b 100644
--- a/src/lib/appManagers/createManagers.ts
+++ b/src/lib/appManagers/createManagers.ts
@@ -108,7 +108,7 @@ export default function createManagers(appStoragesManager: AppStoragesManager, u
const promises: Array void) | void> | void>[] = [];
let names = Object.keys(managers) as (keyof T)[];
- names.unshift('appUsersManager', 'appChatsManager', 'appMessagesManager', 'dialogsStorage');
+ names.unshift('appUsersManager', 'appChatsManager', 'appNotificationsManager', 'appMessagesManager', 'dialogsStorage');
names = filterUnique(names);
for(const name of names) {
const manager = managers[name];
diff --git a/src/lib/appManagers/uiNotificationsManager.ts b/src/lib/appManagers/uiNotificationsManager.ts
index 4d71394e..1994ce34 100644
--- a/src/lib/appManagers/uiNotificationsManager.ts
+++ b/src/lib/appManagers/uiNotificationsManager.ts
@@ -82,11 +82,14 @@ export class UiNotificationsManager {
private pushInited = false;
private managers: AppManagers;
+ private setAppBadge: (contents?: any) => Promise;
construct(managers: AppManagers) {
this.managers = managers;
navigator.vibrate = navigator.vibrate || (navigator as any).mozVibrate || (navigator as any).webkitVibrate;
+ this.setAppBadge = (navigator as any).setAppBadge && (navigator as any).setAppBadge.bind(navigator);
+ this.setAppBadge && this.setAppBadge(0);
this.notificationsUiSupport = ('Notification' in window) || ('mozNotification' in navigator);
@@ -125,6 +128,14 @@ export class UiNotificationsManager {
rootScope.addEventListener('notification_cancel', (str) => {
this.cancel(str);
});
+
+ if(this.setAppBadge) {
+ rootScope.addEventListener('folder_unread', (folder) => {
+ if(folder.id === 0) {
+ this.setAppBadge(folder.unreadUnmutedPeerIds.size);
+ }
+ });
+ }
webPushApiManager.addEventListener('push_init', (tokenData) => {
this.pushInited = true;
@@ -280,7 +291,7 @@ export class UiNotificationsManager {
private toggleToggler(enable = idleController.isIdle) {
if(IS_MOBILE) return;
- const resetTitle = () => {
+ const resetTitle = (isBlink?: boolean) => {
this.titleChanged = false;
document.title = this.titleBackup;
this.setFavicon();
@@ -297,7 +308,7 @@ export class UiNotificationsManager {
if(!count) {
this.toggleToggler(false);
} else if(this.titleChanged) {
- resetTitle();
+ resetTitle(true);
} else {
this.titleChanged = true;
document.title = I18n.format('Notifications.Count', true, [count]);
diff --git a/src/lib/storages/dialogs.ts b/src/lib/storages/dialogs.ts
index 30dde67d..8e392916 100644
--- a/src/lib/storages/dialogs.ts
+++ b/src/lib/storages/dialogs.ts
@@ -45,7 +45,8 @@ export type Folder = {
dialogs: Dialog[],
id: number,
unreadMessagesCount: number,
- unreadDialogsCount: number,
+ unreadPeerIds: Set,
+ unreadUnmutedPeerIds: Set,
dispatchUnreadTimeout?: number
};
@@ -131,6 +132,7 @@ export default class DialogsStorage extends AppManager {
this.rootScope.addEventListener('dialog_notify_settings', (dialog) => {
this.processDialogForFilters(dialog);
+ this.prepareDialogUnreadCountModifying(dialog)();
});
this.rootScope.addEventListener('chat_update', (chatId) => {
@@ -287,7 +289,14 @@ export default class DialogsStorage extends AppManager {
public getFolder(id: number) {
let folder = this.folders[id];
if(!folder) {
- folder = this.folders[id] = {dialogs: [], id, unreadMessagesCount: 0, unreadDialogsCount: 0};
+ folder = this.folders[id] = {
+ dialogs: [],
+ id,
+ unreadMessagesCount: 0,
+ unreadPeerIds: new Set(),
+ unreadUnmutedPeerIds: new Set()
+ };
+
defineNotNumerableProperties(folder, ['dispatchUnreadTimeout']);
}
@@ -326,14 +335,14 @@ export default class DialogsStorage extends AppManager {
const filter = this.filtersStorage.getFilter(filterId);
return getDialogIndexKey(filter.orderIndex);
}
+
+ public isPeerUnmuted(peerId: PeerId) {
+ return !this.appNotificationsManager.isPeerLocalMuted(peerId, true);
+ }
public getFolderUnreadCount(filterId: number) {
const folder = this.getFolder(filterId);
- const foundUnmuted = filterId === 0 || !!folder.dialogs.find((dialog) => {
- return (dialog.unread_count || dialog.pFlags.unread_mark) && !this.appNotificationsManager.isPeerLocalMuted(dialog.peerId, true);
- });
-
- return {foundUnmuted, unreadCount: folder.unreadDialogsCount};
+ return {unreadUnmutedCount: folder.unreadUnmutedPeerIds.size, unreadCount: folder.unreadPeerIds.size};
}
public getCachedDialogs(skipMigrated?: boolean) {
@@ -435,7 +444,7 @@ export default class DialogsStorage extends AppManager {
const newDialogIndex = this.setDialogIndexInFilter(dialog, indexKey, filter);
if(wasDialogIndex === newDialogIndex) {
- return;
+ return false;
}
if((!wasDialogIndex && newDialogIndex) || (wasIndex && !newDialogIndex)) {
@@ -449,6 +458,8 @@ export default class DialogsStorage extends AppManager {
if(newDialogIndex) {
insertInDescendSortedArray(dialogs, dialog, (dialog) => this.getDialogIndex(dialog, indexKey), -1);
}
+
+ return true;
}
public prepareDialogUnreadCountModifying(dialog: Dialog) {
@@ -469,32 +480,46 @@ export default class DialogsStorage extends AppManager {
public prepareFolderUnreadCountModifyingByDialog(folderId: number, dialog: Dialog, toggle?: boolean) {
const wasUnreadCount = this.appMessagesManager.getDialogUnreadCount(dialog);
+ const wasUnmuted = this.isPeerUnmuted(dialog.peerId);
if(toggle !== undefined) {
- this.modifyFolderUnreadCount(folderId, toggle ? wasUnreadCount : -wasUnreadCount, wasUnreadCount ? (toggle ? 1 : -1) : 0);
+ const addMessagesCount = toggle ? wasUnreadCount : -wasUnreadCount;
+ this.modifyFolderUnreadCount(folderId, addMessagesCount, !!wasUnreadCount, wasUnreadCount && wasUnmuted, dialog);
return;
}
return () => {
const newUnreadCount = this.appMessagesManager.getDialogUnreadCount(dialog);
+ const newUnmuted = this.isPeerUnmuted(dialog.peerId);
+
const addMessagesCount = newUnreadCount - wasUnreadCount;
- const addDialogsCount = (newUnreadCount && !wasUnreadCount) || (!newUnreadCount && wasUnreadCount) ? (wasUnreadCount ? -1 : 1) : 0;
- this.modifyFolderUnreadCount(folderId, addMessagesCount, addDialogsCount);
+ this.modifyFolderUnreadCount(folderId, addMessagesCount, !!newUnreadCount, newUnreadCount && newUnmuted, dialog);
};
}
- public modifyFolderUnreadCount(folderId: number, addMessagesCount: number, addDialogsCount: number) {
- if(!addMessagesCount && !addDialogsCount) {
- return;
- }
-
+ public modifyFolderUnreadCount(
+ folderId: number,
+ addMessagesCount: number,
+ toggleDialog: boolean,
+ toggleUnmuted: boolean,
+ dialog: Dialog
+ ) {
const folder = this.getFolder(folderId);
if(addMessagesCount) {
folder.unreadMessagesCount = Math.max(0, folder.unreadMessagesCount + addMessagesCount);
}
- if(addDialogsCount) {
- folder.unreadDialogsCount = Math.max(0, folder.unreadDialogsCount + addDialogsCount);
+ const {peerId} = dialog;
+ if(toggleDialog) {
+ folder.unreadPeerIds.add(peerId);
+ } else {
+ folder.unreadPeerIds.delete(peerId);
+ }
+
+ if(toggleUnmuted) {
+ folder.unreadUnmutedPeerIds.add(peerId);
+ } else {
+ folder.unreadUnmutedPeerIds.delete(peerId);
}
if(folder.dispatchUnreadTimeout === undefined) {
diff --git a/webpack.common.js b/webpack.common.js
index 07a6a442..5e617dc3 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -241,6 +241,9 @@ module.exports = {
// }),
new HtmlWebpackPlugin({
+ title: 'Telegram Web',
+ description: 'Telegram is a cloud-based mobile and desktop messaging app with a focus on security and speed.',
+ url: 'https://web.telegram.org/k/',
filename: 'index.html',
//template: 'public/index_template.html',
template: 'src/index.hbs',