pinme 1.1.1-alpha.1 → 1.1.1-alpha.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/dist/index.js +211 -86
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1485,7 +1485,7 @@ var import_chalk6 = __toESM(require("chalk"));
|
|
|
1485
1485
|
var import_figlet3 = __toESM(require("figlet"));
|
|
1486
1486
|
|
|
1487
1487
|
// package.json
|
|
1488
|
-
var version = "1.1.1-alpha.
|
|
1488
|
+
var version = "1.1.1-alpha.2";
|
|
1489
1489
|
|
|
1490
1490
|
// bin/upload.ts
|
|
1491
1491
|
var import_path5 = __toESM(require("path"));
|
|
@@ -4525,7 +4525,9 @@ var ipfsApiUrl = "https://pinme.dev/api/v3";
|
|
|
4525
4525
|
var maxPollTime = parseInt(process.env.MAX_POLL_TIME_MINUTES || "5") * 60 * 1e3;
|
|
4526
4526
|
var pollInterval = parseInt(process.env.POLL_INTERVAL_SECONDS || "2") * 1e3;
|
|
4527
4527
|
var pollTimeout = parseInt(process.env.POLL_TIMEOUT_SECONDS || "10") * 1e3;
|
|
4528
|
-
async function pollUploadStatus(traceId, deviceId,
|
|
4528
|
+
async function pollUploadStatus(traceId, deviceId, smartProgress, startTime) {
|
|
4529
|
+
let consecutiveErrors = 0;
|
|
4530
|
+
const maxConsecutiveErrors = 3;
|
|
4529
4531
|
while (Date.now() - startTime < maxPollTime) {
|
|
4530
4532
|
try {
|
|
4531
4533
|
const response = await axios_default.get(
|
|
@@ -4542,28 +4544,28 @@ async function pollUploadStatus(traceId, deviceId, spinner, startTime) {
|
|
|
4542
4544
|
);
|
|
4543
4545
|
const { code, msg, data } = response.data;
|
|
4544
4546
|
if (code === 200) {
|
|
4545
|
-
|
|
4547
|
+
consecutiveErrors = 0;
|
|
4546
4548
|
if (data.is_ready) {
|
|
4547
|
-
|
|
4548
|
-
const duration = formatDuration(elapsed);
|
|
4549
|
-
spinner.succeed(`Upload completed ${progressBar} ${duration} (request id: ${traceId})`);
|
|
4549
|
+
smartProgress.complete(traceId);
|
|
4550
4550
|
return data;
|
|
4551
4551
|
} else {
|
|
4552
|
-
|
|
4553
|
-
const progressBar = createProgressBar(estimatedProgress, 1);
|
|
4554
|
-
const duration = formatDuration(elapsed);
|
|
4555
|
-
spinner.text = `Uploading... ${progressBar} ${duration} (request id: ${traceId})`;
|
|
4552
|
+
smartProgress.update();
|
|
4556
4553
|
}
|
|
4557
4554
|
} else {
|
|
4558
4555
|
console.log(import_chalk2.default.yellow(`Warning: ${msg}`));
|
|
4559
4556
|
}
|
|
4560
4557
|
} catch (error) {
|
|
4558
|
+
consecutiveErrors++;
|
|
4561
4559
|
console.log(import_chalk2.default.yellow(`Polling error: ${error.message}`));
|
|
4560
|
+
if (consecutiveErrors >= maxConsecutiveErrors) {
|
|
4561
|
+
console.log(import_chalk2.default.red(`Too many consecutive polling errors (${consecutiveErrors}), stopping progress updates`));
|
|
4562
|
+
break;
|
|
4563
|
+
}
|
|
4562
4564
|
}
|
|
4563
4565
|
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
4564
4566
|
}
|
|
4565
4567
|
const maxPollTimeMinutes = Math.floor(maxPollTime / (60 * 1e3));
|
|
4566
|
-
|
|
4568
|
+
smartProgress.fail(`Upload timeout after ${maxPollTimeMinutes} minutes`, traceId);
|
|
4567
4569
|
return null;
|
|
4568
4570
|
}
|
|
4569
4571
|
function diagnoseDirectoryUploadError(directoryName, resData, expectedName) {
|
|
@@ -4608,12 +4610,20 @@ var ERROR_CODES = {
|
|
|
4608
4610
|
"30001": `File too large, single file max size: ${"20"}MB,single folder max size: ${"500"}MB`,
|
|
4609
4611
|
"30002": `Max storage quorum ${Number("1000") / 1e3} GB reached`
|
|
4610
4612
|
};
|
|
4611
|
-
function loadFilesToArrRecursively(directoryPath, dist) {
|
|
4613
|
+
function loadFilesToArrRecursively(directoryPath, dist, basePath) {
|
|
4612
4614
|
const filesArr = [];
|
|
4613
4615
|
const sep = import_path4.default.sep;
|
|
4614
|
-
|
|
4616
|
+
if (!basePath) {
|
|
4617
|
+
const parentDir = import_path4.default.dirname(directoryPath);
|
|
4618
|
+
basePath = parentDir.endsWith(sep) ? parentDir : parentDir + sep;
|
|
4619
|
+
}
|
|
4620
|
+
console.log(import_chalk2.default.blue("\n\u{1F4C1} Directory Structure Analysis:"));
|
|
4621
|
+
console.log(import_chalk2.default.gray(` Upload directory: ${directoryPath}`));
|
|
4622
|
+
console.log(import_chalk2.default.gray(` Base path: ${basePath}`));
|
|
4623
|
+
console.log(import_chalk2.default.gray(` Directory name: ${dist}`));
|
|
4615
4624
|
if (import_fs_extra3.default.statSync(directoryPath).isDirectory()) {
|
|
4616
4625
|
const files = import_fs_extra3.default.readdirSync(directoryPath);
|
|
4626
|
+
console.log(import_chalk2.default.gray(` Files found in directory: ${files.length}`));
|
|
4617
4627
|
files.forEach((file) => {
|
|
4618
4628
|
const filePath = import_path4.default.join(directoryPath, file);
|
|
4619
4629
|
if (import_fs_extra3.default.statSync(filePath).isFile()) {
|
|
@@ -4625,20 +4635,27 @@ function loadFilesToArrRecursively(directoryPath, dist) {
|
|
|
4625
4635
|
)} (size: ${formatSize(sizeCheck.size)})`
|
|
4626
4636
|
);
|
|
4627
4637
|
}
|
|
4628
|
-
const
|
|
4629
|
-
const
|
|
4638
|
+
const relativePath = filePath.replace(basePath, "");
|
|
4639
|
+
const encodedPath = relativePath.replaceAll(sep, "%2F");
|
|
4640
|
+
console.log(import_chalk2.default.cyan(` \u{1F4C4} File: ${file}`));
|
|
4641
|
+
console.log(import_chalk2.default.gray(` Full path: ${filePath}`));
|
|
4642
|
+
console.log(import_chalk2.default.gray(` Relative path: ${relativePath}`));
|
|
4643
|
+
console.log(import_chalk2.default.gray(` Encoded path: ${encodedPath}`));
|
|
4630
4644
|
filesArr.push({
|
|
4631
|
-
name:
|
|
4645
|
+
name: encodedPath,
|
|
4632
4646
|
path: filePath
|
|
4633
4647
|
});
|
|
4634
4648
|
} else if (import_fs_extra3.default.statSync(filePath).isDirectory()) {
|
|
4635
|
-
|
|
4649
|
+
console.log(import_chalk2.default.yellow(` \u{1F4C2} Subdirectory: ${file}`));
|
|
4650
|
+
console.log(import_chalk2.default.gray(` Path: ${filePath}`));
|
|
4651
|
+
const recursiveFiles = loadFilesToArrRecursively(filePath, dist, basePath);
|
|
4636
4652
|
filesArr.push(...recursiveFiles);
|
|
4637
4653
|
}
|
|
4638
4654
|
});
|
|
4639
4655
|
} else {
|
|
4640
4656
|
console.error("Error: path must be a directory");
|
|
4641
4657
|
}
|
|
4658
|
+
console.log(import_chalk2.default.green(` \u2705 Total files processed: ${filesArr.length}`));
|
|
4642
4659
|
return filesArr;
|
|
4643
4660
|
}
|
|
4644
4661
|
function countFilesInDirectory(directoryPath) {
|
|
@@ -4673,17 +4690,13 @@ async function uploadDirectory(directoryPath, deviceId) {
|
|
|
4673
4690
|
if (totalFiles === 0) {
|
|
4674
4691
|
throw new Error(`Directory ${directoryPath} is empty or contains no valid files`);
|
|
4675
4692
|
}
|
|
4676
|
-
console.log(import_chalk2.default.
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
console.log(import_chalk2.default.gray(` - Files to upload:`));
|
|
4681
|
-
files.slice(0, 5).forEach((file, index) => {
|
|
4682
|
-
console.log(import_chalk2.default.gray(` ${index + 1}. ${file.name} (${file.path})`));
|
|
4693
|
+
console.log(import_chalk2.default.blue("\n\u{1F4CB} Final Upload File List:"));
|
|
4694
|
+
console.log(import_chalk2.default.gray(` Upload root directory: ${dist}`));
|
|
4695
|
+
files.forEach((file, index) => {
|
|
4696
|
+
console.log(import_chalk2.default.gray(` ${index + 1}. ${file.name}`));
|
|
4683
4697
|
});
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
}
|
|
4698
|
+
console.log(import_chalk2.default.green(` Total files to upload: ${totalFiles}
|
|
4699
|
+
`));
|
|
4687
4700
|
files.forEach((file) => {
|
|
4688
4701
|
if (!import_fs_extra3.default.existsSync(file.path)) {
|
|
4689
4702
|
throw new Error(`File not found: ${file.path}`);
|
|
@@ -4697,16 +4710,21 @@ async function uploadDirectory(directoryPath, deviceId) {
|
|
|
4697
4710
|
});
|
|
4698
4711
|
});
|
|
4699
4712
|
const startTime = Date.now();
|
|
4700
|
-
const spinner = (0, import_ora.default)(
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
}
|
|
4713
|
+
const spinner = (0, import_ora.default)(`Preparing upload...`).start();
|
|
4714
|
+
let totalSize = 0;
|
|
4715
|
+
files.forEach((file) => {
|
|
4716
|
+
try {
|
|
4717
|
+
const stats = import_fs_extra3.default.statSync(file.path);
|
|
4718
|
+
totalSize += stats.size;
|
|
4719
|
+
} catch (error) {
|
|
4720
|
+
}
|
|
4721
|
+
});
|
|
4722
|
+
const smartProgress = new SmartProgressBar(dist, totalFiles, totalSize, spinner);
|
|
4723
|
+
const progressInterval = setInterval(() => {
|
|
4724
|
+
smartProgress.update();
|
|
4725
|
+
}, 200);
|
|
4709
4726
|
try {
|
|
4727
|
+
smartProgress.startUpload();
|
|
4710
4728
|
const response = await axios_default.post(
|
|
4711
4729
|
`${ipfsApiUrl}/add?uid=${deviceId}&cidV=1`,
|
|
4712
4730
|
formData,
|
|
@@ -4718,19 +4736,18 @@ async function uploadDirectory(directoryPath, deviceId) {
|
|
|
4718
4736
|
// 30 minutes timeout
|
|
4719
4737
|
}
|
|
4720
4738
|
);
|
|
4721
|
-
clearInterval(
|
|
4739
|
+
clearInterval(progressInterval);
|
|
4740
|
+
smartProgress.startPolling();
|
|
4722
4741
|
const { trace_id } = response.data.data;
|
|
4723
4742
|
if (!trace_id) {
|
|
4724
|
-
|
|
4743
|
+
smartProgress.fail("No request id received from server");
|
|
4725
4744
|
return null;
|
|
4726
4745
|
}
|
|
4727
|
-
|
|
4728
|
-
console.log(import_chalk2.default.blue(`
|
|
4729
|
-
\u{1F50D} REQUEST ID: ${trace_id}`));
|
|
4746
|
+
smartProgress.update();
|
|
4730
4747
|
const uploadResult = await pollUploadStatus(
|
|
4731
4748
|
trace_id,
|
|
4732
4749
|
deviceId,
|
|
4733
|
-
|
|
4750
|
+
smartProgress,
|
|
4734
4751
|
startTime
|
|
4735
4752
|
);
|
|
4736
4753
|
if (!uploadResult) {
|
|
@@ -4760,7 +4777,7 @@ async function uploadDirectory(directoryPath, deviceId) {
|
|
|
4760
4777
|
uploadResult.upload_rst,
|
|
4761
4778
|
dist
|
|
4762
4779
|
);
|
|
4763
|
-
|
|
4780
|
+
smartProgress.fail("Directory hash not found in response", trace_id);
|
|
4764
4781
|
console.log(
|
|
4765
4782
|
import_chalk2.default.red(
|
|
4766
4783
|
`
|
|
@@ -4782,10 +4799,10 @@ async function uploadDirectory(directoryPath, deviceId) {
|
|
|
4782
4799
|
import_chalk2.default.gray(` 3. Try uploading a smaller directory for testing`)
|
|
4783
4800
|
);
|
|
4784
4801
|
} catch (error) {
|
|
4785
|
-
clearInterval(
|
|
4802
|
+
clearInterval(progressInterval);
|
|
4786
4803
|
if (error.message && error.message.includes("multipart")) {
|
|
4787
4804
|
const errorMessage = handleMultipartError(error, `Directory upload: ${dist}`);
|
|
4788
|
-
|
|
4805
|
+
smartProgress.fail(errorMessage);
|
|
4789
4806
|
console.log(import_chalk2.default.red(`
|
|
4790
4807
|
\u274C ${errorMessage}`));
|
|
4791
4808
|
return null;
|
|
@@ -4793,14 +4810,14 @@ async function uploadDirectory(directoryPath, deviceId) {
|
|
|
4793
4810
|
if (error.response && error.response.data && error.response.data.code) {
|
|
4794
4811
|
const errorCode = error.response.data.code.toString();
|
|
4795
4812
|
if (ERROR_CODES[errorCode]) {
|
|
4796
|
-
|
|
4813
|
+
smartProgress.fail(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`);
|
|
4797
4814
|
console.log(
|
|
4798
4815
|
import_chalk2.default.red(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`)
|
|
4799
4816
|
);
|
|
4800
4817
|
return null;
|
|
4801
4818
|
}
|
|
4802
4819
|
}
|
|
4803
|
-
|
|
4820
|
+
smartProgress.fail(`Error: ${error.message}`);
|
|
4804
4821
|
console.log(import_chalk2.default.red(`Error: ${error.message}`));
|
|
4805
4822
|
return null;
|
|
4806
4823
|
}
|
|
@@ -4822,15 +4839,27 @@ async function uploadFile(filePath, deviceId) {
|
|
|
4822
4839
|
if (!fileStats.isFile()) {
|
|
4823
4840
|
throw new Error(`Path is not a file: ${filePath}`);
|
|
4824
4841
|
}
|
|
4842
|
+
console.log(import_chalk2.default.blue("\n\u{1F4C4} File Upload Analysis:"));
|
|
4843
|
+
console.log(import_chalk2.default.gray(` File path: ${filePath}`));
|
|
4844
|
+
console.log(import_chalk2.default.gray(` File name: ${fileName}`));
|
|
4845
|
+
console.log(import_chalk2.default.gray(` File size: ${formatSize(fileStats.size)}`));
|
|
4846
|
+
console.log(import_chalk2.default.gray(` File exists: ${import_fs_extra3.default.existsSync(filePath)}`));
|
|
4847
|
+
console.log(import_chalk2.default.gray(` Is file: ${fileStats.isFile()}
|
|
4848
|
+
`));
|
|
4825
4849
|
const startTime = Date.now();
|
|
4826
|
-
const spinner = (0, import_ora.default)(`
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
const
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
}
|
|
4850
|
+
const spinner = (0, import_ora.default)(`Preparing upload...`).start();
|
|
4851
|
+
let totalSize = 0;
|
|
4852
|
+
try {
|
|
4853
|
+
const stats = import_fs_extra3.default.statSync(filePath);
|
|
4854
|
+
totalSize = stats.size;
|
|
4855
|
+
} catch (error) {
|
|
4856
|
+
}
|
|
4857
|
+
const smartProgress = new SmartProgressBar(fileName, 1, totalSize, spinner);
|
|
4858
|
+
const progressInterval = setInterval(() => {
|
|
4859
|
+
smartProgress.update();
|
|
4860
|
+
}, 200);
|
|
4833
4861
|
try {
|
|
4862
|
+
smartProgress.startUpload();
|
|
4834
4863
|
const formData = new import_form_data2.default();
|
|
4835
4864
|
const encodedFileName = encodeURIComponent(fileName);
|
|
4836
4865
|
formData.append("file", import_fs_extra3.default.createReadStream(filePath), {
|
|
@@ -4847,19 +4876,18 @@ async function uploadFile(filePath, deviceId) {
|
|
|
4847
4876
|
// 30 minutes timeout
|
|
4848
4877
|
}
|
|
4849
4878
|
);
|
|
4850
|
-
clearInterval(
|
|
4879
|
+
clearInterval(progressInterval);
|
|
4880
|
+
smartProgress.startPolling();
|
|
4851
4881
|
const trace_id = response.data.data.trace_id;
|
|
4852
4882
|
if (!trace_id) {
|
|
4853
|
-
|
|
4883
|
+
smartProgress.fail("No request id received from server");
|
|
4854
4884
|
return null;
|
|
4855
4885
|
}
|
|
4856
|
-
|
|
4857
|
-
console.log(import_chalk2.default.blue(`
|
|
4858
|
-
\u{1F50D} REQUEST ID: ${trace_id}`));
|
|
4886
|
+
smartProgress.update();
|
|
4859
4887
|
const uploadResult = await pollUploadStatus(
|
|
4860
4888
|
trace_id,
|
|
4861
4889
|
deviceId,
|
|
4862
|
-
|
|
4890
|
+
smartProgress,
|
|
4863
4891
|
startTime
|
|
4864
4892
|
);
|
|
4865
4893
|
if (!uploadResult) {
|
|
@@ -4878,12 +4906,13 @@ async function uploadFile(filePath, deviceId) {
|
|
|
4878
4906
|
shortUrl: fileItem.ShortUrl || null
|
|
4879
4907
|
};
|
|
4880
4908
|
saveUploadHistory(uploadData);
|
|
4909
|
+
smartProgress.complete(trace_id);
|
|
4881
4910
|
return {
|
|
4882
4911
|
hash: fileItem.Hash,
|
|
4883
4912
|
shortUrl: fileItem.ShortUrl
|
|
4884
4913
|
};
|
|
4885
4914
|
}
|
|
4886
|
-
|
|
4915
|
+
smartProgress.fail("File hash not found in response", trace_id);
|
|
4887
4916
|
console.log(
|
|
4888
4917
|
import_chalk2.default.red(`
|
|
4889
4918
|
\u274C File upload failed: File hash not found in response`)
|
|
@@ -4902,10 +4931,10 @@ async function uploadFile(filePath, deviceId) {
|
|
|
4902
4931
|
console.log(import_chalk2.default.gray(` 2. Check network connection stability`));
|
|
4903
4932
|
console.log(import_chalk2.default.gray(` 3. Try uploading a smaller file for testing`));
|
|
4904
4933
|
} catch (error) {
|
|
4905
|
-
clearInterval(
|
|
4934
|
+
clearInterval(progressInterval);
|
|
4906
4935
|
if (error.message && error.message.includes("multipart")) {
|
|
4907
4936
|
const errorMessage = handleMultipartError(error, `File upload: ${fileName}`);
|
|
4908
|
-
|
|
4937
|
+
smartProgress.fail(errorMessage);
|
|
4909
4938
|
console.log(import_chalk2.default.red(`
|
|
4910
4939
|
\u274C ${errorMessage}`));
|
|
4911
4940
|
return null;
|
|
@@ -4913,40 +4942,136 @@ async function uploadFile(filePath, deviceId) {
|
|
|
4913
4942
|
if (error.response && error.response.data && error.response.data.code) {
|
|
4914
4943
|
const errorCode = error.response.data.code.toString();
|
|
4915
4944
|
if (ERROR_CODES[errorCode]) {
|
|
4916
|
-
|
|
4945
|
+
smartProgress.fail(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`);
|
|
4917
4946
|
console.log(
|
|
4918
4947
|
import_chalk2.default.red(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`)
|
|
4919
4948
|
);
|
|
4920
4949
|
return null;
|
|
4921
4950
|
}
|
|
4922
4951
|
}
|
|
4923
|
-
|
|
4952
|
+
smartProgress.fail(`Error: ${error.message}`);
|
|
4924
4953
|
console.log(import_chalk2.default.red(`Error: ${error.message}`));
|
|
4925
4954
|
return null;
|
|
4926
4955
|
}
|
|
4927
4956
|
}
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4957
|
+
var SmartProgressBar = class {
|
|
4958
|
+
timeConstant;
|
|
4959
|
+
startTime;
|
|
4960
|
+
uploadStartTime;
|
|
4961
|
+
isUploading;
|
|
4962
|
+
isPolling;
|
|
4963
|
+
fileCount;
|
|
4964
|
+
totalSize;
|
|
4965
|
+
spinner;
|
|
4966
|
+
fileName;
|
|
4967
|
+
isCompleted;
|
|
4968
|
+
// Add completion flag
|
|
4969
|
+
constructor(fileName, fileCount, totalSize, spinner) {
|
|
4970
|
+
this.fileName = fileName;
|
|
4971
|
+
this.fileCount = fileCount;
|
|
4972
|
+
this.totalSize = totalSize;
|
|
4973
|
+
this.spinner = spinner;
|
|
4974
|
+
this.timeConstant = this.calcTimeConstant(fileCount, totalSize);
|
|
4975
|
+
this.startTime = Date.now();
|
|
4976
|
+
this.uploadStartTime = 0;
|
|
4977
|
+
this.isUploading = false;
|
|
4978
|
+
this.isPolling = false;
|
|
4979
|
+
this.isCompleted = false;
|
|
4980
|
+
}
|
|
4981
|
+
// Calculate time constant based on file count and total size
|
|
4982
|
+
calcTimeConstant(fileCount, totalSize) {
|
|
4983
|
+
const base = 8e3;
|
|
4984
|
+
const countFactor = 0.3 * Math.log(1 + fileCount);
|
|
4985
|
+
const sizeFactor = 0.7 * Math.log(1 + totalSize / 1024 / 1024);
|
|
4986
|
+
const minTimeConstant = 15e3;
|
|
4987
|
+
const calculatedTimeConstant = base * (1 + countFactor + sizeFactor);
|
|
4988
|
+
return Math.max(calculatedTimeConstant, minTimeConstant);
|
|
4989
|
+
}
|
|
4990
|
+
// Calculate progress using exponential decay model with upper limit
|
|
4991
|
+
calculateProgress() {
|
|
4992
|
+
const elapsed = Date.now() - this.startTime;
|
|
4993
|
+
const rawProgress = 1 - Math.exp(-elapsed / this.timeConstant);
|
|
4994
|
+
const maxProgress = this.isPolling ? 0.95 : 0.9;
|
|
4995
|
+
return Math.min(rawProgress, maxProgress);
|
|
4996
|
+
}
|
|
4997
|
+
// Start upload phase
|
|
4998
|
+
startUpload() {
|
|
4999
|
+
this.isUploading = true;
|
|
5000
|
+
this.uploadStartTime = Date.now();
|
|
5001
|
+
}
|
|
5002
|
+
// Start polling phase
|
|
5003
|
+
startPolling() {
|
|
5004
|
+
this.isPolling = true;
|
|
5005
|
+
this.isUploading = false;
|
|
5006
|
+
}
|
|
5007
|
+
// Update progress display
|
|
5008
|
+
update() {
|
|
5009
|
+
if (this.isCompleted) {
|
|
5010
|
+
return;
|
|
5011
|
+
}
|
|
5012
|
+
const progress = this.calculateProgress();
|
|
5013
|
+
const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
|
|
5014
|
+
const progressBar = this.createProgressBar(progress);
|
|
5015
|
+
const duration = this.formatDuration(elapsed);
|
|
5016
|
+
let status = "";
|
|
5017
|
+
if (this.isUploading) {
|
|
5018
|
+
status = "uploading";
|
|
5019
|
+
} else if (this.isPolling) {
|
|
5020
|
+
status = "processing";
|
|
5021
|
+
} else {
|
|
5022
|
+
status = "preparing";
|
|
5023
|
+
}
|
|
5024
|
+
const fileInfo = this.fileCount > 1 ? `${this.fileName} (${this.fileCount} files)` : this.fileName;
|
|
5025
|
+
this.spinner.text = `Uploading ${fileInfo} ${progressBar} ${duration} (${status})`;
|
|
4948
5026
|
}
|
|
4949
|
-
|
|
5027
|
+
// Complete progress
|
|
5028
|
+
complete(traceId) {
|
|
5029
|
+
if (this.isCompleted) {
|
|
5030
|
+
return;
|
|
5031
|
+
}
|
|
5032
|
+
const progressBar = this.createProgressBar(1);
|
|
5033
|
+
const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
|
|
5034
|
+
const duration = this.formatDuration(elapsed);
|
|
5035
|
+
const traceInfo = traceId ? ` (trace_id: ${traceId})` : "";
|
|
5036
|
+
this.spinner.succeed(`Upload completed ${progressBar} ${duration}${traceInfo}`);
|
|
5037
|
+
this.isCompleted = true;
|
|
5038
|
+
}
|
|
5039
|
+
// Fail progress
|
|
5040
|
+
fail(message, traceId) {
|
|
5041
|
+
if (this.isCompleted) {
|
|
5042
|
+
return;
|
|
5043
|
+
}
|
|
5044
|
+
const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
|
|
5045
|
+
const duration = this.formatDuration(elapsed);
|
|
5046
|
+
const traceInfo = traceId ? ` (trace_id: ${traceId})` : "";
|
|
5047
|
+
this.spinner.fail(`${message} ${duration}${traceInfo}`);
|
|
5048
|
+
this.isCompleted = true;
|
|
5049
|
+
}
|
|
5050
|
+
// Create visual progress bar
|
|
5051
|
+
createProgressBar(progress, width = 20) {
|
|
5052
|
+
const percentage = Math.min(progress, 1);
|
|
5053
|
+
const filledWidth = Math.round(width * percentage);
|
|
5054
|
+
const emptyWidth = width - filledWidth;
|
|
5055
|
+
const filled = "\u2588".repeat(filledWidth);
|
|
5056
|
+
const empty = "\u2591".repeat(emptyWidth);
|
|
5057
|
+
return `[${filled}${empty}] ${Math.round(percentage * 100)}%`;
|
|
5058
|
+
}
|
|
5059
|
+
// Format time duration
|
|
5060
|
+
formatDuration(seconds) {
|
|
5061
|
+
if (seconds < 60) {
|
|
5062
|
+
return `${seconds}s`;
|
|
5063
|
+
} else if (seconds < 3600) {
|
|
5064
|
+
const minutes = Math.floor(seconds / 60);
|
|
5065
|
+
const remainingSeconds = seconds % 60;
|
|
5066
|
+
return `${minutes}m ${remainingSeconds}s`;
|
|
5067
|
+
} else {
|
|
5068
|
+
const hours = Math.floor(seconds / 3600);
|
|
5069
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
5070
|
+
const remainingSeconds = seconds % 60;
|
|
5071
|
+
return `${hours}h ${minutes}m ${remainingSeconds}s`;
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
5074
|
+
};
|
|
4950
5075
|
async function uploadToIpfs_default(filePath) {
|
|
4951
5076
|
const deviceId = getDeviceId();
|
|
4952
5077
|
if (!deviceId) {
|