Browse Source

Active sessions functions

master
Eduard Kuzmenko 4 years ago
parent
commit
ac313c94bd
  1. 1
      src/components/chat/contextMenu.ts
  2. 1
      src/components/dialogsContextMenu.ts
  3. 4
      src/components/popups/index.ts
  4. 153
      src/components/sidebarLeft/tabs/activeSessions.ts
  5. 22
      src/components/sidebarLeft/tabs/privacyAndSecurity.ts
  6. 7
      src/index.hbs
  7. 3
      src/scss/partials/_button.scss
  8. 6
      src/scss/partials/_leftSidebar.scss
  9. 13
      src/scss/style.scss

1
src/components/chat/contextMenu.ts

@ -292,6 +292,7 @@ export default class ChatContextMenu { @@ -292,6 +292,7 @@ export default class ChatContextMenu {
this.element = ButtonMenu(this.buttons, this.chat.bubbles.listenerSetter);
this.element.id = 'bubble-contextmenu';
this.element.classList.add('contextmenu');
this.chat.container.append(this.element);
};

1
src/components/dialogsContextMenu.ts

@ -83,6 +83,7 @@ export default class DialogsContextMenu { @@ -83,6 +83,7 @@ export default class DialogsContextMenu {
this.element = ButtonMenu(this.buttons);
this.element.id = 'dialogs-contextmenu';
this.element.classList.add('contextmenu');
document.getElementById('page-chats').append(this.element);
}

4
src/components/popups/index.ts

@ -50,18 +50,18 @@ export default class PopupElement { @@ -50,18 +50,18 @@ export default class PopupElement {
this.header.prepend(this.btnClose);
this.btnClose.addEventListener('click', this.hide, {once: true});
}
if(options.overlayClosable) {
const onOverlayClick = (e: MouseEvent) => {
if(!findUpClassName(e.target, 'popup-container')) {
this.btnClose.click();
this.hide();
this.element.removeEventListener('click', onOverlayClick);
}
};
this.element.addEventListener('click', onOverlayClick);
}
}
if(options.withConfirm) {
this.btnConfirm = document.createElement('button');

153
src/components/sidebarLeft/tabs/activeSessions.ts

@ -2,75 +2,158 @@ import { SliderSuperTab } from "../../slider"; @@ -2,75 +2,158 @@ import { SliderSuperTab } from "../../slider";
import { SettingSection } from "..";
import Button from "../../button";
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 {
public authorizations: Authorization.authorization[];
private menuElement: HTMLElement;
protected init() {
this.container.classList.add('active-sessions-container');
this.title.innerText = 'Active Sessions';
const Session = (options: {
application: string,
device: string,
ip: string,
location: string,
time?: string
}) => {
const Session = (auth: Authorization.authorization) => {
const row = new Row({
title: options.application,
subtitle: options.ip + ' - ' + options.location,
title: [auth.app_name, auth.app_version].join(' '),
subtitle: [auth.ip, auth.country].join(' - '),
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');
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);
return row;
};
const authorizations = this.authorizations.slice();
{
const section = new SettingSection({
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);
section.content.append(session.container);
const session = Session({
application: 'Telegram Web 1.0',
device: 'Safari, macOS',
ip: '216.3.128.12',
location: 'Paris, France'
if(authorizations.length) {
const btnTerminate = Button('btn-primary btn-transparent danger', {icon: 'stop', text: 'Terminate all other sessions'});
attachClickEvent(btnTerminate, (e) => {
new PopupConfirmAction('revoke-session', [{
text: 'TERMINATE',
isDanger: true,
callback: () => {
toggleDisability([btnTerminate], true);
apiManager.invokeApi('auth.resetAuthorizations').then(value => {
//toggleDisability([btnTerminate], false);
btnTerminate.remove();
otherSection.container.remove();
});
}
}], {
title: 'Terminate All Other Sessions',
text: 'Are you sure you want to terminate all other sessions?'
}).show();
});
section.content.append(session.container, btnTerminate);
section.content.append(btnTerminate);
}
this.scrollable.append(section.container);
}
{
const section = new SettingSection({
if(!authorizations.length) {
return;
}
const otherSection = new SettingSection({
name: 'Other Sessions'
});
[Session({
application: 'Telegram iOS 5.12',
device: 'iPhone X, iOS 13.2',
ip: '216.3.128.12',
location: 'Paris, France',
time: '19:25'
}), Session({
application: 'Telegram Android 5.11',
device: 'Samsung Galaxy S9, Android 9P',
ip: '216.3.128.12',
location: 'Paris, France',
time: '16:34'
})].forEach(session => {
section.content.append(session.container);
authorizations.forEach(auth => {
otherSection.content.append(Session(auth).container);
});
this.scrollable.append(section.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();
}
}

22
src/components/sidebarLeft/tabs/privacyAndSecurity.ts

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import { SliderSuperTab } from "../../slider";
import { generateSection, SettingSection } from "..";
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 AppPrivacyPhoneNumberTab from "./privacy/phoneNumber";
import AppTwoStepVerificationTab from "./2fa";
@ -14,6 +14,7 @@ import AppPrivacyForwardMessagesTab from "./privacy/forwardMessages"; @@ -14,6 +14,7 @@ import AppPrivacyForwardMessagesTab from "./privacy/forwardMessages";
import AppPrivacyAddToGroupsTab from "./privacy/addToGroups";
import AppPrivacyCallsTab from "./privacy/calls";
import AppActiveSessionsTab from "./activeSessions";
import apiManager from "../../../lib/mtproto/mtprotoworker";
export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
protected init() {
@ -62,11 +63,14 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -62,11 +63,14 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
const activeSessionRow = new Row({
icon: 'activesessions',
title: 'Active Sessions',
subtitle: '3 devices',
subtitle: 'Loading...',
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);
this.scrollable.append(section.container);
@ -76,7 +80,15 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -76,7 +80,15 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
twoFactorRow.subtitle.innerText = state.pFlags.has_password ? 'On' : 'Off';
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 { @@ -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);
}
}
}

7
src/index.hbs

@ -206,13 +206,6 @@ @@ -206,13 +206,6 @@
</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-container">
<div class="tabs-container">

3
src/scss/partials/_button.scss

@ -145,9 +145,6 @@ @@ -145,9 +145,6 @@
height: 56px;
cursor: pointer !important;
pointer-events: all !important;
background-position: 16px center;
background-size: 24px 24px;
background-repeat: no-repeat;
color: #000;
text-transform: none;
white-space: nowrap;

6
src/scss/partials/_leftSidebar.scss

@ -1017,6 +1017,12 @@ @@ -1017,6 +1017,12 @@
color: var(--color-text-secondary);
line-height: 1.5;
}
&-midtitle, &-subtitle {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.sidebar-left-section:first-child {

13
src/scss/style.scss

@ -382,12 +382,12 @@ input, textarea { @@ -382,12 +382,12 @@ input, textarea {
background: #fed85a;
}
#bubble-contextmenu, #dialogs-contextmenu {
position: fixed;
right: auto;
bottom: auto;
width: auto;
z-index: 4;
.contextmenu {
position: fixed !important;
right: auto !important;
bottom: auto !important;
width: auto !important;
z-index: 4 !important;
}
@keyframes fade-in-opacity {
@ -458,6 +458,7 @@ input, textarea { @@ -458,6 +458,7 @@ input, textarea {
border-radius: $border-radius-medium;
animation: fade-in-opacity-fade-out-opacity 3s linear forwards;
z-index: 5;
max-width: 22.5rem;
}
hr {

Loading…
Cancel
Save