Language tab
Save language
This commit is contained in:
parent
323b37d5e5
commit
585eb78ea2
@ -10,6 +10,7 @@ import Scrollable from "./scrollable";
|
|||||||
import { FocusDirection } from "../helpers/fastSmoothScroll";
|
import { FocusDirection } from "../helpers/fastSmoothScroll";
|
||||||
import CheckboxField from "./checkboxField";
|
import CheckboxField from "./checkboxField";
|
||||||
import appProfileManager from "../lib/appManagers/appProfileManager";
|
import appProfileManager from "../lib/appManagers/appProfileManager";
|
||||||
|
import { safeAssign } from "../helpers/object";
|
||||||
|
|
||||||
type PeerType = 'contacts' | 'dialogs' | 'channelParticipants';
|
type PeerType = 'contacts' | 'dialogs' | 'channelParticipants';
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ export default class AppSelectPeers {
|
|||||||
rippleEnabled?: boolean,
|
rippleEnabled?: boolean,
|
||||||
avatarSize?: AppSelectPeers['avatarSize'],
|
avatarSize?: AppSelectPeers['avatarSize'],
|
||||||
}) {
|
}) {
|
||||||
Object.assign(this, options);
|
safeAssign(this, options);
|
||||||
|
|
||||||
this.container.classList.add('selector');
|
this.container.classList.add('selector');
|
||||||
|
|
||||||
@ -440,7 +441,7 @@ export default class AppSelectPeers {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public add(peerId: any, title?: string, scroll = true) {
|
public add(peerId: any, title?: string | HTMLElement, scroll = true) {
|
||||||
//console.trace('add');
|
//console.trace('add');
|
||||||
this.selected.add(peerId);
|
this.selected.add(peerId);
|
||||||
|
|
||||||
@ -467,7 +468,12 @@ export default class AppSelectPeers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(title) {
|
if(title) {
|
||||||
div.innerHTML = title;
|
if(typeof(title) === 'string') {
|
||||||
|
div.innerHTML = title;
|
||||||
|
} else {
|
||||||
|
div.innerHTML = '';
|
||||||
|
div.append(title);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.insertAdjacentElement('afterbegin', avatarEl);
|
div.insertAdjacentElement('afterbegin', avatarEl);
|
||||||
|
@ -4,6 +4,7 @@ import AvatarElement from "./avatar";
|
|||||||
import InputField from "./inputField";
|
import InputField from "./inputField";
|
||||||
import ListenerSetter from "../helpers/listenerSetter";
|
import ListenerSetter from "../helpers/listenerSetter";
|
||||||
import Button from "./button";
|
import Button from "./button";
|
||||||
|
import { safeAssign } from "../helpers/object";
|
||||||
|
|
||||||
export default class EditPeer {
|
export default class EditPeer {
|
||||||
public nextBtn: HTMLButtonElement;
|
public nextBtn: HTMLButtonElement;
|
||||||
@ -23,7 +24,7 @@ export default class EditPeer {
|
|||||||
listenerSetter: ListenerSetter,
|
listenerSetter: ListenerSetter,
|
||||||
doNotEditAvatar?: boolean,
|
doNotEditAvatar?: boolean,
|
||||||
}) {
|
}) {
|
||||||
Object.assign(this, options);
|
safeAssign(this, options);
|
||||||
|
|
||||||
this.nextBtn = Button('btn-circle btn-corner tgico-check');
|
this.nextBtn = Button('btn-circle btn-corner tgico-check');
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { getRichValue, isInputEmpty } from "../helpers/dom";
|
import { getRichValue, isInputEmpty } from "../helpers/dom";
|
||||||
import { debounce } from "../helpers/schedulers";
|
import { debounce } from "../helpers/schedulers";
|
||||||
import { checkRTL } from "../helpers/string";
|
import { checkRTL } from "../helpers/string";
|
||||||
import { i18n_, LangPackKey } from "../lib/langPack";
|
import { i18n, LangPackKey } from "../lib/langPack";
|
||||||
import RichTextProcessor from "../lib/richtextprocessor";
|
import RichTextProcessor from "../lib/richtextprocessor";
|
||||||
|
|
||||||
let init = () => {
|
let init = () => {
|
||||||
@ -143,7 +143,7 @@ class InputField {
|
|||||||
|
|
||||||
if(label) {
|
if(label) {
|
||||||
this.label = document.createElement('label');
|
this.label = document.createElement('label');
|
||||||
i18n_({element: this.label, key: label});
|
this.label.append(i18n(label));
|
||||||
this.container.append(this.label);
|
this.container.append(this.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,9 +234,10 @@ class InputField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setState(state: InputState, label?: string) {
|
public setState(state: InputState, label?: LangPackKey) {
|
||||||
if(label) {
|
if(label) {
|
||||||
this.label.innerHTML = label;
|
this.label.innerHTML = '';
|
||||||
|
this.label.append(i18n(label));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.input.classList.toggle('error', !!(state & InputState.Error));
|
this.input.classList.toggle('error', !!(state & InputState.Error));
|
||||||
|
@ -2,6 +2,7 @@ import { isInDOM, cancelEvent, attachClickEvent } from "../helpers/dom";
|
|||||||
import { CancellablePromise } from "../helpers/cancellablePromise";
|
import { CancellablePromise } from "../helpers/cancellablePromise";
|
||||||
import SetTransition from "./singleTransition";
|
import SetTransition from "./singleTransition";
|
||||||
import { fastRaf } from "../helpers/schedulers";
|
import { fastRaf } from "../helpers/schedulers";
|
||||||
|
import { safeAssign } from "../helpers/object";
|
||||||
|
|
||||||
const TRANSITION_TIME = 200;
|
const TRANSITION_TIME = 200;
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ export default class ProgressivePreloader {
|
|||||||
attachMethod: ProgressivePreloader['attachMethod']
|
attachMethod: ProgressivePreloader['attachMethod']
|
||||||
}>) {
|
}>) {
|
||||||
if(options) {
|
if(options) {
|
||||||
Object.assign(this, options);
|
safeAssign(this, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ import AppContactsTab from "./tabs/contacts";
|
|||||||
import AppArchivedTab from "./tabs/archivedTab";
|
import AppArchivedTab from "./tabs/archivedTab";
|
||||||
import AppAddMembersTab from "./tabs/addMembers";
|
import AppAddMembersTab from "./tabs/addMembers";
|
||||||
import { i18n_, LangPackKey } from "../../lib/langPack";
|
import { i18n_, LangPackKey } from "../../lib/langPack";
|
||||||
|
import ButtonMenuToggle from "../buttonMenuToggle";
|
||||||
|
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
|
||||||
|
|
||||||
export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';
|
export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';
|
||||||
|
|
||||||
@ -34,14 +36,6 @@ export class AppSidebarLeft extends SidebarSlider {
|
|||||||
private inputSearch: InputSearch;
|
private inputSearch: InputSearch;
|
||||||
|
|
||||||
private menuEl: HTMLElement;
|
private menuEl: HTMLElement;
|
||||||
private buttons: {
|
|
||||||
newGroup: HTMLButtonElement,
|
|
||||||
contacts: HTMLButtonElement,
|
|
||||||
archived: HTMLButtonElement,
|
|
||||||
saved: HTMLButtonElement,
|
|
||||||
settings: HTMLButtonElement,
|
|
||||||
help: HTMLButtonElement
|
|
||||||
} = {} as any;
|
|
||||||
public archivedCount: HTMLSpanElement;
|
public archivedCount: HTMLSpanElement;
|
||||||
|
|
||||||
private newBtnMenu: HTMLElement;
|
private newBtnMenu: HTMLElement;
|
||||||
@ -68,58 +62,87 @@ export class AppSidebarLeft extends SidebarSlider {
|
|||||||
const sidebarHeader = this.sidebarEl.querySelector('.item-main .sidebar-header');
|
const sidebarHeader = this.sidebarEl.querySelector('.item-main .sidebar-header');
|
||||||
sidebarHeader.append(this.inputSearch.container);
|
sidebarHeader.append(this.inputSearch.container);
|
||||||
|
|
||||||
|
const onNewGroupClick = () => {
|
||||||
|
new AppAddMembersTab(this).open({
|
||||||
|
peerId: 0,
|
||||||
|
type: 'chat',
|
||||||
|
skippable: false,
|
||||||
|
takeOut: (peerIds) => {
|
||||||
|
new AppNewGroupTab(this).open(peerIds);
|
||||||
|
},
|
||||||
|
title: 'Add Members',
|
||||||
|
placeholder: 'Add People...'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onContactsClick = () => {
|
||||||
|
new AppContactsTab(this).open();
|
||||||
|
};
|
||||||
|
|
||||||
this.toolsBtn = this.sidebarEl.querySelector('.sidebar-tools-button') as HTMLButtonElement;
|
this.toolsBtn = this.sidebarEl.querySelector('.sidebar-tools-button') as HTMLButtonElement;
|
||||||
this.backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement;
|
this.backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement;
|
||||||
|
|
||||||
|
const btnArchive: ButtonMenuItemOptions = {
|
||||||
|
icon: 'archive',
|
||||||
|
text: 'Archived',
|
||||||
|
onClick: () => {
|
||||||
|
new AppArchivedTab(this).open();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const btnMenu = ButtonMenu([{
|
||||||
|
icon: 'newgroup',
|
||||||
|
text: 'New Group',
|
||||||
|
onClick: onNewGroupClick
|
||||||
|
}, {
|
||||||
|
icon: 'user',
|
||||||
|
text: 'Contacts',
|
||||||
|
onClick: onContactsClick
|
||||||
|
}, btnArchive, {
|
||||||
|
icon: 'savedmessages',
|
||||||
|
text: 'Saved',
|
||||||
|
onClick: () => {
|
||||||
|
setTimeout(() => { // menu doesn't close if no timeout (lol)
|
||||||
|
appImManager.setPeer(appImManager.myId);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
icon: 'settings',
|
||||||
|
text: 'Settings',
|
||||||
|
onClick: () => {
|
||||||
|
new AppSettingsTab(this).open();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
icon: 'help btn-disabled',
|
||||||
|
text: 'Help',
|
||||||
|
onClick: () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
btnMenu.classList.add('bottom-right');
|
||||||
|
|
||||||
|
this.toolsBtn.append(btnMenu);
|
||||||
|
|
||||||
this.menuEl = this.toolsBtn.querySelector('.btn-menu');
|
this.menuEl = this.toolsBtn.querySelector('.btn-menu');
|
||||||
this.newBtnMenu = this.sidebarEl.querySelector('#new-menu');
|
this.newBtnMenu = this.sidebarEl.querySelector('#new-menu');
|
||||||
|
|
||||||
this.inputSearch.input.addEventListener('focus', () => this.initSearch(), {once: true});
|
this.inputSearch.input.addEventListener('focus', () => this.initSearch(), {once: true});
|
||||||
|
|
||||||
parseMenuButtonsTo(this.buttons, this.menuEl.children);
|
|
||||||
parseMenuButtonsTo(this.newButtons, this.newBtnMenu.firstElementChild.children);
|
parseMenuButtonsTo(this.newButtons, this.newBtnMenu.firstElementChild.children);
|
||||||
|
|
||||||
this.archivedCount = this.buttons.archived.querySelector('.archived-count') as HTMLSpanElement;
|
this.archivedCount = document.createElement('span');
|
||||||
|
this.archivedCount.className = 'archived-count badge badge-24 badge-gray';
|
||||||
|
|
||||||
attachClickEvent(this.buttons.saved, (e) => {
|
btnArchive.element.append(this.archivedCount);
|
||||||
///////this.log('savedbtn click');
|
|
||||||
setTimeout(() => { // menu doesn't close if no timeout (lol)
|
|
||||||
appImManager.setPeer(appImManager.myId);
|
|
||||||
}, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
attachClickEvent(this.buttons.archived, (e) => {
|
|
||||||
new AppArchivedTab(this).open();
|
|
||||||
});
|
|
||||||
|
|
||||||
[this.newButtons.privateChat, this.buttons.contacts].forEach(btn => {
|
attachClickEvent(this.newButtons.privateChat, onContactsClick);
|
||||||
attachClickEvent(btn, (e) => {
|
|
||||||
new AppContactsTab(this).open();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
attachClickEvent(this.buttons.settings, (e) => {
|
|
||||||
new AppSettingsTab(this).open();
|
|
||||||
});
|
|
||||||
|
|
||||||
attachClickEvent(this.newButtons.channel, (e) => {
|
attachClickEvent(this.newButtons.channel, (e) => {
|
||||||
new AppNewChannelTab(this).open();
|
new AppNewChannelTab(this).open();
|
||||||
});
|
});
|
||||||
|
|
||||||
[this.newButtons.group, this.buttons.newGroup].forEach(btn => {
|
attachClickEvent(this.newButtons.group, onNewGroupClick);
|
||||||
attachClickEvent(btn, (e) => {
|
|
||||||
new AppAddMembersTab(this).open({
|
|
||||||
peerId: 0,
|
|
||||||
type: 'chat',
|
|
||||||
skippable: false,
|
|
||||||
takeOut: (peerIds) => {
|
|
||||||
new AppNewGroupTab(this).open(peerIds);
|
|
||||||
},
|
|
||||||
title: 'Add Members',
|
|
||||||
placeholder: 'Add People...'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
rootScope.on('dialogs_archived_unread', (e) => {
|
rootScope.on('dialogs_archived_unread', (e) => {
|
||||||
this.archivedCount.innerText = '' + formatNumber(e.count, 1);
|
this.archivedCount.innerText = '' + formatNumber(e.count, 1);
|
||||||
|
@ -13,6 +13,7 @@ import ButtonMenuToggle from "../../buttonMenuToggle";
|
|||||||
import { ButtonMenuItemOptions } from "../../buttonMenu";
|
import { ButtonMenuItemOptions } from "../../buttonMenu";
|
||||||
import Button from "../../button";
|
import Button from "../../button";
|
||||||
import AppIncludedChatsTab from "./includedChats";
|
import AppIncludedChatsTab from "./includedChats";
|
||||||
|
import { i18n, i18n_, LangPackKey } from "../../../lib/langPack";
|
||||||
|
|
||||||
const MAX_FOLDER_NAME_LENGTH = 12;
|
const MAX_FOLDER_NAME_LENGTH = 12;
|
||||||
|
|
||||||
@ -38,7 +39,8 @@ export default class AppEditFolderTab extends SliderSuperTab {
|
|||||||
this.container.classList.add('edit-folder-container');
|
this.container.classList.add('edit-folder-container');
|
||||||
this.caption = document.createElement('div');
|
this.caption = document.createElement('div');
|
||||||
this.caption.classList.add('caption');
|
this.caption.classList.add('caption');
|
||||||
this.caption.innerHTML = `Choose chats and types of chats that will<br>appear and never appear in this folder.`;
|
this.caption.append(i18n(`Choose chats and types of chats that will
|
||||||
|
appear and never appear in this folder.`));
|
||||||
this.stickerContainer = document.createElement('div');
|
this.stickerContainer = document.createElement('div');
|
||||||
this.stickerContainer.classList.add('sticker-container');
|
this.stickerContainer.classList.add('sticker-container');
|
||||||
|
|
||||||
@ -72,13 +74,13 @@ export default class AppEditFolderTab extends SliderSuperTab {
|
|||||||
|
|
||||||
inputWrapper.append(this.nameInputField.container);
|
inputWrapper.append(this.nameInputField.container);
|
||||||
|
|
||||||
const generateList = (className: string, h2Text: string, buttons: {icon: string, name?: string, withRipple?: true, text: string}[], to: any) => {
|
const generateList = (className: string, h2Text: LangPackKey, buttons: {icon: string, name?: string, withRipple?: true, text: string}[], to: any) => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.classList.add('folder-list', className);
|
container.classList.add('folder-list', className);
|
||||||
|
|
||||||
const h2 = document.createElement('div');
|
const h2 = document.createElement('div');
|
||||||
h2.classList.add('sidebar-left-h2');
|
h2.classList.add('sidebar-left-h2');
|
||||||
h2.innerHTML = h2Text;
|
i18n_({element: h2, key: h2Text});
|
||||||
|
|
||||||
const categories = document.createElement('div');
|
const categories = document.createElement('div');
|
||||||
categories.classList.add('folder-categories');
|
categories.classList.add('folder-categories');
|
||||||
@ -102,46 +104,46 @@ export default class AppEditFolderTab extends SliderSuperTab {
|
|||||||
return container;
|
return container;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.include_peers = generateList('folder-list-included', 'Included chats', [{
|
this.include_peers = generateList('folder-list-included', 'ChatList.Filter.Include.Header', [{
|
||||||
icon: 'add primary',
|
icon: 'add primary',
|
||||||
text: 'Add Chats',
|
text: 'ChatList.Filter.Include.AddChat',
|
||||||
withRipple: true
|
withRipple: true
|
||||||
}, {
|
}, {
|
||||||
text: 'Contacts',
|
text: 'ChatList.Filter.Contacts',
|
||||||
icon: 'newprivate',
|
icon: 'newprivate',
|
||||||
name: 'contacts'
|
name: 'contacts'
|
||||||
}, {
|
}, {
|
||||||
text: 'Non-Contacts',
|
text: 'ChatList.Filter.NonContacts',
|
||||||
icon: 'noncontacts',
|
icon: 'noncontacts',
|
||||||
name: 'non_contacts'
|
name: 'non_contacts'
|
||||||
}, {
|
}, {
|
||||||
text: 'Groups',
|
text: 'ChatList.Filter.Groups',
|
||||||
icon: 'group',
|
icon: 'group',
|
||||||
name: 'groups'
|
name: 'groups'
|
||||||
}, {
|
}, {
|
||||||
text: 'Channels',
|
text: 'ChatList.Filter.Channels',
|
||||||
icon: 'channel',
|
icon: 'channel',
|
||||||
name: 'broadcasts'
|
name: 'broadcasts'
|
||||||
}, {
|
}, {
|
||||||
text: 'Bots',
|
text: 'ChatList.Filter.Bots',
|
||||||
icon: 'bots',
|
icon: 'bots',
|
||||||
name: 'bots'
|
name: 'bots'
|
||||||
}], this.flags);
|
}], this.flags);
|
||||||
|
|
||||||
this.exclude_peers = generateList('folder-list-excluded', 'Excluded chats', [{
|
this.exclude_peers = generateList('folder-list-excluded', 'ChatList.Filter.Exclude.Header', [{
|
||||||
icon: 'minus primary',
|
icon: 'minus primary',
|
||||||
text: 'Remove Chats',
|
text: 'ChatList.Filter.Exclude.AddChat',
|
||||||
withRipple: true
|
withRipple: true
|
||||||
}, {
|
}, {
|
||||||
text: 'Muted',
|
text: 'ChatList.Filter.MutedChats',
|
||||||
icon: 'mute',
|
icon: 'mute',
|
||||||
name: 'exclude_muted'
|
name: 'exclude_muted'
|
||||||
}, {
|
}, {
|
||||||
text: 'Archived',
|
text: 'ChatList.Filter.Archive',
|
||||||
icon: 'archive',
|
icon: 'archive',
|
||||||
name: 'exclude_archived'
|
name: 'exclude_archived'
|
||||||
}, {
|
}, {
|
||||||
text: 'Read',
|
text: 'ChatList.Filter.ReadChats',
|
||||||
icon: 'readchats',
|
icon: 'readchats',
|
||||||
name: 'exclude_read'
|
name: 'exclude_read'
|
||||||
}], this.flags);
|
}], this.flags);
|
||||||
@ -225,7 +227,7 @@ export default class AppEditFolderTab extends SliderSuperTab {
|
|||||||
|
|
||||||
private onCreateOpen() {
|
private onCreateOpen() {
|
||||||
this.caption.style.display = '';
|
this.caption.style.display = '';
|
||||||
this.title.innerText = 'New Folder';
|
this.setTitle('New Folder');
|
||||||
this.menuBtn.classList.add('hide');
|
this.menuBtn.classList.add('hide');
|
||||||
this.confirmBtn.classList.remove('hide');
|
this.confirmBtn.classList.remove('hide');
|
||||||
this.nameInputField.value = '';
|
this.nameInputField.value = '';
|
||||||
@ -238,7 +240,7 @@ export default class AppEditFolderTab extends SliderSuperTab {
|
|||||||
|
|
||||||
private onEditOpen() {
|
private onEditOpen() {
|
||||||
this.caption.style.display = 'none';
|
this.caption.style.display = 'none';
|
||||||
this.title.innerText = this.type === 'create' ? 'New Folder' : 'Edit Folder';
|
this.setTitle(this.type === 'create' ? 'New Folder' : 'Edit Folder');
|
||||||
|
|
||||||
if(this.type === 'edit') {
|
if(this.type === 'edit') {
|
||||||
this.menuBtn.classList.remove('hide');
|
this.menuBtn.classList.remove('hide');
|
||||||
|
@ -5,7 +5,7 @@ import { SliderSuperTab } from "../../slider";
|
|||||||
import { attachClickEvent } from "../../../helpers/dom";
|
import { attachClickEvent } from "../../../helpers/dom";
|
||||||
import EditPeer from "../../editPeer";
|
import EditPeer from "../../editPeer";
|
||||||
import { UsernameInputField } from "../../usernameInputField";
|
import { UsernameInputField } from "../../usernameInputField";
|
||||||
import { i18n_ } from "../../../lib/langPack";
|
import { i18n, i18n_ } from "../../../lib/langPack";
|
||||||
|
|
||||||
// TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист)
|
// TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист)
|
||||||
|
|
||||||
@ -93,8 +93,21 @@ export default class AppEditProfileTab extends SliderSuperTab {
|
|||||||
|
|
||||||
const caption = document.createElement('div');
|
const caption = document.createElement('div');
|
||||||
caption.classList.add('caption');
|
caption.classList.add('caption');
|
||||||
caption.innerHTML = `You can choose a username on Telegram. If you do, other people will be able to find you by this username and contact you without knowing your phone number.<br><br>You can use a-z, 0-9 and underscores. Minimum length is 5 characters.<br><br><div class="profile-url-container">This link opens a chat with you:
|
caption.append(i18n('UsernameSettings.ChangeDescription'));
|
||||||
<br><a class="profile-url" href="#" target="_blank"></a></div>`;
|
caption.append(document.createElement('br'), document.createElement('br'));
|
||||||
|
|
||||||
|
const profileUrlContainer = this.profileUrlContainer = document.createElement('div');
|
||||||
|
profileUrlContainer.classList.add('profile-url-container');
|
||||||
|
profileUrlContainer.append(i18n('This link opens a chat with you:'));
|
||||||
|
|
||||||
|
const profileUrlAnchor = this.profileUrlAnchor = document.createElement('a');
|
||||||
|
profileUrlAnchor.classList.add('profile-url');
|
||||||
|
profileUrlAnchor.href = '#';
|
||||||
|
profileUrlAnchor.target = '_blank';
|
||||||
|
|
||||||
|
profileUrlContainer.append(profileUrlAnchor);
|
||||||
|
|
||||||
|
caption.append(profileUrlContainer);
|
||||||
|
|
||||||
this.profileUrlContainer = caption.querySelector('.profile-url-container');
|
this.profileUrlContainer = caption.querySelector('.profile-url-container');
|
||||||
this.profileUrlAnchor = this.profileUrlContainer.lastElementChild as HTMLAnchorElement;
|
this.profileUrlAnchor = this.profileUrlContainer.lastElementChild as HTMLAnchorElement;
|
||||||
|
@ -10,6 +10,7 @@ import ButtonIcon from "../../buttonIcon";
|
|||||||
import CheckboxField from "../../checkboxField";
|
import CheckboxField from "../../checkboxField";
|
||||||
import Button from "../../button";
|
import Button from "../../button";
|
||||||
import AppEditFolderTab from "./editFolder";
|
import AppEditFolderTab from "./editFolder";
|
||||||
|
import { i18n, LangPackKey, _i18n } from "../../../lib/langPack";
|
||||||
|
|
||||||
export default class AppIncludedChatsTab extends SliderSuperTab {
|
export default class AppIncludedChatsTab extends SliderSuperTab {
|
||||||
private editFolderTab: AppEditFolderTab;
|
private editFolderTab: AppEditFolderTab;
|
||||||
@ -123,7 +124,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
|||||||
dom.containerEl.append(this.checkbox(selected));
|
dom.containerEl.append(this.checkbox(selected));
|
||||||
if(selected) dom.listEl.classList.add('active');
|
if(selected) dom.listEl.classList.add('active');
|
||||||
|
|
||||||
let subtitle = '';
|
let subtitle: LangPackKey;
|
||||||
|
|
||||||
if(peerId > 0) {
|
if(peerId > 0) {
|
||||||
if(peerId === rootScope.myId) {
|
if(peerId === rootScope.myId) {
|
||||||
@ -137,7 +138,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
|||||||
subtitle = appPeersManager.isBroadcast(peerId) ? 'Channel' : 'Group';
|
subtitle = appPeersManager.isBroadcast(peerId) ? 'Channel' : 'Group';
|
||||||
}
|
}
|
||||||
|
|
||||||
dom.lastMessageSpan.innerHTML = subtitle;
|
_i18n(dom.lastMessageSpan, subtitle);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -148,14 +149,14 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.confirmBtn.style.display = this.type === 'excluded' ? '' : 'none';
|
this.confirmBtn.style.display = this.type === 'excluded' ? '' : 'none';
|
||||||
this.title.innerText = this.type === 'included' ? 'Included Chats' : 'Excluded Chats';
|
this.setTitle(this.type === 'included' ? 'Included Chats' : 'Excluded Chats');
|
||||||
|
|
||||||
const filter = this.filter;
|
const filter = this.filter;
|
||||||
|
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
const dd = document.createElement('div');
|
const dd = document.createElement('div');
|
||||||
dd.classList.add('sidebar-left-h2');
|
dd.classList.add('sidebar-left-h2');
|
||||||
dd.innerText = 'Chat types';
|
_i18n(dd, 'ChatList.Add.TopSeparator');
|
||||||
|
|
||||||
const categories = document.createElement('div');
|
const categories = document.createElement('div');
|
||||||
categories.classList.add('folder-categories');
|
categories.classList.add('folder-categories');
|
||||||
@ -163,17 +164,17 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
|||||||
let details: {[flag: string]: {ico: string, text: string}};
|
let details: {[flag: string]: {ico: string, text: string}};
|
||||||
if(this.type === 'excluded') {
|
if(this.type === 'excluded') {
|
||||||
details = {
|
details = {
|
||||||
exclude_muted: {ico: 'mute', text: 'Muted'},
|
exclude_muted: {ico: 'mute', text: 'ChatList.Filter.MutedChats'},
|
||||||
exclude_archived: {ico: 'archive', text: 'Archived'},
|
exclude_archived: {ico: 'archive', text: 'ChatList.Filter.Archive'},
|
||||||
exclude_read: {ico: 'readchats', text: 'Read'}
|
exclude_read: {ico: 'readchats', text: 'ChatList.Filter.ReadChats'}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
details = {
|
details = {
|
||||||
contacts: {ico: 'newprivate', text: 'Contacts'},
|
contacts: {ico: 'newprivate', text: 'ChatList.Filter.Contacts'},
|
||||||
non_contacts: {ico: 'noncontacts', text: 'Non-Contacts'},
|
non_contacts: {ico: 'noncontacts', text: 'ChatList.Filter.NonContacts'},
|
||||||
groups: {ico: 'group', text: 'Groups'},
|
groups: {ico: 'group', text: 'ChatList.Filter.Groups'},
|
||||||
broadcasts: {ico: 'newchannel', text: 'Channels'},
|
broadcasts: {ico: 'newchannel', text: 'ChatList.Filter.Channels'},
|
||||||
bots: {ico: 'bots', text: 'Bots'}
|
bots: {ico: 'bots', text: 'ChatList.Filter.Bots'}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
|||||||
|
|
||||||
const d = document.createElement('div');
|
const d = document.createElement('div');
|
||||||
d.classList.add('sidebar-left-h2');
|
d.classList.add('sidebar-left-h2');
|
||||||
d.innerText = 'Chats';
|
_i18n(d, 'ChatList.Add.BottomSeparator');
|
||||||
|
|
||||||
fragment.append(dd, categories, hr, d);
|
fragment.append(dd, categories, hr, d);
|
||||||
|
|
||||||
@ -210,7 +211,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
|||||||
|
|
||||||
const _add = this.selector.add.bind(this.selector);
|
const _add = this.selector.add.bind(this.selector);
|
||||||
this.selector.add = (peerId, title, scroll) => {
|
this.selector.add = (peerId, title, scroll) => {
|
||||||
const div = _add(peerId, details[peerId]?.text, scroll);
|
const div = _add(peerId, details[peerId] ? i18n(details[peerId].text) : undefined, scroll);
|
||||||
if(details[peerId]) {
|
if(details[peerId]) {
|
||||||
div.querySelector('avatar-element').classList.add('tgico-' + details[peerId].ico);
|
div.querySelector('avatar-element').classList.add('tgico-' + details[peerId].ico);
|
||||||
}
|
}
|
||||||
@ -256,4 +257,4 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
|
|||||||
|
|
||||||
return super.open();
|
return super.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
107
src/components/sidebarLeft/tabs/language.ts
Normal file
107
src/components/sidebarLeft/tabs/language.ts
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { SettingSection } from "..";
|
||||||
|
import { randomLong } from "../../../helpers/random";
|
||||||
|
import I18n from "../../../lib/langPack";
|
||||||
|
import RadioField from "../../radioField";
|
||||||
|
import Row, { RadioFormFromRows } from "../../row";
|
||||||
|
import { SliderSuperTab } from "../../slider"
|
||||||
|
|
||||||
|
export default class AppLanguageTab extends SliderSuperTab {
|
||||||
|
protected init() {
|
||||||
|
this.container.classList.add('language-container');
|
||||||
|
this.setTitle('Telegram.LanguageViewController');
|
||||||
|
|
||||||
|
const section = new SettingSection({});
|
||||||
|
|
||||||
|
const radioRows: Map<string, Row> = new Map();
|
||||||
|
|
||||||
|
let r = [{
|
||||||
|
code: 'en',
|
||||||
|
text: 'English',
|
||||||
|
subtitle: 'English'
|
||||||
|
}, {
|
||||||
|
code: 'be',
|
||||||
|
text: 'Belarusian',
|
||||||
|
subtitle: 'Беларуская'
|
||||||
|
}, {
|
||||||
|
code: 'ca',
|
||||||
|
text: 'Catalan',
|
||||||
|
subtitle: 'Català'
|
||||||
|
}, {
|
||||||
|
code: 'nl',
|
||||||
|
text: 'Dutch',
|
||||||
|
subtitle: 'Nederlands'
|
||||||
|
}, {
|
||||||
|
code: 'fr',
|
||||||
|
text: 'French',
|
||||||
|
subtitle: 'Français'
|
||||||
|
}, {
|
||||||
|
code: 'de',
|
||||||
|
text: 'German',
|
||||||
|
subtitle: 'Deutsch'
|
||||||
|
}, {
|
||||||
|
code: 'it',
|
||||||
|
text: 'Italian',
|
||||||
|
subtitle: 'Italiano'
|
||||||
|
}, {
|
||||||
|
code: 'ms',
|
||||||
|
text: 'Malay',
|
||||||
|
subtitle: 'Bahasa Melayu'
|
||||||
|
}, {
|
||||||
|
code: 'pl',
|
||||||
|
text: 'Polish',
|
||||||
|
subtitle: 'Polski'
|
||||||
|
}, {
|
||||||
|
code: 'pt',
|
||||||
|
text: 'Portuguese (Brazil)',
|
||||||
|
subtitle: 'Português (Brasil)'
|
||||||
|
}, {
|
||||||
|
code: 'ru',
|
||||||
|
text: 'Russian',
|
||||||
|
subtitle: 'Русский'
|
||||||
|
}, {
|
||||||
|
code: 'es',
|
||||||
|
text: 'Spanish',
|
||||||
|
subtitle: 'Español'
|
||||||
|
}, {
|
||||||
|
code: 'tr',
|
||||||
|
text: 'Turkish',
|
||||||
|
subtitle: 'Türkçe'
|
||||||
|
}, {
|
||||||
|
code: 'uk',
|
||||||
|
text: 'Ukrainian',
|
||||||
|
subtitle: 'Українська'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const random = randomLong();
|
||||||
|
r.forEach(({code, text, subtitle}) => {
|
||||||
|
const row = new Row({
|
||||||
|
radioField: new RadioField({
|
||||||
|
text,
|
||||||
|
name: random,
|
||||||
|
value: code
|
||||||
|
}),
|
||||||
|
subtitle
|
||||||
|
});
|
||||||
|
|
||||||
|
radioRows.set(code, row);
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = RadioFormFromRows([...radioRows.values()], (value) => {
|
||||||
|
I18n.getLangPack(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
I18n.getCacheLangPack().then(langPack => {
|
||||||
|
const row = radioRows.get(langPack.lang_code);
|
||||||
|
if(!row) {
|
||||||
|
console.error('no row', row, langPack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
row.radioField.setValueSilently(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
section.content.append(form);
|
||||||
|
|
||||||
|
this.scrollable.append(section.container);
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import AppEditProfileTab from "./editProfile";
|
|||||||
import AppChatFoldersTab from "./chatFolders";
|
import AppChatFoldersTab from "./chatFolders";
|
||||||
import AppNotificationsTab from "./notifications";
|
import AppNotificationsTab from "./notifications";
|
||||||
import PeerTitle from "../../peerTitle";
|
import PeerTitle from "../../peerTitle";
|
||||||
|
import AppLanguageTab from "./language";
|
||||||
//import AppMediaViewer from "../../appMediaViewerNew";
|
//import AppMediaViewer from "../../appMediaViewerNew";
|
||||||
|
|
||||||
export default class AppSettingsTab extends SliderSuperTab {
|
export default class AppSettingsTab extends SliderSuperTab {
|
||||||
@ -28,7 +29,7 @@ export default class AppSettingsTab extends SliderSuperTab {
|
|||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.container.classList.add('settings-container');
|
this.container.classList.add('settings-container');
|
||||||
this.title.innerText = 'Settings';
|
this.setTitle('Settings');
|
||||||
|
|
||||||
const btnMenu = ButtonMenuToggle({}, 'bottom-left', [{
|
const btnMenu = ButtonMenuToggle({}, 'bottom-left', [{
|
||||||
icon: 'logout',
|
icon: 'logout',
|
||||||
@ -130,6 +131,10 @@ export default class AppSettingsTab extends SliderSuperTab {
|
|||||||
this.buttons.privacy.addEventListener('click', () => {
|
this.buttons.privacy.addEventListener('click', () => {
|
||||||
new AppPrivacyAndSecurityTab(this.slider).open();
|
new AppPrivacyAndSecurityTab(this.slider).open();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.buttons.language.addEventListener('click', () => {
|
||||||
|
new AppLanguageTab(this.slider).open();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public fillElements() {
|
public fillElements() {
|
||||||
|
@ -3,6 +3,7 @@ import { horizontalMenu } from "./horizontalMenu";
|
|||||||
import { TransitionSlider } from "./transition";
|
import { TransitionSlider } from "./transition";
|
||||||
import appNavigationController, { NavigationItem } from "./appNavigationController";
|
import appNavigationController, { NavigationItem } from "./appNavigationController";
|
||||||
import SliderSuperTab, { SliderSuperTabConstructable, SliderTab } from "./sliderTab";
|
import SliderSuperTab, { SliderSuperTabConstructable, SliderTab } from "./sliderTab";
|
||||||
|
import { safeAssign } from "../helpers/object";
|
||||||
|
|
||||||
const TRANSITION_TIME = 250;
|
const TRANSITION_TIME = 250;
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ export default class SidebarSlider {
|
|||||||
canHideFirst?: SidebarSlider['canHideFirst'],
|
canHideFirst?: SidebarSlider['canHideFirst'],
|
||||||
navigationType: SidebarSlider['navigationType']
|
navigationType: SidebarSlider['navigationType']
|
||||||
}) {
|
}) {
|
||||||
Object.assign(this, options);
|
safeAssign(this, options);
|
||||||
|
|
||||||
if(!this.tabs) {
|
if(!this.tabs) {
|
||||||
this.tabs = new Map();
|
this.tabs = new Map();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import ListenerSetter from "../helpers/listenerSetter";
|
import ListenerSetter from "../helpers/listenerSetter";
|
||||||
import { debounce } from "../helpers/schedulers";
|
import { debounce } from "../helpers/schedulers";
|
||||||
import appChatsManager from "../lib/appManagers/appChatsManager";
|
import appChatsManager from "../lib/appManagers/appChatsManager";
|
||||||
|
import { LangPackKey } from "../lib/langPack";
|
||||||
import apiManager from "../lib/mtproto/mtprotoworker";
|
import apiManager from "../lib/mtproto/mtprotoworker";
|
||||||
import RichTextProcessor from "../lib/richtextprocessor";
|
import RichTextProcessor from "../lib/richtextprocessor";
|
||||||
import InputField, { InputFieldOptions, InputState } from "./inputField";
|
import InputField, { InputFieldOptions, InputState } from "./inputField";
|
||||||
@ -12,9 +13,9 @@ export class UsernameInputField extends InputField {
|
|||||||
peerId: number,
|
peerId: number,
|
||||||
listenerSetter: ListenerSetter,
|
listenerSetter: ListenerSetter,
|
||||||
onChange?: () => void,
|
onChange?: () => void,
|
||||||
invalidText: string,
|
invalidText: LangPackKey,
|
||||||
takenText: string,
|
takenText: LangPackKey,
|
||||||
availableText: string,
|
availableText: LangPackKey,
|
||||||
head?: string
|
head?: string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Scrollable from "../components/scrollable";
|
import Scrollable from "../components/scrollable";
|
||||||
|
import { safeAssign } from "./object";
|
||||||
|
|
||||||
export default class ScrollableLoader {
|
export default class ScrollableLoader {
|
||||||
public loading = false;
|
public loading = false;
|
||||||
@ -11,7 +12,7 @@ export default class ScrollableLoader {
|
|||||||
scrollable: ScrollableLoader['scrollable'],
|
scrollable: ScrollableLoader['scrollable'],
|
||||||
getPromise: ScrollableLoader['getPromise']
|
getPromise: ScrollableLoader['getPromise']
|
||||||
}) {
|
}) {
|
||||||
Object.assign(this, options);
|
safeAssign(this, options);
|
||||||
|
|
||||||
options.scrollable.onScrolledBottom = () => {
|
options.scrollable.onScrolledBottom = () => {
|
||||||
this.load();
|
this.load();
|
||||||
|
@ -120,3 +120,13 @@ export function validateInitObject(initObject: any, currentObject: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function safeAssign(object: any, fromObject: any) {
|
||||||
|
if(!fromObject) return;
|
||||||
|
|
||||||
|
for(let i in fromObject) {
|
||||||
|
if(fromObject[i] !== undefined) {
|
||||||
|
object[i] = fromObject[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -99,16 +99,7 @@
|
|||||||
<div class="sidebar-header">
|
<div class="sidebar-header">
|
||||||
<div class="sidebar-header__btn-container">
|
<div class="sidebar-header__btn-container">
|
||||||
<div class="animated-menu-icon"></div>
|
<div class="animated-menu-icon"></div>
|
||||||
<div class="btn-icon btn-menu-toggle rp sidebar-tools-button is-visible">
|
<div class="btn-icon btn-menu-toggle rp sidebar-tools-button is-visible"></div>
|
||||||
<div class="btn-menu bottom-right">
|
|
||||||
<div class="btn-menu-item menu-newGroup tgico-newgroup rp">New Group</div>
|
|
||||||
<div class="btn-menu-item menu-contacts tgico-user rp">Contacts</div>
|
|
||||||
<div class="btn-menu-item menu-archived tgico-archive rp">Archived <span class="archived-count badge badge-24 badge-gray"></span></div>
|
|
||||||
<div class="btn-menu-item menu-saved tgico-savedmessages rp">Saved</div>
|
|
||||||
<div class="btn-menu-item menu-settings tgico-settings rp">Settings</div>
|
|
||||||
<div class="btn-menu-item menu-help tgico-help rp btn-disabled">Help</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="btn-icon rp sidebar-back-button"></div>
|
<div class="btn-icon rp sidebar-back-button"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Database from '../config/database';
|
import Database from '../config/database';
|
||||||
import { blobConstruct } from '../helpers/blob';
|
import { blobConstruct } from '../helpers/blob';
|
||||||
|
import { safeAssign } from '../helpers/object';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,7 +37,7 @@ export default class IDBStorage {
|
|||||||
public storeName: string;
|
public storeName: string;
|
||||||
|
|
||||||
constructor(options: IDBOptions) {
|
constructor(options: IDBOptions) {
|
||||||
Object.assign(this, options);
|
safeAssign(this, options);
|
||||||
|
|
||||||
this.openDatabase(true);
|
this.openDatabase(true);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||||
import { LangPackString } from "../layer";
|
import { safeAssign } from "../helpers/object";
|
||||||
|
import { LangPackDifference, LangPackString } from "../layer";
|
||||||
import apiManager from "./mtproto/mtprotoworker";
|
import apiManager from "./mtproto/mtprotoworker";
|
||||||
|
import sessionStorage from "./sessionStorage";
|
||||||
|
|
||||||
export const langPack: {[actionType: string]: string} = {
|
export const langPack: {[actionType: string]: string} = {
|
||||||
"messageActionChatCreate": "created the group",
|
"messageActionChatCreate": "created the group",
|
||||||
@ -41,9 +43,15 @@ namespace Strings {
|
|||||||
|
|
||||||
export type AccountSettings = 'AccountSettings.Filters' | 'AccountSettings.Notifications' | 'AccountSettings.PrivacyAndSecurity' | 'AccountSettings.Language' | 'AccountSettings.Bio';
|
export type AccountSettings = 'AccountSettings.Filters' | 'AccountSettings.Notifications' | 'AccountSettings.PrivacyAndSecurity' | 'AccountSettings.Language' | 'AccountSettings.Bio';
|
||||||
|
|
||||||
export type Telegram = 'Telegram.GeneralSettingsViewController' | 'Telegram.NotificationSettingsViewController';
|
export type Telegram = 'Telegram.GeneralSettingsViewController' | 'Telegram.NotificationSettingsViewController' | 'Telegram.LanguageViewController';
|
||||||
|
|
||||||
export type ChatFilters = 'ChatList.Filter.Header' | 'ChatList.Filter.NewTitle' | 'ChatList.Filter.List.Header' | 'ChatList.Filter.Recommended.Header' | 'ChatList.Filter.Recommended.Add' | 'ChatList.Filter.List.Title';
|
export type ChatList = ChatListFilter;
|
||||||
|
export type ChatListAdd = 'ChatList.Add.TopSeparator' | 'ChatList.Add.BottomSeparator';
|
||||||
|
export type ChatListFilterIncluded = 'ChatList.Filter.Include.Header' | 'ChatList.Filter.Include.AddChat';
|
||||||
|
export type ChatListFilterExcluded = 'ChatList.Filter.Exclude.Header' | 'ChatList.Filter.Exclude.AddChat';
|
||||||
|
export type ChatListFilterList = 'ChatList.Filter.List.Header' | 'ChatList.Filter.List.Title';
|
||||||
|
export type ChatListFilterRecommended = 'ChatList.Filter.Recommended.Header' | 'ChatList.Filter.Recommended.Add';
|
||||||
|
export type ChatListFilter = ChatListAdd | ChatListFilterIncluded | ChatListFilterExcluded | ChatListFilterList | ChatListFilterRecommended | 'ChatList.Filter.Header' | 'ChatList.Filter.NewTitle' | 'ChatList.Filter.NonContacts' | 'ChatList.Filter.Contacts' | 'ChatList.Filter.Groups' | 'ChatList.Filter.Channels' | 'ChatList.Filter.Bots';
|
||||||
|
|
||||||
export type AutoDownloadSettings = 'AutoDownloadSettings.TypePrivateChats' | 'AutoDownloadSettings.TypeChannels';
|
export type AutoDownloadSettings = 'AutoDownloadSettings.TypePrivateChats' | 'AutoDownloadSettings.TypeChannels';
|
||||||
|
|
||||||
@ -51,37 +59,68 @@ namespace Strings {
|
|||||||
|
|
||||||
export type Suggest = 'Suggest.Localization.Other';
|
export type Suggest = 'Suggest.Localization.Other';
|
||||||
|
|
||||||
export type LangPackKey = string | AccountSettings | EditAccount | Telegram | ChatFilters | LoginRegister | Bio | AutoDownloadSettings | DataAndStorage | Suggest;
|
export type UsernameSettings = 'UsernameSettings.ChangeDescription';
|
||||||
|
|
||||||
|
export type LangPackKey = string | AccountSettings | EditAccount | Telegram | ChatList | LoginRegister | Bio | AutoDownloadSettings | DataAndStorage | Suggest | UsernameSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LangPackKey = Strings.LangPackKey;
|
export type LangPackKey = Strings.LangPackKey;
|
||||||
|
|
||||||
namespace I18n {
|
namespace I18n {
|
||||||
let strings: Partial<{[key in LangPackKey]: LangPackString}> = {};
|
export const strings: Map<LangPackKey, LangPackString> = new Map();
|
||||||
|
|
||||||
|
let lastRequestedLangCode: string;
|
||||||
|
export function getCacheLangPack(): Promise<LangPackDifference> {
|
||||||
|
return sessionStorage.get('langPack').then((langPack: LangPackDifference) => {
|
||||||
|
if(!langPack) {
|
||||||
|
return getLangPack('en');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!lastRequestedLangCode) {
|
||||||
|
lastRequestedLangCode = langPack.lang_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyLangPack(langPack);
|
||||||
|
return langPack;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function getLangPack(langCode: string) {
|
export function getLangPack(langCode: string) {
|
||||||
|
lastRequestedLangCode = langCode;
|
||||||
return apiManager.invokeApi('langpack.getLangPack', {
|
return apiManager.invokeApi('langpack.getLangPack', {
|
||||||
lang_code: langCode,
|
lang_code: langCode,
|
||||||
lang_pack: 'macos'
|
lang_pack: 'macos'
|
||||||
}).then(langPack => {
|
}).then(langPack => {
|
||||||
strings = {};
|
return sessionStorage.set({langPack}).then(() => {
|
||||||
for(const string of langPack.strings) {
|
applyLangPack(langPack);
|
||||||
strings[string.key as LangPackKey] = string;
|
return langPack;
|
||||||
}
|
|
||||||
|
|
||||||
const elements = Array.from(document.querySelectorAll(`.i18n`)) as HTMLElement[];
|
|
||||||
elements.forEach(element => {
|
|
||||||
const instance = weakMap.get(element);
|
|
||||||
|
|
||||||
if(instance) {
|
|
||||||
instance.update();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function applyLangPack(langPack: LangPackDifference) {
|
||||||
|
if(langPack.lang_code !== lastRequestedLangCode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strings.clear();
|
||||||
|
|
||||||
|
for(const string of langPack.strings) {
|
||||||
|
strings.set(string.key as LangPackKey, string);
|
||||||
|
}
|
||||||
|
|
||||||
|
const elements = Array.from(document.querySelectorAll(`.i18n`)) as HTMLElement[];
|
||||||
|
elements.forEach(element => {
|
||||||
|
const instance = weakMap.get(element);
|
||||||
|
|
||||||
|
if(instance) {
|
||||||
|
instance.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function getString(key: LangPackKey, args?: any[]) {
|
export function getString(key: LangPackKey, args?: any[]) {
|
||||||
const str = strings[key];
|
const str = strings.get(key);
|
||||||
let out = '';
|
let out = '';
|
||||||
|
|
||||||
if(str) {
|
if(str) {
|
||||||
@ -103,7 +142,7 @@ namespace I18n {
|
|||||||
|
|
||||||
export type IntlElementOptions = {
|
export type IntlElementOptions = {
|
||||||
element?: HTMLElement,
|
element?: HTMLElement,
|
||||||
property?: 'innerHTML' | 'placeholder'
|
property?: 'innerText' | 'innerHTML' | 'placeholder'
|
||||||
key: LangPackKey,
|
key: LangPackKey,
|
||||||
args?: any[]
|
args?: any[]
|
||||||
};
|
};
|
||||||
@ -111,7 +150,7 @@ namespace I18n {
|
|||||||
public element: IntlElementOptions['element'];
|
public element: IntlElementOptions['element'];
|
||||||
public key: IntlElementOptions['key'];
|
public key: IntlElementOptions['key'];
|
||||||
public args: IntlElementOptions['args'];
|
public args: IntlElementOptions['args'];
|
||||||
public property: IntlElementOptions['property'] = 'innerHTML';
|
public property: IntlElementOptions['property'] = 'innerText';
|
||||||
|
|
||||||
constructor(options: IntlElementOptions) {
|
constructor(options: IntlElementOptions) {
|
||||||
this.element = options.element || document.createElement('span');
|
this.element = options.element || document.createElement('span');
|
||||||
@ -122,9 +161,7 @@ namespace I18n {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public update(options?: IntlElementOptions) {
|
public update(options?: IntlElementOptions) {
|
||||||
if(options) {
|
safeAssign(this, options);
|
||||||
Object.assign(this, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
(this.element as any)[this.property] = getString(this.key, this.args);
|
(this.element as any)[this.property] = getString(this.key, this.args);
|
||||||
}
|
}
|
||||||
@ -137,6 +174,10 @@ namespace I18n {
|
|||||||
export function i18n_(options: IntlElementOptions) {
|
export function i18n_(options: IntlElementOptions) {
|
||||||
return new IntlElement(options).element;
|
return new IntlElement(options).element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function _i18n(element: HTMLElement, key: LangPackKey, args?: any[], property?: IntlElementOptions['property']) {
|
||||||
|
return new IntlElement({element, key, args, property}).element;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {I18n};
|
export {I18n};
|
||||||
@ -148,4 +189,7 @@ export {i18n};
|
|||||||
const i18n_ = I18n.i18n_;
|
const i18n_ = I18n.i18n_;
|
||||||
export {i18n_};
|
export {i18n_};
|
||||||
|
|
||||||
|
const _i18n = I18n._i18n;
|
||||||
|
export {_i18n};
|
||||||
|
|
||||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.I18n = I18n);
|
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.I18n = I18n);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { MOUNT_CLASS_TO } from '../config/debug';
|
import { MOUNT_CLASS_TO } from '../config/debug';
|
||||||
|
import { LangPackDifference } from '../layer';
|
||||||
import type { State } from './appManagers/appStateManager';
|
import type { State } from './appManagers/appStateManager';
|
||||||
import AppStorage from './storage';
|
import AppStorage from './storage';
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ const sessionStorage = new AppStorage<{
|
|||||||
top: number
|
top: number
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
langPack: LangPackDifference
|
||||||
} & State>({
|
} & State>({
|
||||||
storeName: 'session'
|
storeName: 'session'
|
||||||
});
|
});
|
||||||
|
@ -569,7 +569,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 15px auto 1rem;
|
margin: 15px auto 1rem;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
padding: 0 12px;
|
padding: 0 24px 0 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,8 +581,9 @@
|
|||||||
.row {
|
.row {
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
padding: 0 12px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
width: 52px;
|
width: auto;
|
||||||
transition: width 0.2s;
|
transition: width 0.2s;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user