Tema dt mod


SUBMITTED BY: Buganet

DATE: Aug. 1, 2022, 9:15 p.m.

UPDATED: May 27, 2024, 11:20 a.m.

FORMAT: Text only

SIZE: 65.8 kB

HITS: 2405

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>DTunnel_s
  8. _t_project_edit</title>
  9. </head>
  10. <style>
  11. * {
  12. margin: 0;
  13. padding: 0;
  14. box-sizing: border-box;
  15. -webkit-tap-highlight-color: transparent;
  16. font-family: 'Verdana', sans-serif;
  17. }
  18. ::placeholder {
  19. color: #b0a8ffff;
  20. }
  21. body {
  22. height: 100vh;
  23. }
  24. @keyframes fade-in {
  25. from {
  26. opacity: 0;
  27. }
  28. to {
  29. opacity: 1;
  30. }
  31. }
  32. @keyframes fade-out {
  33. from {
  34. opacity: 1;
  35. }
  36. to {
  37. opacity: 0;
  38. }
  39. }
  40. @keyframes pulse {
  41. 0% {
  42. transform: scale(1);
  43. box-shadow: none;
  44. }
  45. 50% {
  46. transform: scale(1.2);
  47. box-shadow: 0 0 10px 5px #b0a8ffff;
  48. }
  49. 100% {
  50. transform: scale(1);
  51. box-shadow: none;
  52. }
  53. }
  54. </style>
  55. <body>
  56. <div id="root">
  57. </div>
  58. <script>
  59. const BACKGROUND_COLOR = `linear-gradient(45deg, #14142c, #14142c 25%, #1210246b 25%, #1210246b 50%, #14142c 50%, #14142c 75%, #1210246b 75%, #1210246b), #14142c`;
  60. const INPUT_COLOR = '#1210246b'
  61. const BUTTON_BACKGROUND_COLOR = '#1210246b'
  62. const ICON_COLOR = '#6205d5'
  63. const TEXT_COLOR = '#b0a8ffff'
  64. const TOOLS_BUTTON_BACKGROUND_COLOR = '#1210246b'
  65. const VPN_STATE_TEXT_COLOR = '#b0a8ffff'
  66. const VPN_BUTTON_BACKGROUND_COLOR = '#1210246b'
  67. const CHECKUSER_TEXT_COLOR = '#b0a8ffff'
  68. const LOGGER_TEXT_COLOR = '#b0a8ffff'
  69. const DIALOG_HEADER_TITLE_COLOR = '#b0a8ffff'
  70. const DIALOG_HEADER_CLOSE_BUTTON_COLOR = '#b0a8ffff'
  71. const DIALOG_CONTENT_BACKGROUND_COLOR = '#14142c'
  72. const DIALOG_FOOTER_BUTTON_COLOR = '#1210246b'
  73. const DIALOG_FOOTER_BUTTON_TEXT_COLOR = '#b0a8ffff'
  74. const TERMS_URL = 'https://telksbr.github.io/SSH_T_PROJECT_TERMOS/'
  75. class Component {
  76. constructor(element) {
  77. this.element = element;
  78. }
  79. addEventListener(event, listener) {
  80. this.element.addEventListener(event, listener);
  81. }
  82. append(component) {
  83. if (component instanceof Component) {
  84. this.element.appendChild(component.element);
  85. } else {
  86. this.element.append(component);
  87. }
  88. }
  89. appendChild(component) {
  90. if (component instanceof Component) {
  91. this.element.appendChild(component.element);
  92. } else {
  93. this.element.appendChild(component);
  94. }
  95. }
  96. }
  97. class StyledComponent extends Component {
  98. constructor(element, styles = {}) {
  99. super(element);
  100. this.styles = styles;
  101. this.setStyles(styles);
  102. }
  103. setStyles(styles) {
  104. Object.keys(styles).forEach((key) => {
  105. if (this.element.style.hasOwnProperty(key)) {
  106. this.element.style[key] = styles[key];
  107. }
  108. });
  109. }
  110. }
  111. class AppComponent extends StyledComponent {
  112. constructor(element, styles = {}) {
  113. const defaultStyles = {
  114. width: '100%',
  115. height: '100%',
  116. background: '#404258',
  117. display: 'flex',
  118. flexDirection: 'column',
  119. justifyContent: 'center',
  120. alignItems: 'center',
  121. };
  122. super(element, { ...defaultStyles, ...styles });
  123. }
  124. }
  125. class CardComponent extends StyledComponent {
  126. constructor(styles = {}) {
  127. const defaultStyles = {
  128. display: 'flex',
  129. flexDirection: 'column',
  130. alignItems: 'center',
  131. justifyContent: 'center',
  132. width: '100%',
  133. maxWidth: '23rem',
  134. gap: '10px',
  135. margin: '1.2rem',
  136. padding: '5px',
  137. borderRadius: '5px',
  138. border: 'none',
  139. };
  140. super(document.createElement('div'), { ...defaultStyles, ...styles });
  141. }
  142. }
  143. class InputGroupComponent extends StyledComponent {
  144. constructor(styles = {}) {
  145. const defaultStyles = {
  146. display: 'flex',
  147. width: '100%',
  148. alignItems: 'center',
  149. background: '#363749',
  150. color: '#b0a8ffff',
  151. padding: '0.2rem',
  152. height: '40px',
  153. borderRadius: '10px',
  154. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  155. };
  156. super(document.createElement('div'), { ...defaultStyles, ...styles });
  157. }
  158. append(...components) {
  159. components.forEach((component) => super.append(component));
  160. }
  161. }
  162. class InputComponent extends StyledComponent {
  163. constructor(styles = {}) {
  164. const defaultStyles = {
  165. background: 'transparent',
  166. border: 'none',
  167. width: '100%',
  168. outline: 'none',
  169. color: TEXT_COLOR,
  170. fontSize: '15px',
  171. };
  172. super(document.createElement('input'), { ...defaultStyles, ...styles });
  173. }
  174. setEnabled(value) {
  175. this.element.disabled = !value;
  176. }
  177. }
  178. class InputText extends InputComponent {
  179. constructor(styles = {}) {
  180. super(styles);
  181. this.element.type = 'text';
  182. }
  183. get value() {
  184. return this.element.value;
  185. }
  186. setPlaceholder(text) {
  187. this.element.placeholder = text;
  188. }
  189. setOnInputListener(callback) {
  190. this.addEventListener('input', callback);
  191. }
  192. setValue(value) {
  193. this.element.value = value;
  194. }
  195. setOnInputListener(callback) {
  196. this.addEventListener('input', callback);
  197. }
  198. }
  199. class InputPassword extends InputText {
  200. constructor(styles = {}) {
  201. super(styles);
  202. this.element.type = 'password';
  203. }
  204. setShowing(value) {
  205. this.element.type = !value ? 'password' : 'text';
  206. }
  207. get isShowing() { return this.element.type != 'password' }
  208. }
  209. class SvgComponent extends StyledComponent {
  210. constructor(styles = {}, ...paths) {
  211. const defaultStyles = {
  212. fill: '#1210246b',
  213. padding: '5px',
  214. width: '35px',
  215. height: '35px',
  216. filter: 'drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.5))',
  217. };
  218. super(document.createElementNS('http://www.w3.org/2000/svg', 'svg'), {
  219. ...defaultStyles,
  220. ...styles,
  221. });
  222. this.applyOptions();
  223. paths.forEach((p) => this.addPath(p));
  224. }
  225. applyOptions() {
  226. this.setFill(this.styles.fill || 'currentColor');
  227. this.setWidth(this.styles.width || '16');
  228. this.setHeight(this.styles.height || '16');
  229. this.setViewBox(this.styles.viewBox || '0 0 16 16');
  230. this.setXmlns(this.styles.xmlns || 'http://www.w3.org/2000/svg');
  231. }
  232. setFill(color) {
  233. this.element.setAttribute('fill', color);
  234. }
  235. setWidth(width) {
  236. this.element.setAttribute('width', width);
  237. }
  238. setHeight(height) {
  239. this.element.setAttribute('height', height);
  240. }
  241. setViewBox(viewBox) {
  242. this.element.setAttribute('viewBox', viewBox);
  243. }
  244. setXmlns(xmlns) {
  245. this.element.setAttribute('xmlns', xmlns);
  246. }
  247. addPath(...path) {
  248. path.forEach((item) => {
  249. const pathElement = document.createElementNS(
  250. 'http://www.w3.org/2000/svg',
  251. 'path'
  252. );
  253. pathElement.setAttribute('d', item);
  254. this.element.appendChild(pathElement);
  255. });
  256. }
  257. }
  258. class CalanderIconComponent extends SvgComponent {
  259. constructor(styles = {}) {
  260. super({
  261. cursor: 'pointer',
  262. background: TOOLS_BUTTON_BACKGROUND_COLOR,
  263. borderRadius: '20%',
  264. height: '45px',
  265. width: '45px',
  266. padding: '10px',
  267. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  268. fill: ICON_COLOR,
  269. ...styles,
  270. },
  271. 'M4.684 11.523v-2.3h2.261v-.61H4.684V6.801h2.464v-.61H4v5.332h.684zm3.296 0h.676V8.98c0-.554.227-1.007.953-1.007.125 0 .258.004.329.015v-.613a1.806 1.806 0 0 0-.254-.02c-.582 0-.891.32-1.012.567h-.02v-.504H7.98v4.105zm2.805-5.093c0 .238.192.425.43.425a.428.428 0 1 0 0-.855.426.426 0 0 0-.43.43zm.094 5.093h.672V7.418h-.672v4.105z',
  272. 'M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z'
  273. );
  274. }
  275. }
  276. class LoggerIconComponent extends SvgComponent {
  277. constructor(styles = {}) {
  278. super({
  279. cursor: 'pointer',
  280. background: TOOLS_BUTTON_BACKGROUND_COLOR,
  281. borderRadius: '20%',
  282. height: '45px',
  283. width: '45px',
  284. padding: '10px',
  285. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  286. fill: ICON_COLOR,
  287. ...styles,
  288. },
  289. 'M5 4a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1H5zm-.5 2.5A.5.5 0 0 1 5 6h6a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zM5 8a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1H5zm0 2a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1H5z',
  290. 'M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z'
  291. );
  292. }
  293. }
  294. class ArrowRepeatIconComponent extends SvgComponent {
  295. constructor(styles = {}) {
  296. super({
  297. cursor: 'pointer',
  298. background: TOOLS_BUTTON_BACKGROUND_COLOR,
  299. borderRadius: '20%',
  300. height: '45px',
  301. width: '45px',
  302. padding: '10px',
  303. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  304. fill: ICON_COLOR,
  305. ...styles,
  306. },
  307. 'M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41zm-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9z',
  308. 'M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5.002 5.002 0 0 0 8 3zM3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9H3.1z'
  309. );
  310. }
  311. }
  312. class BatteryIconComponent extends SvgComponent {
  313. constructor(styles = {}) {
  314. super({
  315. cursor: 'pointer',
  316. background: TOOLS_BUTTON_BACKGROUND_COLOR,
  317. borderRadius: '20%',
  318. height: '45px',
  319. width: '45px',
  320. padding: '10px',
  321. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  322. fill: ICON_COLOR,
  323. ...styles,
  324. },
  325. 'M2 6h10v4H2V6z', 'M2 4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H2zm10 1a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h10zm4 3a1.5 1.5 0 0 1-1.5 1.5v-3A1.5 1.5 0 0 1 16 8z'
  326. );
  327. }
  328. }
  329. class SpeedMeterIconComponent extends SvgComponent {
  330. constructor(styles = {}) {
  331. super({
  332. cursor: 'pointer',
  333. background: TOOLS_BUTTON_BACKGROUND_COLOR,
  334. borderRadius: '20%',
  335. height: '45px',
  336. width: '45px',
  337. padding: '10px',
  338. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  339. fill: ICON_COLOR,
  340. ...styles,
  341. },
  342. 'M8 2a.5.5 0 0 1 .5.5V4a.5.5 0 0 1-1 0V2.5A.5.5 0 0 1 8 2zM3.732 3.732a.5.5 0 0 1 .707 0l.915.914a.5.5 0 1 1-.708.708l-.914-.915a.5.5 0 0 1 0-.707zM2 8a.5.5 0 0 1 .5-.5h1.586a.5.5 0 0 1 0 1H2.5A.5.5 0 0 1 2 8zm9.5 0a.5.5 0 0 1 .5-.5h1.5a.5.5 0 0 1 0 1H12a.5.5 0 0 1-.5-.5zm.754-4.246a.389.389 0 0 0-.527-.02L7.547 7.31A.91.91 0 1 0 8.85 8.569l3.434-4.297a.389.389 0 0 0-.029-.518z',
  343. 'M6.664 15.889A8 8 0 1 1 9.336.11a8 8 0 0 1-2.672 15.78zm-4.665-4.283A11.945 11.945 0 0 1 8 10c2.186 0 4.236.585 6.001 1.606a7 7 0 1 0-12.002 0z'
  344. );
  345. }
  346. }
  347. class TrashIconComponent extends SvgComponent {
  348. constructor(styles = {}) {
  349. super({
  350. cursor: 'pointer',
  351. background: TOOLS_BUTTON_BACKGROUND_COLOR,
  352. borderRadius: '20%',
  353. height: '45px',
  354. width: '45px',
  355. padding: '10px',
  356. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  357. fill: ICON_COLOR,
  358. ...styles,
  359. },
  360. 'M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6Z',
  361. 'M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1ZM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118ZM2.5 3h11V2h-11v1Z'
  362. );
  363. }
  364. }
  365. class ArrowDownIconComponent extends SvgComponent {
  366. constructor(style = {}) {
  367. super({
  368. fill: ICON_COLOR,
  369. ...style,
  370. },
  371. 'M1 3.5a.5.5 0 0 1 .5-.5h13a.5.5 0 0 1 0 1h-13a.5.5 0 0 1-.5-.5zM8 6a.5.5 0 0 1 .5.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 0 1 .708-.708L7.5 12.293V6.5A.5.5 0 0 1 8 6z'
  372. );
  373. }
  374. }
  375. class NetworkIconComponent extends SvgComponent {
  376. constructor(style = {}) {
  377. super({
  378. fill: ICON_COLOR,
  379. ...style,
  380. },
  381. 'M4.5 5a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1zM3 4.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0z',
  382. 'M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v1a2 2 0 0 1-2 2H8.5v3a1.5 1.5 0 0 1 1.5 1.5h5.5a.5.5 0 0 1 0 1H10A1.5 1.5 0 0 1 8.5 14h-1A1.5 1.5 0 0 1 6 12.5H.5a.5.5 0 0 1 0-1H6A1.5 1.5 0 0 1 7.5 10V7H2a2 2 0 0 1-2-2V4zm1 0v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1zm6 7.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5z'
  383. );
  384. }
  385. }
  386. class PersonIconComponent extends SvgComponent {
  387. constructor(style = {}) {
  388. super({
  389. fill: ICON_COLOR,
  390. ...style,
  391. },
  392. 'M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6Zm2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0Zm4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4Zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10Z'
  393. );
  394. }
  395. }
  396. class LockIconComponent extends SvgComponent {
  397. constructor(style = {}) {
  398. super({
  399. fill: ICON_COLOR,
  400. ...style,
  401. },
  402. 'M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2zM5 8h6a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1z'
  403. );
  404. }
  405. }
  406. class EyeIconComponent extends SvgComponent {
  407. constructor(style = {}) {
  408. super({
  409. fill: ICON_COLOR,
  410. ...style,
  411. },
  412. 'M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z',
  413. 'M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z',
  414. );
  415. }
  416. }
  417. class ArrowDownShortIconComponent extends SvgComponent {
  418. constructor(style = {}) {
  419. super({
  420. fill: ICON_COLOR,
  421. ...style,
  422. },
  423. 'M8 4a.5.5 0 0 1 .5.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5A.5.5 0 0 1 8 4z'
  424. );
  425. }
  426. }
  427. class ArrowUpShortIconComponent extends SvgComponent {
  428. constructor(style = {}) {
  429. super({
  430. fill: ICON_COLOR,
  431. ...style,
  432. },
  433. 'M8 12a.5.5 0 0 0 .5-.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 .5.5z'
  434. );
  435. }
  436. }
  437. class PowerIconComponent extends SvgComponent {
  438. constructor(style = {}) {
  439. super({
  440. cursor: 'pointer',
  441. height: '7.5rem',
  442. width: '7.5rem',
  443. background: VPN_BUTTON_BACKGROUND_COLOR,
  444. borderRadius: '50%',
  445. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  446. padding: '20px',
  447. // animation: 'pulse 4s infinite',
  448. fill: ICON_COLOR,
  449. ...style,
  450. },
  451. 'M7.5 1v7h1V1h-1z',
  452. 'M3 8.812a4.999 4.999 0 0 1 2.578-4.375l-.485-.874A6 6 0 1 0 11 3.616l-.501.865A5 5 0 1 1 3 8.812z',
  453. );
  454. }
  455. }
  456. class DialogComponent extends Component {
  457. constructor() {
  458. super(document.createElement('div'));
  459. this.element.style.position = 'absolute';
  460. this.element.style.top = '0';
  461. this.element.style.bottom = '0';
  462. this.element.style.left = '0';
  463. this.element.style.right = '0';
  464. this.element.style.height = '100vh';
  465. this.element.style.background = 'rgba(0, 0, 0, 0.5)';
  466. this.element.style.backdropFilter = 'blur(5px)';
  467. this.element.style.display = 'flex';
  468. this.element.style.alignItems = 'center';
  469. this.element.style.justifyContent = 'center';
  470. this.element.style.visibility = 'hidden';
  471. this.element.style.opacity = '0';
  472. this.element.addEventListener('click', (event) => {
  473. if (event.target === this.element) {
  474. this.close();
  475. }
  476. });
  477. this.onCloseEvent = null
  478. }
  479. setOnCloseEvent(callback) {
  480. this.onCloseEvent = callback
  481. }
  482. setContent(content) {
  483. if (!(content instanceof DialogContentComponent)) {
  484. throw new TypeError('Content must be a DialogContentComponent');
  485. }
  486. this.append(content);
  487. }
  488. close() {
  489. this.element.style.opacity = '0';
  490. this.element.style.animation = 'fade-out 0.3s forwards';
  491. setTimeout(() => {
  492. this.element.style.display = 'none';
  493. this.element.style.pointerEvents = 'none';
  494. if (this.onCloseEvent != null) {
  495. this.onCloseEvent()
  496. }
  497. }, 300);
  498. }
  499. show() {
  500. this.element.style.opacity = '1';
  501. this.element.style.visibility = 'visible';
  502. this.element.style.display = 'flex';
  503. this.element.style.animation = 'fade-in 0.3s forwards';
  504. this.element.style.pointerEvents = 'auto';
  505. if (!document.body.contains(this.element)) {
  506. document.body.append(this.element);
  507. }
  508. }
  509. }
  510. class DialogContentComponent extends StyledComponent {
  511. constructor(styles = {}) {
  512. super(document.createElement('div'), {
  513. display: 'flex',
  514. flexDirection: 'column',
  515. justifyContent: 'center',
  516. alignItems: 'center',
  517. background: DIALOG_CONTENT_BACKGROUND_COLOR,
  518. borderRadius: '5px',
  519. maxWidth: '30rem',
  520. width: '85%',
  521. ...styles,
  522. });
  523. }
  524. setHeader(component) {
  525. if (!(component instanceof DialogHeaderComponent)) {
  526. throw new TypeError('Component must be a DialogHeaderComponent instance');
  527. }
  528. this.append(component);
  529. }
  530. setBody(component) {
  531. if (!(component instanceof DialogBodyComponent)) {
  532. throw new TypeError('Component must be a DialogBodyComponent instance');
  533. }
  534. this.append(component);
  535. }
  536. setFooter(component) {
  537. if (!(component instanceof DialogFooterComponent)) {
  538. throw new TypeError('Component must be a DialogFooterComponent instance');
  539. }
  540. this.append(component);
  541. }
  542. }
  543. class DialogHeaderComponent extends StyledComponent {
  544. constructor(styles = {}) {
  545. super(document.createElement('div'), {
  546. display: 'flex',
  547. justifyContent: 'space-between',
  548. alignItems: 'center',
  549. width: '100%',
  550. padding: '5px',
  551. ...styles,
  552. });
  553. this.title = new StyledComponent(document.createElement('span'), {
  554. fontSize: '16px',
  555. color: DIALOG_HEADER_TITLE_COLOR,
  556. fontFamily: 'Verdana',
  557. fontWeight: 'bold',
  558. padding: '5px',
  559. });
  560. this.closeButton = new SvgComponent({
  561. cursor: 'pointer',
  562. height: '35px',
  563. width: '35px',
  564. fill: DIALOG_HEADER_CLOSE_BUTTON_COLOR,
  565. },
  566. 'M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z'
  567. );
  568. this.initialize();
  569. }
  570. setTitleText(title) {
  571. this.title.element.innerText = title;
  572. }
  573. setCloseButtonClickListener(callback) {
  574. this.closeButton.addEventListener('click', callback);
  575. }
  576. initialize() {
  577. this.append(this.title);
  578. this.append(this.closeButton);
  579. }
  580. }
  581. class DialogBodyComponent extends StyledComponent {
  582. constructor(styles = {}) {
  583. super(document.createElement('div'), {
  584. display: 'flex',
  585. width: '100%',
  586. padding: '5px',
  587. ...styles,
  588. });
  589. }
  590. }
  591. class DialogFooterComponent extends StyledComponent {
  592. constructor(styles = {}) {
  593. super(document.createElement('div'), {
  594. display: 'flex',
  595. justifyContent: 'space-between',
  596. gap: '5px',
  597. alignItems: 'center',
  598. width: '100%',
  599. padding: '5px',
  600. ...styles,
  601. });
  602. }
  603. addButton(button) {
  604. if (!(button instanceof DialogFooterButtonComponent)) {
  605. throw new TypeError('Button must be a DialogFooterButtonComponent instance');
  606. }
  607. this.append(button);
  608. }
  609. }
  610. class DialogFooterButtonComponent extends StyledComponent {
  611. constructor(text, onclick, styles = {}) {
  612. super(document.createElement('button'), {
  613. fontSize: '14px',
  614. fontWeight: 'bold',
  615. color: DIALOG_FOOTER_BUTTON_TEXT_COLOR,
  616. background: DIALOG_FOOTER_BUTTON_COLOR,
  617. border: 'none',
  618. borderRadius: '3px',
  619. padding: '5px 10px',
  620. width: '100%',
  621. cursor: 'pointer',
  622. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  623. ...styles,
  624. });
  625. this.setText(text)
  626. this.setClickListener(onclick);
  627. }
  628. setText(text) {
  629. this.element.innerText = text;
  630. }
  631. setClickListener(callback) {
  632. this.addEventListener('click', callback);
  633. }
  634. }
  635. class ConfigComponent extends StyledComponent {
  636. constructor(styles = {}) {
  637. super(document.createElement('div'), {
  638. display: 'flex',
  639. gap: '5px',
  640. alignItems: 'center',
  641. textAlign: 'left',
  642. marginTop: '5px',
  643. padding: '5px',
  644. background: 'rgba(255, 255, 255, 0.1)',
  645. width: '100%',
  646. borderRadius: '5px',
  647. filter: 'drop-shadow rgba(0, 0, 0, 0.5)',
  648. ...styles
  649. });
  650. this.image = document.createElement('img');
  651. this.name = document.createElement('span');
  652. this.description = document.createElement('span');
  653. this.mode = document.createElement('span');
  654. this.initialize();
  655. }
  656. setImage(url) {
  657. this.image.src = url;
  658. }
  659. setName(name) {
  660. this.name.innerHTML = name;
  661. }
  662. setDescription(description) {
  663. this.description.innerHTML = description;
  664. }
  665. setMode(mode) {
  666. this.mode.innerHTML = mode;
  667. }
  668. initialize() {
  669. this.setImageStyles();
  670. this.setNameStyles();
  671. this.setDescriptionStyles();
  672. this.setModeStyles();
  673. const startArea = this.createStartArea();
  674. const endArea = this.createEndArea();
  675. this.appendElements(startArea, endArea);
  676. }
  677. setImageStyles() {
  678. this.image.style.width = '40px';
  679. this.image.style.height = '40px';
  680. }
  681. setNameStyles() {
  682. this.name.style.fontSize = '12px';
  683. this.name.style.fontFamily = 'Verdana', 'sans-serif;';
  684. this.name.style.color = '#b0a8ffff';
  685. this.name.style.fontWeight = 'bold';
  686. }
  687. setDescriptionStyles() {
  688. this.description.style.fontSize = '10px';
  689. this.description.style.fontFamily = 'Verdana', 'sans-serif;';
  690. this.description.style.color = '#b0a8ffff';
  691. this.description.style.fontWeight = 'bold';
  692. this.description.style.fontStyle = 'italic';
  693. }
  694. setModeStyles() {
  695. this.mode.style.fontSize = '10px';
  696. this.mode.style.fontFamily = 'Verdana', 'sans-serif;';
  697. this.mode.style.color = '#b0a8ffff'
  698. this.mode.style.fontWeight = 'bold';
  699. this.mode.style.fontStyle = 'italic';
  700. this.mode.style.whiteSpace = 'nowrap';
  701. }
  702. createStartArea() {
  703. const startArea = document.createElement('div');
  704. startArea.style.display = 'flex';
  705. startArea.style.width = '100%';
  706. startArea.style.gap = '10px';
  707. startArea.style.flexDirection = 'column';
  708. startArea.appendChild(this.name);
  709. startArea.appendChild(this.description);
  710. return startArea;
  711. }
  712. createEndArea() {
  713. const endArea = document.createElement('div');
  714. endArea.style.display = 'flex';
  715. endArea.style.flexDirection = 'column';
  716. endArea.style.alignItems = 'end';
  717. endArea.style.alignSelf = 'end';
  718. endArea.style.width = '50%';
  719. endArea.appendChild(this.mode);
  720. return endArea;
  721. }
  722. appendElements(startArea, endArea) {
  723. this.appendChild(this.image);
  724. this.appendChild(startArea);
  725. this.appendChild(endArea);
  726. }
  727. }
  728. class CategoryComponent extends StyledComponent {
  729. constructor(styles = {}, items = []) {
  730. super(document.createElement('div'), {
  731. display: 'flex',
  732. justifyContent: 'center',
  733. alignItems: 'center',
  734. flexDirection: 'column',
  735. textAlign: 'center',
  736. padding: '2px',
  737. width: '100%',
  738. ...styles
  739. });
  740. this.items = items;
  741. this.name = document.createElement('span');
  742. this.setNameStyles();
  743. this.initialize();
  744. this.setItems(items);
  745. }
  746. setNameStyles() {
  747. this.name.style.width = '100%';
  748. this.name.style.borderRadius = '5px';
  749. this.name.style.fontSize = '12px'
  750. this.name.style.fontFamily = 'Verdana';
  751. this.name.style.color = '#b0a8ffff';
  752. this.name.style.background = 'rgba(255, 255, 255, 0.1)';
  753. this.name.style.padding = '5px';
  754. this.name.style.fontWeight = 'bold';
  755. }
  756. setName(value) {
  757. this.name.innerHTML = value;
  758. }
  759. setItems(items) {
  760. items.forEach(item => this.append(item));
  761. }
  762. initialize() {
  763. this.appendChild(this.name);
  764. }
  765. }
  766. class ConfigBodyComponent extends DialogBodyComponent {
  767. constructor(items) {
  768. super({
  769. flexDirection: 'column',
  770. gap: '5px',
  771. maxHeight: '70vh',
  772. overflowY: 'auto'
  773. });
  774. items.forEach(item => this.append(item));
  775. }
  776. }
  777. class LoggerItemComponent extends StyledComponent {
  778. constructor(styles = {}, message) {
  779. super(document.createElement('span'), {
  780. fontFamily: 'monospace',
  781. width: '100%',
  782. fontSize: '15px',
  783. color: LOGGER_TEXT_COLOR,
  784. ...styles,
  785. });
  786. this.element.innerHTML = message
  787. }
  788. }
  789. class LoggerBodyComponent extends DialogBodyComponent {
  790. constructor(styles = {}, items = []) {
  791. super({
  792. flexDirection: 'column',
  793. maxHeight: '65vh',
  794. overflowY: 'auto',
  795. width: '100%',
  796. ...styles,
  797. });
  798. this.setItems(items);
  799. }
  800. setItems(items) {
  801. this.element.innerHTML = '';
  802. items.forEach(item => this.append(item));
  803. this.scrollDown();
  804. }
  805. scrollDown() {
  806. this.element.scrollTop = this.element.scrollHeight;
  807. }
  808. }
  809. class CheckUserBodyComponent extends DialogBodyComponent {
  810. constructor(data = {}) {
  811. super()
  812. const component = new StyledComponent(document.createElement('div'), {
  813. display: 'flex',
  814. flexDirection: 'column',
  815. color: '#b0a8ffff',
  816. fontFamily: 'Verdana',
  817. gap: '2px',
  818. textAlign: 'center',
  819. width: '100%',
  820. });
  821. component.element.innerHTML = `
  822. <span style="color: ${CHECKUSER_TEXT_COLOR}">👤Nome de usuario: ${data.username}</span>
  823. <span style="color: ${CHECKUSER_TEXT_COLOR}">📆Expira em: ${data.expiration_date}</span>
  824. <span style="color: ${CHECKUSER_TEXT_COLOR}">📆Dias restantes: ${data.expiration_days}</span>
  825. <span style="color: ${CHECKUSER_TEXT_COLOR}">🚫Conexoes: ${data.count_connections}|${data.limit_connections}</span>
  826. `
  827. this.append(component)
  828. }
  829. }
  830. class VpnStateComponent extends StyledComponent {
  831. constructor(style = {}) {
  832. super(document.createElement('span'), {
  833. fontSize: '1.5tem',
  834. fontFamily: 'Verdana',
  835. fontWeight: 'bold',
  836. color: VPN_STATE_TEXT_COLOR,
  837. marginTop: '2rem',
  838. ...style,
  839. })
  840. this.setState('DISCONNECTED')
  841. }
  842. setState(state) {
  843. this.element.innerHTML = state
  844. }
  845. }
  846. class LocalIPComponent extends StyledComponent {
  847. constructor(styles = {}) {
  848. super(document.createElement('span'), {
  849. position: 'absolute',
  850. fontSize: '1rem',
  851. fontFamily: 'Verdana',
  852. color: TEXT_COLOR,
  853. top: `${totalTopValue}px`,
  854. left: '10px',
  855. display: 'flex', // Adicionando display: flex para ativar o flexbox
  856. justifyContent: 'center', // Centralizar horizontalmente
  857. alignItems: 'center', // Centralizar verticalmente
  858. ...styles,
  859. });
  860. this.setIP(window?.DtGetLocalIP?.execute() ?? '127.0.0.1');
  861. setInterval(() => {
  862. this.setIP(window?.DtGetLocalIP?.execute() ?? '127.0.0.1');
  863. }, 1000);
  864. }
  865. setIP(ip) {
  866. this.element.innerHTML = `IP Local: ${ip}`;
  867. }
  868. }
  869. const statusBarHeight = window?.DtGetStatusBarHeight?.execute();
  870. const extraPixels = 3; // Number of extra pixels you want to add
  871. const defaultHeight = 60; // Default height if statusBarHeight is undefined
  872. const totalTopValue = (statusBarHeight !== undefined ? statusBarHeight : defaultHeight) + extraPixels;
  873. class NetworkStatsComponent extends StyledComponent {
  874. constructor(styles = {}) {
  875. super(document.createElement('div'), {
  876. display: 'flex',
  877. position: 'absolute',
  878. gap: '10px',
  879. top: `${(totalTopValue) + 10}px`,
  880. right: '5px',
  881. ...styles,
  882. });
  883. this.meterDownContainer = this.createMeterContainer();
  884. this.meterDownText = this.createMeterText();
  885. this.arrowDownShortIcon = new ArrowDownShortIconComponent();
  886. this.meterDownContainer.append(this.arrowDownShortIcon);
  887. this.meterDownContainer.append(this.meterDownText);
  888. this.meterUpContainer = this.createMeterContainer();
  889. this.meterUpText = this.createMeterText();
  890. this.arrowUpShortIcon = new ArrowUpShortIconComponent();
  891. this.meterUpContainer.append(this.arrowUpShortIcon);
  892. this.meterUpContainer.append(this.meterUpText);
  893. this.append(this.meterDownContainer);
  894. this.append(this.meterUpContainer);
  895. this.getNetworkDownloadFn = () => window?.DtGetNetworkDownloadBytes?.execute() ?? 0;
  896. this.getNetworkUploadFn = () => window?.DtGetNetworkUploadBytes?.execute() ?? 0;
  897. this.currentNetworkDownload = parseFloat(localStorage.getItem('networkDownload') ?? this.getNetworkDownloadFn());
  898. this.currentNetworkUpload = parseFloat(localStorage.getItem('networkUpload') ?? this.getNetworkUploadFn());
  899. localStorage.setItem('networkDownload', this.currentNetworkDownload);
  900. localStorage.setItem('networkUpload', this.currentNetworkUpload);
  901. this.showMeter();
  902. setInterval(() => this.showMeter(), 1000);
  903. }
  904. createMeterContainer() {
  905. return new StyledComponent(document.createElement('div'), {
  906. display: 'flex',
  907. alignItems: 'center',
  908. });
  909. }
  910. createMeterText() {
  911. return new StyledComponent(document.createElement('span'), {
  912. fontSize: '1rem',
  913. marginLeft: '-5px',
  914. fontFamily: 'Helvetica',
  915. fontWeight: 'bold',
  916. whiteSpace: 'nowrap',
  917. color: '#fff',
  918. });
  919. }
  920. formatBytes(bytes) {
  921. const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
  922. if (bytes === 0) return '0 B';
  923. const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  924. return (bytes / Math.pow(1024, i)).toPrecision(3) + ' ' + sizes[i];
  925. }
  926. showMeter() {
  927. const newNetworkDownload = this.getNetworkDownloadFn();
  928. const newNetworkUpload = this.getNetworkUploadFn();
  929. if (!isNaN(newNetworkDownload) && !isNaN(newNetworkUpload)) {
  930. this.meterDownText.element.innerHTML = this.formatBytes(newNetworkDownload - this.currentNetworkDownload);
  931. this.meterUpText.element.innerHTML = this.formatBytes(newNetworkUpload - this.currentNetworkUpload);
  932. }
  933. }
  934. }
  935. class PingComponent extends StyledComponent {
  936. constructor(styles = {}) {
  937. super(document.createElement('span'), {
  938. position: 'absolute',
  939. fontSize: '1rem',
  940. fontFamily: 'Helvetica',
  941. fontWeight: 'bold',
  942. whiteSpace: 'nowrap',
  943. top: `${totalTopValue}px`,
  944. right: '10px',
  945. ...styles,
  946. });
  947. this.startPing();
  948. }
  949. async startPing() {
  950. this.setPing(await this.ping());
  951. setInterval(async () => this.setPing(await this.ping()), 1000);
  952. }
  953. setPing(ping) {
  954. this.element.textContent = `PING: ${ping}ms`;
  955. const pingValue = parseInt(ping, 10);
  956. const color = this.getColorFromPing(pingValue);
  957. this.setStyles({ color });
  958. }
  959. getColorFromPing(ping) {
  960. const pingValue = parseInt(ping, 10);
  961. const color = pingValue >= 0 && pingValue <= 50 ? '#00ff00' :
  962. pingValue > 50 && pingValue <= 100 ? '#ffff00' :
  963. '#ff0000';
  964. return color;
  965. }
  966. async ping() {
  967. const startTime = new Date().getTime();
  968. const url = `https://cdn-icons-png.flaticon.com/512/7517/7517373.png?${startTime}`
  969. try {
  970. const data = await fetch(url)
  971. return new Date().getTime() - startTime;
  972. } catch (err) {
  973. console.log(err);
  974. return -1;
  975. }
  976. }
  977. }
  978. class IframeBodyComponent extends DialogBodyComponent {
  979. constructor(styles = {}, url = null) {
  980. super({
  981. height: '600px',
  982. ...styles
  983. })
  984. this.iframeElement = new StyledComponent(document.createElement('iframe'), {
  985. width: '100%',
  986. border: 'none',
  987. borderRadius: '5px'
  988. })
  989. this.setUrl(url)
  990. this.append(this.iframeElement)
  991. }
  992. setUrl(url) {
  993. this.iframeElement.element.src = url
  994. }
  995. }
  996. class CleanAppMessageBodyComponent extends DialogBodyComponent {
  997. constructor(styles = {}, url = null) {
  998. super({
  999. height: 'auto',
  1000. ...styles
  1001. })
  1002. this.spanComponent = new StyledComponent(document.createElement('span'), {
  1003. fontSize: '16px',
  1004. fontFamily: 'Helvetica',
  1005. fontWeight: 'bold',
  1006. color: TEXT_COLOR,
  1007. })
  1008. this.spanComponent.element.innerHTML = 'Você gostaria de limpar os dados do aplicativo? Por favor, esteja ciente de que essa ação resultará na remoção permanente de todas as informações armazenadas. Você tem certeza de que deseja prosseguir com essa operação?'
  1009. this.append(this.spanComponent)
  1010. }
  1011. }
  1012. class StyledButtonComponent extends StyledComponent {
  1013. constructor(text, styles = {}) {
  1014. super(document.createElement('button'), {
  1015. width: '100%',
  1016. borderRadius: '5px',
  1017. padding: '10px',
  1018. border: 'none',
  1019. color: TEXT_COLOR,
  1020. background: BUTTON_BACKGROUND_COLOR,
  1021. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  1022. cursor: 'pointer',
  1023. filter: 'drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.5))',
  1024. ...styles
  1025. });
  1026. this.textComponent = new StyledComponent(document.createElement('span'), {
  1027. fontSize: '16px',
  1028. fontWeight: 'bold',
  1029. });
  1030. this.textComponent.element.innerHTML = text;
  1031. this.appendChild(this.textComponent);
  1032. }
  1033. }
  1034. class ButtonDonateComponent extends StyledButtonComponent {
  1035. constructor(styles = {}) {
  1036. super('PREMIUM', styles);
  1037. this.addEventListener('click', () => window?.DtStartWebViewActivity?.execute())
  1038. }
  1039. }
  1040. class ButtonApnSettingsComponent extends StyledButtonComponent {
  1041. constructor(styles = {}) {
  1042. super('APN', styles);
  1043. this.addEventListener('click', () => window?.DtStartApnActivity?.execute())
  1044. }
  1045. }
  1046. class ButtonTermsComponent extends StyledButtonComponent {
  1047. constructor(styles = {}) {
  1048. super('TERMOS', styles);
  1049. this.addEventListener('click', () => {
  1050. window?.DtStartWebViewActivity?.execute(TERMS_URL)
  1051. })
  1052. }
  1053. }
  1054. class ButtonHostPotComponent extends StyledButtonComponent {
  1055. constructor(styles = {}) {
  1056. super('HOTSPOT', styles);
  1057. // Flag para controlar o estado do hotspot
  1058. this.hotSpotRunning = false;
  1059. this.addEventListener('click', () => {
  1060. // Função para iniciar o hotspot
  1061. const startHotSpot = () => {
  1062. DtStartHotSpotService.execute();
  1063. this.textContent = 'HOTSPOT';
  1064. this.hotSpotRunning = true;
  1065. };
  1066. // Função para parar o hotspot
  1067. const stopHotSpot = () => {
  1068. DtStopHotSpotService.execute();
  1069. this.textContent = 'HOTSPOT';
  1070. this.hotSpotRunning = false;
  1071. };
  1072. // Função para alternar o estado do hotspot
  1073. const toggleHotSpot = () => {
  1074. this.hotSpotRunning ? stopHotSpot() : startHotSpot();
  1075. };
  1076. // Chama a função para alternar o estado do hotspot
  1077. toggleHotSpot();
  1078. });
  1079. }
  1080. }
  1081. const rootComponent = new AppComponent(document.querySelector('#root'), { background: BACKGROUND_COLOR });
  1082. rootComponent.append(new LocalIPComponent());
  1083. rootComponent.append(new PingComponent());
  1084. rootComponent.append(new NetworkStatsComponent());
  1085. const cardComponent = new CardComponent({
  1086. position: 'absolute',
  1087. bottom: '45%',
  1088. background: 'transparent',
  1089. boxShadow: 'none',
  1090. filter: 'drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.5))',
  1091. })
  1092. const configInputGroup = new InputGroupComponent({ cursor: 'pointer', background: INPUT_COLOR });
  1093. configInputGroup.addEventListener('click', () => {
  1094. const mock = '[{"sorter":6,"color":"#6D08041C","name":"CONFIG","id":1393,"items":[{"mode":"V2RAY - VLESS","sorter":4,"tlsVersion":"TLSv1.2","name":"CONFIG 01","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":11803,"status":"ACTIVE"},{"mode":"SSH_DIRECT","sorter":2,"tlsVersion":"TLSv1.2","name":"CONFIG 02","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":28627,"status":"ACTIVE"},{"mode":"OVPN_PROXY","sorter":23,"tlsVersion":"TLSv1.2","name":"CONFIG 03","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":30001,"status":"ACTIVE"}]},{"sorter":2,"color":"#6D08041C","name":"CONFIG 2","id":1846,"items":[{"mode":"SSH_PROXY","sorter":1,"tlsVersion":"TLSv1.2","name":"CONFIG 01","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":26295,"status":"ACTIVE"}]},{"sorter":4,"color":"#80000000","name":"CONFIG 3","id":3310,"items":[{"mode":"SSH_PROXY","sorter":1,"tlsVersion":"TLSv1.2","name":"CONFIG. TEST","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":29997,"status":"ACTIVE"},{"mode":"OVPN_PROXY","sorter":1,"tlsVersion":"TLSv1.2","name":"CONFIG. TEST 2","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":29998,"status":"ACTIVE"}]}]'
  1095. const items = JSON.parse(window?.DtGetConfigs?.execute() || mock)
  1096. items.sort((a, b) => a.sorter - b.sorter)
  1097. items.forEach(item => item.items.sort((a, b) => a.sorter - b.sorter))
  1098. const dialogComponent = new DialogComponent()
  1099. const dialogContentComponent = new DialogContentComponent()
  1100. const dialogHeaderComponent = new DialogHeaderComponent()
  1101. dialogHeaderComponent.setTitleText('CONFIGURAÇÕES')
  1102. dialogHeaderComponent.setCloseButtonClickListener(() => dialogComponent.close())
  1103. const configBodyComponent = new ConfigBodyComponent(items.map(item => {
  1104. const category = new CategoryComponent()
  1105. category.setName(item.name)
  1106. category.setItems(item.items.map(item => {
  1107. const config = new ConfigComponent()
  1108. config.setName(item.name)
  1109. config.setDescription(item.description ?? '')
  1110. config.setMode(item.mode)
  1111. config.setImage(item.icon)
  1112. config.addEventListener('click', () => {
  1113. window?.DtSetConfig?.execute(item.id)
  1114. dialogComponent.close()
  1115. })
  1116. return config
  1117. }))
  1118. return category
  1119. }))
  1120. dialogContentComponent.setHeader(dialogHeaderComponent)
  1121. dialogContentComponent.setBody(configBodyComponent)
  1122. dialogComponent.setContent(dialogContentComponent)
  1123. dialogComponent.show()
  1124. })
  1125. cardComponent.append(configInputGroup)
  1126. const arrowDownIconComponent = new ArrowDownIconComponent()
  1127. const networkIconComponent = new NetworkIconComponent()
  1128. const configInput = new InputText({ cursor: 'pointer' })
  1129. configInput.setEnabled(false)
  1130. configInput.setPlaceholder('SELECIONE UMA CONFIG.')
  1131. configInput.setValue(JSON.parse(window?.DtGetDefaultConfig?.execute() ?? '{}').name ?? '')
  1132. configInputGroup.append(networkIconComponent, configInput, arrowDownIconComponent)
  1133. const userPassContainer = new StyledComponent(document.createElement('div'), {
  1134. width: '100%',
  1135. display: 'flex',
  1136. gap: '5px',
  1137. })
  1138. cardComponent.append(userPassContainer)
  1139. const usernameGroupComponent = new InputGroupComponent({ background: INPUT_COLOR });
  1140. const personIconComponent = new PersonIconComponent()
  1141. const usernameInput = new InputText()
  1142. usernameInput.setPlaceholder('Nome de usuario')
  1143. usernameInput.setValue(window?.DtUsername?.get() ?? '')
  1144. usernameInput.setOnInputListener(() => { window?.DtUsername?.set(usernameInput.value) })
  1145. usernameGroupComponent.append(personIconComponent, usernameInput)
  1146. userPassContainer.append(usernameGroupComponent)
  1147. const passwordGroupComponent = new InputGroupComponent({ background: INPUT_COLOR });
  1148. const lockIconComponent = new LockIconComponent()
  1149. const passwordInput = new InputPassword()
  1150. const eyeIconComponent = new EyeIconComponent()
  1151. eyeIconComponent.addEventListener('click', () => { passwordInput.setShowing(!passwordInput.isShowing) })
  1152. passwordInput.setPlaceholder('Senha')
  1153. passwordInput.setValue(window?.DtPassword?.get() ?? '')
  1154. passwordInput.setOnInputListener(() => { window?.DtPassword?.set(passwordInput.value) })
  1155. passwordGroupComponent.append(lockIconComponent, passwordInput, eyeIconComponent)
  1156. userPassContainer.append(passwordGroupComponent)
  1157. const v2rayUuidGroupComponent = new InputGroupComponent({ background: INPUT_COLOR });
  1158. const v2rayLockIconComponent = new LockIconComponent();
  1159. const v2rayUuidInput = new InputPassword()
  1160. v2rayUuidInput.setPlaceholder('V2Ray UUID')
  1161. v2rayUuidInput.setValue(window?.DtUuid?.get() ?? '')
  1162. v2rayUuidInput.setOnInputListener(() => { window?.DtUuid?.set(v2rayUuidInput.value) })
  1163. v2rayUuidGroupComponent.append(v2rayLockIconComponent, v2rayUuidInput)
  1164. cardComponent.append(v2rayUuidGroupComponent)
  1165. const buttonAndStateContainer = new StyledComponent(document.createElement('div'), {
  1166. display: 'flex',
  1167. flexDirection: 'column',
  1168. alignItems: 'center',
  1169. position: 'absolute',
  1170. top: '10%',
  1171. })
  1172. const startOrStopButtonComponent = new PowerIconComponent()
  1173. startOrStopButtonComponent.addEventListener('click', () => {
  1174. if (DtGetVpnState.execute() != 'DISCONNECTED') {
  1175. DtExecuteVpnStop.execute()
  1176. } else {
  1177. DtExecuteVpnStart.execute()
  1178. }
  1179. })
  1180. buttonAndStateContainer.append(startOrStopButtonComponent)
  1181. const vpnStateComponent = new VpnStateComponent()
  1182. buttonAndStateContainer.append(vpnStateComponent)
  1183. const cardToolsComponent = new CardComponent({
  1184. flexDirection: 'row',
  1185. justifyContent: 'space-between',
  1186. position: 'absolute',
  1187. bottom: '13%',
  1188. background: 'transparent',
  1189. boxShadow: 'none',
  1190. })
  1191. const calanderIconComponent = new CalanderIconComponent()
  1192. calanderIconComponent.addEventListener('click', () => window?.DtStartCheckUser?.execute())
  1193. cardToolsComponent.append(calanderIconComponent)
  1194. const dialogComponent = new DialogComponent()
  1195. const dialogContentComponent = new DialogContentComponent()
  1196. const dialogHeaderComponent = new DialogHeaderComponent()
  1197. const dialogFooterComponent = new DialogFooterComponent()
  1198. const loggerBodyComponent = new LoggerBodyComponent({})
  1199. dialogHeaderComponent.setTitleText('REGISTRO')
  1200. dialogHeaderComponent.setCloseButtonClickListener(() => dialogComponent.close())
  1201. dialogFooterComponent.addButton(new DialogFooterButtonComponent(
  1202. 'LIMPAR',
  1203. () => window?.DtClearLogs?.execute()
  1204. ))
  1205. dialogFooterComponent.addButton(new DialogFooterButtonComponent(
  1206. 'FECHAR',
  1207. () => dialogComponent.close()
  1208. ))
  1209. dialogContentComponent.setHeader(dialogHeaderComponent)
  1210. dialogContentComponent.setBody(loggerBodyComponent)
  1211. dialogContentComponent.setFooter(dialogFooterComponent)
  1212. dialogComponent.setContent(dialogContentComponent)
  1213. const loggerIconComponent = new LoggerIconComponent()
  1214. loggerIconComponent.addEventListener('click', () => dialogComponent.show())
  1215. cardToolsComponent.append(loggerIconComponent)
  1216. const arrowRepeatIconComponent = new ArrowRepeatIconComponent()
  1217. arrowRepeatIconComponent.addEventListener('click', () => window?.DtStartAppUpdate?.execute());
  1218. cardToolsComponent.append(arrowRepeatIconComponent)
  1219. const batteryIconComponent = new BatteryIconComponent()
  1220. batteryIconComponent.addEventListener('click', () => window?.DtIgnoreBatteryOptimizations?.execute());
  1221. cardToolsComponent.append(batteryIconComponent)
  1222. const speedMeterComponent = new SpeedMeterIconComponent()
  1223. speedMeterComponent.addEventListener('click', () => {
  1224. const dialog = new DialogComponent()
  1225. const content = new DialogContentComponent()
  1226. const header = new DialogHeaderComponent()
  1227. header.setTitleText('SPEEDTEST')
  1228. header.setCloseButtonClickListener(() => dialog.close())
  1229. const body = new IframeBodyComponent({}, 'https://fast.com')
  1230. content.setHeader(header)
  1231. content.setBody(body)
  1232. dialog.setOnCloseEvent(() => body.setUrl(""))
  1233. dialog.setContent(content)
  1234. dialog.show()
  1235. })
  1236. cardToolsComponent.append(speedMeterComponent)
  1237. const trashIconComponent = new TrashIconComponent()
  1238. trashIconComponent.addEventListener('click', () => {
  1239. const dialog = new DialogComponent()
  1240. const content = new DialogContentComponent()
  1241. const header = new DialogHeaderComponent()
  1242. const footer = new DialogFooterComponent()
  1243. footer.addButton(new DialogFooterButtonComponent('NÃO', () => dialog.close()))
  1244. footer.addButton(new DialogFooterButtonComponent('SIM', () => window?.DtCleanApp?.execute()))
  1245. header.setTitleText('LIMPAR DADOS')
  1246. header.setCloseButtonClickListener(() => dialog.close())
  1247. content.setHeader(header)
  1248. content.setBody(new CleanAppMessageBodyComponent())
  1249. content.setFooter(footer)
  1250. dialog.setContent(content)
  1251. dialog.show()
  1252. })
  1253. cardToolsComponent.append(trashIconComponent)
  1254. const buttonsCard = new CardComponent({
  1255. flexDirection: 'row',
  1256. justifyContent: 'space-between',
  1257. position: 'absolute',
  1258. bottom: '5%',
  1259. background: 'transparent',
  1260. boxShadow: 'none',
  1261. })
  1262. const buttonHostPotCard = new CardComponent({
  1263. flexDirection: 'row',
  1264. justifyContent: 'space-between',
  1265. position: 'absolute',
  1266. bottom: '22%',
  1267. background: 'transparent',
  1268. boxShadow: 'none',
  1269. })
  1270. buttonsCard.append(new ButtonDonateComponent())
  1271. buttonsCard.append(new ButtonApnSettingsComponent())
  1272. buttonsCard.append(new ButtonTermsComponent())
  1273. buttonHostPotCard.append(new ButtonHostPotComponent())
  1274. rootComponent.append(buttonAndStateContainer)
  1275. rootComponent.append(cardComponent)
  1276. rootComponent.append(cardToolsComponent)
  1277. rootComponent.append(buttonsCard)
  1278. rootComponent.append(buttonHostPotCard)
  1279. const dtCheckUserModelListener = model => {
  1280. const data = JSON.parse(model ?? `{"username": "test"}`)
  1281. const dialogComponent = new DialogComponent()
  1282. const dialogContentComponent = new DialogContentComponent()
  1283. const dialogHeaderComponent = new DialogHeaderComponent()
  1284. dialogHeaderComponent.setTitleText(`📆 Olá, ${data.username}`)
  1285. dialogHeaderComponent.setCloseButtonClickListener(() => dialogComponent.close())
  1286. dialogContentComponent.setHeader(dialogHeaderComponent)
  1287. dialogContentComponent.setBody(new CheckUserBodyComponent(data))
  1288. dialogComponent.setContent(dialogContentComponent)
  1289. dialogComponent.show()
  1290. }
  1291. const dtConfigClickListener = () => {
  1292. const data = JSON.parse(window?.DtGetDefaultConfig?.execute() ?? '{"auth":{"password": ""}, "mode": "v2ra"}')
  1293. configInput.setValue(data.name ?? '')
  1294. const isV2ray = data?.mode?.toLowerCase()?.startsWith('v2ray');
  1295. usernameGroupComponent.setStyles({
  1296. display: isV2ray || data?.auth?.username ? 'none' : 'flex',
  1297. })
  1298. passwordGroupComponent.setStyles({
  1299. display: isV2ray || data?.auth?.password ? 'none' : 'flex',
  1300. })
  1301. v2rayUuidGroupComponent.setStyles({
  1302. display: !isV2ray || data?.auth?.v2ray_uuid ? 'none' : 'flex',
  1303. })
  1304. }
  1305. const dtVpnStateListener = state => {
  1306. const isRunning = state != 'DISCONNECTED';
  1307. vpnStateComponent.setState((window?.DtTranslateText?.execute('LBL_STATE_' + state) ?? 'UNKNOWN').toUpperCase())
  1308. usernameInput.setEnabled(!isRunning)
  1309. passwordInput.setEnabled(!isRunning)
  1310. }
  1311. const dtOnNewLogListener = () => {
  1312. const mock = [];
  1313. for (let i = 0; i < 300; i++) {
  1314. mock.push({ 'TIME': 'MESSAGE ' + i })
  1315. }
  1316. const data = JSON.parse(window?.DtGetLogs?.execute() ?? JSON.stringify(mock))
  1317. loggerBodyComponent.setItems(data.map(log => {
  1318. return new LoggerItemComponent({}, Object.keys(log)[0] + ' ' + log[Object.keys(log)])
  1319. }))
  1320. }
  1321. dtVpnStateListener(window?.DtGetVpnState?.execute() ?? 'DISCONNECTED')
  1322. dtOnNewLogListener()
  1323. dtConfigClickListener()
  1324. function createElements() {
  1325. const container = document.createElement("div");
  1326. container.classList.add("container");
  1327. container.style.position = 'absolute';
  1328. const content = document.createElement("div");
  1329. content.classList.add("content");
  1330. const background = document.createElement("div");
  1331. const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  1332. svg.setAttribute("width", "16");
  1333. svg.setAttribute("height", "16");
  1334. svg.setAttribute("fill", "currentColor");
  1335. svg.classList.add("bi", "bi-git");
  1336. svg.setAttribute("viewBox", "0 0 16 16");
  1337. const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
  1338. path.setAttribute("d", "M15.698 7.287 8.712.302a1.03 1.03 0 0 0-1.457 0l-1.45 1.45 1.84 1.84a1.223 1.223 0 0 1 1.55 1.56l1.773 1.774a1.224 1.224 0 0 1 1.267 2.025 1.226 1.226 0 0 1-2.002-1.334L8.58 5.963v4.353a1.226 1.226 0 1 1-1.008-.036V5.887a1.226 1.226 0 0 1-.666-1.608L5.093 2.465l-4.79 4.79a1.03 1.03 0 0 0 0 1.457l6.986 6.986a1.03 1.03 0 0 0 1.457 0l6.953-6.953a1.031 1.031 0 0 0 0-1.457");
  1339. svg.appendChild(path);
  1340. const span = document.createElement("span");
  1341. span.classList.add("ms-2");
  1342. span.setAttribute("id", "version");
  1343. span.textContent = ' 1.1';
  1344. // Montando a estrutura
  1345. background.appendChild(svg);
  1346. background.appendChild(span);
  1347. content.appendChild(background);
  1348. container.appendChild(content);
  1349. // Aplicando estilos
  1350. container.style.fontSize = '1rem';
  1351. container.style.fontFamily = 'Verdana';
  1352. container.style.color = TEXT_COLOR;
  1353. const statusBarHeight = window?.DtGetStatusBarHeight?.execute();
  1354. const extraPixels = 25; // Number of extra pixels you want to add
  1355. const defaultHeight = 60; // Default height if statusBarHeight is undefined
  1356. const totalTopValue = (statusBarHeight !== undefined ? statusBarHeight : defaultHeight) + extraPixels;
  1357. container.style.top = `${totalTopValue}px`;
  1358. container.style.left = '10px';
  1359. // Adicionando ao DOM
  1360. document.body.appendChild(container);
  1361. // Atualizar a versão a cada 2 segundos
  1362. setInterval(updateVersion, 2000);
  1363. }
  1364. // Função para atualizar a versão
  1365. function updateVersion() {
  1366. const versionElement = document.getElementById('version');
  1367. const version = window?.DtGetLocalConfigVersion?.execute() ?? ' 1.0';
  1368. versionElement.textContent = version;
  1369. }
  1370. // Chamar a função para criar elementos e configurar a versão inicial
  1371. createElements();
  1372. updateVersion();
  1373. </script>
  1374. </body>
  1375. </html>

comments powered by Disqus