Remove 10 more

This commit is contained in:
Romaric Mourgues
2023-04-20 15:06:43 +02:00
parent 335301612a
commit 5c2f8a6cf8
10 changed files with 0 additions and 1382 deletions
@@ -1,46 +0,0 @@
/* eslint-disable react/prop-types */
import React, { Component } from 'react';
import Input from './input.jsx';
import Icon from '@components/icon/icon.jsx';
import './inputs.scss';
export default class InputEnter extends Component {
constructor() {
super();
}
render() {
var parentClassName = '';
if (this.props.big) {
parentClassName += ' big ';
}
if (this.props.medium) {
parentClassName += ' medium ';
}
if (this.props.small) {
parentClassName += ' small ';
}
if (
parentClassName.indexOf('medium') === parentClassName.indexOf('small') &&
parentClassName.indexOf('big') === parentClassName.indexOf('small') &&
parentClassName.indexOf('big') < 0
) {
parentClassName += ' medium';
}
return (
<div className={'input_icon input_enter ' + parentClassName}>
<Input
onEchap={this.props.onEchap}
onEnter={this.props.onEnter}
autoFocus={this.props.autoFocus}
onKeyDown={this.props.onKeyDown}
{...this.props}
/>
<Icon type={'enter'} />
</div>
);
}
}
@@ -1,47 +0,0 @@
/* eslint-disable react/prop-types */
import React, { Component } from 'react';
import Input from './input.jsx';
import Icon from '@components/icon/icon.jsx';
import './inputs.scss';
export default class InputIcon extends Component {
constructor() {
super();
}
render() {
var parentClassName = '';
if (this.props.big) {
parentClassName += ' big ';
}
if (this.props.medium) {
parentClassName += ' medium ';
}
if (this.props.small) {
parentClassName += ' small ';
}
if (
parentClassName.indexOf('medium') === parentClassName.indexOf('small') &&
parentClassName.indexOf('big') === parentClassName.indexOf('small') &&
parentClassName.indexOf('big') < 0
) {
parentClassName += ' medium';
}
return (
<div className={'input_icon ' + parentClassName}>
<Icon type={this.props.icon} />
<Input
onEchap={this.props.onEchap}
onEnter={this.props.onEnter}
autoFocus={this.props.autoFocus}
onKeyDown={this.props.onKeyDown}
ref={this.refInput}
{...this.props}
/>
</div>
);
}
}
@@ -1,84 +0,0 @@
import React from 'react';
import { Switch } from 'antd';
import './inputs.scss';
export default (props: {
big?: boolean;
medium?: boolean;
small?: boolean;
loading?: boolean;
className?: string;
label?: string;
checked?: boolean;
disabled?: boolean;
onChange: (value: boolean) => void;
}) => {
const renderSwitch = () => {
let className = props.className || '';
if (props.big) {
className += ' big ';
}
if (props.medium) {
className += ' medium ';
}
if (props.small) {
className += ' small ';
}
if (
className.indexOf('medium') === className.indexOf('small') &&
className.indexOf('big') === className.indexOf('small') &&
className.indexOf('big') < 0
) {
className += ' medium';
}
return (
<Switch
checked={props.checked}
onChange={(value: boolean) => {
props.onChange(value);
}}
className={className}
loading={props.loading}
disabled={props.disabled}
/>
);
};
let parentClassName = '';
if (props.big) {
parentClassName += ' big ';
}
if (props.medium) {
parentClassName += ' medium ';
}
if (props.small) {
parentClassName += ' small ';
}
if (
parentClassName.indexOf('medium') === parentClassName.indexOf('small') &&
parentClassName.indexOf('big') === parentClassName.indexOf('small') &&
parentClassName.indexOf('big') < 0
) {
parentClassName += ' medium';
}
if (props.label) {
return (
<div
className={
'switch_with_label ' + (props.disabled ? 'disabled' : '') + ' ' + parentClassName
}
>
{renderSwitch()}
<div className="label">{props.label}</div>
</div>
);
} else {
return renderSwitch();
}
};
@@ -1,262 +0,0 @@
/* eslint-disable react/jsx-key */
import React, { Component } from 'react';
import AutoComplete from 'components/auto-complete/auto-complete';
import Icon from '@components/icon/icon.jsx';
import Languages from '@features/global/services/languages-service';
import './picker.scss';
export default class Picker extends React.Component {
/*
placeholder : string,
search : Array of search function,
renderItem(item) : how to render item
renderItemChoosen(item) : how to add item in input
renderItemSimply(item) : what user will type on input and what we have to replace
onChangeSuggested(list)
onChange(list) :
canCreate
onCreate
disableNavigationKey :
*/
constructor(props) {
super(props);
this.state = {
currentSelected: props.value || [],
inputValue: '',
currentList: [],
selected: [],
};
this.alreadyBackspace = false;
}
componentWillUnmount() {
document.removeEventListener('click', this.outsideClickListener);
}
componentDidMount() {
if (!this.props.inline) {
this.focus();
}
var element = this.container;
this.outsideClickListener = event => {
if (!element.contains(event.target) && document.contains(event.target)) {
this.setState({ focused: false });
}
};
this.outsideClickListener = this.outsideClickListener.bind(this);
document.addEventListener('click', this.outsideClickListener);
}
UNSAFE_componentWillUpdate(nextProps, nextState) {
if (nextProps.value != this.props.value) {
nextState.currentSelected = nextProps.value;
}
return true;
}
onSelect(item) {
this.alreadyBackspace = true;
if (item && (item.id === undefined || item.id < 0) && item.front_id === undefined) {
this.onCreate(item.textSearched);
return;
}
var newList = this.state.currentSelected;
for (var i = 0; i < newList.length; i++) {
if (newList[i].id == item.id) {
this.setState({ inputValue: '' });
return false;
}
}
newList.push(item);
this.setState({ currentSelected: newList });
this.setState({ inputValue: '' });
if (this.props.onChange) {
this.props.onChange(newList);
}
this.focus();
}
onRemove(item) {
var newList = this.state.currentSelected;
var index = newList.indexOf(item);
if (index >= 0) {
newList.splice(index, 1);
this.setState({ currentSelected: newList });
if (this.props.onChange) {
this.props.onChange(newList);
}
}
this.focus();
}
onBackspace() {
if (this.alreadyBackspace) {
// if already typed on backspace once
var newList = this.state.currentSelected;
newList.splice(newList.length - 1, 1);
this.setState({ currentSelected: newList });
} else {
this.alreadyBackspace = true;
}
}
onCreate(text) {
if (this.props.onCreate) {
var item = this.props.onCreate(text, item => {
this.onSelect(item);
});
}
}
focus() {
if (this.autocomplete_node) {
this.autocomplete_node.focus();
}
}
render() {
var that = this;
var objects = [
<div className="picker">
<div className={'pickerInput ' + (this.props.readOnly ? 'readOnly ' : '')}>
{this.state.currentSelected.map(item => {
return this.props.renderItemChoosen(item);
})}
{!this.props.readOnly && (
<AutoComplete
search={[
(text, cb) => {
text = this.state.inputValue;
this.props.search(text, list => {
if (that.props.canCreate && text.length > 0) {
list.push({ id: -1, autocomplete_id: list.length, textSearched: text });
}
cb(list);
});
},
]}
renderItemChoosen={[
item => {
if (item.id < 0 && this.props.canCreate) {
return item.textSearched;
} else {
return this.props.renderItemSimply(item);
}
},
]}
max={[this.props.max || 10]}
renderItem={[() => {}]}
regexHooked={[/(.*)/]}
placeholder={
this.state.currentSelected.length
? ''
: this.props.placeholder ||
Languages.t('scenes.apps.drive.left.search', [], 'Search')
}
onChange={evt => {
this.alreadyBackspace = false;
this.setState({ inputValue: evt.target.value });
}}
onSelect={item => {
this.onSelect(item);
}}
value={this.state.inputValue}
onChangeCurrentList={(list, selected) => {
this.setState({ currentList: list, selected: selected });
if (this.props.onChangeSuggested) {
this.props.onChangeSuggested(list);
}
}}
hideResult={true}
onBackspace={() => {
this.onBackspace();
}}
disableNavigationKey={this.props.disableNavigationKey}
showResultsOnInit={true}
onHide={() => this.setState({ focused: false })}
ref={node => {
this.autocomplete_node = node;
}}
/>
)}
</div>
</div>,
];
if (!this.props.readOnly) {
if (!this.props.inline) {
objects.push(<div className="menu-text">{!!this.props.title && this.props.title}</div>);
}
var results = [];
if (this.state.currentList.length > 0) {
results = this.state.currentList.map((item, index) => {
if (item.id < 0) {
return (
<div
key={'create'}
className={
'menu ' +
(!this.props.disableNavigationKey && item.autocomplete_id == this.state.selected
? 'is_selected'
: '')
}
onClick={evt => {
evt.stopPropagation();
evt.preventDefault();
this.onSelect(item);
}}
>
<div className="text">
<Icon type="plus" />
Create {this.props.renderItem(item.textSearched)}
</div>
</div>
);
} else {
return (
<div
key={item.id}
className={
'menu ' +
(!this.props.disableNavigationKey && item.autocomplete_id == this.state.selected
? 'is_selected'
: '')
}
onClick={evt => {
evt.stopPropagation();
evt.preventDefault();
this.onSelect(item);
}}
>
<div className="text">{this.props.renderItem(item)}</div>
</div>
);
}
});
}
if (this.props.inline) {
results = (
<div className={'dropmenu inline ' + (this.state.focused ? 'fade_in ' : '')}>
{results}
</div>
);
}
objects = objects.concat(results);
}
objects = (
<div
onClick={() => {
this.focus();
this.setState({ focused: true });
}}
ref={node => (this.container = node)}
className={
'picker_container ' +
(this.props.readOnly ? 'readOnly ' : '') +
(this.props.inline ? 'inline ' : '') +
(this.state.focused ? 'focused ' : '') +
this.props.className
}
>
{objects}
</div>
);
return objects;
}
}
@@ -1,55 +0,0 @@
.picker_container {
position: relative;
border-radius: var(--border-radius-large);
&.inline {
transition: box-shadow 0.2s;
.dropmenu {
opacity: 0;
transition: opacity 0.2s;
pointer-events: none;
}
&.focused {
&.readOnly {
box-shadow: none !important;
}
.autocomplete {
box-shadow: none !important;
}
.dropmenu {
opacity: 1;
pointer-events: all;
}
}
}
}
.picker {
.pickerInput {
border-radius: var(--border-radius-base);
display: flex;
flex-wrap: wrap;
position: relative;
background: #f2f2f2;
&.readOnly {
margin: 0;
display: inline;
padding: 0;
background: transparent;
}
.autocomplete {
flex: 1;
min-width: 50px;
position: unset;
input {
background: inherit;
margin-top: 0px;
margin-bottom: 0px;
}
}
}
}
@@ -1,98 +0,0 @@
rm .table {
overflow: hidden;
border-radius: var(--border-radius-base);
margin-bottom: 16px;
border: 1px solid var(--grey-background);
font-weight: 500;
&.unfocused {
box-shadow: none;
}
&.loading {
opacity: 0.5;
.tr .item .line {
pointer-events: none;
border-radius: var(--border-radius-large);
height: 16px;
margin-top: 8px;
width: 200px;
animation-duration: 1s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: placeHolderShimmer;
animation-timing-function: linear;
background-repeat: repeat !important;
background-image: linear-gradient(
to right,
var(--grey-light) 0px,
#f2f2f2 120px,
var(--grey-light) 234px
) !important;
& > * {
opacity: 0 !important;
}
}
}
.headerTable {
background: var(--grey-background);
font-weight: 700;
font-size: 14px;
display: flex;
padding: 8px;
border-bottom: 1px solid var(--grey-background);
}
.footerTable {
text-align: center;
line-height: 32px;
font-size: 14px;
padding: 5px 10px;
border-top: 1px solid var(--grey-background);
border-bottom: 1px solid var(--grey-background);
}
.contentTable {
.tr {
display: flex;
border-bottom: 1px solid var(--grey-background);
padding: 8px;
font-size: 12px;
&:hover {
background: var(--grey-background);
}
&:last-child {
border-bottom: none;
}
& > div {
position: relative;
min-height: 32px;
& > .absolute_position {
width: 100%;
position: absolute;
height: 100%;
display: flex;
}
}
}
.fix_text_padding_medium {
padding: 8px 0;
display: inline-block;
line-height: 18px;
}
.text-complete-width {
overflow: hidden;
flex: 1;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
@@ -1,243 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable jsx-a11y/anchor-is-valid */
import React, { Component } from 'react';
import Languages from '@features/global/services/languages-service';
import Button from 'components/buttons/button.jsx';
import InputIcon from 'components/inputs/input-icon.jsx';
import './table.scss';
type Props = {
column?: any;
noHeader: boolean;
onAdd: () => void;
onRequestMore: (refresh: boolean) => Promise<any[]>;
onSearch: (query: string, maxResults: number, callback: (res: any[]) => void) => Promise<any[]>;
updatedData: (data: any) => any;
addText?: string;
resultsPerPage?: number;
unFocused: boolean;
};
type State = {
data: null | any[];
searchResults: any[];
loading: boolean;
has_more: boolean;
page: number;
searching: boolean;
};
export default class Table extends Component<Props, State> {
searchFieldValue = '';
searchRunning = false;
searchRunningTimeout: number | null = null;
constructor(props: Props) {
super(props);
this.state = {
data: null,
searchResults: [],
loading: true,
has_more: true,
page: 0,
searching: false,
};
Languages.addListener(this);
}
componentWillUnmount() {
Languages.removeListener(this);
}
componentDidMount() {
if (this.state.data === null) {
this.requestMore(true);
}
}
search() {
if (this.searchFieldValue?.length <= 2) {
return false;
}
if (this.searchRunning) {
clearTimeout(this.searchRunningTimeout as number);
this.searchRunningTimeout = window.setTimeout(() => {
this.search();
}, 1000);
return;
}
this.setState({
loading: true,
});
this.searchRunning = true;
this.props.onSearch(this.searchFieldValue, 10, (data: any[]) => {
this.searchRunning = false;
this.setState({
loading: false,
searchResults: data,
});
});
}
renderItem(col: any, item: any) {
if (col.render) {
return col.render(item);
} else {
return <div className="">{col.dataIndex ? item[col.dataIndex] : ''}</div>;
}
}
requestMore(refresh = false) {
this.setState({ loading: true });
this.props.onRequestMore(refresh).then(res => {
const hasMore = res.length !== (this.state.data || []).length;
this.setState({ loading: false, data: res, has_more: hasMore });
});
}
setPosition() {
if (!!this.props.onSearch && !this.props.onAdd) return 'flex-end';
else return 'space-between';
}
nextPage() {
this.setState({ page: this.state.page + 1 });
if (this.getPageData().length < (this.state.page + 1) * this.getResultsPerPage()) {
this.requestMore();
}
}
getPageData() {
const from = this.state.page * this.getResultsPerPage();
return (this.state.data || []).slice(0, from + this.getResultsPerPage());
}
getResultsPerPage(): number {
return this.props.resultsPerPage || 50;
}
render() {
let page_data = this.state.searching ? this.state.searchResults : this.getPageData();
page_data = page_data
.map(data => {
data = this.props.updatedData ? this.props.updatedData(data) : data;
if (!data) {
return false;
}
return data;
})
.filter(i => i);
return (
<div>
<div
className="small-y-margin full-width"
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: this.setPosition(),
}}
>
{this.props.onAdd && (
<Button
className="medium"
value={this.props.addText || 'Add'}
onClick={this.props.onAdd}
/>
)}
{!!this.props.onSearch && (
<div>
<InputIcon
icon="search"
small
placeholder={Languages.t('components.listmanager.filter', [], 'Search')}
onChange={(event: any) => {
const q = event.target.value;
this.searchFieldValue = q;
this.setState({ searching: q.length > 0 });
this.search();
}}
/>
</div>
)}
</div>
<div
className={
'table ' +
(this.props.unFocused ? 'unfocused ' : '') +
(this.state.loading ? 'loading ' : '')
}
>
{!this.props.noHeader && (
<div className="headerTable">
{this.props.column.map((col: any, i: number) => {
return (
<div
key={i}
className="headerItem"
style={{
width: col.width || 'inherit',
flex: col.width ? 'inherit' : '1',
textAlign: (col.titleStyle || {}).textAlign,
}}
>
{col.title}
</div>
);
})}
</div>
)}
<div className="contentTable">
{(page_data || []).length === 0 && !this.state.loading && (
<div className="tr" style={{ justifyContent: 'center', display: 'flex' }}>
<div className="item" style={{ lineHeight: '32px' }}>
{Languages.t('components.user_picker.modal_no_result')}
</div>
</div>
)}
{(page_data || []).length === 0 &&
!!this.state.loading &&
Array(this.state.searching ? 1 : this.getResultsPerPage()).map((_, i: number) => {
return (
<div key={i} className="tr">
<div className="item">
<div className="line"></div>
</div>
</div>
);
})}
{(page_data || []).map((data: any, i: number) => {
return (
<div key={i} className="tr">
{this.props.column.map((col: any, j: number) => {
return (
<div
key={j}
className="item"
style={{ width: col.width || 'inherit', flex: col.width ? 'inherit' : '1' }}
>
{this.renderItem(col, data)}
</div>
);
})}
</div>
);
})}
</div>
{!this.state.searching &&
!!this.state.has_more &&
page_data.length >= this.getResultsPerPage() && (
<div className="footerTable">
<a href="#" onClick={() => this.nextPage()}>
{Languages.t('components.searchpopup.load_more', [], 'Load more results')}
</a>
</div>
)}
</div>
</div>
);
}
}
@@ -1,98 +0,0 @@
import SecuredConnection from './SecuredConnection.js';
/** MultipleSecuredConnections
* Manage multiple secured connections as one (multiple publish and centralized event manager)
*/
export default class MultipleSecuredConnections {
constructor(callback, options) {
if (!options) {
options = {};
}
//Options :
this.disableDuplicates = options.disableDuplicates !== false;
this.secured_connections = {};
this.callback = callback;
this.removing_secured_connections_timeouts = {};
}
publish(data) {
Object.keys(this.secured_connections).forEach(secured_connection_key => {
var secured_connection = this.secured_connections[secured_connection_key];
secured_connection.publish(data, () => {});
});
}
event(route, event, data) {
//Disable duplicates
var string = JSON.stringify(data);
if (
string === this.last_event &&
this.disableDuplicates &&
!(event === 'close' || event === 'open' || event === 'init')
) {
return;
}
this.last_event = string;
if (!data) {
data = {};
}
data._route = route;
if (this.callback) this.callback(event, data);
}
addConnection(route, option, http_options, key) {
if (this.secured_connections[route]) {
this.secured_connections[route].removing = false;
if (this.removing_secured_connections_timeouts[route]) {
clearTimeout(this.removing_secured_connections_timeouts[route]);
}
return;
}
if (this.secured_connections[route]) {
return;
}
this.secured_connections[route] = new SecuredConnection(
route,
option,
(event, data) => {
this.event(route, event, data);
},
http_options,
key,
);
}
removeConnection(route) {
if (!this.secured_connections[route] || this.secured_connections[route].removing) {
return;
}
if (this.removing_secured_connections_timeouts[route]) {
clearTimeout(this.removing_secured_connections_timeouts[route]);
}
this.secured_connections[route].removing = true;
this.removing_secured_connections_timeouts[route] = setTimeout(() => {
if (this.secured_connections[route]) {
this.secured_connections[route].close();
delete this.secured_connections[route];
}
}, 10000);
}
getRoutes() {
return Object.keys(this.secured_connections);
}
closeAll() {
Object.keys(this.secured_connections).foEach(route => {
this.removeConnection(route);
});
}
}
@@ -1,265 +0,0 @@
import Api from '@features/global/framework/api-service';
import ws from '@deprecated/websocket/websocket.js';
import CryptoJS from 'crypto-js';
import sha256 from 'crypto-js/sha256';
/** SecuredConnection
* Create websockets encrypted connection
*/
import Globals from '@features/global/services/globals-tdrive-app-service';
export default class SecuredConnection {
constructor(route, options, callback, http_options, collectionId) {
this.ready = false;
this.collectionId = collectionId;
this.route = route;
this.options = options;
this.callback = callback;
//Room idea
this.websocket_id = '';
//Store keys
this.keys = [];
this.keys_by_version = {};
this.publish_buffer = [];
this.http_options = http_options;
this.init(http_options);
Globals.window.CryptoAES = CryptoJS.AES;
}
init(http_options) {
this.ready = false;
this.options.get_options = http_options;
var data = {
collection_id: this.route,
options: this.options,
_grouped: true,
};
Api.GroupedQueryApiPost('/ajax/core/collections/init', data, res => {
var did_get = false;
if (res.data) {
var data = res.data;
this.ready = true;
this.websocket_id = data.room_id;
this.receiveNewKey(data.key, data.key_version, false);
this.open();
if (data.get) {
this.callback('get', { collectionId: this.collectionId, data: data.get });
did_get = true;
}
}
if (!did_get) {
this.callback('init', {});
}
});
}
open() {
var websocket_id = this.websocket_id;
ws.subscribe(
'collections/' + websocket_id,
(uri, obj) => {
this.receiveEvent(obj);
},
websocket_id,
);
ws.onReconnect(websocket_id, () => {
this.close();
this.init();
});
this.callback('open', {});
this.publish();
}
close() {
var websocket_id = this.websocket_id;
ws.offReconnect(websocket_id);
ws.unsubscribe(
'collections/' + websocket_id,
(uri, obj) => {
this.receiveEvent(obj);
},
websocket_id,
);
this.callback('close', {});
}
publish(data, callback) {
if (!data) {
//Read buffer
var publish_buffer = JSON.parse(JSON.stringify(this.publish_buffer));
this.publish_buffer = [];
publish_buffer.forEach(item => {
this.publish(item, callback);
});
return;
}
if (!this.ready) {
this.publish_buffer.push(data);
return;
}
var websocket_id = this.websocket_id;
var encrypted = this.encrypt(data);
ws.publish('collections/' + websocket_id, encrypted);
if (callback) {
callback();
}
}
receiveEvent(event) {
if (event.encrypted) {
event = this.decrypt(event);
}
if (event.new_key) {
this.receiveNewKey(event.new_key, event.key_version, true);
return;
}
if (!event) {
return;
}
this.callback('event', event);
}
//Receive new key as addon for previous key or as replacing key (sent by php server)
receiveNewKey(key, version, asAddon) {
if (asAddon) {
var lastKey = this.keys[this.keys.length - 1];
key = sha256(lastKey.key + key).toString(); //Mix keys
}
this.keys.push({
key: key,
version: version,
});
this.keys_by_version[version] = key;
this.prepareEncryptKey();
}
prepareEncryptKey() {
var lastKey = this.keys[this.keys.length - 1];
try {
if (this.prepared_key_original !== lastKey) {
this.prepared_key_salt = CryptoJS.lib.WordArray.random(256);
this.prepared_key_original = lastKey;
this.prepared_key = CryptoJS.PBKDF2(lastKey.key, this.prepared_key_salt, {
hasher: CryptoJS.algo.SHA512,
keySize: 64 / 8,
iterations: 9,
});
}
} catch (e) {
console.log(e);
}
return this.prepared_key;
}
encrypt(data) {
var lastKey = this.keys[this.keys.length - 1];
var prepared_key = this.prepareEncryptKey();
if (!prepared_key) {
prepared_key = '';
}
var iv = CryptoJS.lib.WordArray.random(16);
var encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), prepared_key, { iv: iv });
// eslint-disable-next-line no-redeclare
var data = {
encrypted: CryptoJS.enc.Base64.stringify(encrypted.ciphertext),
iv: CryptoJS.enc.Hex.stringify(iv),
salt: CryptoJS.enc.Hex.stringify(this.prepared_key_salt),
key_version: lastKey.version,
};
return data;
}
decrypt(data) {
if (!data.key_version) {
return false;
}
let res = '';
let str = '';
try {
if (data.public) {
return typeof data.public === 'string' ? JSON.parse(data.public) : data.public;
}
var encrypted_data = data.encrypted;
var key = this.keys_by_version[data.key_version];
if (!key) {
if (
this.getKeyTimestamp(key) > this.getKeyTimestamp(this.keys[this.keys.length - 1].version)
) {
//We have a old key, we have to update and request the message again
this.init(this.http_options);
//TODO reask lost message after init
} else {
//We have only newer keys, ask everybody to update
//TODO ws.publish('collections/' + websocket_id, encrypted);
}
return false;
}
var salt = CryptoJS.enc.Hex.parse(data.salt);
var prepared_key = CryptoJS.PBKDF2(key, salt, {
hasher: CryptoJS.algo.SHA512,
keySize: 64 / 8,
iterations: 9,
});
var iv = CryptoJS.enc.Hex.parse(data.iv);
var bytes = CryptoJS.AES.decrypt(encrypted_data, prepared_key, { iv: iv });
str = bytes.toString(CryptoJS.enc.Utf8);
if (str) {
res = JSON.parse(str);
} else {
res = '';
}
} catch (err) {
console.error('Unable to read encrypted websocket event', str, err.message);
}
return res;
}
getKeyTimestamp(key) {
try {
if (typeof key !== 'string') {
if (key !== undefined) {
console.log('wrong websocket key format: ', key);
}
return 0;
}
return parseInt((key || '').split('-')[1]);
} catch (e) {
console.log(key, e);
}
}
}
@@ -1,184 +0,0 @@
import Number from '@features/global/utils/Numbers';
import Observable from '@deprecated/CollectionsV1/observable.js';
import LoginService from '@features/auth/login-service';
import Logger from '@features/global/framework/logger-service';
import Globals from '@features/global/services/globals-tdrive-app-service';
import WebSocket from '../../features/global/types/websocket-types';
/**
* @deprecated Keeps old PHP websocket working doing the bridge with the new implementation
*/
class DeprecatedWebsocket extends Observable {
constructor() {
super();
this.logger = Logger.getLogger('Websocket');
this.setObservableName('websockets');
this.ws = null;
this.connection = null;
this.afterError = false;
this.lastData = 1;
this.testNetwork = false;
this.connected = true;
this.subscribed = {};
this.subscribedKey = {};
this.disconnectListeners = {};
this.alive_connected = true;
this.firstTime = true;
this.last_reconnect_call = new Date();
this.last_reconnect_call_if_needed = new Date();
window.websocketsManager = this;
this.window_focus = true;
this.window_last_blur = new Date();
this.deconnectionBlurTimeout = setTimeout(() => {}, 0);
Globals.window.addEventListener('focus', () => {
this.reconnectIfNeeded(60);
clearTimeout(this.deconnectionBlurTimeout);
this.didFocusedLastMinute = true;
this.window_focus = true;
this.window_last_blur = new Date();
if (this.ws == null || new Date().getTime() - this.window_last_blur.getTime() > 30000) {
this.alive_connected = false;
this.alive();
}
});
Globals.window.addEventListener('blur', () => {
this.window_focus = false;
this.window_last_blur = new Date();
});
this.alive.bind(this);
this.message.bind(this);
this.updateConnected.bind(this);
}
//Send I'm alive !
alive() {
var nw = new Date().getTime();
if (!this.lastAlive || nw - this.lastAlive > 60000) {
// Wait at least 60 seconds
this.lastAlive = nw;
this.alive_timeout = setTimeout(() => {
this.alive_connected = false;
}, 5100);
this.reconnectIfNeeded();
clearTimeout(this.alive_timeout);
this.alive_connected = true;
this.didFocusedLastMinute = Globals.isReactNative || Globals.window.document.hasFocus();
}
}
//Receive server message
message(unid, route, data) {
route = (route || '').split('previous::').pop();
if (unid !== this.subscribedKey[route]) {
return;
}
if (this.subscribed[route]) {
this.subscribed[route].forEach(c => {
try {
c.callback(route, data);
} catch (err) {
console.log(err);
}
});
} else {
this.unsubscribe(route);
}
}
//Subscribe to channel
subscribe(route, callback, key) {
this.logger.debug(`Subscribe to ${route}`);
route = (route || '').split('previous::').pop();
if (!key) {
key = callback.name;
}
if (!this.subscribed[route]) {
this.subscribed[route] = [];
}
this.subscribed[route].push({ name: key, callback: callback });
if (this.subscribed[route].length === 1) {
const unid = Number.unid();
this.subscribedKey[route] = unid;
WebSocket.get().join('previous::' + route, '', '', (type, data) => {
if (type === 'realtime:event') {
this.message(unid, data.name, data.data);
}
if (type === 'connected') {
this.updateConnected(true);
}
if (type === 'disconnected') {
this.updateConnected(false);
}
});
}
}
//Unsubscribe from channel
unsubscribe(route, callback, key) {
this.logger.debug(`Unsubscribe from ${route}`);
route = (route || '').split('previous::').pop();
if (!key && callback) {
key = callback.name;
}
if (!key) {
key = 'default';
}
if (!this.subscribed[route]) {
this.subscribed[route] = [];
}
var remaining = [];
this.subscribed[route].forEach(c => {
if (c.name !== key) {
remaining.push(c);
}
});
this.subscribed[route] = remaining;
if (this.subscribed[route].length === 0) {
WebSocket.get().leave('previous::' + route, '');
}
}
publish(route, value) {
this.logger.debug(`Publish to ${route}`);
WebSocket.get().send('previous::' + route, value);
}
reconnectIfNeeded(seconds = 30) {
if (new Date().getTime() - this.last_reconnect_call_if_needed.getTime() > seconds * 1000) {
//30 seconds
if (LoginService.currentUserId) {
LoginService.updateUser();
}
this.last_reconnect_call_if_needed = new Date();
}
}
onReconnect(id, callback) {
this.disconnectListeners[id] = callback;
}
offReconnect(id) {
delete this.disconnectListeners[id];
}
updateConnected(state) {
if (state !== this.connected) {
this.connected = state;
this.notify();
}
}
isConnected() {
return this.connected;
}
}
export default new DeprecatedWebsocket();