Telegram Web K with changes to work inside I2P https://web.telegram.i2p/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

268 lines
9.0 KiB

/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import replaceContent from '../helpers/dom/replaceContent';
import {randomLong} from '../helpers/random';
import {InputPrivacyKey, InputPrivacyRule} from '../layer';
import {AppManagers} from '../lib/appManagers/managers';
import getPrivacyRulesDetails from '../lib/appManagers/utils/privacy/getPrivacyRulesDetails';
import PrivacyType from '../lib/appManagers/utils/privacy/privacyType';
import {i18n, join, LangPackKey, _i18n} from '../lib/langPack';
import RadioField from './radioField';
import Row, {RadioFormFromRows} from './row';
import Scrollable from './scrollable';
import {SettingSection, generateSection} from './sidebarLeft';
import AppAddMembersTab from './sidebarLeft/tabs/addMembers';
import {SliderSuperTabEventable} from './sliderTab';
export type PrivacySectionStr = LangPackKey | '' | HTMLElement;
export default class PrivacySection {
public radioRows: Map<PrivacyType, Row>;
public radioSection: SettingSection;
public exceptions: Map<keyof PrivacySection['peerIds'], {
titleLangKey: LangPackKey,
key: keyof PrivacySection['peerIds'],
row: Row,
icon: string,
subtitleLangKey: LangPackKey,
clickable: true
}>;
public peerIds: {
disallow?: PeerId[],
allow?: PeerId[]
};
public type: PrivacyType;
constructor(public options: {
tab: SliderSuperTabEventable,
title: LangPackKey,
inputKey: InputPrivacyKey['_'],
captions?: [PrivacySectionStr, PrivacySectionStr, PrivacySectionStr],
appendTo?: Scrollable,
noExceptions?: boolean,
onRadioChange?: (value: number) => any,
skipTypes?: PrivacyType[],
exceptionTexts?: [LangPackKey, LangPackKey],
managers: AppManagers
}) {
if(options.captions) {
options.captions.reverse();
}
const managers = options.managers;
this.radioSection = new SettingSection({name: options.title, caption: true});
this.radioRows = new Map();
let r: Array<{type: PrivacyType, langKey: LangPackKey}> = [{
type: PrivacyType.Everybody,
langKey: 'PrivacySettingsController.Everbody'
}, {
type: PrivacyType.Contacts,
langKey: 'PrivacySettingsController.MyContacts'
}, {
type: PrivacyType.Nobody,
langKey: 'PrivacySettingsController.Nobody'
}];
if(options.skipTypes) {
r = r.filter((r) => !options.skipTypes.includes(r.type));
}
const random = randomLong();
r.forEach(({type, langKey}) => {
const row = new Row({
radioField: new RadioField({
langKey,
name: random,
value: '' + type
})
});
this.radioRows.set(type, row);
});
const form = RadioFormFromRows([...this.radioRows.values()], this.onRadioChange);
this.radioSection.content.append(form);
if(options.appendTo) {
options.appendTo.append(this.radioSection.container);
}
if(!options.noExceptions) {
const container = generateSection(options.appendTo, 'PrivacyExceptions', 'PrivacySettingsController.PeerInfo');
this.exceptions = new Map([[
'disallow',
{
titleLangKey: options.exceptionTexts[0],
key: 'disallow',
row: null,
icon: 'deleteuser',
subtitleLangKey: 'PrivacySettingsController.AddUsers',
clickable: true
}
], [
'allow',
{
titleLangKey: options.exceptionTexts[1],
key: 'allow',
row: null,
icon: 'adduser',
subtitleLangKey: 'PrivacySettingsController.AddUsers',
clickable: true
}
]]);
this.exceptions.forEach((exception) => {
exception.row = new Row(exception);
exception.row.container.addEventListener('click', () => {
promise.then(() => {
const _peerIds = this.peerIds[exception.key];
options.tab.slider.createTab(AppAddMembersTab).open({
type: 'privacy',
skippable: true,
title: exception.titleLangKey,
placeholder: 'PrivacyModal.Search.Placeholder',
takeOut: (newPeerIds) => {
_peerIds.length = 0;
_peerIds.push(...newPeerIds);
exception.row.subtitle.innerHTML = '';
exception.row.subtitle.append(...this.generateStr(this.splitPeersByType(newPeerIds)));
},
selectedPeerIds: _peerIds
});
});
});
container.append(exception.row.container);
});
}
/* setTimeout(() => {
this.setRadio(PrivacyType.Contacts);
}, 0); */
const promise = managers.appPrivacyManager.getPrivacy(options.inputKey).then((rules) => {
const details = getPrivacyRulesDetails(rules);
this.setRadio(details.type);
if(this.exceptions) {
this.peerIds = {};
['allow' as const, 'disallow' as const].forEach((k) => {
const arr = [];
const from = k === 'allow' ? details.allowPeers : details.disallowPeers;
arr.push(...from.users.map((id) => id.toPeerId()));
arr.push(...from.chats.map((id) => id.toPeerId(true)));
this.peerIds[k] = arr;
const s = this.exceptions.get(k).row.subtitle;
s.innerHTML = '';
s.append(...this.generateStr(from));
});
}
options.tab.eventListener.addEventListener('destroy', async() => {
const rules: InputPrivacyRule[] = [];
switch(this.type) {
case PrivacyType.Everybody:
rules.push({_: 'inputPrivacyValueAllowAll'});
break;
case PrivacyType.Contacts:
rules.push({_: 'inputPrivacyValueAllowContacts'});
break;
case PrivacyType.Nobody:
rules.push({_: 'inputPrivacyValueDisallowAll'});
break;
}
if(this.exceptions) {
const a = ([
['allow', 'inputPrivacyValueAllowChatParticipants', 'inputPrivacyValueAllowUsers'],
['disallow', 'inputPrivacyValueDisallowChatParticipants', 'inputPrivacyValueDisallowUsers']
] as Array<[
'allow' | 'disallow',
'inputPrivacyValueAllowChatParticipants' | 'inputPrivacyValueDisallowChatParticipants',
'inputPrivacyValueAllowUsers' | 'inputPrivacyValueDisallowUsers'
]>);
for(const [k, chatKey, usersKey] of a) {
if(this.exceptions.get(k).row.container.classList.contains('hide')) {
continue;
}
const _peerIds = this.peerIds[k];
if(_peerIds) {
const splitted = this.splitPeersByType(_peerIds);
if(splitted.chats.length) {
rules.push({_: chatKey, chats: splitted.chats});
}
if(splitted.users.length) {
rules.push({
_: usersKey,
users: await Promise.all(splitted.users.map((id) => managers.appUsersManager.getUserInput(id)))
});
}
}
}
}
managers.appPrivacyManager.setPrivacy(options.inputKey, rules);
}, {once: true});
});
}
private onRadioChange = (value: string | PrivacySection['type']) => {
value = +value as PrivacySection['type'];
this.type = value;
const caption = this.options.captions[this.type];
const captionElement = this.radioSection.caption;
if(!caption) {
captionElement.innerHTML = '';
} else if(caption instanceof HTMLElement) {
replaceContent(captionElement, caption);
} else {
_i18n(captionElement, caption);
}
captionElement.classList.toggle('hide', !caption);
if(this.exceptions) {
this.exceptions.get('allow').row.container.classList.toggle('hide', this.type === PrivacyType.Everybody);
this.exceptions.get('disallow').row.container.classList.toggle('hide', this.type === PrivacyType.Nobody);
}
this.options.onRadioChange && this.options.onRadioChange(value);
};
public setRadio(type: PrivacySection['type']) {
const row = this.radioRows.get(type);
this.onRadioChange(type);
row.radioField.input.checked = true;
}
private splitPeersByType(peerIds: PeerId[]) {
const peers = {users: [] as UserId[], chats: [] as ChatId[]};
peerIds.forEach((peerId) => {
peers[peerId.isAnyChat() ? 'chats' : 'users'].push(peerId.isAnyChat() ? peerId.toChatId() : peerId);
});
return peers;
}
private generateStr(peers: {users: UserId[], chats: ChatId[]}) {
if(!peers.users.length && !peers.chats.length) {
return [i18n('PrivacySettingsController.AddUsers')];
}
return join([
peers.users.length ? i18n('Users', [peers.users.length]) : null,
peers.chats.length ? i18n('Chats', [peers.chats.length]) : null
].filter(Boolean), false);
}
}