@iksdev/shard-cli 0.1.48 → 0.1.50

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.
Files changed (2) hide show
  1. package/bin/shard.js +111 -58
  2. package/package.json +1 -1
package/bin/shard.js CHANGED
@@ -702,49 +702,12 @@ async function shareFile(positionals, flags) {
702
702
  if (Number.isFinite(n) && n > 0) createdShareId = n;
703
703
  }
704
704
 
705
- // ── Affichage statut partage actif ─────────────────────────────────────
706
- const WS = 58;
707
- const hr = (l, m, r, col) => `${c(col, l + m.repeat(WS) + r)}`;
708
- const rowS = (content, col) => {
709
- const vis = content.replace(/\x1b\[[0-9;]*m/g, '');
710
- const pad = WS - vis.length;
711
- return `${c(col, '│')}${content}${' '.repeat(Math.max(0, pad))}${c(col, '│')}`;
712
- };
705
+ // Ecran "Partage actif" - affiché après connexion
706
+ printShareActiveScreen(share, fileName, limits, temps);
713
707
 
714
- process.stdout.write('\x1Bc');
715
- console.log('');
716
- console.log(hr('┌', '─', '┐', '\x1b[32m'));
717
- const titleShare = '\x1b[1m\x1b[32m' + ' PARTAGE ACTIF' + '\x1b[0m';
718
- console.log(rowS(titleShare + ' '.repeat(WS - 15), '\x1b[32m'));
719
- console.log(hr('├', '─', '┤', '\x1b[32m'));
720
- console.log(rowS('', '\x1b[32m'));
721
- if (share.url) {
722
- const urlLabel = ' \x1b[90mURL \x1b[0m \x1b[1m\x1b[97m' + share.url + '\x1b[0m';
723
- console.log(rowS(urlLabel, '\x1b[32m'));
724
- }
725
- if (share.token) {
726
- const tokLabel = ' \x1b[90mToken \x1b[0m \x1b[36m' + share.token + '\x1b[0m';
727
- console.log(rowS(tokLabel, '\x1b[32m'));
728
- }
729
- const fileLabel = ' \x1b[90mFichier \x1b[0m \x1b[97m' + fileName + '\x1b[0m';
730
- console.log(rowS(fileLabel, '\x1b[32m'));
731
- const dlLabel = ' \x1b[90mLimite \x1b[0m \x1b[97m' + (limits && limits > 0 ? String(limits) + ' telechargement(s)' : 'illimite') + '\x1b[0m';
732
- console.log(rowS(dlLabel, '\x1b[32m'));
733
- const expLabel = ' \x1b[90mExpire \x1b[0m \x1b[97m' + (temps && temps > 0 ? `dans ${temps} jour(s)` : 'jamais') + '\x1b[0m';
734
- console.log(rowS(expLabel, '\x1b[32m'));
735
- console.log(rowS('', '\x1b[32m'));
736
- console.log(hr('├', '─', '┤', '\x1b[90m'));
737
- const hint = ' \x1b[90mTape \x1b[0m\x1b[1m\x1b[97m q \x1b[0m\x1b[90m + Entree pour cloture le partage et revenir au menu\x1b[0m';
738
- console.log(rowS(hint, '\x1b[90m'));
739
- console.log(hr('└', '─', '┘', '\x1b[90m'));
740
- console.log('');
741
-
742
- // Attend soit la fermeture du socket, soit que l'utilisateur tape 'q'
708
+ // Attend 'q' + Entree ou fermeture du socket
743
709
  await new Promise((resolve) => {
744
- // Fermeture côté serveur
745
710
  relaySocket.on('close', () => resolve('closed'));
746
-
747
- // Écoute clavier : 'q' + Entrée = clôture manuelle
748
711
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
749
712
  const onLine = (line) => {
750
713
  if (line.trim().toLowerCase() === 'q') {
@@ -753,21 +716,15 @@ async function shareFile(positionals, flags) {
753
716
  }
754
717
  };
755
718
  rl.on('line', onLine);
756
- // Nettoyer si le socket se ferme en premier
757
719
  relaySocket.once('close', () => {
758
720
  rl.removeListener('line', onLine);
759
- rl.close();
721
+ try { rl.close(); } catch (_) {}
760
722
  });
761
723
  });
762
724
 
763
- if (heartbeat) {
764
- clearInterval(heartbeat);
765
- heartbeat = null;
766
- }
725
+ if (heartbeat) { clearInterval(heartbeat); heartbeat = null; }
767
726
  await revokeCreatedShare();
768
- for (const sig of stopSignals) {
769
- process.off(sig, stopRelayShare);
770
- }
727
+ for (const sig of stopSignals) process.off(sig, stopRelayShare);
771
728
  closeRelay();
772
729
  return;
773
730
  } catch (error) {
@@ -1198,7 +1155,8 @@ function strip(s) { return s.replace(/\x1b\[[0-9;]*m/g, ''); }
1198
1155
 
1199
1156
  // ─── Panel interactif ────────────────────────────────────────────────────────
1200
1157
 
1201
- const W = 58; // largeur intérieure (sans les bordures)
1158
+ function getW() { const cols = process.stdout.columns || 80; return Math.min(90, Math.max(60, cols - 4)); }
1159
+ const W = getW();
1202
1160
 
1203
1161
  function clearScreen() {
1204
1162
  process.stdout.write('\x1Bc');
@@ -1209,7 +1167,7 @@ function hr(left = '├', mid = '─', right = '┤', color = C.gray) {
1209
1167
  return c(color, `${left}${mid.repeat(W)}${right}`);
1210
1168
  }
1211
1169
 
1212
- // Ligne avec bordures latérales, contenu centré ou libre
1170
+ // Ligne avec bordures latérales
1213
1171
  function row(content = '', color = C.gray) {
1214
1172
  const vis = strip(content);
1215
1173
  const pad = W - vis.length;
@@ -1223,6 +1181,99 @@ function rowCentered(content, color = C.gray) {
1223
1181
  return row(' '.repeat(l) + content + ' '.repeat(r), color);
1224
1182
  }
1225
1183
 
1184
+ // ── Écran de partage actif ────────────────────────────────────────────────────
1185
+
1186
+ function printShareActiveScreen(share, fileName, limits, temps) {
1187
+ const GRN = '\x1b[32m';
1188
+ const DGRN = '\x1b[90m';
1189
+ const WHT = '\x1b[97m';
1190
+ const BWHT = '\x1b[1m\x1b[97m';
1191
+ const CYN = '\x1b[36m';
1192
+ const RST = '\x1b[0m';
1193
+
1194
+ // Recalcule W au moment de l'affichage pour coller à la taille réelle du terminal
1195
+ const WW = getW();
1196
+ const LABEL_W = 10;
1197
+ const valW = WW - 2 - LABEL_W - 2; // espace dispo pour la valeur
1198
+
1199
+ // Ligne simple label + valeur (valeur tronquée si elle dépasse)
1200
+ const rowShare = (label, value, valColor, border = GRN) => {
1201
+ const lbl = ` ${DGRN}${label.padEnd(LABEL_W)}${RST}`;
1202
+ const v = value.length > valW ? value.slice(0, valW - 1) + '…' : value;
1203
+ const val = `${valColor}${v}${RST}`;
1204
+ const vis = strip(lbl + val);
1205
+ const pad = WW - vis.length;
1206
+ return `${border}│${RST}${lbl}${val}${' '.repeat(Math.max(0, pad))}${border}│${RST}`;
1207
+ };
1208
+
1209
+ // Ligne URL sur 2 lignes si trop longue (jamais tronquée)
1210
+ const rowUrl = (label, value) => {
1211
+ const lines = [];
1212
+ const lbl = ` ${DGRN}${label.padEnd(LABEL_W)}${RST}`;
1213
+ const lblVis = strip(lbl);
1214
+ const available = WW - lblVis.length; // espace pour la valeur sur la 1ère ligne
1215
+ const available2 = WW - 2; // espace pour la continuation (indentée)
1216
+
1217
+ if (value.length <= available) {
1218
+ // Rentre sur une seule ligne
1219
+ const val = `${BWHT}${value}${RST}`;
1220
+ const vis = strip(lbl + val);
1221
+ const pad = WW - vis.length;
1222
+ lines.push(`${GRN}│${RST}${lbl}${val}${' '.repeat(Math.max(0, pad))}${GRN}│${RST}`);
1223
+ } else {
1224
+ // Première ligne : label + début de l'URL
1225
+ const part1 = value.slice(0, available);
1226
+ const val1 = `${BWHT}${part1}${RST}`;
1227
+ const vis1 = strip(lbl + val1);
1228
+ lines.push(`${GRN}│${RST}${lbl}${val1}${' '.repeat(Math.max(0, WW - vis1.length))}${GRN}│${RST}`);
1229
+ // Deuxième ligne : suite de l'URL indentée sous la valeur
1230
+ const indent = ' '.repeat(lblVis.length);
1231
+ let rest = value.slice(available);
1232
+ while (rest.length > 0) {
1233
+ const chunk = rest.slice(0, available2 - lblVis.length);
1234
+ rest = rest.slice(chunk.length);
1235
+ const val2 = `${BWHT}${chunk}${RST}`;
1236
+ const vis2 = strip(indent + val2);
1237
+ lines.push(`${GRN}│${RST}${indent}${val2}${' '.repeat(Math.max(0, WW - vis2.length))}${GRN}│${RST}`);
1238
+ }
1239
+ }
1240
+ return lines.join('\n');
1241
+ };
1242
+
1243
+ const dlLabel = limits && limits > 0 ? `${limits} telechargement(s)` : 'illimite';
1244
+ const expLabel = temps && temps > 0 ? `dans ${temps} jour(s)` : 'jamais';
1245
+
1246
+ clearScreen();
1247
+ console.log('');
1248
+
1249
+ // ── Titre ─────────────────────────────────────────────────────────────────
1250
+ console.log(`${GRN}┌${'─'.repeat(WW)}┐${RST}`);
1251
+ const badge = `${GRN}▸${RST} ${BWHT}PARTAGE ACTIF${RST}`;
1252
+ const badgeVis = strip(badge);
1253
+ const bL = Math.floor((WW - badgeVis.length) / 2);
1254
+ const bR = WW - badgeVis.length - bL;
1255
+ console.log(`${GRN}│${RST}${' '.repeat(bL)}${badge}${' '.repeat(bR)}${GRN}│${RST}`);
1256
+ console.log(`${GRN}├${'─'.repeat(WW)}┤${RST}`);
1257
+
1258
+ // ── Infos ─────────────────────────────────────────────────────────────────
1259
+ console.log(`${GRN}│${RST}${' '.repeat(WW)}${GRN}│${RST}`);
1260
+ if (share.url) console.log(rowUrl('URL', share.url));
1261
+ if (share.token) console.log(rowShare('Token', share.token, CYN));
1262
+ console.log(rowShare('Fichier', fileName, WHT));
1263
+ console.log(rowShare('Limite', dlLabel, WHT));
1264
+ console.log(rowShare('Expire', expLabel, WHT));
1265
+ console.log(`${GRN}│${RST}${' '.repeat(WW)}${GRN}│${RST}`);
1266
+
1267
+ // ── Footer ────────────────────────────────────────────────────────────────
1268
+ console.log(`${DGRN}├${'─'.repeat(WW)}┤${RST}`);
1269
+ const hint = ` Tape ${BWHT}q${RST}${DGRN} + Entree pour cloture et revenir au menu${RST}`;
1270
+ const hintVis = strip(hint);
1271
+ const hPad = WW - hintVis.length;
1272
+ console.log(`${DGRN}│${RST}${hint}${' '.repeat(Math.max(0, hPad))}${DGRN}│${RST}`);
1273
+ console.log(`${DGRN}└${'─'.repeat(WW)}┘${RST}`);
1274
+ console.log('');
1275
+ }
1276
+
1226
1277
  function printPanel(username, plan, statusMsg) {
1227
1278
  const now = new Date();
1228
1279
  const timeStr = now.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });
@@ -1332,24 +1383,26 @@ async function panelShare() {
1332
1383
  if (parseInt(limits, 10) > 0) flags.limits = limits;
1333
1384
  if (parseInt(temps, 10) > 0) flags.temps = temps;
1334
1385
 
1386
+ // Écran de chargement pendant la connexion au relay
1335
1387
  clearScreen();
1336
- printSubHeader('Partage en cours...');
1337
- console.log(` ${c(C.gray, 'Connexion au relay...')}\n`);
1388
+ printSubHeader('Connexion au relay...');
1389
+ console.log(` ${c(C.gray, 'Initialisation du partage, patiente...')}\n`);
1338
1390
 
1339
1391
  try {
1340
1392
  await shareFile([target], flags);
1341
- // shareFile retourne quand l'utilisateur tape 'q' ou que le socket se ferme
1342
- printSuccess('Partage cloture.');
1393
+ // Retour au menu : shareFile a déjà révoqué et fermé
1394
+ clearScreen();
1395
+ printSubHeader('Partager un fichier');
1396
+ printSuccess('Partage cloture avec succes.');
1343
1397
  } catch (err) {
1398
+ clearScreen();
1399
+ printSubHeader('Partager un fichier');
1344
1400
  if (err?.data?.code === 'PLAN_FILE_LIMIT_EXCEEDED') {
1345
1401
  printPlanLimitBox(err);
1346
1402
  } else {
1347
1403
  printError(err.message);
1348
1404
  }
1349
- await pressEnter();
1350
- return;
1351
1405
  }
1352
-
1353
1406
  await pressEnter();
1354
1407
  }
1355
1408
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iksdev/shard-cli",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "description": "CLI pour synchroniser un dossier local avec Shard",
5
5
  "bin": {
6
6
  "shard": "bin/shard.js"