gitxelectron 1.2.6 → 1.2.7
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/out/main/index.js +231 -19
- package/out/preload/index.js +4 -0
- package/out/renderer/assets/{index-C-5ryxXi.js → index-CHyCU0WO.js} +78 -1
- package/out/renderer/assets/index-IDBlHWWX.css +1365 -0
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/out/renderer/assets/index-ByoEJy2t.css +0 -1365
package/out/main/index.js
CHANGED
|
@@ -4,6 +4,8 @@ const path = require("path");
|
|
|
4
4
|
const fs = require("fs/promises");
|
|
5
5
|
const simpleGit = require("simple-git");
|
|
6
6
|
const crypto = require("crypto");
|
|
7
|
+
const child_process = require("child_process");
|
|
8
|
+
const readline = require("readline");
|
|
7
9
|
const generativeAi = require("@google/generative-ai");
|
|
8
10
|
const OpenAI = require("openai");
|
|
9
11
|
const chokidar = require("chokidar");
|
|
@@ -26,6 +28,7 @@ function _interopNamespaceDefault(e) {
|
|
|
26
28
|
}
|
|
27
29
|
const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
|
|
28
30
|
const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
|
|
31
|
+
const readline__namespace = /* @__PURE__ */ _interopNamespaceDefault(readline);
|
|
29
32
|
const GITHUB_CLIENT_ID = "Ov23livWfiaPADGiwSXq";
|
|
30
33
|
let accounts = [];
|
|
31
34
|
const activeSessions = /* @__PURE__ */ new Map();
|
|
@@ -690,9 +693,56 @@ async function initializeRepo(sessionId, dir) {
|
|
|
690
693
|
}
|
|
691
694
|
}
|
|
692
695
|
async function getStatus(sessionId) {
|
|
693
|
-
const { git } = getGitSession(sessionId);
|
|
694
|
-
|
|
695
|
-
|
|
696
|
+
const { git, repoPath } = getGitSession(sessionId);
|
|
697
|
+
return new Promise((resolve, reject) => {
|
|
698
|
+
const child = child_process.spawn("git", ["status", "--porcelain"], { cwd: repoPath });
|
|
699
|
+
let count = 0;
|
|
700
|
+
let isMassive = false;
|
|
701
|
+
child.stdout.on("data", (chunk) => {
|
|
702
|
+
for (let i = 0; i < chunk.length; ++i) {
|
|
703
|
+
if (chunk[i] === 10) {
|
|
704
|
+
count++;
|
|
705
|
+
if (count > 1e4) {
|
|
706
|
+
isMassive = true;
|
|
707
|
+
child.kill();
|
|
708
|
+
break;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
});
|
|
713
|
+
child.on("close", async () => {
|
|
714
|
+
if (isMassive) {
|
|
715
|
+
resolve({
|
|
716
|
+
not_added: [],
|
|
717
|
+
created: [],
|
|
718
|
+
deleted: [],
|
|
719
|
+
modified: [],
|
|
720
|
+
conflicted: [],
|
|
721
|
+
renamed: [],
|
|
722
|
+
staged: [],
|
|
723
|
+
files: [],
|
|
724
|
+
current: "main",
|
|
725
|
+
ahead: 0,
|
|
726
|
+
behind: 0,
|
|
727
|
+
tracking: null,
|
|
728
|
+
isMassive: true,
|
|
729
|
+
totalChanges: count
|
|
730
|
+
});
|
|
731
|
+
} else {
|
|
732
|
+
try {
|
|
733
|
+
const status = await git.status();
|
|
734
|
+
const result = JSON.parse(JSON.stringify(status));
|
|
735
|
+
result.isMassive = false;
|
|
736
|
+
result.totalChanges = count;
|
|
737
|
+
if (!result.staged) result.staged = [];
|
|
738
|
+
resolve(result);
|
|
739
|
+
} catch (e) {
|
|
740
|
+
reject(e);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
child.on("error", reject);
|
|
745
|
+
});
|
|
696
746
|
}
|
|
697
747
|
async function stageFiles(sessionId, files) {
|
|
698
748
|
const { git, repoPath } = getGitSession(sessionId);
|
|
@@ -727,7 +777,15 @@ async function stageFiles(sessionId, files) {
|
|
|
727
777
|
const chunkSize = 50;
|
|
728
778
|
for (let i = 0; i < fileArray.length; i += chunkSize) {
|
|
729
779
|
const chunk = fileArray.slice(i, i + chunkSize);
|
|
730
|
-
|
|
780
|
+
try {
|
|
781
|
+
await git.raw(["-c", "core.safecrlf=false", "-c", "core.autocrlf=false", "add", "--force", ...chunk]);
|
|
782
|
+
} catch (e) {
|
|
783
|
+
if (e.message && e.message.includes("LF will be replaced by CRLF") && !e.message.includes("fatal:")) {
|
|
784
|
+
console.warn("Ignored CRLF warning during stage");
|
|
785
|
+
} else {
|
|
786
|
+
throw e;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
731
789
|
}
|
|
732
790
|
return true;
|
|
733
791
|
}
|
|
@@ -779,6 +837,123 @@ function injectAuthToken(sessionId, remoteUrl) {
|
|
|
779
837
|
}
|
|
780
838
|
return remoteUrl;
|
|
781
839
|
}
|
|
840
|
+
async function pushMassiveRepository(sessionId, remote, branch, chunkSize = 5e3, onProgress, onDetailedProgress) {
|
|
841
|
+
const { repoPath } = getGitSession(sessionId);
|
|
842
|
+
if (onProgress) onProgress("Starting rapid file count to prepare massive chunking...");
|
|
843
|
+
const totalFiles = await new Promise((resolve) => {
|
|
844
|
+
const child2 = child_process.spawn("git", ["status", "--porcelain"], { cwd: repoPath });
|
|
845
|
+
let count = 0;
|
|
846
|
+
child2.stdout.on("data", (chunk) => {
|
|
847
|
+
for (let i = 0; i < chunk.length; ++i) {
|
|
848
|
+
if (chunk[i] === 10) count++;
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
child2.on("close", () => resolve(count));
|
|
852
|
+
child2.on("error", () => resolve(0));
|
|
853
|
+
});
|
|
854
|
+
if (totalFiles === 0) {
|
|
855
|
+
if (onProgress) onProgress("No files to push.");
|
|
856
|
+
return true;
|
|
857
|
+
}
|
|
858
|
+
if (onProgress) onProgress(`Total files to push: ${totalFiles}. Starting chunked upload...`);
|
|
859
|
+
const { git } = getGitSession(sessionId);
|
|
860
|
+
const remotes = await getRemotes(sessionId);
|
|
861
|
+
const remoteObj = remotes.find((r) => r.name === remote);
|
|
862
|
+
if (onProgress) onProgress("Starting massive repository push...");
|
|
863
|
+
await git.addConfig("http.postBuffer", "1048576000");
|
|
864
|
+
await git.addConfig("core.safecrlf", "false");
|
|
865
|
+
await git.addConfig("core.autocrlf", "false");
|
|
866
|
+
let authUrl = remote;
|
|
867
|
+
if (remoteObj && remoteObj.refs.push) {
|
|
868
|
+
authUrl = injectAuthToken(sessionId, remoteObj.refs.push);
|
|
869
|
+
}
|
|
870
|
+
const child = child_process.spawn("git", ["status", "--porcelain"], { cwd: repoPath });
|
|
871
|
+
const rl = readline__namespace.createInterface({
|
|
872
|
+
input: child.stdout,
|
|
873
|
+
crlfDelay: Infinity
|
|
874
|
+
});
|
|
875
|
+
let currentChunk = [];
|
|
876
|
+
let chunkCount = 0;
|
|
877
|
+
let processedFiles = 0;
|
|
878
|
+
const startTime = Date.now();
|
|
879
|
+
const processChunk = async (chunk) => {
|
|
880
|
+
chunkCount++;
|
|
881
|
+
processedFiles += chunk.length;
|
|
882
|
+
const percentage = Math.min(100, processedFiles / totalFiles * 100);
|
|
883
|
+
const elapsedMs = Date.now() - startTime;
|
|
884
|
+
const msPerFile = elapsedMs / processedFiles;
|
|
885
|
+
const remainingFiles = totalFiles - processedFiles;
|
|
886
|
+
const etaMs = msPerFile * remainingFiles;
|
|
887
|
+
const formatEta = (ms) => {
|
|
888
|
+
if (!isFinite(ms) || ms < 0) return "calculating...";
|
|
889
|
+
const totalSec = Math.floor(ms / 1e3);
|
|
890
|
+
const min = Math.floor(totalSec / 60);
|
|
891
|
+
const sec = totalSec % 60;
|
|
892
|
+
if (min > 0) return `${min}m ${sec}s left`;
|
|
893
|
+
return `${sec}s left`;
|
|
894
|
+
};
|
|
895
|
+
const etaStr = formatEta(etaMs);
|
|
896
|
+
if (onProgress) onProgress(`Processing chunk ${chunkCount} (${chunk.length} files)... ETA: ${etaStr}`);
|
|
897
|
+
if (onDetailedProgress) {
|
|
898
|
+
onDetailedProgress({
|
|
899
|
+
processed: processedFiles,
|
|
900
|
+
total: totalFiles,
|
|
901
|
+
percentage,
|
|
902
|
+
eta: etaStr
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
const tempFile = path__namespace.join(repoPath, ".git", "massive_chunk.txt");
|
|
906
|
+
await fs__namespace.writeFile(tempFile, chunk.join("\n"), "utf-8");
|
|
907
|
+
try {
|
|
908
|
+
await git.raw(["-c", "core.safecrlf=false", "add", "--force", "--pathspec-from-file=" + tempFile]);
|
|
909
|
+
} catch (e) {
|
|
910
|
+
if (e.message && e.message.includes("fatal:")) {
|
|
911
|
+
throw e;
|
|
912
|
+
}
|
|
913
|
+
} finally {
|
|
914
|
+
try {
|
|
915
|
+
await fs__namespace.unlink(tempFile);
|
|
916
|
+
} catch (e) {
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
try {
|
|
920
|
+
await git.commit(`Auto-sync chunk ${chunkCount} (Massive Push)`);
|
|
921
|
+
} catch (e) {
|
|
922
|
+
}
|
|
923
|
+
try {
|
|
924
|
+
await git.raw(["-c", "credential.helper=", "push", authUrl, branch]);
|
|
925
|
+
} catch (err) {
|
|
926
|
+
if (err.message && (err.message.includes("non-fast-forward") || err.message.includes("fetch first") || err.message.includes("branch is behind"))) {
|
|
927
|
+
await git.pull(authUrl, branch, { "--rebase": null, "--autostash": null });
|
|
928
|
+
await git.raw(["-c", "credential.helper=", "push", authUrl, branch]);
|
|
929
|
+
} else {
|
|
930
|
+
if (err.message && !err.message.includes("nothing to commit")) {
|
|
931
|
+
throw err;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
for await (const line of rl) {
|
|
937
|
+
if (line.length < 3) continue;
|
|
938
|
+
let file = line.substring(3).trim();
|
|
939
|
+
if (file.startsWith('"') && file.endsWith('"')) {
|
|
940
|
+
file = file.substring(1, file.length - 1);
|
|
941
|
+
}
|
|
942
|
+
if (!file) continue;
|
|
943
|
+
currentChunk.push(file);
|
|
944
|
+
if (currentChunk.length >= chunkSize) {
|
|
945
|
+
rl.pause();
|
|
946
|
+
await processChunk(currentChunk);
|
|
947
|
+
currentChunk = [];
|
|
948
|
+
rl.resume();
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
if (currentChunk.length > 0) {
|
|
952
|
+
await processChunk(currentChunk);
|
|
953
|
+
}
|
|
954
|
+
if (onProgress) onProgress("✅ Massive push completed successfully!");
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
782
957
|
async function pushToRemote(sessionId, remote, branch) {
|
|
783
958
|
const remotes = await getRemotes(sessionId);
|
|
784
959
|
const remoteObj = remotes.find((r) => r.name === remote);
|
|
@@ -1127,7 +1302,15 @@ async function commitUniversalWorkspace(workspacePath, message, branch) {
|
|
|
1127
1302
|
GIT_TERMINAL_PROMPT: "0",
|
|
1128
1303
|
GIT_ASKPASS: "echo"
|
|
1129
1304
|
});
|
|
1130
|
-
|
|
1305
|
+
try {
|
|
1306
|
+
await git.raw(["-c", "core.safecrlf=false", "-c", "core.autocrlf=false", "add", "--sparse", "."]);
|
|
1307
|
+
} catch (e) {
|
|
1308
|
+
if (e.message && e.message.includes("LF will be replaced by CRLF") && !e.message.includes("fatal:")) {
|
|
1309
|
+
console.warn("Ignored CRLF warning in universal workspace");
|
|
1310
|
+
} else {
|
|
1311
|
+
throw e;
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1131
1314
|
await git.commit(message);
|
|
1132
1315
|
try {
|
|
1133
1316
|
await git.raw(["-c", "credential.helper=", "push", "origin", branch]);
|
|
@@ -1517,13 +1700,15 @@ let isResolving = false;
|
|
|
1517
1700
|
let globalOnLog = null;
|
|
1518
1701
|
let globalOnErrorApproval = null;
|
|
1519
1702
|
let globalOnResolveComplete = null;
|
|
1703
|
+
let globalOnMassiveProgress = null;
|
|
1520
1704
|
const DEBOUNCE_MS = 3e3;
|
|
1521
1705
|
const changedFiles = /* @__PURE__ */ new Set();
|
|
1522
|
-
function toggleAutoSync(sessionId, repoPath, enabled, onLog, onErrorApproval, onResolveComplete) {
|
|
1706
|
+
function toggleAutoSync(sessionId, repoPath, enabled, onLog, onErrorApproval, onResolveComplete, onMassiveProgress) {
|
|
1523
1707
|
isAutoSyncEnabled = enabled;
|
|
1524
1708
|
globalOnLog = onLog;
|
|
1525
1709
|
if (onErrorApproval) globalOnErrorApproval = onErrorApproval;
|
|
1526
1710
|
if (onResolveComplete) globalOnResolveComplete = onResolveComplete;
|
|
1711
|
+
if (onMassiveProgress) globalOnMassiveProgress = onMassiveProgress;
|
|
1527
1712
|
if (currentWatcher) {
|
|
1528
1713
|
currentWatcher.close();
|
|
1529
1714
|
currentWatcher = null;
|
|
@@ -1553,7 +1738,11 @@ function toggleAutoSync(sessionId, repoPath, enabled, onLog, onErrorApproval, on
|
|
|
1553
1738
|
currentWatcher.on("all", (_event, filePath) => {
|
|
1554
1739
|
if (!isAutoSyncEnabled || isResolving) return;
|
|
1555
1740
|
const relativePath = path__namespace.relative(repoPath, filePath).replace(/\\/g, "/");
|
|
1556
|
-
changedFiles.
|
|
1741
|
+
if (changedFiles.size < 1e4) {
|
|
1742
|
+
changedFiles.add(relativePath);
|
|
1743
|
+
} else if (!changedFiles.has("__MASSIVE__")) {
|
|
1744
|
+
changedFiles.add("__MASSIVE__");
|
|
1745
|
+
}
|
|
1557
1746
|
if (syncTimeout) {
|
|
1558
1747
|
clearTimeout(syncTimeout);
|
|
1559
1748
|
}
|
|
@@ -1574,9 +1763,29 @@ async function triggerSyncSequence(sessionId, _repoPath, onLog) {
|
|
|
1574
1763
|
onLog("No valid files to sync (temp files filtered).");
|
|
1575
1764
|
return;
|
|
1576
1765
|
}
|
|
1577
|
-
|
|
1766
|
+
if (changedFiles.has("__MASSIVE__")) {
|
|
1767
|
+
onLog("Massive file changes detected in watcher. Checking status...");
|
|
1768
|
+
}
|
|
1578
1769
|
const status = await getStatus(sessionId);
|
|
1579
|
-
|
|
1770
|
+
if (status.isMassive) {
|
|
1771
|
+
onLog(`🚨 Massive repository change detected! Engaging chunked sync mode...`);
|
|
1772
|
+
const branch2 = status.current || "main";
|
|
1773
|
+
const success = await pushMassiveRepository(
|
|
1774
|
+
sessionId,
|
|
1775
|
+
"origin",
|
|
1776
|
+
branch2,
|
|
1777
|
+
5e3,
|
|
1778
|
+
onLog,
|
|
1779
|
+
globalOnMassiveProgress || void 0
|
|
1780
|
+
);
|
|
1781
|
+
if (success) {
|
|
1782
|
+
onLog(`✅ Successfully pushed massive repository sync!`);
|
|
1783
|
+
}
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
await stageFiles(sessionId, existingFiles);
|
|
1787
|
+
const finalStatus = await getStatus(sessionId);
|
|
1788
|
+
const branch = finalStatus.current || "main";
|
|
1580
1789
|
onLog("Generating AI commit message...");
|
|
1581
1790
|
let commitMsg = `Auto-sync: update ${filesToSync.length > 1 ? filesToSync.length + " files" : filesToSync[0]}`;
|
|
1582
1791
|
try {
|
|
@@ -1688,7 +1897,15 @@ async function applyAiFixAndResume(sessionId, resolvedCode) {
|
|
|
1688
1897
|
if (resolvedCode) {
|
|
1689
1898
|
for (const [file, content] of Object.entries(resolvedCode)) {
|
|
1690
1899
|
await fs__namespace.writeFile(path__namespace.join(repoPath, file), content, "utf-8");
|
|
1691
|
-
|
|
1900
|
+
try {
|
|
1901
|
+
await git.raw(["-c", "core.safecrlf=false", "-c", "core.autocrlf=false", "add", "--force", file]);
|
|
1902
|
+
} catch (e) {
|
|
1903
|
+
if (e.message && e.message.includes("LF will be replaced by CRLF") && !e.message.includes("fatal:")) {
|
|
1904
|
+
console.warn("Ignored CRLF warning during AI fix apply");
|
|
1905
|
+
} else {
|
|
1906
|
+
throw e;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1692
1909
|
}
|
|
1693
1910
|
}
|
|
1694
1911
|
try {
|
|
@@ -2073,15 +2290,10 @@ electron.app.whenReady().then(async () => {
|
|
|
2073
2290
|
event.sender.id,
|
|
2074
2291
|
repoPath,
|
|
2075
2292
|
enabled,
|
|
2076
|
-
(msg) =>
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
(
|
|
2080
|
-
event.sender.send("auto-sync-error-approval", payload);
|
|
2081
|
-
},
|
|
2082
|
-
() => {
|
|
2083
|
-
event.sender.send("auto-sync-resolved");
|
|
2084
|
-
}
|
|
2293
|
+
(msg) => event.sender.send("auto-sync-log", msg),
|
|
2294
|
+
(payload) => event.sender.send("auto-sync-error-approval", payload),
|
|
2295
|
+
() => event.sender.send("auto-sync-resolved"),
|
|
2296
|
+
(data) => event.sender.send("massive-push-progress", data)
|
|
2085
2297
|
);
|
|
2086
2298
|
});
|
|
2087
2299
|
electron.ipcMain.handle("approve-ai-fix", async (event, resolvedCode) => {
|
package/out/preload/index.js
CHANGED
|
@@ -93,6 +93,10 @@ const api = {
|
|
|
93
93
|
electron.ipcRenderer.removeAllListeners("auto-sync-resolved");
|
|
94
94
|
electron.ipcRenderer.on("auto-sync-resolved", () => callback());
|
|
95
95
|
},
|
|
96
|
+
onMassivePushProgress: (callback) => {
|
|
97
|
+
electron.ipcRenderer.removeAllListeners("massive-push-progress");
|
|
98
|
+
electron.ipcRenderer.on("massive-push-progress", (_event, data) => callback(data));
|
|
99
|
+
},
|
|
96
100
|
getAppVersion: () => electron.ipcRenderer.invoke("get-app-version"),
|
|
97
101
|
// AI Fixer API
|
|
98
102
|
askAi: (provider, apiKey, errorMsg, gitStatus, repoPath) => electron.ipcRenderer.invoke("ask-ai", provider, apiKey, errorMsg, gitStatus, repoPath),
|
|
@@ -24165,6 +24165,70 @@ const CommitReceiptPrinter = ({ commit, onClose }) => {
|
|
|
24165
24165
|
] }) })
|
|
24166
24166
|
] });
|
|
24167
24167
|
};
|
|
24168
|
+
const MassivePushLoader = ({ percentage, eta }) => {
|
|
24169
|
+
const clampedPercentage = Math.min(100, Math.max(0, percentage));
|
|
24170
|
+
const check1 = clampedPercentage >= 33;
|
|
24171
|
+
const check2 = clampedPercentage >= 66;
|
|
24172
|
+
const check3 = clampedPercentage >= 99;
|
|
24173
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center space-y-6 py-12", children: [
|
|
24174
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-primary mb-2", children: [
|
|
24175
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold", children: "Massive Push in Progress" }),
|
|
24176
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm opacity-70", children: "Chunking thousands of files to prevent freezing" })
|
|
24177
|
+
] }),
|
|
24178
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative bg-[#3a3a3a] rounded-full h-4 w-[330px] shadow-inner", children: [
|
|
24179
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24180
|
+
"div",
|
|
24181
|
+
{
|
|
24182
|
+
className: "absolute left-0 top-0 h-full rounded-full transition-all duration-500 ease-out",
|
|
24183
|
+
style: {
|
|
24184
|
+
width: `${clampedPercentage}%`,
|
|
24185
|
+
backgroundColor: "var(--color-brand, #00cd00)"
|
|
24186
|
+
}
|
|
24187
|
+
}
|
|
24188
|
+
),
|
|
24189
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute -top-1 left-0 z-10 flex w-full justify-between px-1", children: [
|
|
24190
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6" }),
|
|
24191
|
+
" ",
|
|
24192
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Checkmark, { active: check1 }),
|
|
24193
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Checkmark, { active: check2 }),
|
|
24194
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Checkmark, { active: check3 })
|
|
24195
|
+
] })
|
|
24196
|
+
] }),
|
|
24197
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-primary mt-4", children: [
|
|
24198
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "font-semibold text-2xl", children: [
|
|
24199
|
+
clampedPercentage.toFixed(1),
|
|
24200
|
+
"%"
|
|
24201
|
+
] }),
|
|
24202
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-md opacity-80 mt-1", children: [
|
|
24203
|
+
"ETA: ",
|
|
24204
|
+
eta
|
|
24205
|
+
] })
|
|
24206
|
+
] })
|
|
24207
|
+
] });
|
|
24208
|
+
};
|
|
24209
|
+
const Checkmark = ({ active }) => {
|
|
24210
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24211
|
+
"div",
|
|
24212
|
+
{
|
|
24213
|
+
className: `rounded-full h-6 w-6 p-[3px] transition-all duration-500 flex items-center justify-center shadow-md ${active ? "scale-110" : "scale-90"}`,
|
|
24214
|
+
style: {
|
|
24215
|
+
backgroundColor: active ? "var(--color-brand, #00cd00)" : "#535353",
|
|
24216
|
+
opacity: active ? 1 : 0.5
|
|
24217
|
+
},
|
|
24218
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24219
|
+
"svg",
|
|
24220
|
+
{
|
|
24221
|
+
stroke: "white",
|
|
24222
|
+
strokeWidth: 3,
|
|
24223
|
+
viewBox: "0 0 24 24",
|
|
24224
|
+
fill: "none",
|
|
24225
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
24226
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "m4.5 12.75 6 6 9-13.5", strokeLinejoin: "round", strokeLinecap: "round" })
|
|
24227
|
+
}
|
|
24228
|
+
)
|
|
24229
|
+
}
|
|
24230
|
+
);
|
|
24231
|
+
};
|
|
24168
24232
|
const translations = {
|
|
24169
24233
|
en: {
|
|
24170
24234
|
settings: "Settings",
|
|
@@ -24745,6 +24809,7 @@ function App() {
|
|
|
24745
24809
|
const [conflictQueue, setConflictQueue] = reactExports.useState([]);
|
|
24746
24810
|
const [autoSyncErrorPayload, setAutoSyncErrorPayload] = reactExports.useState(null);
|
|
24747
24811
|
const [failedFiles, setFailedFiles] = reactExports.useState([]);
|
|
24812
|
+
const [massivePushData, setMassivePushData] = reactExports.useState(null);
|
|
24748
24813
|
const [isLocked, setIsLocked] = reactExports.useState(true);
|
|
24749
24814
|
const [storedPin, setStoredPin] = reactExports.useState(localStorage.getItem("gitelectron-pin"));
|
|
24750
24815
|
const [pinInput, setPinInput] = reactExports.useState("");
|
|
@@ -25115,6 +25180,11 @@ function App() {
|
|
|
25115
25180
|
setFailedFiles([]);
|
|
25116
25181
|
refreshRepoState();
|
|
25117
25182
|
});
|
|
25183
|
+
if (window.api.onMassivePushProgress) {
|
|
25184
|
+
window.api.onMassivePushProgress((data) => {
|
|
25185
|
+
setMassivePushData(data);
|
|
25186
|
+
});
|
|
25187
|
+
}
|
|
25118
25188
|
}, []);
|
|
25119
25189
|
const handleToggleAutoSync = () => {
|
|
25120
25190
|
const next = !autoSyncEnabled;
|
|
@@ -26586,6 +26656,7 @@ function App() {
|
|
|
26586
26656
|
onReplace: handleConflictReplace
|
|
26587
26657
|
}
|
|
26588
26658
|
),
|
|
26659
|
+
showUniversalWizard && /* @__PURE__ */ jsxRuntimeExports.jsx(UniversalPushWizard, { isOpen: showUniversalWizard, onClose: () => setShowUniversalWizard(false) }),
|
|
26589
26660
|
showSetupWizard && repoPath && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
26590
26661
|
RepositoryWizard,
|
|
26591
26662
|
{
|
|
@@ -27534,7 +27605,13 @@ function App() {
|
|
|
27534
27605
|
)
|
|
27535
27606
|
] })
|
|
27536
27607
|
] }),
|
|
27537
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
27608
|
+
status?.isMassive ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col items-center justify-center p-8 bg-canvas", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
27609
|
+
MassivePushLoader,
|
|
27610
|
+
{
|
|
27611
|
+
percentage: massivePushData?.percentage || 0,
|
|
27612
|
+
eta: massivePushData?.eta || "calculating..."
|
|
27613
|
+
}
|
|
27614
|
+
) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-auto p-4 custom-scrollbar", children: [
|
|
27538
27615
|
changesTab === "changes" && /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "space-y-1", children: [
|
|
27539
27616
|
status.conflicted.map((f) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
27540
27617
|
"li",
|