Browse Source

Show alert when pinning dialog over the limit

master
Eduard Kuzmenko 3 years ago
parent
commit
9d93fe65a5
  1. 4
      src/components/chat/selection.ts
  2. 26
      src/components/dialogsContextMenu.ts
  3. 2
      src/components/languageChangeButton.ts
  4. 7
      src/components/popups/newMedia.ts
  5. 2
      src/components/popups/peer.ts
  6. 5
      src/lang.ts
  7. 12
      src/lib/appManagers/appMessagesManager.ts
  8. 16
      src/lib/mtproto/mtprotoworker.ts
  9. 10
      src/lib/rootScope.ts
  10. 4
      src/lib/storages/dialogs.ts
  11. 4
      src/lib/storages/filters.ts

4
src/components/chat/selection.ts

@ -26,8 +26,8 @@ import blurActiveElement from "../../helpers/dom/blurActiveElement"; @@ -26,8 +26,8 @@ import blurActiveElement from "../../helpers/dom/blurActiveElement";
import { cancelEvent } from "../../helpers/dom/cancelEvent";
import cancelSelection from "../../helpers/dom/cancelSelection";
import getSelectedText from "../../helpers/dom/getSelectedText";
import rootScope from "../../lib/rootScope";
const MAX_SELECTION_LENGTH = 100;
//const MIN_CLICK_MOVE = 32; // minimum bubble height
export default class ChatSelection {
@ -473,7 +473,7 @@ export default class ChatSelection { @@ -473,7 +473,7 @@ export default class ChatSelection {
if(found) {
this.selectedMids.delete(mid);
} else {
const diff = MAX_SELECTION_LENGTH - this.selectedMids.size - 1;
const diff = rootScope.config.forwarded_count_max - this.selectedMids.size - 1;
if(diff < 0) {
toast(I18n.format('Chat.Selection.LimitToast', true));
return;

26
src/components/dialogsContextMenu.ts

@ -14,6 +14,10 @@ import PopupDeleteDialog from "./popups/deleteDialog"; @@ -14,6 +14,10 @@ import PopupDeleteDialog from "./popups/deleteDialog";
import { i18n } from "../lib/langPack";
import findUpTag from "../helpers/dom/findUpTag";
import appNotificationsManager from "../lib/appManagers/appNotificationsManager";
import PopupPeer from "./popups/peer";
import AppChatFoldersTab from "./sidebarLeft/tabs/chatFolders";
import appSidebarLeft from "./sidebarLeft";
import { toastNew } from "./toast";
export default class DialogsContextMenu {
private element: HTMLElement;
@ -101,7 +105,27 @@ export default class DialogsContextMenu { @@ -101,7 +105,27 @@ export default class DialogsContextMenu {
};
private onPinClick = () => {
appMessagesManager.toggleDialogPin(this.selectedId, this.filterId);
appMessagesManager.toggleDialogPin(this.selectedId, this.filterId).catch(err => {
if(err.type === 'PINNED_DIALOGS_TOO_MUCH') {
if(this.filterId >= 1) {
toastNew({langPackKey: 'PinFolderLimitReached'});
} else {
new PopupPeer('pinned-dialogs-too-much', {
buttons: [{
langKey: 'OK',
isCancel: true
}, {
langKey: 'FiltersSetupPinAlert',
callback: () => {
new AppChatFoldersTab(appSidebarLeft).open();
}
}],
descriptionLangKey: 'PinToTopLimitReached2',
descriptionLangArgs: [i18n('Chats', [rootScope.config.pinned_dialogs_count_max])]
}).show();
}
}
});
};
private onUnmuteClick = () => {

2
src/components/languageChangeButton.ts

@ -26,7 +26,7 @@ rootScope.addEventListener('language_change', () => { @@ -26,7 +26,7 @@ rootScope.addEventListener('language_change', () => {
function getLang(): Promise<[Config.config, LangPackString[], LangPackDifference.langPackDifference]> {
if(cachedPromise) return cachedPromise;
return cachedPromise = apiManager.invokeApiCacheable('help.getConfig').then(config => {
return cachedPromise = apiManager.getConfig().then(config => {
if(config.suggested_lang_code !== I18n.lastRequestedLangCode) {
//I18n.loadLangPack(config.suggested_lang_code);

7
src/components/popups/newMedia.ts

@ -19,6 +19,7 @@ import appDownloadManager from "../../lib/appManagers/appDownloadManager"; @@ -19,6 +19,7 @@ import appDownloadManager from "../../lib/appManagers/appDownloadManager";
import calcImageInBox from "../../helpers/calcImageInBox";
import isSendShortcutPressed from "../../helpers/dom/isSendShortcutPressed";
import placeCaretAtEnd from "../../helpers/dom/placeCaretAtEnd";
import rootScope from "../../lib/rootScope";
type SendFileParams = Partial<{
file: File,
@ -30,8 +31,6 @@ type SendFileParams = Partial<{ @@ -30,8 +31,6 @@ type SendFileParams = Partial<{
duration: number
}>;
const MAX_LENGTH_CAPTION = 1024;
// TODO: .gif upload as video
export default class PopupNewMedia extends PopupElement {
@ -87,7 +86,7 @@ export default class PopupNewMedia extends PopupElement { @@ -87,7 +86,7 @@ export default class PopupNewMedia extends PopupElement {
placeholder: 'PreviewSender.CaptionPlaceholder',
label: 'Caption',
name: 'photo-caption',
maxLength: MAX_LENGTH_CAPTION,
maxLength: rootScope.config.caption_length_max,
showLengthOn: 80
});
this.input = this.inputField.input;
@ -150,7 +149,7 @@ export default class PopupNewMedia extends PopupElement { @@ -150,7 +149,7 @@ export default class PopupNewMedia extends PopupElement {
}
let caption = this.inputField.value;
if(caption.length > MAX_LENGTH_CAPTION) {
if(caption.length > rootScope.config.caption_length_max) {
toast(I18n.format('Error.PreviewSender.CaptionTooLong', true));
return;
}

2
src/components/popups/peer.ts

@ -36,7 +36,7 @@ export default class PopupPeer extends PopupElement { @@ -36,7 +36,7 @@ export default class PopupPeer extends PopupElement {
this.header.prepend(avatarEl);
}
if(options.descriptionLangKey) this.title.append(i18n(options.titleLangKey, options.titleLangArgs));
if(options.titleLangKey || !options.title) this.title.append(i18n(options.titleLangKey || 'AppName', options.titleLangArgs));
else this.title.innerText = options.title || '';
let p = document.createElement('p');

5
src/lang.ts

@ -518,6 +518,11 @@ const lang = { @@ -518,6 +518,11 @@ const lang = {
"AddMembersAlertCountText": "Are you sure you want to add %1$s to **%2$s**?",
"AddMembersForwardMessages": "Show the last 100 messages to the new members",
"AddOneMemberForwardMessages": "Show the last 100 messages to **%1$s**",
"PinToTopLimitReached2": "Sorry, you can only pin %1$s to the top in the main list. More chats can be pinned in Chat Folders and your Archive.",
"FiltersSetupPinAlert": "Set Up Folders",
"AppName": "Telegram",
"OK": "OK",
"PinFolderLimitReached": "Sorry, you can\'t pin any more chats to the top.",
// * macos
"AccountSettings.Filters": "Chat Folders",

12
src/lib/appManagers/appMessagesManager.ts

@ -438,7 +438,7 @@ export class AppMessagesManager { @@ -438,7 +438,7 @@ export class AppMessagesManager {
options.replyToMsgId = options.threadId;
}
const MAX_LENGTH = 4096;
const MAX_LENGTH = rootScope.config.message_length_max;
if(text.length > MAX_LENGTH) {
const splitted = splitStringByLength(text, MAX_LENGTH);
text = splitted[0];
@ -2913,6 +2913,11 @@ export class AppMessagesManager { @@ -2913,6 +2913,11 @@ export class AppMessagesManager {
public toggleDialogPin(peerId: number, filterId?: number) {
if(filterId > 1) {
return this.filtersStorage.toggleDialogPin(peerId, filterId);
} else {
const max = filterId === 1 ? rootScope.config.pinned_infolder_count_max : rootScope.config.pinned_dialogs_count_max;
if(this.dialogsStorage.getPinnedOrders(filterId).length >= max) {
return Promise.reject({type: 'PINNED_DIALOGS_TOO_MUCH'});
}
}
const dialog = this.getDialogOnly(peerId);
@ -3017,11 +3022,12 @@ export class AppMessagesManager { @@ -3017,11 +3022,12 @@ export class AppMessagesManager {
}
// * second rule for saved messages, because there is no 'out' flag
if(message.pFlags.out || this.getMessagePeer(message) === appUsersManager.getSelf().id) {
if(/* message.pFlags.out || */this.getMessagePeer(message) === appUsersManager.getSelf().id) {
return true;
}
if((message.date < (tsNow(true) - (2 * 86400)) && message.media?._ !== 'messageMediaPoll') || !message.pFlags.out) {
if((message.date < (tsNow(true) - rootScope.config.edit_time_limit) &&
message.media?._ !== 'messageMediaPoll') || !message.pFlags.out) {
return false;
}

16
src/lib/mtproto/mtprotoworker.ts

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
import type { LocalStorageProxyTask, LocalStorageProxyTaskResponse } from '../localStorage';
//import type { LocalStorageProxyDeleteTask, LocalStorageProxySetTask } from '../storage';
import type { Awaited, InvokeApiOptions, WorkerTaskVoidTemplate } from '../../types';
import type { InputFile, MethodDeclMap } from '../../layer';
import type { Config, InputFile, MethodDeclMap } from '../../layer';
import MTProtoWorker from 'worker-loader!./mtproto.worker';
//import './mtproto.worker';
import { isObject } from '../../helpers/object';
@ -99,6 +99,8 @@ export class ApiManagerProxy extends CryptoWorkerMethods { @@ -99,6 +99,8 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
private postMessagesWaiting: any[][] = [];
private getConfigPromise: Promise<Config.config>;
constructor() {
super();
this.log('constructor');
@ -210,6 +212,10 @@ export class ApiManagerProxy extends CryptoWorkerMethods { @@ -210,6 +212,10 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
/// #if !MTPROTO_SW
this.registerWorker();
/// #endif
setTimeout(() => {
this.getConfig();
}, 5000);
}
public isServiceWorkerOnline() {
@ -597,6 +603,14 @@ export class ApiManagerProxy extends CryptoWorkerMethods { @@ -597,6 +603,14 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
public forceReconnect() {
this.postMessage({type: 'forceReconnect'});
}
public getConfig() {
if(this.getConfigPromise) return this.getConfigPromise;
return this.getConfigPromise = this.invokeApi('help.getConfig').then(config => {
rootScope.config = config;
return config;
});
}
}
const apiManagerProxy = new ApiManagerProxy();

10
src/lib/rootScope.ts

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import type { Message, StickerSet, Update, NotifyPeer, PeerNotifySettings, ConstructorDeclMap } from "../layer";
import type { Message, StickerSet, Update, NotifyPeer, PeerNotifySettings, ConstructorDeclMap, Config } from "../layer";
import type { MyDocument } from "./appManagers/appDocsManager";
import type { AppMessagesManager, Dialog, MessagesStorage } from "./appManagers/appMessagesManager";
import type { Poll, PollResults } from "./appManagers/appPollsManager";
@ -144,6 +144,14 @@ export class RootScope extends EventListenerBase<{ @@ -144,6 +144,14 @@ export class RootScope extends EventListenerBase<{
public settings: State['settings'];
public peerId = 0;
public systemTheme: Theme['name'];
public config: Partial<Config.config> = {
forwarded_count_max: 100,
edit_time_limit: 86400 * 2,
pinned_dialogs_count_max: 5,
pinned_infolder_count_max: 100,
message_length_max: 4096,
caption_length_max: 1024,
};
constructor() {
super();

4
src/lib/storages/dialogs.ts

@ -146,6 +146,10 @@ export default class DialogsStorage { @@ -146,6 +146,10 @@ export default class DialogsStorage {
this.pinnedOrders[folderId] = [];
}
public getPinnedOrders(folderId: number) {
return this.pinnedOrders[folderId];
}
public getOffsetDate(folderId: number) {
return this.dialogsOffsetDate[folderId] || 0;
}

4
src/lib/storages/filters.ts

@ -182,6 +182,10 @@ export default class FiltersStorage { @@ -182,6 +182,10 @@ export default class FiltersStorage {
public toggleDialogPin(peerId: number, filterId: number) {
const filter = this.filters[filterId];
if(filter.pinned_peers.length >= this.rootScope.config.pinned_infolder_count_max) {
return Promise.reject({type: 'PINNED_DIALOGS_TOO_MUCH'});
}
const wasPinned = filter.pinned_peers.findAndSplice(p => p === peerId);
if(!wasPinned) {
filter.pinned_peers.unshift(peerId);

Loading…
Cancel
Save