xx-chat 1.0.0 → 1.0.2

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/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { parseCli } from './src/cli.js';
3
3
  import { startServer } from './src/server.js';
4
4
  import { startClient } from './src/client.js';
5
- import { initUI, renderSystemMessage, renderChatMessage } from './src/ui.js';
5
+ import { initUI, renderSystemMessage, renderChatMessage, setSendColor, setRecvColor } from './src/ui.js';
6
6
 
7
7
  async function main() {
8
8
  const { role, ip, nickname } = await parseCli();
@@ -28,7 +28,7 @@ async function main() {
28
28
  const command = parts[0];
29
29
 
30
30
  if (command === '/' || command === '/help') {
31
- renderSystemMessage('可用命令:\n /nickname <新昵称> - 修改昵称\n /quit - 退出聊天');
31
+ renderSystemMessage('可用命令:\n /nickname <新昵称> - 修改昵称\n /color-send <颜色> - 修改发送消息颜色\n /color-recv <颜色> - 修改接收消息颜色\n /quit - 退出聊天\n支持的颜色: red, green, yellow, blue, magenta, cyan, white, gray, 或者十六进制颜色(如 #ff0000)');
32
32
  } else if (command === '/nickname') {
33
33
  const newNickname = parts.slice(1).join(' ').trim();
34
34
  if (newNickname) {
@@ -38,6 +38,20 @@ async function main() {
38
38
  } else {
39
39
  renderSystemMessage('用法: /nickname <新昵称>');
40
40
  }
41
+ } else if (command === '/color-send') {
42
+ const color = parts[1];
43
+ if (color && setSendColor(color)) {
44
+ renderSystemMessage(`发送消息颜色已修改为 ${color}`);
45
+ } else {
46
+ renderSystemMessage('用法: /color-send <颜色> (如: green, red, cyan, 或十六进制如 #ff0000)');
47
+ }
48
+ } else if (command === '/color-recv') {
49
+ const color = parts[1];
50
+ if (color && setRecvColor(color)) {
51
+ renderSystemMessage(`接收消息颜色已修改为 ${color}`);
52
+ } else {
53
+ renderSystemMessage('用法: /color-recv <颜色> (如: green, red, cyan, 或十六进制如 #ff0000)');
54
+ }
41
55
  } else if (command === '/quit') {
42
56
  renderSystemMessage('正在退出聊天...');
43
57
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xx-chat",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A simple LAN CLI chat tool",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/src/cli.js CHANGED
@@ -42,7 +42,10 @@ export async function parseCli() {
42
42
  validate: (input) => input.trim() ? true : 'IP cannot be empty',
43
43
  });
44
44
 
45
- const answers = await inquirer.prompt(questions);
45
+ let answers = {};
46
+ if (questions.length > 0) {
47
+ answers = await inquirer.prompt(questions);
48
+ }
46
49
 
47
50
  return {
48
51
  role: answers.role || options.role,
package/src/ui.js CHANGED
@@ -2,19 +2,49 @@ import readline from 'readline';
2
2
  import chalk from 'chalk';
3
3
 
4
4
  let rl;
5
+ let sendColor = 'green';
6
+ let recvColor = 'cyan';
7
+ const validColors = ['red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'gray'];
8
+
9
+ function isValidHexColor(color) {
10
+ return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/i.test(color);
11
+ }
12
+
13
+ export function setSendColor(color) {
14
+ if (validColors.includes(color) || isValidHexColor(color)) {
15
+ sendColor = color;
16
+ return true;
17
+ }
18
+ return false;
19
+ }
20
+
21
+ export function setRecvColor(color) {
22
+ if (validColors.includes(color) || isValidHexColor(color)) {
23
+ recvColor = color;
24
+ return true;
25
+ }
26
+ return false;
27
+ }
5
28
 
6
29
  function completer(line) {
7
- const completions = ['/nickname', '/quit', '/help'];
30
+ const completions = ['/nickname', '/quit', '/help', '/color-send', '/color-recv'];
8
31
  const hits = completions.filter((c) => c.startsWith(line));
9
32
  return [hits.length ? hits : line.startsWith('/') ? completions : [], line];
10
33
  }
11
34
 
12
35
  export function initUI(onMessage) {
36
+ process.stdin.removeAllListeners('keypress');
37
+ if (process.stdin.isTTY) {
38
+ process.stdin.setRawMode(true);
39
+ }
40
+ process.stdin.resume();
41
+
13
42
  rl = readline.createInterface({
14
43
  input: process.stdin,
15
44
  output: process.stdout,
16
45
  prompt: '> ',
17
- completer
46
+ completer,
47
+ terminal: true
18
48
  });
19
49
 
20
50
  rl.prompt();
@@ -42,10 +72,13 @@ export function renderSystemMessage(msg) {
42
72
 
43
73
  export function renderChatMessage(nickname, message, isSelf = false) {
44
74
  clearLine();
75
+ const time = new Date().toLocaleTimeString();
45
76
  if (isSelf) {
46
- console.log(chalk.green(`[我(${nickname})] ${message}`));
77
+ const colorFn = isValidHexColor(sendColor) ? chalk.hex(sendColor) : (chalk[sendColor] || chalk.green);
78
+ console.log(colorFn(`[我(${nickname})] ${message} `) + chalk.gray(`[${time}]`));
47
79
  } else {
48
- console.log(chalk.blue(`[${nickname}] ${message}`));
80
+ const colorFn = isValidHexColor(recvColor) ? chalk.hex(recvColor) : (chalk[recvColor] || chalk.cyan);
81
+ console.log(colorFn(`[${nickname}] ${message} `) + chalk.gray(`[${time}]`));
49
82
  }
50
83
  if (rl) rl.prompt(true);
51
84
  }
@@ -0,0 +1,16 @@
1
+ import { exec } from 'child_process';
2
+ const child = exec('xx-chat');
3
+ child.stdout.on('data', d => console.log('OUT:', JSON.stringify(d)));
4
+ child.stderr.on('data', d => console.log('ERR:', JSON.stringify(d)));
5
+ setTimeout(() => {
6
+ child.stdin.write('\r'); // Select server
7
+ }, 500);
8
+ setTimeout(() => {
9
+ child.stdin.write('Host\r'); // Type nickname
10
+ }, 1000);
11
+ setTimeout(() => {
12
+ child.stdin.write('hello\r'); // Chat message
13
+ }, 2000);
14
+ setTimeout(() => {
15
+ child.kill();
16
+ }, 3000);