Browse Source

Update icons

Unread badge
master
Eduard Kuzmenko 2 years ago
parent
commit
bad2574647
  1. 2
      src/components/sidebarLeft/index.ts
  2. 45
      src/index.hbs
  3. 3
      src/index.ts
  4. 28
      src/lib/appManagers/appDialogsManager.ts
  5. 16
      src/lib/appManagers/appMessagesManager.ts
  6. 13
      src/lib/appManagers/appNotificationsManager.ts
  7. 2
      src/lib/appManagers/createManagers.ts
  8. 15
      src/lib/appManagers/uiNotificationsManager.ts
  9. 61
      src/lib/storages/dialogs.ts
  10. 3
      webpack.common.js

2
src/components/sidebarLeft/index.ts

@ -310,7 +310,7 @@ export class AppSidebarLeft extends SidebarSlider { @@ -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);
}

45
src/index.hbs

@ -3,26 +3,45 @@ @@ -3,26 +3,45 @@
<head>
<meta charset="utf-8">
<title>Telegram Web</title>
<meta name="description" content="Telegram is a cloud-based mobile and desktop messaging app with a focus on security and speed.">
<title>{{htmlWebpackPlugin.options.title}}</title>
<meta name="description" content="{{htmlWebpackPlugin.options.description}}">
<!--<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<!-- do not paste other icons here, only change these. 'icon' type must be single -->
<link rel="apple-touch-icon" sizes="180x180" href="assets/img/apple-touch-icon.png?v=jw3mK7G9Ry">
<link rel="icon" type="image/png" sizes="32x32" href="assets/img/favicon-32x32.png?v=jw3mK7G9Ry">
<!--<link rel="icon" type="image/png" sizes="192x192" href="assets/img/android-chrome-192x192.png?v=jw3mK7G9Ry">
<link rel="icon" type="image/png" sizes="16x16" href="assets/img/favicon-16x16.png?v=jw3mK7G9Ry">-->
<link rel="manifest" href="site.webmanifest?v=jw3mK7G9Aq">
<link rel="mask-icon" href="assets/img/safari-pinned-tab.svg?v=jw3mK7G9Ry" color="#3390ec">
<!--<link rel="shortcut icon" href="assets/img/favicon.ico?v=jw3mK7G9Ry">-->
<meta name="apple-mobile-web-app-title" content="Telegram WebK">
<meta name="application-name" content="Telegram WebK">
<meta name="mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-title" content="{{htmlWebpackPlugin.options.title}}">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="{{htmlWebpackPlugin.options.title}}">
<meta name="application-name" content="{{htmlWebpackPlugin.options.title}}">
<meta name="msapplication-TileColor" content="#2d89ef">
<meta name="msapplication-TileImage" content="assets/img/mstile-144x144.png?v=jw3mK7G9Ry">
<meta name="msapplication-config" content="browserconfig.xml?v=jw3mK7G9Ry">
<meta name="theme-color" content="#ffffff">
<meta name="color-scheme" content="light">
<meta name="google" content="notranslate">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="{{htmlWebpackPlugin.options.url}}">
<meta property="og:title" content="{{htmlWebpackPlugin.options.title}}">
<meta property="og:description" content="{{htmlWebpackPlugin.options.description}}">
<meta property="og:image" content="assets/img/android-chrome-192x192.png?v=jw3mK7G9Ry">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="{{htmlWebpackPlugin.options.url}}">
<meta property="twitter:title" content="{{htmlWebpackPlugin.options.title}}">
<meta property="twitter:description" content="{{htmlWebpackPlugin.options.description}}">
<meta property="twitter:image" content="assets/img/android-chrome-192x192.png?v=jw3mK7G9Ry">
<link rel="apple-touch-icon" sizes="180x180" href="assets/img/apple-touch-icon.png?v=jw3mK7G9Ry">
<link rel="icon" type="image/png" sizes="16x16" href="assets/img/favicon-16x16.png?v=jw3mK7G9Ry">
<link rel="icon" type="image/png" sizes="32x32" href="assets/img/favicon-32x32.png?v=jw3mK7G9Ry">
<link rel="icon" type="image/png" sizes="192x192" href="assets/img/android-chrome-192x192.png?v=jw3mK7G9Ry">
<link rel="alternate icon" href="assets/img/favicon.ico?v=jw3mK7G9Ry" type="image/x-icon">
<link rel="mask-icon" href="assets/img/safari-pinned-tab.svg?v=jw3mK7G9Ry" color="#3390ec">
<link rel="manifest" id="manifest">
{{#each htmlWebpackPlugin.files.css}}
<link rel="stylesheet" href="{{this}}">
{{/each}}

3
src/index.ts

@ -32,6 +32,9 @@ document.addEventListener('DOMContentLoaded', async() => { @@ -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/)

28
src/lib/appManagers/appDialogsManager.ts

@ -205,7 +205,6 @@ export class AppDialogsManager { @@ -205,7 +205,6 @@ export class AppDialogsManager {
}
} = {};
private showFiltersPromise: Promise<void>;
private allUnreadCount: HTMLElement;
private sliceTimeout: number;
@ -236,8 +235,6 @@ export class AppDialogsManager { @@ -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 { @@ -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 { @@ -667,20 +663,6 @@ export class AppDialogsManager {
}
}
if(state.notifySettings) {
const promises: Promise<any>[] = [];
for(const key in state.notifySettings) {
assumeType<Exclude<NotifyPeer['_'], 'notifyPeer'>>(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 { @@ -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 : '';
}

16
src/lib/appManagers/appMessagesManager.ts

@ -3113,18 +3113,14 @@ export class AppMessagesManager extends AppManager { @@ -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);
}
}
}

13
src/lib/appManagers/appNotificationsManager.ts

@ -17,6 +17,7 @@ import convertInputKeyToKey from "../../helpers/string/convertInputKeyToKey"; @@ -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> | PeerNotifySettings;
export class AppNotificationsManager extends AppManager {
@ -50,6 +51,18 @@ 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<Exclude<NotifyPeer['_'], 'notifyPeer'>>(key);
this.savePeerSettings({
key,
settings: state.notifySettings[key]
});
}
}
});
}
public getNotifySettings(peer: InputNotifyPeer): ImSadAboutIt {

2
src/lib/appManagers/createManagers.ts

@ -108,7 +108,7 @@ export default function createManagers(appStoragesManager: AppStoragesManager, u @@ -108,7 +108,7 @@ export default function createManagers(appStoragesManager: AppStoragesManager, u
const promises: Array<Promise<(() => 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];

15
src/lib/appManagers/uiNotificationsManager.ts

@ -82,11 +82,14 @@ export class UiNotificationsManager { @@ -82,11 +82,14 @@ export class UiNotificationsManager {
private pushInited = false;
private managers: AppManagers;
private setAppBadge: (contents?: any) => Promise<void>;
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 { @@ -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 { @@ -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 { @@ -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]);

61
src/lib/storages/dialogs.ts

@ -45,7 +45,8 @@ export type Folder = { @@ -45,7 +45,8 @@ export type Folder = {
dialogs: Dialog[],
id: number,
unreadMessagesCount: number,
unreadDialogsCount: number,
unreadPeerIds: Set<PeerId>,
unreadUnmutedPeerIds: Set<PeerId>,
dispatchUnreadTimeout?: number
};
@ -131,6 +132,7 @@ export default class DialogsStorage extends AppManager { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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) {

3
webpack.common.js

@ -241,6 +241,9 @@ module.exports = { @@ -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',

Loading…
Cancel
Save