tunli 0.0.26 → 0.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tunli",
3
3
  "description": "Node.js application for creating HTTP tunnels to make local software projects accessible over the internet.",
4
- "version": "0.0.26",
4
+ "version": "0.0.27",
5
5
  "main": "bin/tunli",
6
6
  "bin": {
7
7
  "tunli": "bin/tunli"
@@ -28,6 +28,7 @@
28
28
  "blessed": "^0.1.81",
29
29
  "chalk": "^5.5.0",
30
30
  "commander": "^14.0.0",
31
+ "qrcode": "^1.5.4",
31
32
  "socket.io-client": "^4.8.1"
32
33
  },
33
34
  "devDependencies": {
@@ -6,6 +6,7 @@ import chalk from "chalk";
6
6
  import {getLatestVersion} from "#lib/Flow/getLatestVersion";
7
7
  import {exec} from 'child_process'
8
8
  import {checkGlobalInstallation, checkLocalInstallation} from "#src/utils/npmFunctions";
9
+ import QRCode from 'qrcode'
9
10
 
10
11
  export class Dashboard {
11
12
 
@@ -82,6 +83,13 @@ export class Dashboard {
82
83
  const lastBlockedIp = ref('')
83
84
  const availableUpdate = ref('')
84
85
 
86
+ screen.key('C-q', () => {
87
+ QRCode.toString(forwardingUrl.value, {type: 'terminal'}, (err, url) => {
88
+ if (err) throw err
89
+ screen.newFullScreenModal(url)
90
+ })
91
+ })
92
+
85
93
  getLatestVersion().then((version) => {
86
94
  if (version && version !== packageJson.version) {
87
95
  availableUpdate.value = chalk.yellow(`update available (version ${version}, Ctrl-U to update)`)
@@ -182,6 +190,7 @@ export class Dashboard {
182
190
  infoList.row(chalk.yellow('Update'), availableUpdate).if(() => availableUpdate)
183
191
  infoList.row('Profile', config.profile)
184
192
  infoList.row('Config', config.configPath)
193
+ infoList.row('QR-Code', 'Ctrl-Q')
185
194
 
186
195
  if (allowedCidr || deniedCidr) infoList.row('')
187
196
  if (allowedCidr) infoList.row('Allowed', allowedCidr)
@@ -0,0 +1,63 @@
1
+ import blessed from "blessed";
2
+
3
+ const centerContent = (text, boxWidth) => {
4
+ const lines = text.split('\n')
5
+ return lines.map(line => {
6
+ const pad = Math.floor((boxWidth - line.length) / 2)
7
+ return ' '.repeat(Math.max(pad, 0)) + line
8
+ }).join('\n')
9
+ }
10
+ export const newFullScreenModal = (screen, text) => {
11
+ // Backdrop zum Blocken von Inputs „unter“ dem Modal
12
+ const backdrop = blessed.box({
13
+ top: 0, left: 0, width: '100%', height: '100%',
14
+ style: {bg: 'black'},
15
+ mouse: true, clickable: true
16
+ })
17
+
18
+ // Größe anhand des Inhalts bestimmen (mit Padding & Border)
19
+ const lines = text.split('\n')
20
+ const contentWidth = Math.max(...lines.map(l => l.length))
21
+ const contentHeight = lines.length
22
+ const boxWidth = Math.min(contentWidth + 4, screen.width - 2)
23
+ //const centeredQr = centerContent(text, screen.width - 2) // -2 wegen Padding/Border
24
+
25
+ const qrBox = blessed.box({
26
+ top: 'center',
27
+ left: 'center',
28
+ width: boxWidth,
29
+ height: Math.min(contentHeight + 2, screen.height - 2),
30
+ padding: {left: 1, right: 1},
31
+ tags: false,
32
+ scrollable: true,
33
+ content: text,
34
+ border: 'line',
35
+ style: {
36
+ fg: 'white',
37
+ bg: 'black',
38
+ border: {fg: 'cyan'}
39
+ },
40
+ keys: true,
41
+ mouse: true,
42
+ alwaysScroll: true
43
+ })
44
+
45
+ // Einfügen und nach vorne bringen
46
+ screen.append(backdrop)
47
+ screen.append(qrBox)
48
+ qrBox.focus()
49
+ screen.render()
50
+
51
+ const close = () => {
52
+ backdrop.detach()
53
+ qrBox.detach()
54
+ screen.render()
55
+ }
56
+
57
+ // Schließen über Tastatur/Click
58
+ qrBox.key(['escape', 'q', 'C-q'], close)
59
+ backdrop.on('click', close)
60
+
61
+ // Bei Resize neu zentriert blessed automatisch; nur neu rendern
62
+ screen.on('resize', () => screen.render())
63
+ }
@@ -4,6 +4,7 @@ import {Row} from "#src/cli-app/elements/Row";
4
4
  import {ElementNode} from "#src/cli-app/elements/ElementNode";
5
5
  import {arrayRemoveEntry} from "#src/utils/arrayFunctions";
6
6
  import {Line} from "#src/cli-app/elements/Line";
7
+ import {newFullScreenModal} from "#src/cli-app/Screen/FullScreenModal";
7
8
 
8
9
  export class Screen extends EventEmitter {
9
10
 
@@ -52,6 +53,10 @@ export class Screen extends EventEmitter {
52
53
  return this.#screen.height
53
54
  }
54
55
 
56
+ newFullScreenModal(text) {
57
+ return newFullScreenModal(this, text)
58
+ }
59
+
55
60
  /**
56
61
  * @param {string|array} key
57
62
  * @param {keypressEventListener} callback