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: 83.2 kB

HITS: 2405

  1. <html lang="pt-br">
  2. <head>
  3. <meta charset="UTF-8">
  4. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>LAYOUT_APP_WEBVIEW</title>
  7. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu">
  8. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Orbitron">
  9. <script async="" src="https://www.googletagmanager.com/gtag/js?id=G-Q2HPLXNHN0"></script>
  10. <script>
  11. window.dataLayer = window.dataLayer || [];
  12. function gtag() {
  13. dataLayer.push(arguments);
  14. }
  15. gtag('js', new Date());
  16. gtag('config', 'G-Q2HPLXNHN0');
  17. </script>
  18. <style>
  19. * {
  20. margin: 0;
  21. padding: 0;
  22. box-sizing: border-box;
  23. -webkit-tap-highlight-color: transparent;
  24. font-family: 'Ubuntu';
  25. }
  26. ::placeholder {
  27. color: #b0a8ffff;
  28. }
  29. body {
  30. height: 100vh;
  31. }
  32. @keyframes fade-in {
  33. from {
  34. opacity: 0;
  35. }
  36. to {
  37. opacity: 1;
  38. }
  39. }
  40. @keyframes fade-out {
  41. from {
  42. opacity: 1;
  43. }
  44. to {
  45. opacity: 0;
  46. }
  47. }
  48. @keyframes pulse {
  49. 0% {
  50. transform: scale(1);
  51. box-shadow: none;
  52. }
  53. 50% {
  54. transform: scale(1.2);
  55. box-shadow: 0 0 10px 5px #b0a8ffff;
  56. }
  57. 100% {
  58. transform: scale(1);
  59. box-shadow: none;
  60. }
  61. }
  62. </style>
  63. </head>
  64. <body>
  65. <div id="root" style="width: 100%; height: 100%; background: linear-gradient(45deg, rgb(20, 20, 44), rgb(27, 27, 27), rgb(31, 28, 58)); display: flex; flex-direction: column; justify-content: center; align-items: center;">
  66. <span style="position: absolute; font-size: 1rem; font-family: Ubuntu; font-weight: bold; white-space: nowrap; color: rgb(176, 168, 255); top: 30px; left: 10px;">IP:
  67. 127.0.0.1</span>
  68. <div style="display: flex; position: absolute; gap: 5px; top: 50px; left: -5px;">
  69. <div style="display: flex; align-items: center;"><svg fill="#6205D5" width="2.2rem" height="2.2rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 5px; width: 2.2rem; height: 2.2rem;">
  70. <path d="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">
  71. </path>
  72. </svg><span style="font-size: 1rem; margin-left: -5px; font-family: Ubuntu; font-weight: bold; white-space: nowrap; color: rgb(255, 255, 255);">0
  73. B</span></div>
  74. <div style="display: flex; align-items: center;"><svg fill="#6205D5" width="2.2rem" height="2.2rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 5px; width: 2.2rem; height: 2.2rem;">
  75. <path d="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">
  76. </path>
  77. </svg><span style="font-size: 1rem; margin-left: -5px; font-family: Ubuntu; font-weight: bold; white-space: nowrap; color: rgb(255, 255, 255);">0
  78. B</span></div>
  79. </div>
  80. <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; width: 85%; max-width: 23rem; margin: 1.2rem; border-radius: 5px; border: none; position: absolute; top: 45%;">
  81. <div style="display: flex; width: 100%; align-items: center; background: rgba(30, 28, 47, 0.314); color: rgb(255, 255, 255); padding: 0.2rem; border-radius: 50px; top: 90%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; cursor: pointer;">
  82. <svg fill="#6205D5" width="2.2rem" height="2.2rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 5px; width: 2.2rem; height: 2.2rem;">
  83. <path d="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"></path>
  84. <path d="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">
  85. </path>
  86. </svg><input type="text" disabled="" placeholder="SELECIONE UM SERVIDOR" style="background: transparent; border: none; width: 100%; outline: none; color: rgb(176, 168, 255); font-size: 15px; cursor: pointer; font-family: Ubuntu;"><svg fill="#6205D5" width="2.2rem" height="2.2rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 5px; width: 2.2rem; height: 2.2rem;">
  87. <path d="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">
  88. </path>
  89. </svg>
  90. </div>
  91. <div style="display: flex; margin-top: 5px; width: 100%; gap: 5px;">
  92. <div style="display: flex; width: 100%; align-items: center; background: rgba(30, 28, 47, 0.314); color: rgb(255, 255, 255); padding: 0.2rem; border-radius: 50px; top: 90%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
  93. <svg fill="#6205D5" width="2.2rem" height="2.2rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 5px; width: 2.2rem; height: 2.2rem;">
  94. <path d="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">
  95. </path>
  96. </svg><input type="text" placeholder="Nome de usuário" style="background: transparent; border: none; width: 100%; outline: none; color: rgb(176, 168, 255); font-size: 15px;">
  97. </div>
  98. <div style="display: flex; width: 100%; align-items: center; background: rgba(30, 28, 47, 0.314); color: rgb(255, 255, 255); padding: 0.2rem; border-radius: 50px; top: 90%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
  99. <svg fill="#6205D5" width="2.2rem" height="2.2rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 5px; width: 2.2rem; height: 2.2rem;">
  100. <path d="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">
  101. </path>
  102. </svg><input type="password" placeholder="Senha" style="background: transparent; border: none; width: 100%; outline: none; color: rgb(176, 168, 255); font-size: 15px;"><svg fill="#6205D5" width="2.2rem" height="2.2rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 5px; width: 2.2rem; height: 2.2rem;">
  103. <path d="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">
  104. </path>
  105. <path d="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">
  106. </path>
  107. </svg>
  108. </div>
  109. <div style="display: none; width: 100%; align-items: center; background: rgba(30, 28, 47, 0.314); color: rgb(255, 255, 255); padding: 0.2rem; border-radius: 50px; top: 90%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
  110. <svg fill="#6205D5" width="2.2rem" height="2.2rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 5px; width: 2.2rem; height: 2.2rem;">
  111. <path d="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">
  112. </path>
  113. </svg><input type="password" placeholder="V2Ray UUID" style="background: transparent; border: none; width: 100%; outline: none; color: rgb(176, 168, 255); font-size: 15px;">
  114. </div>
  115. </div>
  116. <div style="display: flex; flex-direction: row; align-items: center; justify-content: space-between; width: 100%; max-width: 23rem; margin: 50px 0px; border-radius: 5px; border: none; background: transparent; box-shadow: none; filter: drop-shadow(rgba(0, 0, 0, 0.1) 2px 2px 4px);">
  117. <svg fill="#6205D5" width="45px" height="45px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 10px; width: 45px; height: 45px; cursor: pointer; background: rgba(30, 28, 47, 0.314); border-radius: 20%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
  118. <path d="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">
  119. </path>
  120. <path d="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">
  121. </path>
  122. </svg><svg fill="#6205D5" width="45px" height="45px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 10px; width: 45px; height: 45px; cursor: pointer; background: rgba(30, 28, 47, 0.314); border-radius: 20%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
  123. <path d="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">
  124. </path>
  125. <path d="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">
  126. </path>
  127. </svg><svg fill="#6205D5" width="45px" height="45px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 10px; width: 45px; height: 45px; cursor: pointer; background: rgba(30, 28, 47, 0.314); border-radius: 20%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
  128. <path d="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">
  129. </path>
  130. <path d="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">
  131. </path>
  132. </svg><svg fill="#6205D5" width="45px" height="45px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 10px; width: 45px; height: 45px; cursor: pointer; background: rgba(30, 28, 47, 0.314); border-radius: 20%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
  133. <path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z">
  134. </path>
  135. </svg>
  136. </div>
  137. <div style="display: flex; flex-direction: column; align-items: center; position: absolute; bottom: 120%; margin-top: 3rem;">
  138. <svg fill="#6205D5" width="7.5rem" height="7.5rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" style="fill: rgb(98, 5, 213); padding: 20px; width: 7.5rem; height: 7.5rem; cursor: pointer; background: rgba(30, 28, 47, 0.314); border-radius: 50%; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; filter: drop-shadow(rgba(0, 0, 0, 0.1) 2px 2px 4px);">
  139. <path d="M7.5 1v7h1V1h-1z"></path>
  140. <path d="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">
  141. </path>
  142. </svg><span style="font-size: 1.4rem; font-family: Ubuntu; font-weight: bold; color: rgb(98, 5, 213); margin-top: 2rem;">UNKNOWN</span>
  143. </div>
  144. </div>
  145. </div>
  146. <script>
  147. const BACKGROUND_IMAGE = null // JSON.parse(window?.DtGetAppConfig?.execute('APP_BACKGROUND_IMAGE') ?? '{"value": "https://i.ibb.co/0XyvpHx/DT7xsqhdau.jpg"}').value;
  148. const BACKGROUND_COLOR = BACKGROUND_IMAGE ?
  149. `url(${BACKGROUND_IMAGE}) center center / cover rgb(32, 32, 32)` :
  150. 'linear-gradient(45deg, rgba(20, 20, 44, 1), rgb(27, 27, 27), rgba(31, 28, 58, 1))'
  151. const INPUT_COLOR = '#1e1c2f50'
  152. const BUTTON_BACKGROUND_COLOR = '#1e1c2f50'
  153. const ICON_COLOR = '#6205D5'
  154. const TEXT_COLOR = '#b0a8ffff'
  155. const TOOLS_BUTTON_BACKGROUND_COLOR = '#1e1c2f50'
  156. const VPN_BUTTON_BACKGROUND_COLOR = '#1e1c2f50'
  157. const VPN_STOPPED_COLOR = '#6205D5'
  158. const VPN_STARTING_COLOR = '#6205D5'
  159. const VPN_RUNNING_COLOR = '#6205D5'
  160. const CHECKUSER_TEXT_COLOR = '#b0a8ffff'
  161. const LOGGER_TEXT_COLOR = '#b0a8ffff'
  162. const DIALOG_HEADER_TITLE_COLOR = '#b0a8ffff'
  163. const DIALOG_HEADER_CLOSE_BUTTON_COLOR = '#b0a8ffff'
  164. const DIALOG_CONTENT_BACKGROUND_COLOR = 'linear-gradient(45deg, rgba(20, 20, 44, 1), rgb(27, 27, 27), rgba(31, 28, 58, 1))'
  165. const DIALOG_FOOTER_BUTTON_COLOR = '#1e1c2f50'
  166. const DIALOG_FOOTER_BUTTON_TEXT_COLOR = '#b0a8ffff'
  167. const URL_SPEEDTEST = 'https://fast.com'
  168. const URL_YOUTUBE = 'https://www.youtube.com/embed/g9JLURIh9lE'
  169. const URL_MP3 = 'https://www.palcomp3.com.br'
  170. const POLITC_URL = 'https://sshtproject.com/privacidade/'
  171. const TERMS_URL = 'https://sshtproject.com/termos/'
  172. const SERVER_URL = 'http://sshtproject.com/servers/'
  173. const TUTO_URL = 'https://sshtproject.com/tutoriais/'
  174. const PREMIUM_URL = 'https://sshtproject.com/premium/'
  175. class Component {
  176. constructor(element) {
  177. this.element = element;
  178. }
  179. addEventListener(event, listener) {
  180. this.element.addEventListener(event, listener);
  181. }
  182. append(component) {
  183. if (component instanceof Component) {
  184. this.element.appendChild(component.element);
  185. } else {
  186. this.element.append(component);
  187. }
  188. }
  189. appendChild(component) {
  190. if (component instanceof Component) {
  191. this.element.appendChild(component.element);
  192. } else {
  193. this.element.appendChild(component);
  194. }
  195. }
  196. remove() {
  197. this.element.remove();
  198. }
  199. contains(component) {
  200. if (component instanceof Component) {
  201. return this.element.contains(component.element);
  202. } else {
  203. return this.element.contains(component);
  204. }
  205. }
  206. }
  207. class StyledComponent extends Component {
  208. constructor(element, styles = {}) {
  209. super(element);
  210. this.styles = styles;
  211. this.setStyles(styles);
  212. }
  213. setStyles(styles) {
  214. Object.keys(styles).forEach((key) => {
  215. if (this.element.style.hasOwnProperty(key)) {
  216. this.element.style[key] = styles[key];
  217. }
  218. });
  219. }
  220. }
  221. class Toast extends StyledComponent {
  222. constructor(element, styles = {}) {
  223. super(element, styles);
  224. }
  225. showToast(message, type, duration = 3000) {
  226. this.element.innerHTML = message;
  227. this.element.style.wordWrap = 'break-word';
  228. this.element.style.width = '90%';
  229. this.element.style.maxWidth = '400px';
  230. this.element.style.textAlign = 'center';
  231. this.element.style.display = 'block';
  232. this.element.style.position = 'fixed';
  233. this.element.style.bottom = '10%';
  234. this.element.style.left = '50%';
  235. this.element.style.transform = 'translateX(-50%)';
  236. this.element.style.opacity = '0';
  237. this.element.style.color = '#FFFFFF';
  238. switch (type) {
  239. case 'success':
  240. this.element.style.background = 'linear-gradient(135deg, #4CAF50, #009688)';
  241. break;
  242. case 'error':
  243. this.element.style.background = 'linear-gradient(135deg, #F44336, #FF5722)';
  244. break;
  245. case 'info':
  246. default:
  247. this.element.style.background = 'linear-gradient(135deg, #2196F3, #03A9F4)';
  248. break;
  249. }
  250. this.element.style.padding = '10px';
  251. this.element.style.borderRadius = '4px';
  252. this.element.style.opacity = '0';
  253. this.element.style.transition = 'opacity 0.3s ease-in-out';
  254. setTimeout(() => {
  255. this.element.style.opacity = '1';
  256. }, 100);
  257. setTimeout(() => this.hideToast(), duration);
  258. this.element.addEventListener('click', () => this.hideToast());
  259. }
  260. hideToast() {
  261. this.element.style.transition = 'opacity 0.3s ease-in-out';
  262. this.element.style.opacity = '0';
  263. setTimeout(() => {
  264. this.element.remove();
  265. }, 300);
  266. }
  267. static success(message, duration = 3000) {
  268. const toastElement = document.createElement('div');
  269. document.body.appendChild(toastElement);
  270. const toast = new Toast(toastElement);
  271. toast.showToast(message, 'success', duration);
  272. }
  273. static error(message, duration = 3000) {
  274. const toastElement = document.createElement('div');
  275. document.body.appendChild(toastElement);
  276. const toast = new Toast(toastElement);
  277. toast.showToast(message, 'error', duration);
  278. }
  279. static info(message, duration = 3000) {
  280. const toastElement = document.createElement('div');
  281. document.body.appendChild(toastElement);
  282. const toast = new Toast(toastElement);
  283. toast.showToast(message, 'info', duration);
  284. }
  285. }
  286. class AppComponent extends StyledComponent {
  287. constructor(element, styles = {}) {
  288. const defaultStyles = {
  289. width: '100%',
  290. height: '100%',
  291. background: '#404258',
  292. display: 'flex',
  293. flexDirection: 'column',
  294. justifyContent: 'center',
  295. alignItems: 'center',
  296. };
  297. super(element, {
  298. ...defaultStyles,
  299. ...styles
  300. });
  301. }
  302. }
  303. class CardComponent extends StyledComponent {
  304. constructor(styles = {}) {
  305. const defaultStyles = {
  306. display: 'flex',
  307. flexDirection: 'column',
  308. alignItems: 'center',
  309. justifyContent: 'center',
  310. width: '85%',
  311. maxWidth: '23rem',
  312. margin: '1.2rem',
  313. borderRadius: '5px',
  314. border: 'none',
  315. };
  316. super(document.createElement('div'), {
  317. ...defaultStyles,
  318. ...styles
  319. });
  320. }
  321. }
  322. class InputGroupComponent extends StyledComponent {
  323. constructor(styles = {}) {
  324. const defaultStyles = {
  325. display: 'flex',
  326. width: '100%',
  327. alignItems: 'center',
  328. background: '#363749',
  329. color: '#FFF',
  330. padding: '0.2rem',
  331. borderRadius: '50px',
  332. top: '90%',
  333. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  334. };
  335. super(document.createElement('div'), {
  336. ...defaultStyles,
  337. ...styles
  338. });
  339. }
  340. append(...components) {
  341. components.forEach((component) => super.append(component));
  342. }
  343. }
  344. class InputComponent extends StyledComponent {
  345. constructor(styles = {}) {
  346. const defaultStyles = {
  347. background: 'transparent',
  348. border: 'none',
  349. width: '100%',
  350. outline: 'none',
  351. color: TEXT_COLOR,
  352. fontSize: '15px',
  353. };
  354. super(document.createElement('input'), {
  355. ...defaultStyles,
  356. ...styles
  357. });
  358. }
  359. setEnabled(value) {
  360. this.element.disabled = !value;
  361. }
  362. }
  363. class InputText extends InputComponent {
  364. constructor(styles = {}) {
  365. super(styles);
  366. this.element.type = 'text';
  367. }
  368. get value() {
  369. return this.element.value;
  370. }
  371. setPlaceholder(text) {
  372. this.element.placeholder = text;
  373. }
  374. setOnInputListener(callback) {
  375. this.addEventListener('input', callback);
  376. }
  377. setValue(value) {
  378. this.element.value = value;
  379. }
  380. setOnInputListener(callback) {
  381. this.addEventListener('input', callback);
  382. }
  383. }
  384. class InputPassword extends InputText {
  385. constructor(styles = {}) {
  386. super(styles);
  387. this.element.type = 'password';
  388. }
  389. setShowing(value) {
  390. this.element.type = !value ? 'password' : 'text';
  391. }
  392. get isShowing() {
  393. return this.element.type != 'password'
  394. }
  395. }
  396. class SvgComponent extends StyledComponent {
  397. constructor(styles = {}, ...paths) {
  398. const defaultStyles = {
  399. fill: '#FFFFFF',
  400. padding: '5px',
  401. width: '2.2rem',
  402. height: '2.2rem',
  403. };
  404. super(document.createElementNS('http://www.w3.org/2000/svg', 'svg'), {
  405. ...defaultStyles,
  406. ...styles,
  407. });
  408. this.applyOptions();
  409. paths.forEach((p) => this.addPath(p));
  410. }
  411. applyOptions() {
  412. this.setFill(this.styles.fill || 'currentColor');
  413. this.setWidth(this.styles.width || '16');
  414. this.setHeight(this.styles.height || '16');
  415. this.setViewBox(this.styles.viewBox || '0 0 16 16');
  416. this.setXmlns(this.styles.xmlns || 'http://www.w3.org/2000/svg');
  417. }
  418. setFill(color) {
  419. this.element.setAttribute('fill', color);
  420. }
  421. setWidth(width) {
  422. this.element.setAttribute('width', width);
  423. }
  424. setHeight(height) {
  425. this.element.setAttribute('height', height);
  426. }
  427. setViewBox(viewBox) {
  428. this.element.setAttribute('viewBox', viewBox);
  429. }
  430. setXmlns(xmlns) {
  431. this.element.setAttribute('xmlns', xmlns);
  432. }
  433. addPath(...path) {
  434. path.forEach((item) => {
  435. const pathElement = document.createElementNS(
  436. 'http://www.w3.org/2000/svg',
  437. 'path'
  438. );
  439. pathElement.setAttribute('d', item);
  440. this.element.appendChild(pathElement);
  441. });
  442. }
  443. }
  444. class Spinner extends StyledComponent {
  445. constructor() {
  446. super(document.createElement('div'), {
  447. display: 'flex',
  448. width: '100%',
  449. alignItems: 'center',
  450. justifyContent: 'center',
  451. padding: '20px'
  452. });
  453. this.createSpinnerElements();
  454. }
  455. createSpinnerElements() {
  456. const spinnerElement = new StyledComponent(document.createElement('div'));
  457. spinnerElement.setStyles({
  458. borderTop: '4px solid transparent',
  459. borderRight: '4px solid #ccc',
  460. borderBottom: '4px solid #ccc',
  461. borderLeft: '4px solid #ccc',
  462. borderRadius: '50%',
  463. width: '45px',
  464. height: '45px',
  465. animation: 'spin 1s linear infinite',
  466. });
  467. this.append(spinnerElement)
  468. }
  469. }
  470. class IconComponent extends SvgComponent {
  471. constructor(styles = {}, ...iconPath) {
  472. super({
  473. cursor: 'pointer',
  474. background: TOOLS_BUTTON_BACKGROUND_COLOR,
  475. borderRadius: '20%',
  476. height: '45px',
  477. width: '45px',
  478. padding: '10px',
  479. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  480. fill: ICON_COLOR,
  481. ...styles,
  482. },
  483. ...iconPath,
  484. );
  485. }
  486. }
  487. class CalanderIconComponent extends IconComponent {
  488. constructor(styles = {}) {
  489. super(styles,
  490. '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',
  491. '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'
  492. );
  493. }
  494. }
  495. class LoggerIconComponent extends IconComponent {
  496. constructor(styles = {}) {
  497. super(styles,
  498. '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',
  499. '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'
  500. )
  501. }
  502. }
  503. class ArrowRepeatIconComponent extends IconComponent {
  504. constructor(styles = {}) {
  505. super(styles,
  506. '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',
  507. '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'
  508. );
  509. }
  510. }
  511. class MoreIconComponent extends IconComponent {
  512. constructor(styles = {}) {
  513. super(styles,
  514. 'M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z'
  515. );
  516. }
  517. }
  518. class BatteryIconComponent extends IconComponent {
  519. constructor(styles = {}) {
  520. super(styles,
  521. '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'
  522. );
  523. }
  524. }
  525. class HeadsetIconComponent extends IconComponent {
  526. constructor(styles = {}) {
  527. super(styles,
  528. 'M8 1a5 5 0 0 0-5 5v1h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V6a6 6 0 1 1 12 0v6a2.5 2.5 0 0 1-2.5 2.5H9.366a1 1 0 0 1-.866.5h-1a1 1 0 1 1 0-2h1a1 1 0 0 1 .866.5H11.5A1.5 1.5 0 0 0 13 12h-1a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1h1V6a5 5 0 0 0-5-5z'
  529. );
  530. }
  531. }
  532. class ServerIconComponet extends IconComponent {
  533. constructor(styles = {}) {
  534. super(styles,
  535. '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 0zm2 7a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0zm-2.5.5a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1z',
  536. 'M2 2a2 2 0 0 0-2 2v1a2 2 0 0 0 2 2h1v2H2a2 2 0 0 0-2 2v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1a2 2 0 0 0-2-2h-1V7h1a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H2zm13 2v1a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1zm0 7v1a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1zm-3-4v2H4V7h8z'
  537. );
  538. }
  539. }
  540. class policyIconComponet extends IconComponent {
  541. constructor(styles = {}) {
  542. super(styles,
  543. 'M10.854 6.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 8.793l2.646-2.647a.5.5 0 0 1 .708 0z',
  544. 'M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z',
  545. 'M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z'
  546. );
  547. }
  548. }
  549. class BuyIconComponet extends IconComponent {
  550. constructor(styles = {}) {
  551. super(styles,
  552. 'M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z'
  553. );
  554. }
  555. }
  556. class TutorialIconComponet extends IconComponent {
  557. constructor(styles = {}) {
  558. super(styles,
  559. 'M2.5 3.5a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-11zm2-2a.5.5 0 0 1 0-1h7a.5.5 0 0 1 0 1h-7zM0 13a1.5 1.5 0 0 0 1.5 1.5h13A1.5 1.5 0 0 0 16 13V6a1.5 1.5 0 0 0-1.5-1.5h-13A1.5 1.5 0 0 0 0 6v7zm6.258-6.437a.5.5 0 0 1 .507.013l4 2.5a.5.5 0 0 1 0 .848l-4 2.5A.5.5 0 0 1 6 12V7a.5.5 0 0 1 .258-.437z'
  560. );
  561. }
  562. }
  563. class SpeedMeterIconComponent extends IconComponent {
  564. constructor(styles = {}) {
  565. super(styles,
  566. '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',
  567. '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'
  568. );
  569. }
  570. }
  571. class YouTubeIconComponent extends IconComponent {
  572. constructor(styles = {}) {
  573. super(styles,
  574. 'M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z'
  575. );
  576. }
  577. }
  578. class Mp3IconComponent extends IconComponent {
  579. constructor(styles = {}) {
  580. super(styles,
  581. 'M4 3a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V3zm1 0v3h6V3H5zm3 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2z',
  582. 'M11 11a3 3 0 1 1-6 0 3 3 0 0 1 6 0zm-3 2a2 2 0 1 0 0-4 2 2 0 0 0 0 4z',
  583. '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-2V2zm2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H4z',
  584. );
  585. }
  586. }
  587. class TrashIconComponent extends IconComponent {
  588. constructor(styles = {}) {
  589. super(styles,
  590. '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',
  591. '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'
  592. );
  593. }
  594. }
  595. class ReceptionIconComponent extends IconComponent {
  596. constructor(styles = {}) {
  597. super(styles,
  598. 'M0 11.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-5zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-8zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-11z'
  599. );
  600. }
  601. }
  602. class InfoIconComponent extends SvgComponent {
  603. constructor(styles = {}) {
  604. super(styles,
  605. 'M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z',
  606. 'm8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z'
  607. );
  608. }
  609. }
  610. class ArrowDownIconComponent extends SvgComponent {
  611. constructor(style = {}) {
  612. super({
  613. fill: ICON_COLOR,
  614. ...style,
  615. },
  616. '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'
  617. );
  618. }
  619. }
  620. class NetworkIconComponent extends SvgComponent {
  621. constructor(style = {}) {
  622. super({
  623. fill: ICON_COLOR,
  624. ...style,
  625. },
  626. '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',
  627. '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'
  628. );
  629. }
  630. }
  631. class RouterIconComponent extends IconComponent {
  632. constructor(style = {}) {
  633. super({
  634. fill: ICON_COLOR,
  635. ...style,
  636. },
  637. 'M5.525 3.025a3.5 3.5 0 0 1 4.95 0 .5.5 0 1 0 .707-.707 4.5 4.5 0 0 0-6.364 0 .5.5 0 0 0 .707.707Z',
  638. 'M6.94 4.44a1.5 1.5 0 0 1 2.12 0 .5.5 0 0 0 .708-.708 2.5 2.5 0 0 0-3.536 0 .5.5 0 0 0 .707.707ZM2.5 11a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1Zm4.5-.5a.5.5 0 1 0 1 0 .5.5 0 0 0-1 0Zm2.5.5a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1Zm1.5-.5a.5.5 0 1 0 1 0 .5.5 0 0 0-1 0Zm2 0a.5.5 0 1 0 1 0 .5.5 0 0 0-1 0Z',
  639. 'M2.974 2.342a.5.5 0 1 0-.948.316L3.806 8H1.5A1.5 1.5 0 0 0 0 9.5v2A1.5 1.5 0 0 0 1.5 13H2a.5.5 0 0 0 .5.5h2A.5.5 0 0 0 5 13h6a.5.5 0 0 0 .5.5h2a.5.5 0 0 0 .5-.5h.5a1.5 1.5 0 0 0 1.5-1.5v-2A1.5 1.5 0 0 0 14.5 8h-2.306l1.78-5.342a.5.5 0 1 0-.948-.316L11.14 8H4.86L2.974 2.342ZM14.5 9a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5h13Z',
  640. 'M8.5 5.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z'
  641. );
  642. }
  643. }
  644. class PersonIconComponent extends SvgComponent {
  645. constructor(style = {}) {
  646. super({
  647. fill: ICON_COLOR,
  648. ...style,
  649. },
  650. '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'
  651. );
  652. }
  653. }
  654. class LockIconComponent extends SvgComponent {
  655. constructor(style = {}) {
  656. super({
  657. fill: ICON_COLOR,
  658. ...style,
  659. },
  660. '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'
  661. );
  662. }
  663. }
  664. class EyeIconComponent extends SvgComponent {
  665. constructor(style = {}) {
  666. super({
  667. fill: ICON_COLOR,
  668. ...style,
  669. },
  670. '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',
  671. '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',
  672. );
  673. }
  674. }
  675. class ArrowDownShortIconComponent extends SvgComponent {
  676. constructor(style = {}) {
  677. super({
  678. fill: ICON_COLOR,
  679. ...style,
  680. },
  681. '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'
  682. );
  683. }
  684. }
  685. class ArrowUpShortIconComponent extends SvgComponent {
  686. constructor(style = {}) {
  687. super({
  688. fill: ICON_COLOR,
  689. ...style,
  690. },
  691. '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'
  692. );
  693. }
  694. }
  695. class PowerIconComponent extends SvgComponent {
  696. constructor(style = {}) {
  697. super({
  698. cursor: 'pointer',
  699. height: '7.5rem',
  700. width: '7.5rem',
  701. background: VPN_BUTTON_BACKGROUND_COLOR,
  702. borderRadius: '50%',
  703. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  704. padding: '20px',
  705. filter: 'drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.1))',
  706. fill: ICON_COLOR,
  707. ...style,
  708. },
  709. 'M7.5 1v7h1V1h-1z',
  710. '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',
  711. );
  712. }
  713. }
  714. class DialogComponent extends StyledComponent {
  715. constructor(styles = {}) {
  716. super(document.createElement('div'), {
  717. position: 'absolute',
  718. top: '0',
  719. bottom: '0',
  720. left: '0',
  721. right: '0',
  722. height: '100vh',
  723. background: 'rgba(0, 0, 0, 0.5)',
  724. backdropFilter: 'blur(5px)',
  725. display: 'flex',
  726. alignItems: 'center',
  727. justifyContent: 'center',
  728. visibility: 'hidden',
  729. opacity: '0',
  730. ...styles,
  731. });
  732. this.element.addEventListener('click', (event) => {
  733. if (event.target === this.element) {
  734. this.close();
  735. }
  736. });
  737. this.onCloseEvent = null
  738. }
  739. setOnCloseEventListener(callback) {
  740. this.onCloseEvent = callback
  741. }
  742. setContent(content) {
  743. if (!(content instanceof DialogContentComponent)) {
  744. throw new TypeError('Content must be a DialogContentComponent');
  745. }
  746. if (!this.contains(content)) {
  747. this.append(content);
  748. }
  749. }
  750. show() {
  751. this.setStyles({
  752. opacity: '1',
  753. visibility: 'visible',
  754. display: 'flex',
  755. animation: 'fade-in 0.3s forwards',
  756. pointerEvents: 'auto',
  757. })
  758. if (!document.body.contains(this.element)) {
  759. document.body.append(this.element);
  760. }
  761. }
  762. close() {
  763. this.setStyles({
  764. opacity: '0',
  765. animation: 'fade-out 0.3s forwards',
  766. })
  767. setTimeout(() => {
  768. this.setStyles({
  769. display: 'none',
  770. pointerEvents: 'none',
  771. })
  772. if (this.onCloseEvent != null) {
  773. this.onCloseEvent()
  774. }
  775. }, 300);
  776. }
  777. remove() {
  778. if (document.body.contains(this.element)) {
  779. this.element.remove();
  780. }
  781. }
  782. }
  783. class DialogContentComponent extends StyledComponent {
  784. constructor(styles = {}) {
  785. super(document.createElement('div'), {
  786. display: 'flex',
  787. flexDirection: 'column',
  788. justifyContent: 'center',
  789. alignItems: 'center',
  790. background: DIALOG_CONTENT_BACKGROUND_COLOR,
  791. borderRadius: '5px',
  792. maxWidth: '30rem',
  793. width: '85%',
  794. ...styles,
  795. });
  796. this.lastHeader = null;
  797. this.lastBody = null;
  798. this.lastFooter = null;
  799. }
  800. setHeader(component) {
  801. this?.lastHeader?.remove()
  802. this.lastHeader = component
  803. this.append(component);
  804. }
  805. setBody(component) {
  806. this?.lastBody?.remove()
  807. this.lastBody = component
  808. this.append(component);
  809. }
  810. setFooter(component) {
  811. this?.lastFooter?.remove()
  812. this.lastFooter = component
  813. this.append(component);
  814. }
  815. }
  816. class DialogHeaderComponent extends StyledComponent {
  817. constructor(styles = {}) {
  818. super(document.createElement('div'), {
  819. display: 'flex',
  820. justifyContent: 'space-between',
  821. alignItems: 'center',
  822. width: '100%',
  823. padding: '5px',
  824. ...styles,
  825. });
  826. this.title = new StyledComponent(document.createElement('span'), {
  827. fontSize: '16px',
  828. color: DIALOG_HEADER_TITLE_COLOR,
  829. fontFamily: 'Ubuntu',
  830. fontWeight: 'bold',
  831. padding: '5px',
  832. });
  833. this.closeButton = new SvgComponent({
  834. cursor: 'pointer',
  835. height: '35px',
  836. width: '35px',
  837. fill: DIALOG_HEADER_CLOSE_BUTTON_COLOR,
  838. },
  839. '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'
  840. );
  841. this.initialize();
  842. }
  843. setTitleText(title) {
  844. this.title.element.innerText = title;
  845. }
  846. setCloseButtonClickListener(callback) {
  847. this.closeButton.addEventListener('click', callback);
  848. }
  849. initialize() {
  850. this.append(this.title);
  851. this.append(this.closeButton);
  852. }
  853. }
  854. class DialogBodyComponent extends StyledComponent {
  855. constructor(styles = {}) {
  856. super(document.createElement('div'), {
  857. display: 'flex',
  858. width: '100%',
  859. padding: '5px',
  860. ...styles,
  861. });
  862. }
  863. }
  864. class DialogFooterComponent extends StyledComponent {
  865. constructor(styles = {}) {
  866. super(document.createElement('div'), {
  867. display: 'flex',
  868. justifyContent: 'space-between',
  869. gap: '5px',
  870. alignItems: 'center',
  871. width: '100%',
  872. padding: '5px',
  873. ...styles,
  874. });
  875. }
  876. addButton(button) {
  877. if (!(button instanceof DialogFooterButtonComponent)) {
  878. throw new TypeError('Button must be a DialogFooterButtonComponent instance');
  879. }
  880. this.append(button);
  881. return this;
  882. }
  883. }
  884. class DialogFooterButtonComponent extends StyledComponent {
  885. constructor(text, onclick, styles = {}) {
  886. super(document.createElement('button'), {
  887. fontSize: '14px',
  888. fontWeight: 'bold',
  889. color: DIALOG_FOOTER_BUTTON_TEXT_COLOR,
  890. background: DIALOG_FOOTER_BUTTON_COLOR,
  891. border: 'none',
  892. borderRadius: '3px',
  893. padding: '10px',
  894. width: '100%',
  895. cursor: 'pointer',
  896. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  897. ...styles,
  898. });
  899. this.setText(text)
  900. this.setClickListener(onclick);
  901. }
  902. setText(text) {
  903. this.element.innerText = text;
  904. }
  905. setClickListener(callback) {
  906. this.addEventListener('click', callback);
  907. }
  908. }
  909. class DialogBuilder {
  910. constructor(styles = {}) {
  911. this.dialog = new DialogComponent(styles);
  912. this.header = new DialogHeaderComponent();
  913. this.content = new DialogContentComponent();
  914. this.footer = new DialogFooterComponent();
  915. this.footerButtons = [];
  916. this.content.setHeader(this.header);
  917. this.header.setCloseButtonClickListener(() => this.dialog.close());
  918. }
  919. static create(styles = {}) {
  920. return new DialogBuilder(styles);
  921. }
  922. setTitle(title) {
  923. this.header.setTitleText(title);
  924. return this;
  925. }
  926. setAutoRemove(autoRemove) {
  927. this.dialog.setOnCloseEventListener(() => {
  928. if (autoRemove) {
  929. this.dialog.remove();
  930. }
  931. });
  932. return this;
  933. }
  934. setBody(bodyComponent) {
  935. this.content.setBody(bodyComponent);
  936. return this;
  937. }
  938. addFooterButton(text, callback) {
  939. const button = new DialogFooterButtonComponent(text, callback);
  940. this.footerButtons.push(button);
  941. return this;
  942. }
  943. show() {
  944. this.dialog.setContent(this.content);
  945. if (this.footerButtons.length > 0) {
  946. this.content.setFooter(this.footer);
  947. this.footerButtons.forEach((button) => {
  948. this.footer.addButton(button);
  949. });
  950. }
  951. this.dialog.show();
  952. return this;
  953. }
  954. close() {
  955. this.dialog.close();
  956. }
  957. }
  958. class ConfigComponent extends StyledComponent {
  959. constructor(styles = {}) {
  960. super(document.createElement('div'), {
  961. display: 'flex',
  962. gap: '5px',
  963. alignItems: 'center',
  964. textAlign: 'left',
  965. marginTop: '5px',
  966. padding: '5px',
  967. background: 'rgba(116, 35, 217, 0.1)',
  968. width: '100%',
  969. borderRadius: '15px',
  970. filter: 'drop-shadow rgba(0, 0, 0, 0.1)',
  971. ...styles
  972. });
  973. this.image = document.createElement('img');
  974. this.name = document.createElement('span');
  975. this.description = document.createElement('span');
  976. this.mode = document.createElement('span');
  977. this.initialize();
  978. }
  979. setImage(url) {
  980. this.image.src = url;
  981. }
  982. setName(name) {
  983. this.name.innerHTML = name;
  984. }
  985. setDescription(description) {
  986. this.description.innerHTML = description;
  987. }
  988. setMode(mode) {
  989. this.mode.innerHTML = mode;
  990. }
  991. initialize() {
  992. this.setImageStyles();
  993. this.setNameStyles();
  994. this.setDescriptionStyles();
  995. this.setModeStyles();
  996. const startArea = this.createStartArea();
  997. const endArea = this.createEndArea();
  998. this.appendElements(startArea, endArea);
  999. }
  1000. setImageStyles() {
  1001. this.image.style.width = '40px';
  1002. this.image.style.height = '40px';
  1003. }
  1004. setNameStyles() {
  1005. this.name.style.fontSize = '12px';
  1006. this.name.style.fontFamily = 'Ubuntu', 'Ubuntu;';
  1007. this.name.style.color = '#b0a8ffff';
  1008. this.name.style.fontWeight = 'bold';
  1009. }
  1010. setDescriptionStyles() {
  1011. this.description.style.fontSize = '12px';
  1012. this.description.style.fontFamily = 'Ubuntu', 'Ubuntu;';
  1013. this.description.style.color = '#b0a8ffff';
  1014. this.description.style.fontWeight = 'bold';
  1015. }
  1016. setModeStyles() {
  1017. this.mode.style.fontSize = '12px';
  1018. this.mode.style.fontFamily = 'Ubuntu', 'Ubuntu;';
  1019. this.mode.style.color = '#b0a8ffff'
  1020. this.mode.style.fontWeight = 'bold';
  1021. this.mode.style.whiteSpace = 'nowrap';
  1022. }
  1023. createStartArea() {
  1024. const startArea = document.createElement('div');
  1025. startArea.style.display = 'flex';
  1026. startArea.style.width = '100%';
  1027. startArea.style.gap = '10px';
  1028. startArea.style.flexDirection = 'column';
  1029. startArea.appendChild(this.name);
  1030. startArea.appendChild(this.description);
  1031. return startArea;
  1032. }
  1033. createEndArea() {
  1034. const endArea = document.createElement('div');
  1035. endArea.style.display = 'flex';
  1036. endArea.style.flexDirection = 'column';
  1037. endArea.style.alignItems = 'end';
  1038. endArea.style.alignSelf = 'end';
  1039. endArea.style.width = '50%';
  1040. endArea.appendChild(this.mode);
  1041. return endArea;
  1042. }
  1043. appendElements(startArea, endArea) {
  1044. this.appendChild(this.image);
  1045. this.appendChild(startArea);
  1046. this.appendChild(endArea);
  1047. }
  1048. }
  1049. class CategoryComponent extends StyledComponent {
  1050. constructor(styles = {}, items = []) {
  1051. super(document.createElement('div'), {
  1052. display: 'flex',
  1053. justifyContent: 'center',
  1054. alignItems: 'center',
  1055. flexDirection: 'column',
  1056. textAlign: 'center',
  1057. padding: '1px',
  1058. width: '100%',
  1059. ...styles
  1060. });
  1061. this.items = items;
  1062. this.name = document.createElement('span');
  1063. this.setNameStyles();
  1064. this.initialize();
  1065. this.setItems(items);
  1066. }
  1067. setNameStyles() {
  1068. this.name.style.width = '100%';
  1069. this.name.style.fontSize = '16px'
  1070. this.name.style.fontFamily = 'Ubuntu';
  1071. this.name.style.color = '#b0a8ffff';
  1072. this.name.style.background = 'rgba(116, 35, 217, 0.1)';
  1073. this.name.style.padding = '5px';
  1074. this.name.style.fontWeight = 'bold';
  1075. this.name.style.filter = 'drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.1))';
  1076. }
  1077. setName(value) {
  1078. this.name.innerHTML = value;
  1079. }
  1080. setItems(items) {
  1081. items.forEach(item => this.append(item));
  1082. }
  1083. initialize() {
  1084. this.appendChild(this.name);
  1085. }
  1086. }
  1087. class ConfigBodyComponent extends DialogBodyComponent {
  1088. constructor(items) {
  1089. super({
  1090. flexDirection: 'column',
  1091. gap: '15px',
  1092. maxHeight: '80vh',
  1093. overflowY: 'auto'
  1094. });
  1095. items.forEach(item => this.append(item));
  1096. }
  1097. }
  1098. class LoggerItemComponent extends StyledComponent {
  1099. constructor(styles = {}, message) {
  1100. super(document.createElement('span'), {
  1101. fontFamily: 'monospace',
  1102. width: '100%',
  1103. fontSize: '15px',
  1104. color: LOGGER_TEXT_COLOR,
  1105. ...styles,
  1106. });
  1107. this.element.innerHTML = message
  1108. }
  1109. }
  1110. class LoggerBodyComponent extends DialogBodyComponent {
  1111. constructor(styles = {}, items = []) {
  1112. super({
  1113. flexDirection: 'column',
  1114. maxHeight: '65vh',
  1115. overflowY: 'auto',
  1116. width: '100%',
  1117. ...styles,
  1118. });
  1119. this.setItems(items);
  1120. }
  1121. setItems(items) {
  1122. this.element.innerHTML = '';
  1123. items.forEach(item => this.append(item));
  1124. this.scrollDown();
  1125. }
  1126. scrollDown() {
  1127. this.element.scrollTop = this.element.scrollHeight;
  1128. }
  1129. }
  1130. class CheckUserBodyComponent extends DialogBodyComponent {
  1131. constructor(data = {}) {
  1132. super()
  1133. const component = new StyledComponent(document.createElement('div'), {
  1134. display: 'flex',
  1135. flexDirection: 'column',
  1136. color: TEXT_COLOR,
  1137. fontFamily: 'Ubuntu',
  1138. gap: '2px',
  1139. textAlign: 'center',
  1140. width: '100%',
  1141. });
  1142. component.element.innerHTML = `
  1143. <span style="color: ${CHECKUSER_TEXT_COLOR}">=dNome de usuario: ${data.username}</span>
  1144. <span style="color: ${CHECKUSER_TEXT_COLOR}">=ÆExpira em: ${data.expiration_date}</span>
  1145. <span style="color: ${CHECKUSER_TEXT_COLOR}">=ÆDias restantes: ${data.expiration_days}</span>
  1146. <span style="color: ${CHECKUSER_TEXT_COLOR}">=«Conexoes: ${data.count_connections}|${data.limit_connections}</span>
  1147. `
  1148. this.append(component)
  1149. }
  1150. }
  1151. class VpnStateComponent extends StyledComponent {
  1152. constructor(style = {}) {
  1153. super(document.createElement('span'), {
  1154. fontSize: '1.4rem',
  1155. fontFamily: 'Ubuntu',
  1156. fontWeight: 'bold',
  1157. color: '#FFF',
  1158. marginTop: '2rem',
  1159. ...style,
  1160. })
  1161. this.setState('DISCONNECTED')
  1162. }
  1163. setState(state) {
  1164. this.element.innerHTML = state
  1165. }
  1166. }
  1167. class LocalIPComponent extends StyledComponent {
  1168. constructor(styles = {}) {
  1169. super(document.createElement('span'), {
  1170. position: 'absolute',
  1171. fontSize: '1rem',
  1172. fontFamily: 'Ubuntu',
  1173. fontWeight: 'bold',
  1174. whiteSpace: 'nowrap',
  1175. color: TEXT_COLOR,
  1176. top: `${window?.DtGetStatusBarHeight?.execute() ?? '30'}px`,
  1177. left: '10px',
  1178. ...styles,
  1179. })
  1180. this.setIP(window?.DtGetLocalIP?.execute() ?? '127.0.0.1')
  1181. setInterval(() => {
  1182. this.setIP(window?.DtGetLocalIP?.execute() ?? '127.0.0.1')
  1183. }, 1000)
  1184. }
  1185. setIP(ip) {
  1186. this.element.innerHTML = `IP: ${ip}`
  1187. }
  1188. }
  1189. class NetworkStatsComponent extends StyledComponent {
  1190. constructor(styles = {}) {
  1191. super(document.createElement('div'), {
  1192. display: 'flex',
  1193. position: 'absolute',
  1194. gap: '5px',
  1195. top: `${(window?.DtGetStatusBarHeight?.execute() ?? 30) + 20}px`,
  1196. left: '-5px',
  1197. ...styles,
  1198. });
  1199. this.meterDownContainer = this.createMeterContainer();
  1200. this.meterDownText = this.createMeterText();
  1201. this.arrowDownShortIcon = new ArrowDownShortIconComponent();
  1202. this.meterDownContainer.append(this.arrowDownShortIcon);
  1203. this.meterDownContainer.append(this.meterDownText);
  1204. this.meterUpContainer = this.createMeterContainer();
  1205. this.meterUpText = this.createMeterText();
  1206. this.arrowUpShortIcon = new ArrowUpShortIconComponent();
  1207. this.meterUpContainer.append(this.arrowUpShortIcon);
  1208. this.meterUpContainer.append(this.meterUpText);
  1209. this.append(this.meterDownContainer);
  1210. this.append(this.meterUpContainer);
  1211. this.getNetworkDownloadFn = () => window?.DtGetNetworkDownloadBytes?.execute() ?? 0;
  1212. this.getNetworkUploadFn = () => window?.DtGetNetworkUploadBytes?.execute() ?? 0;
  1213. this.currentNetworkDownload = parseFloat(localStorage.getItem('networkDownload') ?? this.getNetworkDownloadFn());
  1214. this.currentNetworkUpload = parseFloat(localStorage.getItem('networkUpload') ?? this.getNetworkUploadFn());
  1215. localStorage.setItem('networkDownload', this.currentNetworkDownload);
  1216. localStorage.setItem('networkUpload', this.currentNetworkUpload);
  1217. this.showMeter();
  1218. setInterval(() => this.showMeter(), 1000);
  1219. }
  1220. createMeterContainer() {
  1221. return new StyledComponent(document.createElement('div'), {
  1222. display: 'flex',
  1223. alignItems: 'center',
  1224. });
  1225. }
  1226. createMeterText() {
  1227. return new StyledComponent(document.createElement('span'), {
  1228. fontSize: '1rem',
  1229. marginLeft: '-5px',
  1230. fontFamily: 'Ubuntu',
  1231. fontWeight: 'bold',
  1232. whiteSpace: 'nowrap',
  1233. color: '#fff',
  1234. });
  1235. }
  1236. formatBytes(bytes) {
  1237. const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
  1238. if (bytes === 0) return '0 B';
  1239. const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  1240. return (bytes / Math.pow(1024, i)).toPrecision(3) + ' ' + sizes[i];
  1241. }
  1242. showMeter() {
  1243. const newNetworkDownload = this.getNetworkDownloadFn();
  1244. const newNetworkUpload = this.getNetworkUploadFn();
  1245. this.meterDownText.element.innerHTML = this.formatBytes(newNetworkDownload - this.currentNetworkDownload);
  1246. this.meterUpText.element.innerHTML = this.formatBytes(newNetworkUpload - this.currentNetworkUpload);
  1247. }
  1248. }
  1249. class IframeBodyComponent extends DialogBodyComponent {
  1250. constructor(styles = {}, url = null) {
  1251. super({
  1252. minHeight: '600px',
  1253. ...styles
  1254. })
  1255. this.iframeElement = new StyledComponent(document.createElement('iframe'), {
  1256. width: '100%',
  1257. border: 'none',
  1258. borderRadius: '5px',
  1259. display: 'none',
  1260. })
  1261. this.spinner = new Spinner()
  1262. this.iframeElement.addEventListener('load', () => {
  1263. this.iframeElement.setStyles({
  1264. display: 'block'
  1265. })
  1266. this.spinner.setStyles({
  1267. display: 'none'
  1268. })
  1269. })
  1270. this.setUrl(url)
  1271. this.applyOptions()
  1272. this.append(this.iframeElement)
  1273. this.append(this.spinner)
  1274. }
  1275. setUrl(url) {
  1276. this.iframeElement.element.src = url
  1277. }
  1278. setOnLoadListener(callback) {
  1279. this.iframeElement.addEventListener('load', callback)
  1280. }
  1281. applyOptions() {
  1282. this.iframeElement.element.setAttribute('allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share')
  1283. this.iframeElement.element.setAttribute('allowfullscreen', '')
  1284. this.iframeElement.element.setAttribute('frameborder', '0')
  1285. }
  1286. }
  1287. class CleanAppMessageBodyComponent extends DialogBodyComponent {
  1288. constructor(styles = {}, url = null) {
  1289. super({
  1290. height: 'auto',
  1291. ...styles
  1292. })
  1293. this.spanComponent = new StyledComponent(document.createElement('span'), {
  1294. fontSize: '16px',
  1295. fontFamily: 'Ubuntu',
  1296. fontWeight: 'bold',
  1297. color: TEXT_COLOR,
  1298. })
  1299. 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?'
  1300. this.append(this.spanComponent)
  1301. }
  1302. }
  1303. class StyledButtonComponent extends StyledComponent {
  1304. constructor(text, icon, onclick, styles = {}) {
  1305. super(document.createElement('button'), {
  1306. width: '100%',
  1307. borderRadius: '5px',
  1308. padding: '10px',
  1309. border: 'none',
  1310. color: TEXT_COLOR,
  1311. background: BUTTON_BACKGROUND_COLOR,
  1312. boxShadow: 'rgba(0, 0, 0, 0.35) 0px 5px 15px',
  1313. cursor: 'pointer',
  1314. display: 'flex',
  1315. alignItems: 'center',
  1316. filter: 'drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.1))',
  1317. ...styles
  1318. });
  1319. this.textComponent = new StyledComponent(document.createElement('span'), {
  1320. fontSize: '16px',
  1321. fontWeight: 'bold',
  1322. });
  1323. this.textComponent.element.innerHTML = text;
  1324. this.element.addEventListener('click', onclick)
  1325. this.append(icon ?? '')
  1326. this.append(this.textComponent);
  1327. }
  1328. }
  1329. class ApnSettingStyledButtonComponent extends StyledButtonComponent {
  1330. constructor() {
  1331. super(
  1332. 'APN',
  1333. new ReceptionIconComponent(),
  1334. () => window?.DtStartApnActivity?.execute()
  1335. )
  1336. }
  1337. }
  1338. class BatteryStyledButtonComponent extends StyledButtonComponent {
  1339. constructor() {
  1340. super(
  1341. 'BATERIA',
  1342. new BatteryIconComponent(),
  1343. () => window?.DtIgnoreBatteryOptimizations?.execute(),
  1344. )
  1345. }
  1346. }
  1347. class SupportStyledButtonComponent extends StyledButtonComponent {
  1348. constructor() {
  1349. super(
  1350. 'SUPORTE',
  1351. new HeadsetIconComponent(),
  1352. () => window?.DtStartWebViewActivity?.execute(LINK_SUPPORT)
  1353. );
  1354. }
  1355. }
  1356. class SpeedTestStyledButtonComponent extends StyledButtonComponent {
  1357. constructor() {
  1358. super(
  1359. 'SPEEDTEST',
  1360. new SpeedMeterIconComponent(),
  1361. () => {
  1362. DialogBuilder.create()
  1363. .setTitle('SPEEDTEST')
  1364. .setAutoRemove(true)
  1365. .setBody(new IframeBodyComponent({}, URL_SPEEDTEST))
  1366. .show()
  1367. })
  1368. }
  1369. }
  1370. class ButtonServersComponent extends StyledButtonComponent {
  1371. constructor() {
  1372. super(
  1373. 'SERVIDORES',
  1374. new ServerIconComponet(),
  1375. () => window?.DtStartWebViewActivity?.execute(SERVER_URL)
  1376. );
  1377. }
  1378. }
  1379. class PolicyServersComponent extends StyledButtonComponent {
  1380. constructor() {
  1381. super(
  1382. 'PRIVACIDADE',
  1383. new policyIconComponet(),
  1384. () => window?.DtStartWebViewActivity?.execute(POLITC_URL)
  1385. );
  1386. }
  1387. }
  1388. class TermosComponent extends StyledButtonComponent {
  1389. constructor() {
  1390. super(
  1391. 'TERMOS',
  1392. new policyIconComponet(),
  1393. () => window?.DtStartWebViewActivity?.execute(TERMS_URL)
  1394. );
  1395. }
  1396. }
  1397. class BuyComponent extends StyledButtonComponent {
  1398. constructor() {
  1399. super(
  1400. 'COMPRAR LOGIN',
  1401. new BuyIconComponet(),
  1402. () => window?.DtStartWebViewActivity?.execute(PREMIUM_URL)
  1403. );
  1404. }
  1405. }
  1406. class ButtonTutorialComponent extends StyledButtonComponent {
  1407. constructor() {
  1408. super(
  1409. 'TUTORIAIS',
  1410. new TutorialIconComponet(),
  1411. () => window?.DtStartWebViewActivity?.execute(TUTO_URL)
  1412. );
  1413. }
  1414. }
  1415. class YouTubeStyledButtonComponent extends StyledButtonComponent {
  1416. static dialog = DialogBuilder.create({
  1417. zIndex: 1
  1418. })
  1419. .setTitle('YOUTUBE')
  1420. .setBody(new IframeBodyComponent({}, URL_YOUTUBE))
  1421. constructor() {
  1422. super(
  1423. 'YOUTUBE',
  1424. new YouTubeIconComponent(),
  1425. () => this.dialog.show(),
  1426. )
  1427. }
  1428. get dialog() {
  1429. return YouTubeStyledButtonComponent.dialog;
  1430. }
  1431. }
  1432. class Mp3StyledButtonComponent extends StyledButtonComponent {
  1433. static dialog = DialogBuilder.create({
  1434. zIndex: 1
  1435. })
  1436. .setTitle('MP3')
  1437. .setBody(new IframeBodyComponent({}, URL_MP3))
  1438. constructor() {
  1439. super(
  1440. 'MP3',
  1441. new Mp3IconComponent(),
  1442. () => this.dialog.show(),
  1443. )
  1444. }
  1445. get dialog() {
  1446. return Mp3StyledButtonComponent.dialog;
  1447. }
  1448. }
  1449. class CleanAppStyledButtonComponent extends StyledButtonComponent {
  1450. constructor() {
  1451. super(
  1452. 'LIMPAR',
  1453. new TrashIconComponent(),
  1454. () => {
  1455. const dialog = DialogBuilder.create()
  1456. .setTitle('LIMPAR DADOS')
  1457. .setAutoRemove(true)
  1458. .setBody(new CleanAppMessageBodyComponent())
  1459. .addFooterButton('NÃO', () => dialog.close())
  1460. .addFooterButton('SIM', () => window?.DtCleanApp?.execute())
  1461. .show();
  1462. })
  1463. }
  1464. }
  1465. class HotSpotStyledButtonComponent extends StyledButtonComponent {
  1466. constructor() {
  1467. super(
  1468. 'HOTSPOT',
  1469. new RouterIconComponent(),
  1470. () => this.toggleHotSpot())
  1471. }
  1472. startHotSpot() {
  1473. window?.DtStartHotSpotService?.execute();
  1474. Toast.success('HotSpot iniciado com sucesso!')
  1475. }
  1476. stopHotSpot() {
  1477. window?.DtStopHotSpotService?.execute();
  1478. Toast.success('HotSpot parado com sucesso!')
  1479. }
  1480. toggleHotSpot() {
  1481. const hotSpotStatus = window?.DtGetStatusHotSpotService?.execute() ?? 'STOPPED';
  1482. hotSpotStatus == 'RUNNING' ? this.stopHotSpot() : this.startHotSpot();
  1483. }
  1484. }
  1485. class MenuDialogBodyComponent extends DialogBodyComponent {
  1486. constructor() {
  1487. super({
  1488. display: 'flex',
  1489. flexDirection: 'column',
  1490. gap: '5px'
  1491. })
  1492. }
  1493. addRowButtons(...buttons) {
  1494. const element = new StyledComponent(document.createElement('div'), {
  1495. display: 'flex',
  1496. gap: '5px',
  1497. width: '100%'
  1498. });
  1499. buttons.forEach(button => element.append(button));
  1500. this.append(element);
  1501. return this;
  1502. }
  1503. }
  1504. class ConfigInputComponent extends InputGroupComponent {
  1505. constructor() {
  1506. super({
  1507. cursor: 'pointer',
  1508. background: INPUT_COLOR
  1509. });
  1510. this.configInput = new InputText({
  1511. cursor: 'pointer',
  1512. fontFamily: 'Ubuntu'
  1513. });
  1514. this.configInput.setEnabled(false);
  1515. this.configInput.setPlaceholder('SELECIONE UM SERVIDOR');
  1516. this.configInput.setValue(JSON.parse(window?.DtGetDefaultConfig?.execute() ?? '{}').name ?? '');
  1517. this.append(new NetworkIconComponent(), this.configInput, new ArrowDownIconComponent());
  1518. this.configure()
  1519. this.addEventListener('click', () => {
  1520. 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"}]}]';
  1521. const items = JSON.parse(window?.DtGetConfigs?.execute() || mock);
  1522. items.sort((a, b) => a.sorter - b.sorter);
  1523. items.forEach((item) => item.items.sort((a, b) => a.sorter - b.sorter));
  1524. const dialog = DialogBuilder.create()
  1525. .setTitle('CONFIGURAÇÕES')
  1526. .setAutoRemove(true)
  1527. .setBody(
  1528. new ConfigBodyComponent(
  1529. items.map((item) => {
  1530. const category = new CategoryComponent();
  1531. category.setName(item.name);
  1532. category.setItems(
  1533. item.items.map((item) => {
  1534. const config = new ConfigComponent();
  1535. config.setName(item.name);
  1536. config.setDescription(item.description ?? '');
  1537. config.setMode(item.mode);
  1538. config.setImage(item.icon);
  1539. config.addEventListener('click', () => {
  1540. window?.DtSetConfig?.execute(item.id);
  1541. dialog.close();
  1542. });
  1543. return config;
  1544. })
  1545. );
  1546. return category;
  1547. })
  1548. )
  1549. )
  1550. .show();
  1551. });
  1552. const originalClickListener = window.dtConfigClickListener;
  1553. window.dtConfigClickListener = () => {
  1554. if (originalClickListener) {
  1555. originalClickListener();
  1556. }
  1557. this.configure();
  1558. };
  1559. this.configure();
  1560. }
  1561. configure() {
  1562. const config = JSON.parse(window?.DtGetDefaultConfig?.execute() ?? '{"auth":{"password": ""}, "mode": "v2ra"}')
  1563. this.configInput.setValue(config.name ?? '')
  1564. }
  1565. }
  1566. class UserPassInputComponent extends StyledComponent {
  1567. constructor() {
  1568. super(document.createElement('div'), {
  1569. display: 'flex',
  1570. marginTop: '5px',
  1571. width: '100%',
  1572. display: 'flex',
  1573. gap: '5px',
  1574. });
  1575. this.usernameGroupComponent = new InputGroupComponent({
  1576. background: INPUT_COLOR
  1577. });
  1578. const personIconComponent = new PersonIconComponent();
  1579. this.usernameInput = new InputText();
  1580. this.usernameInput.setPlaceholder('Nome de usuário');
  1581. this.usernameInput.setValue(window?.DtUsername?.get() ?? '');
  1582. this.usernameInput.setOnInputListener(() => window?.DtUsername?.set(this.usernameInput.value));
  1583. this.usernameGroupComponent.append(personIconComponent, this.usernameInput);
  1584. this.append(this.usernameGroupComponent);
  1585. this.passwordGroupComponent = new InputGroupComponent({
  1586. background: INPUT_COLOR
  1587. });
  1588. this.passwordInput = new InputPassword();
  1589. const eyeIconComponent = new EyeIconComponent();
  1590. eyeIconComponent.addEventListener('click', () => this.passwordInput.setShowing(!this.passwordInput.isShowing));
  1591. this.passwordInput.setPlaceholder('Senha');
  1592. this.passwordInput.setValue(window?.DtPassword?.get() ?? '');
  1593. this.passwordInput.setOnInputListener(() => {
  1594. window?.DtPassword?.set(this.passwordInput.value)
  1595. });
  1596. this.passwordGroupComponent.append(new LockIconComponent(), this.passwordInput, eyeIconComponent);
  1597. this.append(this.passwordGroupComponent);
  1598. this.v2rayUuidGroupComponent = new InputGroupComponent({
  1599. background: INPUT_COLOR
  1600. });
  1601. this.v2rayUuidInput = new InputPassword();
  1602. this.v2rayUuidInput.setPlaceholder('V2Ray UUID');
  1603. this.v2rayUuidInput.setValue(window?.DtUuid?.get() ?? '');
  1604. this.v2rayUuidInput.setOnInputListener(() => window?.DtUuid?.set(this.v2rayUuidInput.value));
  1605. this.v2rayUuidGroupComponent.append(new LockIconComponent(), this.v2rayUuidInput);
  1606. this.append(this.v2rayUuidGroupComponent);
  1607. const originalClickListener = window.dtConfigClickListener;
  1608. window.dtConfigClickListener = () => {
  1609. if (originalClickListener) {
  1610. originalClickListener();
  1611. }
  1612. this.configure();
  1613. };
  1614. this.configure();
  1615. }
  1616. configure() {
  1617. const config = JSON.parse(window?.DtGetDefaultConfig?.execute() ?? '{"auth":{"password": ""}, "mode": "v2ra"}')
  1618. const isV2ray = config?.mode?.toLowerCase()?.startsWith('v2ray');
  1619. this.usernameGroupComponent.setStyles({
  1620. display: isV2ray || config?.auth?.username ? 'none' : 'flex',
  1621. })
  1622. this.passwordGroupComponent.setStyles({
  1623. display: isV2ray || config?.auth?.password ? 'none' : 'flex',
  1624. })
  1625. this.v2rayUuidGroupComponent.setStyles({
  1626. display: !isV2ray || config?.auth?.v2ray_uuid ? 'none' : 'flex',
  1627. })
  1628. const isRunning = (window?.DtGetVpnState?.execute() ?? 'DISCONNECTED') != 'DISCONNECTED';
  1629. this.usernameInput.setEnabled(!isRunning)
  1630. this.passwordInput.setEnabled(!isRunning)
  1631. this.v2rayUuidInput.setEnabled(!isRunning)
  1632. }
  1633. }
  1634. class ButtonAndStateContainerComponent extends StyledComponent {
  1635. constructor(styles = {}) {
  1636. super(document.createElement('div'), {
  1637. display: 'flex',
  1638. flexDirection: 'column',
  1639. alignItems: 'center',
  1640. position: 'absolute',
  1641. bottom: '120%',
  1642. ...styles,
  1643. });
  1644. this.startOrStopButtonComponent = new PowerIconComponent();
  1645. this.startOrStopButtonComponent.addEventListener('click', () => {
  1646. if (window?.DtGetVpnState?.execute() !== 'DISCONNECTED') {
  1647. window?.DtExecuteVpnStop?.execute();
  1648. } else {
  1649. window?.DtExecuteVpnStart?.execute();
  1650. }
  1651. });
  1652. this.append(this.startOrStopButtonComponent);
  1653. this.vpnStateComponent = new VpnStateComponent();
  1654. this.append(this.vpnStateComponent);
  1655. window.dtVpnStateListener = state => this.configureState(state);
  1656. this.configureState(window?.DtGetVpnState?.execute() ?? 'DISCONNECTED');
  1657. }
  1658. configureState(state) {
  1659. const isRunning = state != 'DISCONNECTED';
  1660. this.vpnStateComponent.setState((window?.DtTranslateText?.execute('LBL_STATE_' + state) ?? 'UNKNOWN').toUpperCase())
  1661. if (state == 'DISCONNECTED') {
  1662. this.vpnStateComponent.setStyles({
  1663. color: VPN_STOPPED_COLOR
  1664. })
  1665. this.startOrStopButtonComponent.setStyles({
  1666. fill: VPN_STOPPED_COLOR
  1667. })
  1668. }
  1669. if (state != 'DISCONNECTED' && state != 'CONNECTED') {
  1670. this.vpnStateComponent.setStyles({
  1671. color: VPN_STARTING_COLOR
  1672. })
  1673. this.startOrStopButtonComponent.setStyles({
  1674. fill: VPN_STARTING_COLOR
  1675. })
  1676. }
  1677. if (state == 'CONNECTED') {
  1678. this.vpnStateComponent.setStyles({
  1679. color: VPN_RUNNING_COLOR
  1680. })
  1681. this.startOrStopButtonComponent.setStyles({
  1682. fill: VPN_RUNNING_COLOR
  1683. })
  1684. }
  1685. }
  1686. }
  1687. class CardToolsComponent extends CardComponent {
  1688. constructor() {
  1689. super({
  1690. margin: '50px 0',
  1691. width: '100%',
  1692. flexDirection: 'row',
  1693. justifyContent: 'space-between',
  1694. background: 'transparent',
  1695. boxShadow: 'none',
  1696. filter: 'drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.1))',
  1697. });
  1698. this.loggerBody = new LoggerBodyComponent({});
  1699. this.addArrowRepeatIcon();
  1700. this.addLoggerIcon();
  1701. this.addCalanderIcon();
  1702. this.addMoreButton();
  1703. window.dtOnNewLogListener = () => this.renderizeLogger();
  1704. this.renderizeLogger();
  1705. }
  1706. addCalanderIcon() {
  1707. const calanderIconComponent = new CalanderIconComponent();
  1708. calanderIconComponent.addEventListener('click', () =>
  1709. window?.DtStartCheckUser?.execute()
  1710. );
  1711. this.append(calanderIconComponent);
  1712. }
  1713. addLoggerIcon() {
  1714. const loggerIconComponent = new LoggerIconComponent();
  1715. loggerIconComponent.addEventListener('click', () => {
  1716. const loggerDialog = DialogBuilder.create()
  1717. .setTitle('REGISTRO')
  1718. .setBody(this.loggerBody)
  1719. .setAutoRemove(true)
  1720. .addFooterButton('LIMPAR', () => window?.DtClearLogs?.execute())
  1721. .addFooterButton('FECHAR', () => loggerDialog.close())
  1722. .show();
  1723. this.loggerBody.scrollDown();
  1724. });
  1725. this.append(loggerIconComponent);
  1726. }
  1727. addArrowRepeatIcon() {
  1728. const arrowRepeatIconComponent = new ArrowRepeatIconComponent();
  1729. arrowRepeatIconComponent.addEventListener('click', () =>
  1730. window?.DtStartAppUpdate?.execute()
  1731. );
  1732. this.append(arrowRepeatIconComponent);
  1733. }
  1734. addMoreButton() {
  1735. const moreButton = new MoreIconComponent();
  1736. moreButton.addEventListener('click', () => {
  1737. DialogBuilder.create()
  1738. .setTitle('FERRAMENTAS')
  1739. .setAutoRemove(true)
  1740. .setBody(
  1741. new MenuDialogBodyComponent()
  1742. .addRowButtons(
  1743. new BuyComponent(),
  1744. new ButtonServersComponent(),
  1745. )
  1746. .addRowButtons(
  1747. new ButtonTutorialComponent(),
  1748. new SpeedTestStyledButtonComponent(),
  1749. )
  1750. .addRowButtons(
  1751. new HotSpotStyledButtonComponent(),
  1752. new BatteryStyledButtonComponent(),
  1753. )
  1754. .addRowButtons(
  1755. new ApnSettingStyledButtonComponent(),
  1756. new CleanAppStyledButtonComponent()
  1757. )
  1758. .addRowButtons(
  1759. new PolicyServersComponent(),
  1760. new TermosComponent(),
  1761. )
  1762. )
  1763. .show();
  1764. });
  1765. this.append(moreButton);
  1766. }
  1767. renderizeLogger() {
  1768. const mock = Array.from({
  1769. length: 300
  1770. }, (_, i) => ({
  1771. TIME: `MESSAGE ${i}`
  1772. }));
  1773. const data = JSON.parse(window?.DtGetLogs?.execute() ?? JSON.stringify(mock))
  1774. const items = data.map(log => {
  1775. const message = Object.keys(log)[0] + ' ' + log[Object.keys(log)]
  1776. return new LoggerItemComponent({}, message)
  1777. })
  1778. this.loggerBody.setItems(items)
  1779. }
  1780. }
  1781. class CheckUserDialog {
  1782. constructor() {
  1783. this.dialog = DialogBuilder.create()
  1784. .setAutoRemove(true)
  1785. .setTitle('CHECKUSER')
  1786. .setBody(new Spinner());
  1787. }
  1788. initialize() {
  1789. window.dtCheckUserStartedListener = () => this.checkUserStartedListener();
  1790. window.dtCheckUserModelListener = model => this.checkUserModelListener(model);
  1791. }
  1792. checkUserStartedListener() {
  1793. const config = JSON.parse(window?.DtGetDefaultConfig?.execute() ?? '{}');
  1794. if (!config.url_check_user) return;
  1795. this.dialog.show();
  1796. }
  1797. checkUserModelListener(model) {
  1798. const data = JSON.parse(model ?? `{"username": "test"}`);
  1799. this.dialog
  1800. .setTitle(` Olá, ${data.username}`)
  1801. .setBody(new CheckUserBodyComponent(data));
  1802. }
  1803. }
  1804. const rootComponent = new AppComponent(document.querySelector('#root'), {
  1805. background: BACKGROUND_COLOR
  1806. });
  1807. window.onerror = e => {
  1808. rootComponent.element.style.color = '#FFFFFF';
  1809. rootComponent.element.style.fontSize = '18px';
  1810. rootComponent.element.innerHTML = e
  1811. return false;
  1812. };
  1813. const cardComponent = new CardComponent({
  1814. position: 'absolute',
  1815. top: '45%'
  1816. });
  1817. const configInput = new ConfigInputComponent();
  1818. cardComponent.append(configInput);
  1819. const userPassInputComponent = new UserPassInputComponent()
  1820. cardComponent.append(userPassInputComponent);
  1821. const cardToolsComponent = new CardToolsComponent();
  1822. cardComponent.append(cardToolsComponent);
  1823. const buttonAndStateContainer = new ButtonAndStateContainerComponent({
  1824. marginTop: '3rem'
  1825. });
  1826. cardComponent.append(buttonAndStateContainer);
  1827. rootComponent.append(new LocalIPComponent());
  1828. rootComponent.append(new NetworkStatsComponent());
  1829. rootComponent.append(cardComponent);
  1830. const checkUserDialog = new CheckUserDialog();
  1831. checkUserDialog.initialize();
  1832. function createElements() {
  1833. const container = document.createElement("div");
  1834. container.classList.add("container");
  1835. container.style.position = 'absolute';
  1836. const content = document.createElement("div");
  1837. content.classList.add("content");
  1838. const background = document.createElement("div");
  1839. const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  1840. svg.setAttribute("width", "16");
  1841. svg.setAttribute("height", "16");
  1842. svg.setAttribute("fill", "currentColor");
  1843. svg.classList.add("bi", "bi-git");
  1844. svg.setAttribute("viewBox", "0 0 16 16");
  1845. const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
  1846. 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");
  1847. svg.appendChild(path);
  1848. const span = document.createElement("span");
  1849. span.classList.add("ms-2");
  1850. span.setAttribute("id", "version");
  1851. span.textContent = ' 1.1';
  1852. // Montando a estrutura
  1853. background.appendChild(svg);
  1854. background.appendChild(span);
  1855. content.appendChild(background);
  1856. container.appendChild(content);
  1857. // Aplicando estilos
  1858. container.style.fontSize = '1.4rem';
  1859. container.style.fontFamily = 'Verdana';
  1860. container.style.color = TEXT_COLOR;
  1861. const statusBarHeight = window?.DtGetStatusBarHeight?.execute();
  1862. const extraPixels = 0; // Number of extra pixels you want to add
  1863. const defaultHeight = 60; // Default height if statusBarHeight is undefined
  1864. const totalTopValue = (statusBarHeight !== undefined ? statusBarHeight : defaultHeight) + extraPixels;
  1865. container.style.top = `${totalTopValue}px`;
  1866. container.style.right = '10px';
  1867. // Adicionando ao DOM
  1868. document.body.appendChild(container);
  1869. // Atualizar a versão a cada 2 segundos
  1870. setInterval(updateVersion, 2000);
  1871. }
  1872. // Função para atualizar a versão
  1873. function updateVersion() {
  1874. const versionElement = document.getElementById('version');
  1875. const version = window?.DtGetLocalConfigVersion?.execute() ?? ' 1.0';
  1876. versionElement.textContent = version;
  1877. }
  1878. // Chamar a função para criar elementos e configurar a versão inicial
  1879. createElements();
  1880. updateVersion();
  1881. </script>
  1882. <div class="container" style="position: absolute; font-size: 1.4rem; font-family: Verdana; color: rgb(176, 168, 255); top: 60px; right: 10px;">
  1883. <div class="content">
  1884. <div><svg width="16" height="16" fill="currentColor" class="bi bi-git" viewBox="0 0 16 16">
  1885. <path 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">
  1886. </path>
  1887. </svg><span class="ms-2" id="version"> 1.0</span></div>
  1888. </div>
  1889. </div>
  1890. </body>
  1891. </html>

comments powered by Disqus