Browse Source

Temp

master
Eduard Kuzmenko 3 years ago
parent
commit
bb1ea43c9b
  1. 22
      src/components/chat/input.ts
  2. 16
      src/components/chat/pinnedMessage.ts
  3. 6
      src/components/chat/selection.ts
  4. 8
      src/components/chat/sendContextMenu.ts
  5. 30
      src/components/chat/topbar.ts
  6. 8
      src/components/inputField.ts
  7. 58
      src/components/popups/datePicker.ts
  8. 4
      src/components/popups/index.ts
  9. 30
      src/components/popups/newMedia.ts
  10. 12
      src/components/sidebarLeft/tabs/archivedTab.ts
  11. 10
      src/index.hbs
  12. 54
      src/lang.ts
  13. 35
      src/lib/appManagers/appDialogsManager.ts
  14. 8
      src/lib/langPack.ts
  15. 36
      src/scss/partials/_chat.scss
  16. 15
      src/scss/partials/_chatPinned.scss

22
src/components/chat/input.ts

@ -38,6 +38,7 @@ import { debounce } from '../../helpers/schedulers'; @@ -38,6 +38,7 @@ import { debounce } from '../../helpers/schedulers';
import { tsNow } from '../../helpers/date';
import appNavigationController from '../appNavigationController';
import { isMobile } from '../../helpers/userAgent';
import { i18n } from '../../lib/langPack';
const RECORD_MIN_TIME = 500;
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
@ -117,6 +118,9 @@ export default class ChatInput { @@ -117,6 +118,9 @@ export default class ChatInput {
public saveDraftDebounced: () => void;
public fakeRowsWrapper: HTMLDivElement;
private fakePinnedControlBtn: HTMLElement;
constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appDocsManager: AppDocsManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appWebPagesManager: AppWebPagesManager, private appImManager: AppImManager, private appDraftsManager: AppDraftsManager, private serverTimeManager: ServerTimeManager, private appNotificationsManager: AppNotificationsManager) {
this.listenerSetter = new ListenerSetter();
}
@ -132,7 +136,7 @@ export default class ChatInput { @@ -132,7 +136,7 @@ export default class ChatInput {
this.rowsWrapper = document.createElement('div');
this.rowsWrapper.classList.add('rows-wrapper', 'chat-input-wrapper');
const fakeRowsWrapper = document.createElement('div');
const fakeRowsWrapper = this.fakeRowsWrapper = document.createElement('div');
fakeRowsWrapper.classList.add('fake-wrapper', 'fake-rows-wrapper');
const fakeSelectionWrapper = document.createElement('div');
@ -274,7 +278,7 @@ export default class ChatInput { @@ -274,7 +278,7 @@ export default class ChatInput {
this.attachMenuButtons = [{
icon: 'photo',
text: 'Photo or Video',
text: 'Chat.Input.Attach.PhotoOrVideo',
onClick: () => {
this.fileInput.value = '';
this.fileInput.setAttribute('accept', 'image/*, video/*');
@ -284,7 +288,7 @@ export default class ChatInput { @@ -284,7 +288,7 @@ export default class ChatInput {
verify: (peerId: number) => peerId > 0 || this.appChatsManager.hasRights(peerId, 'send_media')
}, {
icon: 'document',
text: 'Document',
text: 'Chat.Input.Attach.Document',
onClick: () => {
this.fileInput.value = '';
this.fileInput.removeAttribute('accept');
@ -501,6 +505,10 @@ export default class ChatInput { @@ -501,6 +505,10 @@ export default class ChatInput {
this.pinnedControlBtn = Button('btn-primary btn-transparent text-bold pinned-container-button', {icon: 'unpin'});
container.append(this.pinnedControlBtn);
const fakeContainer = container.cloneNode(true);
this.fakePinnedControlBtn = fakeContainer.firstChild as HTMLElement;
this.fakeRowsWrapper.append(fakeContainer);
this.listenerSetter.add(this.pinnedControlBtn, 'click', () => {
const peerId = this.chat.peerId;
@ -690,7 +698,13 @@ export default class ChatInput { @@ -690,7 +698,13 @@ export default class ChatInput {
this.attachMenu.toggleAttribute('disabled', !visible.length);
this.updateSendBtn();
} else if(this.pinnedControlBtn) {
this.pinnedControlBtn.append(this.appPeersManager.canPinMessage(this.chat.peerId) ? 'Unpin all messages' : 'Don\'t show pinned messages');
if(this.appPeersManager.canPinMessage(this.chat.peerId)) {
this.pinnedControlBtn.append(i18n('Chat.Input.UnpinAll'));
this.fakePinnedControlBtn.append(i18n('Chat.Input.UnpinAll'));
} else {
this.pinnedControlBtn.append(i18n('Chat.Pinned.DontShow'));
this.fakePinnedControlBtn.append(i18n('Chat.Pinned.DontShow'));
}
}
}

16
src/components/chat/pinnedMessage.ts

@ -12,6 +12,7 @@ import ListenerSetter from "../../helpers/listenerSetter"; @@ -12,6 +12,7 @@ import ListenerSetter from "../../helpers/listenerSetter";
import ButtonIcon from "../buttonIcon";
import { debounce } from "../../helpers/schedulers";
import { getHeavyAnimationPromise } from "../../hooks/useHeavyAnimationCheck";
import { i18n } from "../../lib/langPack";
class AnimatedSuper {
static DURATION = 200;
@ -242,6 +243,8 @@ export default class ChatPinnedMessage { @@ -242,6 +243,8 @@ export default class ChatPinnedMessage {
public setPinnedMessage: () => void;
private isStatic = false;
private debug = false;
constructor(private topbar: ChatTopbar, private chat: Chat, private appMessagesManager: AppMessagesManager, private appPeersManager: AppPeersManager) {
this.listenerSetter = new ListenerSetter();
@ -267,8 +270,7 @@ export default class ChatPinnedMessage { @@ -267,8 +270,7 @@ export default class ChatPinnedMessage {
this.pinnedMessageContainer.divAndCaption.content.prepend(this.animatedMedia.container);
this.animatedCounter = new AnimatedCounter(true);
this.pinnedMessageContainer.divAndCaption.title.innerHTML = 'Pinned Message ';
this.pinnedMessageContainer.divAndCaption.title.append(this.animatedCounter.container);
this.pinnedMessageContainer.divAndCaption.title.append(i18n('PinnedMessage'), ' ', this.animatedCounter.container);
this.btnOpen = ButtonIcon('pinlist pinned-container-close pinned-message-pinlist', {noRipple: true});
this.pinnedMessageContainer.divAndCaption.container.prepend(this.btnOpen);
@ -459,7 +461,7 @@ export default class ChatPinnedMessage { @@ -459,7 +461,7 @@ export default class ChatPinnedMessage {
this.loadedTop = (this.offsetIndex + this.mids.length) === this.count;
this.loadedBottom = !this.offsetIndex;
this.chat.log('[PM]: getCurrentIndex result:', mid, result, backLimited, this.offsetIndex, this.loadedTop, this.loadedBottom);
this.debug && this.chat.log('[PM]: getCurrentIndex result:', mid, result, backLimited, this.offsetIndex, this.loadedTop, this.loadedBottom);
} catch(err) {
this.chat.log.error('[PM]: getCurrentIndex error', err);
}
@ -503,7 +505,7 @@ export default class ChatPinnedMessage { @@ -503,7 +505,7 @@ export default class ChatPinnedMessage {
public async handleFollowingPinnedMessage() {
this.locked = true;
this.chat.log('[PM]: handleFollowingPinnedMessage');
this.debug && this.chat.log('[PM]: handleFollowingPinnedMessage');
try {
this.setScrollDownListener();
@ -519,7 +521,7 @@ export default class ChatPinnedMessage { @@ -519,7 +521,7 @@ export default class ChatPinnedMessage {
await this.getCurrentIndexPromise;
}
this.chat.log('[PM]: handleFollowingPinnedMessage: unlock');
this.debug && this.chat.log('[PM]: handleFollowingPinnedMessage: unlock');
this.locked = false;
/* // подождём, пока скролл остановится
@ -576,7 +578,7 @@ export default class ChatPinnedMessage { @@ -576,7 +578,7 @@ export default class ChatPinnedMessage {
const fromTop = pinnedIndex > this.wasPinnedIndex;
this.chat.log('[PM]: setPinnedMessage: fromTop', fromTop, pinnedIndex, this.wasPinnedIndex);
this.debug && this.chat.log('[PM]: setPinnedMessage: fromTop', fromTop, pinnedIndex, this.wasPinnedIndex);
const writeTo = this.animatedSubtitle.getRow(pinnedIndex);
const writeMediaTo = this.animatedMedia.getRow(pinnedIndex);
@ -614,4 +616,4 @@ export default class ChatPinnedMessage { @@ -614,4 +616,4 @@ export default class ChatPinnedMessage {
this.pinnedMessageContainer.divAndCaption.container.classList.toggle('is-many', this.count > 1);
//});
}
}
}

6
src/components/chat/selection.ts

@ -350,7 +350,7 @@ export default class ChatSelection { @@ -350,7 +350,7 @@ export default class ChatSelection {
if(this.chat.type === 'scheduled') {
this.selectionSendNowBtn = Button('btn-primary btn-transparent btn-short text-bold selection-container-send', {icon: 'send2'});
_i18n(this.selectionSendNowBtn, 'Chat.Context.Scheduled.SendNow');
this.selectionSendNowBtn.append(i18n('Chat.Context.Scheduled.SendNow'));
this.listenerSetter.add(this.selectionSendNowBtn, 'click', () => {
new PopupSendNow(this.bubbles.peerId, [...this.selectedMids], () => {
this.cancelSelection();
@ -358,7 +358,7 @@ export default class ChatSelection { @@ -358,7 +358,7 @@ export default class ChatSelection {
});
} else {
this.selectionForwardBtn = Button('btn-primary btn-transparent text-bold selection-container-forward', {icon: 'forward'});
_i18n(this.selectionForwardBtn, 'Forward');
this.selectionForwardBtn.append(i18n('Forward'));
this.listenerSetter.add(this.selectionForwardBtn, 'click', () => {
new PopupForward(this.bubbles.peerId, [...this.selectedMids], () => {
this.cancelSelection();
@ -367,7 +367,7 @@ export default class ChatSelection { @@ -367,7 +367,7 @@ export default class ChatSelection {
}
this.selectionDeleteBtn = Button('btn-primary btn-transparent danger text-bold selection-container-delete', {icon: 'delete'});
_i18n(this.selectionDeleteBtn, 'Delete');
this.selectionDeleteBtn.append(i18n('Delete'));
this.listenerSetter.add(this.selectionDeleteBtn, 'click', () => {
new PopupDeleteMessages(this.bubbles.peerId, [...this.selectedMids], this.chat.type, () => {
this.cancelSelection();

8
src/components/chat/sendContextMenu.ts

@ -19,17 +19,17 @@ export default class SendMenu { @@ -19,17 +19,17 @@ export default class SendMenu {
}) {
this.sendMenuButtons = [{
icon: 'mute',
text: 'Send Without Sound',
text: 'Chat.Send.WithoutSound',
onClick: options.onSilentClick,
verify: () => this.type === 'schedule'
}, {
icon: 'schedule',
text: 'Schedule Message',
text: 'Chat.Send.ScheduledMessage',
onClick: options.onScheduleClick,
verify: () => this.type === 'schedule'
}, {
icon: 'schedule',
text: 'Set a reminder',
text: 'Chat.Send.SetReminder',
onClick: options.onScheduleClick,
verify: () => this.type === 'reminder'
}];
@ -54,4 +54,4 @@ export default class SendMenu { @@ -54,4 +54,4 @@ export default class SendMenu {
public setPeerId(peerId: number) {
this.type = peerId === rootScope.myId ? 'reminder' : 'schedule';
}
};
};

30
src/components/chat/topbar.ts

@ -23,6 +23,7 @@ import appNavigationController from "../appNavigationController"; @@ -23,6 +23,7 @@ import appNavigationController from "../appNavigationController";
import { LEFT_COLUMN_ACTIVE_CLASSNAME } from "../sidebarLeft";
import AppPrivateSearchTab from "../sidebarRight/tabs/search";
import PeerTitle from "../peerTitle";
import { i18n } from "../../lib/langPack";
export default class ChatTopbar {
container: HTMLDivElement;
@ -203,14 +204,14 @@ export default class ChatTopbar { @@ -203,14 +204,14 @@ export default class ChatTopbar {
verify: () => this.chat.type === 'chat' && rootScope.myId !== this.peerId && this.appNotificationsManager.isPeerLocalMuted(this.peerId, false)
}, {
icon: 'select',
text: 'Select Messages',
text: 'Chat.Menu.SelectMessages',
onClick: () => {
this.chat.selection.toggleSelection(true, true);
},
verify: () => !this.chat.selection.isSelecting && !!Object.keys(this.chat.bubbles.bubbles).length
}, {
icon: 'select',
text: 'Clear Selection',
text: 'Chat.Menu.ClearSelection',
onClick: () => {
this.chat.selection.cancelSelection();
},
@ -250,7 +251,7 @@ export default class ChatTopbar { @@ -250,7 +251,7 @@ export default class ChatTopbar {
this.pinnedMessage = new ChatPinnedMessage(this, this.chat, this.appMessagesManager, this.appPeersManager);
this.btnJoin = Button('btn-primary btn-color-primary chat-join hide');
this.btnJoin.append('SUBSCRIBE');
this.btnJoin.append(i18n('Chat.Subscribe'));
this.btnPinned = ButtonIcon('pinlist');
this.btnMute = ButtonIcon('mute');
@ -437,10 +438,10 @@ export default class ChatTopbar { @@ -437,10 +438,10 @@ export default class ChatTopbar {
}
public setTitle(count?: number) {
let title = '';
let titleEl: HTMLElement;
if(this.chat.type === 'pinned') {
title = [count > 1 ? count : false, 'Pinned Messages'].filter(Boolean).join(' ');
titleEl = i18n('PinnedMessagesCount', [count]);
if(count === undefined) {
this.appMessagesManager.getSearchCounters(this.peerId, [{_: 'inputMessagesFilterPinned'}]).then(result => {
const count = result[0].count;
@ -460,9 +461,11 @@ export default class ChatTopbar { @@ -460,9 +461,11 @@ export default class ChatTopbar {
}
} else if(this.chat.type === 'scheduled') {
if(this.peerId === rootScope.myId) {
title = [count > 1 ? count : false, 'Reminders'].filter(Boolean).join(' ');
//title = [count > 1 ? count : false, 'Reminders'].filter(Boolean).join(' ');
titleEl = i18n('Reminders');
} else {
title = [count > 1 ? count : false, 'Scheduled Messages'].filter(Boolean).join(' ');
titleEl = i18n('ScheduledMessages');
//title = [count > 1 ? count : false, 'Scheduled Messages'].filter(Boolean).join(' ');
}
if(count === undefined) {
@ -471,7 +474,7 @@ export default class ChatTopbar { @@ -471,7 +474,7 @@ export default class ChatTopbar {
});
}
} else if(this.chat.type === 'discussion') {
title = [count > 1 ? count : false, 'Comments'].filter(Boolean).join(' ');
titleEl = i18n('Chat.Title.Comments', [count]);
if(count === undefined) {
Promise.all([
@ -482,15 +485,14 @@ export default class ChatTopbar { @@ -482,15 +485,14 @@ export default class ChatTopbar {
});
}
} else if(this.chat.type === 'chat') {
this.title.innerHTML = '';
this.title.append(new PeerTitle({
titleEl = new PeerTitle({
peerId: this.peerId,
dialog: true,
}).element);
return;
}).element;
}
this.title.innerHTML = title;
this.title.textContent = '';
this.title.append(titleEl);
}
public setMutedState() {

8
src/components/inputField.ts

@ -97,7 +97,7 @@ class InputField { @@ -97,7 +97,7 @@ class InputField {
}
this.container.innerHTML = `
<div ${placeholder ? `data-placeholder="${placeholder}"` : ''} contenteditable="true" class="input-field-input"></div>
<div contenteditable="true" class="input-field-input"></div>
`;
input = this.container.firstElementChild as HTMLElement;
@ -139,10 +139,10 @@ class InputField { @@ -139,10 +139,10 @@ class InputField {
input = this.container.firstElementChild as HTMLElement;
input.addEventListener('input', () => checkAndSetRTL(input));
}
if(placeholder) {
_i18n(input, placeholder, undefined, 'placeholder');
}
if(placeholder) {
_i18n(input, placeholder, undefined, 'placeholder');
}
if(label) {

58
src/components/popups/datePicker.ts

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
import PopupElement, { PopupOptions } from ".";
import { getFullDate, months } from "../../helpers/date";
import { getFullDate } from "../../helpers/date";
import mediaSizes from "../../helpers/mediaSizes";
import I18n from "../../lib/langPack";
import InputField from "../inputField";
export default class PopupDatePicker extends PopupElement {
@ -33,14 +34,14 @@ export default class PopupDatePicker extends PopupElement { @@ -33,14 +34,14 @@ export default class PopupDatePicker extends PopupElement {
showOverflowMonths: true
}> & PopupOptions = {}) {
super('popup-date-picker', options.noButtons ? [] : [{
text: 'JUMP TO DATE',
langKey: 'JumpToDate',
callback: () => {
if(this.onPick) {
this.onPick(this.selectedDate.getTime() / 1000 | 0);
}
}
}, {
text: 'CANCEL',
langKey: 'Cancel',
isCancel: true
}], {body: true, overlayClosable: true, ...options});
@ -257,11 +258,20 @@ export default class PopupDatePicker extends PopupElement { @@ -257,11 +258,20 @@ export default class PopupDatePicker extends PopupElement {
}
public setTitle() {
const splitted = this.selectedDate.toString().split(' ', 3);
this.title.innerText = splitted[0] + ', ' + splitted[1] + ' ' + splitted[2];
//const splitted = this.selectedDate.toString().split(' ', 3);
//this.title.innerText = splitted[0] + ', ' + splitted[1] + ' ' + splitted[2];
this.title.textContent = '';
this.title.append(new I18n.IntlDateElement({
date: this.selectedDate,
options: {
day: 'numeric',
month: 'long',
weekday: 'short'
}
}).element);
}
private renderElement(disabled: boolean, innerText = '') {
private renderElement(disabled: boolean, innerText: string | HTMLElement = '') {
const el = document.createElement('button');
el.classList.add('btn-icon', 'date-picker-month-date');
@ -270,15 +280,23 @@ export default class PopupDatePicker extends PopupElement { @@ -270,15 +280,23 @@ export default class PopupDatePicker extends PopupElement {
}
if(innerText) {
el.innerText = innerText;
el.append(innerText);
}
return el;
}
public setMonth() {
const monthName = months[this.selectedMonth.getMonth()];
this.monthTitle.innerText = (this.timeDiv && mediaSizes.isMobile ? monthName.slice(0, 3) : monthName) + ' ' + this.selectedMonth.getFullYear();
const firstDate = new Date(this.selectedMonth);
const options: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: this.timeDiv && mediaSizes.isMobile ? 'short' : 'long'
};
this.monthTitle.textContent = '';
this.monthTitle.append(new I18n.IntlDateElement({date: firstDate, options}).element);
//this.monthTitle.innerText = (this.timeDiv && mediaSizes.isMobile ? monthName.slice(0, 3) : monthName) + ' ' + this.selectedMonth.getFullYear();
if(this.month) {
this.month.remove();
@ -287,19 +305,23 @@ export default class PopupDatePicker extends PopupElement { @@ -287,19 +305,23 @@ export default class PopupDatePicker extends PopupElement {
this.month = document.createElement('div');
this.month.classList.add('date-picker-month');
const days = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
this.month.append(...days.map(s => {
const el = this.renderElement(true, s);
const weekStartDate = new Date();
const day = weekStartDate.getDay();
if(day !== 1) {
weekStartDate.setHours(-24 * (day - 1));
}
for(let i = 0; i < 7; ++i) {
const el = this.renderElement(true, new I18n.IntlDateElement({date: weekStartDate, options: {weekday: 'narrow'}}).element);
el.classList.remove('date-picker-month-date');
el.classList.add('date-picker-month-day');
return el;
}));
const firstDate = new Date(this.selectedMonth);
this.month.append(el);
weekStartDate.setDate(weekStartDate.getDate() + 1);
}
// 0 - sunday
let dayIndex = firstDate.getDay() - 1;
if(dayIndex === -1) dayIndex = days.length - 1;
if(dayIndex === -1) dayIndex = 7 - 1;
const clonedDate = new Date(firstDate.getTime());
clonedDate.setDate(clonedDate.getDate() - dayIndex - 1);
@ -342,4 +364,4 @@ export default class PopupDatePicker extends PopupElement { @@ -342,4 +364,4 @@ export default class PopupDatePicker extends PopupElement {
this.monthsContainer.append(this.month);
}
}
}

4
src/components/popups/index.ts

@ -17,7 +17,7 @@ export type PopupButton = { @@ -17,7 +17,7 @@ export type PopupButton = {
export type PopupOptions = Partial<{
closable: true,
overlayClosable: true,
withConfirm: string,
withConfirm: LangPackKey,
body: true
}>;
@ -69,7 +69,7 @@ export default class PopupElement { @@ -69,7 +69,7 @@ export default class PopupElement {
if(options.withConfirm) {
this.btnConfirm = document.createElement('button');
this.btnConfirm.classList.add('btn-primary', 'btn-color-primary');
this.btnConfirm.innerText = options.withConfirm;
this.btnConfirm.append(i18n(options.withConfirm));
this.header.append(this.btnConfirm);
ripple(this.btnConfirm);
}

30
src/components/popups/newMedia.ts

@ -10,6 +10,7 @@ import CheckboxField from "../checkboxField"; @@ -10,6 +10,7 @@ import CheckboxField from "../checkboxField";
import SendContextMenu from "../chat/sendContextMenu";
import { createPosterForVideo, createPosterFromVideo, onVideoLoad } from "../../helpers/files";
import { MyDocument } from "../../lib/appManagers/appDocsManager";
import I18n, { i18n, LangPackKey } from "../../lib/langPack";
type SendFileParams = Partial<{
file: File,
@ -43,7 +44,7 @@ export default class PopupNewMedia extends PopupElement { @@ -43,7 +44,7 @@ export default class PopupNewMedia extends PopupElement {
inputField: InputField;
constructor(private chat: Chat, files: File[], willAttachType: PopupNewMedia['willAttach']['type']) {
super('popup-send-photo popup-new-media', null, {closable: true, withConfirm: 'SEND'});
super('popup-send-photo popup-new-media', null, {closable: true, withConfirm: 'PreviewSender.Send'});
this.willAttach.type = willAttachType;
@ -75,7 +76,7 @@ export default class PopupNewMedia extends PopupElement { @@ -75,7 +76,7 @@ export default class PopupNewMedia extends PopupElement {
scrollable.container.append(this.mediaContainer);
this.inputField = new InputField({
placeholder: 'Add a caption...',
placeholder: 'PreviewSender.CaptionPlaceholder',
label: 'Caption',
name: 'photo-caption',
maxLength: MAX_LENGTH_CAPTION,
@ -90,7 +91,7 @@ export default class PopupNewMedia extends PopupElement { @@ -90,7 +91,7 @@ export default class PopupNewMedia extends PopupElement {
if(files.length > 1) {
this.groupCheckboxField = new CheckboxField({
text: 'Group items',
text: 'PreviewSender.GroupItems',
name: 'group-items'
});
this.container.append(this.groupCheckboxField.label, this.inputField.container);
@ -138,7 +139,7 @@ export default class PopupNewMedia extends PopupElement { @@ -138,7 +139,7 @@ export default class PopupNewMedia extends PopupElement {
let caption = this.inputField.value;
if(caption.length > MAX_LENGTH_CAPTION) {
toast('Caption is too long.');
toast(I18n.format('Error.PreviewSender.CaptionTooLong', true));
return;
}
@ -350,8 +351,11 @@ export default class PopupNewMedia extends PopupElement { @@ -350,8 +351,11 @@ export default class PopupNewMedia extends PopupElement {
this.mediaContainer.innerHTML = '';
if(files.length) {
let key: LangPackKey;
const args: any[] = [];
if(willAttach.type === 'document') {
this.title.innerText = 'Send ' + (files.length > 1 ? files.length + ' Files' : 'File');
key = 'PreviewSender.SendFile';
args.push(files.length);
container.classList.add('is-document');
} else {
container.classList.add('is-media');
@ -363,14 +367,22 @@ export default class PopupNewMedia extends PopupElement { @@ -363,14 +367,22 @@ export default class PopupNewMedia extends PopupElement {
else if(file.type.indexOf('video/') === 0) ++foundVideos;
});
if(foundPhotos && foundVideos && willAttach.group) {
this.title.innerText = 'Send Album';
const sum = foundPhotos + foundVideos;
if(sum > 1 && willAttach.group) {
key = 'PreviewSender.SendAlbum';
const albumsLength = Math.ceil(sum / 10);
args.push(albumsLength);
} else if(foundPhotos) {
this.title.innerText = 'Send ' + (foundPhotos > 1 ? foundPhotos + ' Photos' : 'Photo');
key = 'PreviewSender.SendPhoto';
args.push(foundPhotos);
} else if(foundVideos) {
this.title.innerText = 'Send ' + (foundVideos > 1 ? foundVideos + ' Videos' : 'Video');
key = 'PreviewSender.SendVideo';
args.push(foundVideos);
}
}
this.title.textContent = '';
this.title.append(i18n(key, args));
}
if(willAttach.type === 'media') {

12
src/components/sidebarLeft/tabs/archivedTab.ts

@ -2,6 +2,7 @@ import appDialogsManager from "../../../lib/appManagers/appDialogsManager"; @@ -2,6 +2,7 @@ import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
import { SliderSuperTab } from "../../slider";
export default class AppArchivedTab extends SliderSuperTab {
public static filterId = 1;
public loadedAll: boolean;
public loadDialogsPromise: Promise<any>;
public wasFilterId: number;
@ -11,13 +12,14 @@ export default class AppArchivedTab extends SliderSuperTab { @@ -11,13 +12,14 @@ export default class AppArchivedTab extends SliderSuperTab {
this.setTitle('ArchivedChats');
//this.scrollable = new Scrollable(this.container, 'CLA', 500);
this.scrollable.append(appDialogsManager.chatListArchived);
const chatList = appDialogsManager.chatLists[AppArchivedTab.filterId];
this.scrollable.append(chatList);
this.scrollable.container.addEventListener('scroll', appDialogsManager.onChatsRegularScroll);
this.scrollable.setVirtualContainer(appDialogsManager.chatListArchived);
this.scrollable.setVirtualContainer(chatList);
this.scrollable.onScrolledBottom = appDialogsManager.onChatsScroll;
///this.scroll.attachSentinels();
appDialogsManager.setListClickListener(appDialogsManager.chatListArchived, null, true);
appDialogsManager.setListClickListener(chatList, null, true);
window.addEventListener('resize', () => {
setTimeout(appDialogsManager.scroll.checkForTriggers, 0);
@ -32,7 +34,7 @@ export default class AppArchivedTab extends SliderSuperTab { @@ -32,7 +34,7 @@ export default class AppArchivedTab extends SliderSuperTab {
this.wasFilterId = appDialogsManager.filterId;
appDialogsManager.scroll = this.scrollable;
appDialogsManager.filterId = 1;
appDialogsManager.filterId = AppArchivedTab.filterId;
appDialogsManager.onTabChange();
}
@ -48,7 +50,7 @@ export default class AppArchivedTab extends SliderSuperTab { @@ -48,7 +50,7 @@ export default class AppArchivedTab extends SliderSuperTab {
}
onCloseAfterTimeout() {
appDialogsManager.chatListArchived.innerHTML = '';
appDialogsManager.chatLists[AppArchivedTab.filterId].innerHTML = '';
return super.onCloseAfterTimeout();
}
}

10
src/index.hbs

@ -106,15 +106,9 @@ @@ -106,15 +106,9 @@
<div class="sidebar-content transition zoom-fade">
<div class="transition-item active" id="chatlist-container">
<div class="folders-tabs-scrollable menu-horizontal-scrollable hide">
<nav class="menu-horizontal-div" id="folders-tabs">
<div class="menu-horizontal-div-item rp"><span><span class="text-super">All</span><div class="badge badge-20 badge-blue"></div><i></i></span></div>
</nav>
</div>
<div class="tabs-container" id="folders-container">
<div>
<ul id="dialogs" class="chatlist chatlist-72"></ul>
</div>
<nav class="menu-horizontal-div" id="folders-tabs"></nav>
</div>
<div class="tabs-container" id="folders-container"></div>
</div>
<div class="transition-item sidebar-search" id="search-container"></div>
<button class="btn-circle rp btn-corner tgico-newchat_filled btn-menu-toggle" id="new-menu"></button>

54
src/lang.ts

@ -24,6 +24,12 @@ const lang = { @@ -24,6 +24,12 @@ const lang = {
"EditProfile.Username.Help": "You can choose a username on Telegram. If you do, people will be able to find you by this username and contact you without needing your phone number.\n\nYou can use a–z, 0–9 and underscores. Minimum length is 5 characters.",
"ExceptionModal.Search.Placeholder": "Add exception...",
"ChatList.Menu.Archived": "Archived",
"Chat.Menu.SelectMessages": "Select Messages",
"Chat.Menu.ClearSelection": "Clear Selection",
"Chat.Input.UnpinAll": "Unpin All Messages",
"Chat.Input.Attach.PhotoOrVideo": "Photo or Video",
"Chat.Input.Attach.Document": "Document",
"Chat.Subscribe": "SUBSCRIBE",
"Chat.Selection.MessagesCount": {
"one_value": "%d Message",
"other_value": "%d Messages",
@ -49,6 +55,13 @@ const lang = { @@ -49,6 +55,13 @@ const lang = {
"Message.Context.Selection.SendNow": "Send Now selected",
"Checkbox.Enabled": "Enabled",
"Checkbox.Disabled": "Disabled",
"Error.PreviewSender.CaptionTooLong": "Caption is too long.",
"PreviewSender.GroupItems": "Group items",
"PreviewSender.Send": "SEND",
"PreviewSender.SendAlbum": {
"one_value": "Send Album",
"other_value": "Send %d Albums"
},
"Privacy.Devices": {
"one_value": "%1$d device",
"other_value": "%1$d devices"
@ -155,6 +168,12 @@ const lang = { @@ -155,6 +168,12 @@ const lang = {
"BlockedUsersInfo": "Blocked users will not be able to contact you and will not see your Last Seen time.",
"BlockedEmpty": "None",
"TwoStepVerification": "Two-Step Verification",
"PinnedMessage": "Pinned Message",
"PinnedMessagesCount": {
"one_value": "Pinned Message",
"other_value": "%1$d Pinned Messages"
},
//"PreviousPinnedMessage": "Previous Message",
"PrivacyExceptions": "Exceptions",
"PrivacyLastSeen": "Last Seen & Online",
"PrivacySettings": "Privacy and Security",
@ -168,6 +187,8 @@ const lang = { @@ -168,6 +187,8 @@ const lang = {
"PrivacyProfilePhotoTitle": "Who can see my profile photos & videos?",
"PrivacyP2PHeader": "Peer-to-Peer",
"PrivacyForwardsTitle": "Who can add a link to my account when forwarding my messages?",
"Reminders": "Reminders",
"ScheduledMessages": "Scheduled Messages",
"LastSeenTitle": "Who can see your Last Seen time?",
"SessionsTitle": "Active Sessions",
"CurrentSession": "This device",
@ -197,6 +218,10 @@ const lang = { @@ -197,6 +218,10 @@ const lang = {
"GroupAddMembers": "Add Members",
"SendMessageTo": "Add people...",
"SelectChat": "Select Chat",
"JumpToDate": "Jump to Date",
"Caption": "Caption",
"Message": "Message",
"Poll": "Poll",
// * macos
"AccountSettings.Filters": "Chat Folders",
@ -216,8 +241,20 @@ const lang = { @@ -216,8 +241,20 @@ const lang = {
"Chat.Service.BotPermissionAllowed": "You allowed this bot to message you when you logged in on %@",
"Chat.Poll.Unvote": "Retract Vote",
"Chat.Poll.Stop": "Stop Poll",
"Chat.Poll.Stop.Confirm.Header": "Stop Poll?",
"Chat.Poll.Stop.Confirm.Text": "If you stop this poll now, nobody will be able to vote in it anymore. This action cannot be undone.",
/* "Chat.Poll.Stop.Confirm.Header": "Stop Poll?",
"Chat.Poll.Stop.Confirm.Text": "If you stop this poll now, nobody will be able to vote in it anymore. This action cannot be undone.", */
/* "Chat.Pinned.UnpinAll": {
"one_value": "Unpin %d Message",
"other_value": "Unpin All %d Messages"
}, */
"Chat.Pinned.DontShow": "Don't Show Pinned Messages",
"Chat.Title.Comments": {
"one_value": "%d Comment",
"other_value": "%d Comments"
},
"Chat.Send.WithoutSound": "Send Without Sound",
"Chat.Send.SetReminder": "Set a Reminder",
"Chat.Send.ScheduledMessage": "Schedule Message",
"ChatList.Context.Mute": "Mute",
"ChatList.Context.Unmute": "Unmute",
"ChatList.Context.Pin": "Pin",
@ -254,6 +291,19 @@ const lang = { @@ -254,6 +291,19 @@ const lang = {
"Stickers.SuggestStickers": "Suggest Stickers by Emoji",
"ShareModal.Search.ForwardPlaceholder": "Forward to...",
"InstalledStickers.LoopAnimated": "Loop Animated Stickers",
"PreviewSender.CaptionPlaceholder": "Add a caption...",
"PreviewSender.SendFile": {
"one_value": "Send File",
"other_value": "Send %d Files"
},
"PreviewSender.SendPhoto": {
"one_value": "Send Photo",
"other_value": "Send %d Photos"
},
"PreviewSender.SendVideo": {
"one_value": "Send Video",
"other_value": "Send %d Videos"
},
"PrivacyAndSecurity.Item.On": "On",
"PrivacyAndSecurity.Item.Off": "Off",
"PrivacySettings.VoiceCalls": "Calls",

35
src/lib/appManagers/appDialogsManager.ts

@ -177,9 +177,7 @@ class ConnectionStatusComponent { @@ -177,9 +177,7 @@ class ConnectionStatusComponent {
}
export class AppDialogsManager {
public _chatList = document.getElementById('dialogs') as HTMLUListElement;
public chatList = this._chatList;
public chatListArchived: HTMLUListElement;
public chatList: HTMLUListElement;
public doms: {[peerId: number]: DialogDom} = {};
@ -196,7 +194,7 @@ export class AppDialogsManager { @@ -196,7 +194,7 @@ export class AppDialogsManager {
public contextMenu = new DialogsContextMenu();
public chatLists: {[filterId: number]: HTMLUListElement};
public filterId = 0;
public filterId: number;
private folders: {[k in 'menu' | 'container' | 'menuScrollContainer']: HTMLElement} = {
menu: document.getElementById('folders-tabs'),
menuScrollContainer: null,
@ -223,12 +221,8 @@ export class AppDialogsManager { @@ -223,12 +221,8 @@ export class AppDialogsManager {
private lastActiveElements: Set<HTMLElement> = new Set();
constructor() {
this.chatListArchived = this.createChatList();
this.chatListArchived.id = 'dialogs-archived';
this.chatLists = {
0: this.chatList,
1: this.chatListArchived
1: this.createChatList()
};
this.chatsPreloader = putPreloader(null, true);
@ -245,7 +239,6 @@ export class AppDialogsManager { @@ -245,7 +239,6 @@ export class AppDialogsManager {
this.scroll.container.addEventListener('scroll', this.onChatsRegularScroll);
this.scroll.onScrolledTop = this.onChatsScrollTop;
this.scroll.onScrolledBottom = this.onChatsScroll;
this.scroll.setVirtualContainer(this.chatList);
//this.scroll.attachSentinels();
/* if(isTouchSupported && isSafari) {
@ -270,7 +263,16 @@ export class AppDialogsManager { @@ -270,7 +263,16 @@ export class AppDialogsManager {
});
} */
this.setListClickListener(this.chatList, null, true);
this.filterId = 0;
this.addFilter({
id: this.filterId,
title: '',
titleEl: i18n('ChatList.Filter.All'),
orderIndex: 0
});
this.chatList = this.chatLists[this.filterId];
this.scroll.setVirtualContainer(this.chatList);
/* if(testScroll) {
let i = 0;
@ -523,12 +525,6 @@ export class AppDialogsManager { @@ -523,12 +525,6 @@ export class AppDialogsManager {
new ConnectionStatusComponent(this.chatsContainer);
this.chatsContainer.append(bottomPart);
/* const mutationObserver = new MutationObserver((mutationList, observer) => {
});
mutationObserver.observe */
}
private getOffset(side: 'top' | 'bottom'): {index: number, pos: number} {
@ -667,7 +663,7 @@ export class AppDialogsManager { @@ -667,7 +663,7 @@ export class AppDialogsManager {
}
}
private addFilter(filter: DialogFilter) {
private addFilter(filter: Pick<DialogFilter, 'title' | 'id' | 'orderIndex'> & Partial<{titleEl: HTMLElement}>) {
if(this.filtersRendered[filter.id]) return;
const menuTab = document.createElement('div');
@ -675,7 +671,8 @@ export class AppDialogsManager { @@ -675,7 +671,8 @@ export class AppDialogsManager {
const span = document.createElement('span');
const titleSpan = document.createElement('span');
titleSpan.classList.add('text-super');
titleSpan.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);
if(filter.titleEl) titleSpan.append(filter.titleEl);
else titleSpan.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);
const unreadSpan = document.createElement('div');
unreadSpan.classList.add('badge', 'badge-20', 'badge-blue');
const i = document.createElement('i');

8
src/lib/langPack.ts

@ -264,7 +264,13 @@ namespace I18n { @@ -264,7 +264,13 @@ namespace I18n {
this.element.textContent = '';
this.element.append(...format(this.key, false, this.args));
} else {
(this.element as HTMLInputElement)[this.property] = format(this.key, true, this.args);
// @ts-ignore
const v = this.element[this.property];
const formatted = format(this.key, true, this.args);
// * hasOwnProperty won't work here
if(v === undefined) this.element.dataset[this.property] = formatted;
else (this.element as HTMLInputElement)[this.property] = formatted;
}
}
}

36
src/scss/partials/_chat.scss

@ -364,6 +364,20 @@ $chat-helper-size: 39px; @@ -364,6 +364,20 @@ $chat-helper-size: 39px;
transition: opacity .1s 0s;
}
.pinned-container {
width: auto;
/* width: 17.125rem;
.chat-input.can-pin & {
width: 13.125rem;
} */
&-button {
height: 2.5rem;
padding: 0 .625rem;
}
}
.bubbles.is-selecting ~ & {
.new-message-wrapper {
pointer-events: none;
@ -704,12 +718,15 @@ $chat-helper-size: 39px; @@ -704,12 +718,15 @@ $chat-helper-size: 39px;
.rows-wrapper, .fake-rows-wrapper {
.chat-input.type-pinned & {
width: auto;
}
/* .chat-input.type-pinned & {
width: 17.125rem;
}
.chat-input.type-pinned.can-pin & {
width: 13.125rem;
}
} */
}
.fake-rows-wrapper {
@ -717,6 +734,10 @@ $chat-helper-size: 39px; @@ -717,6 +734,10 @@ $chat-helper-size: 39px;
left: var(--padding-horizontal);
top: 0;
width: calc(100% - var(--chat-input-size) - (var(--padding-horizontal) * 2) - .5625rem);
.pinned-container {
padding: 0 .5rem;
}
}
.rows-wrapper {
@ -876,19 +897,6 @@ $chat-helper-size: 39px; @@ -876,19 +897,6 @@ $chat-helper-size: 39px;
position: relative;
}
}
.pinned-container {
width: 17.125rem;
.chat-input.can-pin & {
width: 13.125rem;
}
&-button {
height: 2.5rem;
padding: 0;
}
}
.btn-icon {
flex: 0 0 auto;

15
src/scss/partials/_chatPinned.scss

@ -80,7 +80,7 @@ @@ -80,7 +80,7 @@
flex-direction: column;
justify-content: space-between;
}
&-title {
color: $color-blue;
}
@ -283,7 +283,6 @@ @@ -283,7 +283,6 @@
&.is-media {
.pinned-message-title, .pinned-message-subtitle {
transform: translateX(2.5rem);
width: calc(100% - 2.5rem);
//overflow: hidden !important;
}
}
@ -294,7 +293,11 @@ @@ -294,7 +293,11 @@
}
&:not(.is-floating) {
width: 15.5rem;
//width: 15.5rem;
.pinned-message-content {
margin-right: 2.5rem;
}
.pinned-message-close {
display: flex;
@ -303,6 +306,12 @@ @@ -303,6 +306,12 @@
}
&.is-floating {
&.is-media {
.pinned-message-title, .pinned-message-subtitle {
width: calc(100% - 2.5rem);
}
}
.chat:not(.type-discussion) & {
.pinned-container-wrapper {
padding-right: 3rem;

Loading…
Cancel
Save