Active sessions functions
This commit is contained in:
parent
0330059dd0
commit
ac313c94bd
@ -292,6 +292,7 @@ export default class ChatContextMenu {
|
|||||||
|
|
||||||
this.element = ButtonMenu(this.buttons, this.chat.bubbles.listenerSetter);
|
this.element = ButtonMenu(this.buttons, this.chat.bubbles.listenerSetter);
|
||||||
this.element.id = 'bubble-contextmenu';
|
this.element.id = 'bubble-contextmenu';
|
||||||
|
this.element.classList.add('contextmenu');
|
||||||
this.chat.container.append(this.element);
|
this.chat.container.append(this.element);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ export default class DialogsContextMenu {
|
|||||||
|
|
||||||
this.element = ButtonMenu(this.buttons);
|
this.element = ButtonMenu(this.buttons);
|
||||||
this.element.id = 'dialogs-contextmenu';
|
this.element.id = 'dialogs-contextmenu';
|
||||||
|
this.element.classList.add('contextmenu');
|
||||||
document.getElementById('page-chats').append(this.element);
|
document.getElementById('page-chats').append(this.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,17 +50,17 @@ export default class PopupElement {
|
|||||||
this.header.prepend(this.btnClose);
|
this.header.prepend(this.btnClose);
|
||||||
|
|
||||||
this.btnClose.addEventListener('click', this.hide, {once: true});
|
this.btnClose.addEventListener('click', this.hide, {once: true});
|
||||||
|
}
|
||||||
|
|
||||||
if(options.overlayClosable) {
|
if(options.overlayClosable) {
|
||||||
const onOverlayClick = (e: MouseEvent) => {
|
const onOverlayClick = (e: MouseEvent) => {
|
||||||
if(!findUpClassName(e.target, 'popup-container')) {
|
if(!findUpClassName(e.target, 'popup-container')) {
|
||||||
this.btnClose.click();
|
this.hide();
|
||||||
this.element.removeEventListener('click', onOverlayClick);
|
this.element.removeEventListener('click', onOverlayClick);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.element.addEventListener('click', onOverlayClick);
|
this.element.addEventListener('click', onOverlayClick);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(options.withConfirm) {
|
if(options.withConfirm) {
|
||||||
|
@ -2,75 +2,158 @@ import { SliderSuperTab } from "../../slider";
|
|||||||
import { SettingSection } from "..";
|
import { SettingSection } from "..";
|
||||||
import Button from "../../button";
|
import Button from "../../button";
|
||||||
import Row from "../../row";
|
import Row from "../../row";
|
||||||
|
import { Authorization } from "../../../layer";
|
||||||
|
import { formatDateAccordingToToday } from "../../../helpers/date";
|
||||||
|
import { attachContextMenuListener, openBtnMenu, positionMenu } from "../../misc";
|
||||||
|
import { attachClickEvent, findUpClassName, toggleDisability } from "../../../helpers/dom";
|
||||||
|
import ButtonMenu from "../../buttonMenu";
|
||||||
|
import PopupConfirmAction from "../../popups/confirmAction";
|
||||||
|
import apiManager from "../../../lib/mtproto/mtprotoworker";
|
||||||
|
import { toast } from "../../toast";
|
||||||
|
|
||||||
export default class AppActiveSessionsTab extends SliderSuperTab {
|
export default class AppActiveSessionsTab extends SliderSuperTab {
|
||||||
|
public authorizations: Authorization.authorization[];
|
||||||
|
private menuElement: HTMLElement;
|
||||||
|
|
||||||
protected init() {
|
protected init() {
|
||||||
this.container.classList.add('active-sessions-container');
|
this.container.classList.add('active-sessions-container');
|
||||||
this.title.innerText = 'Active Sessions';
|
this.title.innerText = 'Active Sessions';
|
||||||
|
|
||||||
const Session = (options: {
|
const Session = (auth: Authorization.authorization) => {
|
||||||
application: string,
|
|
||||||
device: string,
|
|
||||||
ip: string,
|
|
||||||
location: string,
|
|
||||||
time?: string
|
|
||||||
}) => {
|
|
||||||
const row = new Row({
|
const row = new Row({
|
||||||
title: options.application,
|
title: [auth.app_name, auth.app_version].join(' '),
|
||||||
subtitle: options.ip + ' - ' + options.location,
|
subtitle: [auth.ip, auth.country].join(' - '),
|
||||||
clickable: true,
|
clickable: true,
|
||||||
titleRight: options.time
|
titleRight: auth.pFlags.current ? undefined : formatDateAccordingToToday(new Date(Math.max(auth.date_active, auth.date_created) * 1000))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
row.container.dataset.hash = auth.hash;
|
||||||
|
|
||||||
const midtitle = document.createElement('div');
|
const midtitle = document.createElement('div');
|
||||||
midtitle.classList.add('row-midtitle');
|
midtitle.classList.add('row-midtitle');
|
||||||
midtitle.innerHTML = options.device;
|
midtitle.innerHTML = [auth.device_model, auth.system_version].join(', ');
|
||||||
|
|
||||||
row.subtitle.parentElement.insertBefore(midtitle, row.subtitle);
|
row.subtitle.parentElement.insertBefore(midtitle, row.subtitle);
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const authorizations = this.authorizations.slice();
|
||||||
|
|
||||||
{
|
{
|
||||||
const section = new SettingSection({
|
const section = new SettingSection({
|
||||||
name: 'Current Session'
|
name: 'Current Session'
|
||||||
});
|
});
|
||||||
|
|
||||||
const btnTerminate = Button('btn-primary btn-transparent danger', {icon: 'stop', text: 'Terminate all other sessions'});
|
const auth = authorizations.findAndSplice(auth => auth.pFlags.current);
|
||||||
|
const session = Session(auth);
|
||||||
|
|
||||||
const session = Session({
|
section.content.append(session.container);
|
||||||
application: 'Telegram Web 1.0',
|
|
||||||
device: 'Safari, macOS',
|
|
||||||
ip: '216.3.128.12',
|
|
||||||
location: 'Paris, France'
|
|
||||||
});
|
|
||||||
|
|
||||||
section.content.append(session.container, btnTerminate);
|
if(authorizations.length) {
|
||||||
this.scrollable.append(section.container);
|
const btnTerminate = Button('btn-primary btn-transparent danger', {icon: 'stop', text: 'Terminate all other sessions'});
|
||||||
}
|
attachClickEvent(btnTerminate, (e) => {
|
||||||
|
new PopupConfirmAction('revoke-session', [{
|
||||||
{
|
text: 'TERMINATE',
|
||||||
const section = new SettingSection({
|
isDanger: true,
|
||||||
name: 'Other Sessions'
|
callback: () => {
|
||||||
});
|
toggleDisability([btnTerminate], true);
|
||||||
|
apiManager.invokeApi('auth.resetAuthorizations').then(value => {
|
||||||
[Session({
|
//toggleDisability([btnTerminate], false);
|
||||||
application: 'Telegram iOS 5.12',
|
btnTerminate.remove();
|
||||||
device: 'iPhone X, iOS 13.2',
|
otherSection.container.remove();
|
||||||
ip: '216.3.128.12',
|
});
|
||||||
location: 'Paris, France',
|
}
|
||||||
time: '19:25'
|
}], {
|
||||||
}), Session({
|
title: 'Terminate All Other Sessions',
|
||||||
application: 'Telegram Android 5.11',
|
text: 'Are you sure you want to terminate all other sessions?'
|
||||||
device: 'Samsung Galaxy S9, Android 9P',
|
}).show();
|
||||||
ip: '216.3.128.12',
|
});
|
||||||
location: 'Paris, France',
|
|
||||||
time: '16:34'
|
section.content.append(btnTerminate);
|
||||||
})].forEach(session => {
|
}
|
||||||
section.content.append(session.container);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.scrollable.append(section.container);
|
this.scrollable.append(section.container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!authorizations.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const otherSection = new SettingSection({
|
||||||
|
name: 'Other Sessions'
|
||||||
|
});
|
||||||
|
|
||||||
|
authorizations.forEach(auth => {
|
||||||
|
otherSection.content.append(Session(auth).container);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.scrollable.append(otherSection.container);
|
||||||
|
|
||||||
|
let target: HTMLElement;
|
||||||
|
const onTerminateClick = () => {
|
||||||
|
const hash = target.dataset.hash;
|
||||||
|
|
||||||
|
new PopupConfirmAction('revoke-session', [{
|
||||||
|
text: 'TERMINATE',
|
||||||
|
isDanger: true,
|
||||||
|
callback: () => {
|
||||||
|
apiManager.invokeApi('account.resetAuthorization', {hash})
|
||||||
|
.then(value => {
|
||||||
|
if(value) {
|
||||||
|
target.remove();
|
||||||
|
}
|
||||||
|
}, (err) => {
|
||||||
|
if(err.type === 'FRESH_RESET_AUTHORISATION_FORBIDDEN') {
|
||||||
|
toast('For security reasons, you can\'t terminate older sessions from a device that you\'ve just connected. Please use an earlier connection or wait for a few hours.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}], {
|
||||||
|
title: 'Terminate Session',
|
||||||
|
text: 'Do you want to terminate this session?'
|
||||||
|
}).show();
|
||||||
|
};
|
||||||
|
|
||||||
|
const element = this.menuElement = ButtonMenu([{
|
||||||
|
icon: 'stop',
|
||||||
|
text: 'Terminate',
|
||||||
|
onClick: onTerminateClick
|
||||||
|
}]);
|
||||||
|
element.id = 'active-sessions-contextmenu';
|
||||||
|
element.classList.add('contextmenu');
|
||||||
|
|
||||||
|
document.getElementById('page-chats').append(element);
|
||||||
|
|
||||||
|
attachContextMenuListener(this.scrollable.container, (e) => {
|
||||||
|
target = findUpClassName(e.target, 'row');
|
||||||
|
if(!target || target.dataset.hash === '0') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e instanceof MouseEvent) e.preventDefault();
|
||||||
|
// smth
|
||||||
|
if(e instanceof MouseEvent) e.cancelBubble = true;
|
||||||
|
|
||||||
|
positionMenu(e, element);
|
||||||
|
openBtnMenu(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
attachClickEvent(this.scrollable.container, (e) => {
|
||||||
|
target = findUpClassName(e.target, 'row');
|
||||||
|
if(!target || target.dataset.hash === '0') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onTerminateClick();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCloseAfterTimeout() {
|
||||||
|
if(this.menuElement) {
|
||||||
|
this.menuElement.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onCloseAfterTimeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { SliderSuperTab } from "../../slider";
|
import { SliderSuperTab } from "../../slider";
|
||||||
import { generateSection, SettingSection } from "..";
|
import { generateSection, SettingSection } from "..";
|
||||||
import Row from "../../row";
|
import Row from "../../row";
|
||||||
import { AccountPassword, InputPrivacyKey, PrivacyRule } from "../../../layer";
|
import { AccountPassword, Authorization, InputPrivacyKey, PrivacyRule } from "../../../layer";
|
||||||
import appPrivacyManager, { PrivacyType } from "../../../lib/appManagers/appPrivacyManager";
|
import appPrivacyManager, { PrivacyType } from "../../../lib/appManagers/appPrivacyManager";
|
||||||
import AppPrivacyPhoneNumberTab from "./privacy/phoneNumber";
|
import AppPrivacyPhoneNumberTab from "./privacy/phoneNumber";
|
||||||
import AppTwoStepVerificationTab from "./2fa";
|
import AppTwoStepVerificationTab from "./2fa";
|
||||||
@ -14,6 +14,7 @@ import AppPrivacyForwardMessagesTab from "./privacy/forwardMessages";
|
|||||||
import AppPrivacyAddToGroupsTab from "./privacy/addToGroups";
|
import AppPrivacyAddToGroupsTab from "./privacy/addToGroups";
|
||||||
import AppPrivacyCallsTab from "./privacy/calls";
|
import AppPrivacyCallsTab from "./privacy/calls";
|
||||||
import AppActiveSessionsTab from "./activeSessions";
|
import AppActiveSessionsTab from "./activeSessions";
|
||||||
|
import apiManager from "../../../lib/mtproto/mtprotoworker";
|
||||||
|
|
||||||
export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
|
export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
|
||||||
protected init() {
|
protected init() {
|
||||||
@ -62,11 +63,14 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
|
|||||||
const activeSessionRow = new Row({
|
const activeSessionRow = new Row({
|
||||||
icon: 'activesessions',
|
icon: 'activesessions',
|
||||||
title: 'Active Sessions',
|
title: 'Active Sessions',
|
||||||
subtitle: '3 devices',
|
subtitle: 'Loading...',
|
||||||
clickable: () => {
|
clickable: () => {
|
||||||
new AppActiveSessionsTab(this.slider).open();
|
const tab = new AppActiveSessionsTab(this.slider);
|
||||||
|
tab.authorizations = authorizations;
|
||||||
|
tab.open();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
activeSessionRow.freezed = true;
|
||||||
|
|
||||||
section.content.append(blockedUsersRow.container, twoFactorRow.container, activeSessionRow.container);
|
section.content.append(blockedUsersRow.container, twoFactorRow.container, activeSessionRow.container);
|
||||||
this.scrollable.append(section.container);
|
this.scrollable.append(section.container);
|
||||||
@ -76,7 +80,15 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
|
|||||||
twoFactorRow.subtitle.innerText = state.pFlags.has_password ? 'On' : 'Off';
|
twoFactorRow.subtitle.innerText = state.pFlags.has_password ? 'On' : 'Off';
|
||||||
twoFactorRow.freezed = false;
|
twoFactorRow.freezed = false;
|
||||||
|
|
||||||
console.log('password state', state);
|
//console.log('password state', state);
|
||||||
|
});
|
||||||
|
|
||||||
|
let authorizations: Authorization.authorization[];
|
||||||
|
apiManager.invokeApi('account.getAuthorizations').then(auths => {
|
||||||
|
activeSessionRow.freezed = false;
|
||||||
|
authorizations = auths.authorizations;
|
||||||
|
activeSessionRow.subtitle.innerText = authorizations.length + ' ' + (authorizations.length > 1 ? 'devices' : 'device');
|
||||||
|
console.log('auths', auths);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +161,7 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
container.append(numberVisibilityRow.container, lastSeenTimeRow.container, photoVisibilityRow.container,/* callRow.container, */linkAccountRow.container, groupChatsAddRow.container);
|
container.append(numberVisibilityRow.container, lastSeenTimeRow.container, photoVisibilityRow.container, callRow.container, linkAccountRow.container, groupChatsAddRow.container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,13 +206,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-menu" id="dialogs-contextmenu">
|
|
||||||
<div class="btn-menu-item menu-unread tgico rp"><div></div></div>
|
|
||||||
<div class="btn-menu-item menu-pin tgico rp"><div></div></div>
|
|
||||||
<div class="btn-menu-item menu-mute tgico rp"><div></div></div>
|
|
||||||
<div class="btn-menu-item menu-archive tgico rp"><div></div></div>
|
|
||||||
<div class="btn-menu-item menu-delete tgico-delete danger rp"><div></div></div>
|
|
||||||
</div>
|
|
||||||
<div class="emoji-dropdown" id="emoji-dropdown" style="display: none;">
|
<div class="emoji-dropdown" id="emoji-dropdown" style="display: none;">
|
||||||
<div class="emoji-container">
|
<div class="emoji-container">
|
||||||
<div class="tabs-container">
|
<div class="tabs-container">
|
||||||
|
@ -145,9 +145,6 @@
|
|||||||
height: 56px;
|
height: 56px;
|
||||||
cursor: pointer !important;
|
cursor: pointer !important;
|
||||||
pointer-events: all !important;
|
pointer-events: all !important;
|
||||||
background-position: 16px center;
|
|
||||||
background-size: 24px 24px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
color: #000;
|
color: #000;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -1017,6 +1017,12 @@
|
|||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-midtitle, &-subtitle {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-left-section:first-child {
|
.sidebar-left-section:first-child {
|
||||||
|
@ -382,12 +382,12 @@ input, textarea {
|
|||||||
background: #fed85a;
|
background: #fed85a;
|
||||||
}
|
}
|
||||||
|
|
||||||
#bubble-contextmenu, #dialogs-contextmenu {
|
.contextmenu {
|
||||||
position: fixed;
|
position: fixed !important;
|
||||||
right: auto;
|
right: auto !important;
|
||||||
bottom: auto;
|
bottom: auto !important;
|
||||||
width: auto;
|
width: auto !important;
|
||||||
z-index: 4;
|
z-index: 4 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fade-in-opacity {
|
@keyframes fade-in-opacity {
|
||||||
@ -458,6 +458,7 @@ input, textarea {
|
|||||||
border-radius: $border-radius-medium;
|
border-radius: $border-radius-medium;
|
||||||
animation: fade-in-opacity-fade-out-opacity 3s linear forwards;
|
animation: fade-in-opacity-fade-out-opacity 3s linear forwards;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
max-width: 22.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user