gitxelectron 1.2.7 → 1.2.9

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.
@@ -12540,6 +12540,180 @@ function Loader() {
12540
12540
  /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "680", cy: "340", r: "5", fill: "black" })
12541
12541
  ] }) }) });
12542
12542
  }
12543
+ const MassivePushLoader = ({ percentage, eta, hideHeader, compact }) => {
12544
+ const isIndeterminate = percentage < 0;
12545
+ const clampedPercentage = isIndeterminate ? 0 : Math.min(100, Math.max(0, percentage));
12546
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex flex-col items-center justify-center w-full h-full ${compact ? "" : "space-y-8 py-8"}`, children: [
12547
+ !hideHeader && !compact && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-primary mb-4 relative z-10", children: [
12548
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold", children: "Massive Push in Progress" }),
12549
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm opacity-70 mt-1", children: "Chunking thousands of files to prevent freezing" })
12550
+ ] }),
12551
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `loader-wrapper ${compact ? "is-compact" : ""}`, children: [
12552
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "loader", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "box", children: [
12553
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "top-side" }),
12554
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bottom-side" }),
12555
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "screen", children: [
12556
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "lightray-limit", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "lightray" }) }),
12557
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "loader-box-container", children: [
12558
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "loader-progress-box", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
12559
+ "div",
12560
+ {
12561
+ className: `progress-bar-fill transition-all duration-300 ease-out ${isIndeterminate ? "indeterminate-progress" : ""}`,
12562
+ style: { width: isIndeterminate ? "0%" : `${clampedPercentage}%` }
12563
+ }
12564
+ ) }),
12565
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex flex-col items-center mt-2 text-primary font-mono drop-shadow-md ${compact ? "scale-95" : ""}`, children: [
12566
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `${compact ? "text-2xl" : "text-3xl mt-2"} font-bold`, children: isIndeterminate ? ". . ." : `${clampedPercentage.toFixed(1)}%` }),
12567
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `${compact ? "text-xs" : "text-xs"} opacity-90 mt-1 font-semibold`, children: eta })
12568
+ ] })
12569
+ ] })
12570
+ ] })
12571
+ ] }) }),
12572
+ /* @__PURE__ */ jsxRuntimeExports.jsx("style", { children: `
12573
+ .loader-wrapper .loader .box {
12574
+ background-color: var(--color-surface-hover);
12575
+ width: var(--size, 240px);
12576
+ height: var(--size, 240px);
12577
+ padding: var(--pad, 20px);
12578
+ border-radius: 50%;
12579
+ border: var(--border-w, 5px) solid var(--color-border);
12580
+ position: relative;
12581
+ overflow: hidden;
12582
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3), inset 0 5px 15px rgba(0,0,0,0.2);
12583
+ transform: rotate(-45deg);
12584
+ margin: 0 auto;
12585
+ }
12586
+
12587
+ .loader-wrapper.is-compact {
12588
+ --size: 180px;
12589
+ --pad: 15px;
12590
+ --border-w: 4px;
12591
+ --top-offset: 40px;
12592
+ --bottom-offset: 45px;
12593
+ --screen-pad: 8px;
12594
+ --prog-pad: 3px;
12595
+ --prog-h: 6px;
12596
+ }
12597
+
12598
+ .loader-wrapper:not(.is-compact) {
12599
+ --top-offset: 50px;
12600
+ --bottom-offset: 60px;
12601
+ --screen-pad: 10px;
12602
+ --prog-pad: 4px;
12603
+ --prog-h: 8px;
12604
+ }
12605
+
12606
+ .loader-wrapper .loader .box .screen {
12607
+ position: absolute;
12608
+ top: 50%;
12609
+ left: 50%;
12610
+ transform: translate(-50%, -50%) rotate(45deg);
12611
+ background-color: var(--color-canvas);
12612
+ width: calc(100% - calc(var(--pad, 20px) * 2));
12613
+ height: calc(100% - calc(var(--pad, 20px) * 2));
12614
+ border-radius: 50%;
12615
+ padding: var(--screen-pad);
12616
+ overflow: hidden;
12617
+ display: flex;
12618
+ flex-direction: column;
12619
+ align-items: center;
12620
+ justify-content: center;
12621
+ box-shadow: inset 0 0 15px rgba(0,0,0,0.4);
12622
+ }
12623
+
12624
+ .loader-wrapper .screen .lightray-limit {
12625
+ position: absolute;
12626
+ top: 50%;
12627
+ left: 50%;
12628
+ transform: translate(-50%, -50%);
12629
+ width: calc(100% - 10px);
12630
+ height: calc(100% - 10px);
12631
+ overflow: hidden;
12632
+ border-radius: 50%;
12633
+ pointer-events: none;
12634
+ }
12635
+
12636
+ .loader-wrapper .screen .lightray {
12637
+ position: absolute;
12638
+ left: 0;
12639
+ top: 0;
12640
+ transform: translate(-50%, -50%);
12641
+ width: 250%;
12642
+ height: 250%;
12643
+ background-image: radial-gradient(var(--color-primary), transparent, transparent);
12644
+ border-radius: 50% 10px 0 0;
12645
+ animation: rotateRay 8s linear infinite;
12646
+ opacity: 0.15;
12647
+ }
12648
+
12649
+ @keyframes rotateRay {
12650
+ 0% { transform: translate(-50%, -50%) rotate(0deg); }
12651
+ 100% { transform: translate(-50%, -50%) rotate(360deg); }
12652
+ }
12653
+
12654
+ .loader-wrapper .screen .loader-box-container {
12655
+ position: absolute;
12656
+ left: 50%;
12657
+ top: 50%;
12658
+ transform: translate(-50%, -50%);
12659
+ width: 75%;
12660
+ display: flex;
12661
+ flex-direction: column;
12662
+ align-items: center;
12663
+ z-index: 10;
12664
+ }
12665
+
12666
+ .loader-wrapper .screen .loader-progress-box {
12667
+ width: 100%;
12668
+ padding: var(--prog-pad);
12669
+ border: 2px solid var(--color-border);
12670
+ border-radius: 6px;
12671
+ background: var(--color-surface);
12672
+ box-shadow: inset 0 1px 3px rgba(0,0,0,0.2);
12673
+ }
12674
+
12675
+ .loader-wrapper .screen .progress-bar-fill {
12676
+ height: var(--prog-h);
12677
+ background-color: var(--color-brand);
12678
+ border-radius: 3px;
12679
+ box-shadow: 0 0 8px var(--color-brand);
12680
+ }
12681
+
12682
+ .loader-wrapper .top-side {
12683
+ position: absolute;
12684
+ width: 100%;
12685
+ height: 50%;
12686
+ top: var(--top-offset);
12687
+ left: 50%;
12688
+ transform: translate(-50%, -50%);
12689
+ box-shadow: 0 10px 15px rgba(0,0,0,0.2);
12690
+ background-color: rgba(0, 0, 0, 0.2);
12691
+ }
12692
+
12693
+ .loader-wrapper .bottom-side {
12694
+ position: absolute;
12695
+ width: 100%;
12696
+ height: 50%;
12697
+ top: calc(100% + var(--bottom-offset));
12698
+ left: 50%;
12699
+ transform: translate(-50%, -100%);
12700
+ box-shadow: 0 -15px 25px rgba(255,255,255,0.1);
12701
+ background-color: rgba(255, 255, 255, 0.1);
12702
+ }
12703
+
12704
+ .indeterminate-progress {
12705
+ animation: indeterminateProgress 5s infinite;
12706
+ }
12707
+
12708
+ @keyframes indeterminateProgress {
12709
+ 0% { width: 0%; }
12710
+ 50% { width: 100%; }
12711
+ 100% { width: 0%; }
12712
+ }
12713
+ ` })
12714
+ ] })
12715
+ ] });
12716
+ };
12543
12717
  function RepositoryWizard({ repoPath, onClose, onSuccess }) {
12544
12718
  const [step, setStep] = reactExports.useState(1);
12545
12719
  const [deviceFlowData, setDeviceFlowData] = reactExports.useState(null);
@@ -12554,8 +12728,15 @@ function RepositoryWizard({ repoPath, onClose, onSuccess }) {
12554
12728
  const [selectedRepoUrl, setSelectedRepoUrl] = reactExports.useState("");
12555
12729
  const [isLoading, setIsLoading] = reactExports.useState(false);
12556
12730
  const [error, setError] = reactExports.useState("");
12731
+ const [massivePushData, setMassivePushData] = reactExports.useState(null);
12732
+ const [localProgress, setLocalProgress] = reactExports.useState(null);
12557
12733
  reactExports.useEffect(() => {
12558
12734
  checkAuth();
12735
+ if (window.api.onMassivePushProgress) {
12736
+ window.api.onMassivePushProgress((data) => {
12737
+ setMassivePushData(data);
12738
+ });
12739
+ }
12559
12740
  }, []);
12560
12741
  const checkAuth = async () => {
12561
12742
  const status = await window.api.getAuthStatus();
@@ -12596,8 +12777,10 @@ function RepositoryWizard({ repoPath, onClose, onSuccess }) {
12596
12777
  setError("");
12597
12778
  try {
12598
12779
  localStorage.setItem("gitquickpush-last-repo", repoPath);
12780
+ setLocalProgress({ percentage: 5, eta: "Initializing Git locally..." });
12599
12781
  await window.api.initRepo(repoPath);
12600
12782
  if (action === "new") {
12783
+ setLocalProgress({ percentage: 15, eta: "Creating GitHub Repository..." });
12601
12784
  const autoInit = addReadme || !!gitignoreTemplate || !!licenseTemplate;
12602
12785
  const newRepo = await window.api.createGitHubRepository(
12603
12786
  repoName,
@@ -12607,10 +12790,13 @@ function RepositoryWizard({ repoPath, onClose, onSuccess }) {
12607
12790
  gitignoreTemplate,
12608
12791
  licenseTemplate
12609
12792
  );
12793
+ setLocalProgress({ percentage: 35, eta: "Linking Remote..." });
12610
12794
  await window.api.addRemote("origin", newRepo.clone_url);
12611
12795
  if (autoInit) {
12796
+ setLocalProgress({ percentage: 45, eta: "Syncing with Remote..." });
12612
12797
  await window.api.resetToRemote("origin", "main");
12613
12798
  }
12799
+ setLocalProgress({ percentage: 55, eta: "Scanning files..." });
12614
12800
  const status = await window.api.getStatus();
12615
12801
  const allFiles = [
12616
12802
  ...status.not_added,
@@ -12619,17 +12805,24 @@ function RepositoryWizard({ repoPath, onClose, onSuccess }) {
12619
12805
  ...status.conflicted
12620
12806
  ];
12621
12807
  if (allFiles.length > 0) {
12808
+ setLocalProgress({ percentage: 70, eta: `Staging ${allFiles.length} files...` });
12622
12809
  await window.api.stageFiles(allFiles);
12810
+ setLocalProgress({ percentage: 85, eta: "Committing changes..." });
12623
12811
  await window.api.commitChanges("Initial commit");
12624
12812
  }
12813
+ setLocalProgress({ percentage: 95, eta: "Pushing to GitHub..." });
12625
12814
  const branches = await window.api.getBranches();
12626
12815
  const currentBranch = branches.current || "main";
12627
12816
  await window.api.pushToRemote("origin", currentBranch);
12817
+ setLocalProgress({ percentage: 100, eta: "Complete!" });
12628
12818
  } else if (action === "existing") {
12819
+ setLocalProgress({ percentage: 50, eta: "Linking existing repository..." });
12629
12820
  if (selectedRepoUrl) {
12630
12821
  await window.api.addRemote("origin", selectedRepoUrl);
12822
+ setLocalProgress({ percentage: 80, eta: "Fetching remote data..." });
12631
12823
  await window.api.fetchRemote();
12632
12824
  }
12825
+ setLocalProgress({ percentage: 100, eta: "Complete!" });
12633
12826
  } else if (action === "local") {
12634
12827
  localStorage.setItem(`gitquickpush-wizard-dismissed-${repoPath}`, "true");
12635
12828
  }
@@ -12644,10 +12837,19 @@ function RepositoryWizard({ repoPath, onClose, onSuccess }) {
12644
12837
  localStorage.setItem(`gitquickpush-wizard-dismissed-${repoPath}`, "true");
12645
12838
  if (onClose) onClose();
12646
12839
  };
12840
+ const effectiveProgress = massivePushData || localProgress;
12647
12841
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-[70] p-4 sm:p-6 transition-opacity", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-surface/95 backdrop-blur-xl rounded-xl shadow-2xl border border-border w-full max-w-[550px] mx-auto overflow-hidden animate-float relative flex flex-col max-h-[90vh]", children: [
12648
- isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute inset-0 bg-surface/90 backdrop-blur-md z-10 flex flex-col items-center justify-center", children: [
12649
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-[250px] sm:w-[350px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Loader, {}) }),
12650
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-4 font-mono text-sm text-primary animate-pulse", children: "Processing..." })
12842
+ isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute inset-0 bg-surface/90 backdrop-blur-md z-10 flex flex-col items-center justify-center pt-8", children: [
12843
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-[280px] sm:w-[380px] shrink-0 -mt-8", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Loader, {}) }),
12844
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full mt-4 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
12845
+ MassivePushLoader,
12846
+ {
12847
+ percentage: effectiveProgress ? effectiveProgress.percentage : -1,
12848
+ eta: effectiveProgress ? effectiveProgress.eta : "Processing...",
12849
+ hideHeader: true,
12850
+ compact: true
12851
+ }
12852
+ ) })
12651
12853
  ] }),
12652
12854
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border bg-surface-hover/50 shrink-0", children: [
12653
12855
  /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-lg font-bold text-primary flex items-center gap-2", children: [
@@ -23662,6 +23864,247 @@ function WelcomeWizard({ onComplete }) {
23662
23864
  ] })
23663
23865
  ] });
23664
23866
  }
23867
+ function CloneRepoWizard({ onClose, onSuccess }) {
23868
+ const [repoUrl, setRepoUrl] = reactExports.useState("");
23869
+ const [destFolder, setDestFolder] = reactExports.useState("");
23870
+ const [folderName, setFolderName] = reactExports.useState("");
23871
+ const [isLoading, setIsLoading] = reactExports.useState(false);
23872
+ const [error, setError] = reactExports.useState("");
23873
+ const [cloneProgress, setCloneProgress] = reactExports.useState(null);
23874
+ const [showOptions, setShowOptions] = reactExports.useState(false);
23875
+ const [clonedPathState, setClonedPathState] = reactExports.useState("");
23876
+ reactExports.useEffect(() => {
23877
+ if (window.api.onGitProgress) {
23878
+ window.api.onGitProgress((data) => {
23879
+ if (data && data.progress !== void 0) {
23880
+ setCloneProgress({
23881
+ percentage: data.progress,
23882
+ eta: data.stage || "Cloning..."
23883
+ });
23884
+ }
23885
+ });
23886
+ }
23887
+ }, []);
23888
+ reactExports.useEffect(() => {
23889
+ if (repoUrl && !folderName) {
23890
+ let extracted = repoUrl.split("/").pop() || "";
23891
+ if (extracted.endsWith(".git")) {
23892
+ extracted = extracted.substring(0, extracted.length - 4);
23893
+ }
23894
+ if (extracted) {
23895
+ setFolderName(extracted);
23896
+ }
23897
+ }
23898
+ }, [repoUrl]);
23899
+ const handleSelectFolder = async () => {
23900
+ try {
23901
+ const result = await window.api.selectDirectory();
23902
+ if (result) {
23903
+ setDestFolder(result.path);
23904
+ }
23905
+ } catch (e) {
23906
+ setError(e.message);
23907
+ }
23908
+ };
23909
+ const handleClone = async () => {
23910
+ if (!repoUrl) {
23911
+ setError("Repository URL is required");
23912
+ return;
23913
+ }
23914
+ if (!destFolder) {
23915
+ setError("Destination folder is required");
23916
+ return;
23917
+ }
23918
+ const finalPath = destFolder + "\\" + (folderName || "cloned-repo");
23919
+ setIsLoading(true);
23920
+ setError("");
23921
+ setCloneProgress({ percentage: 0, eta: "Starting clone..." });
23922
+ try {
23923
+ const clonedPath = await window.api.cloneRepository(repoUrl, finalPath);
23924
+ setCloneProgress({ percentage: 100, eta: "Clone complete!" });
23925
+ setClonedPathState(clonedPath);
23926
+ try {
23927
+ const authStatus = await window.api.getAuthStatus();
23928
+ const myUsername = authStatus?.username?.toLowerCase();
23929
+ let repoOwner = "";
23930
+ const urlParts = repoUrl.replace(".git", "").split("/");
23931
+ if (repoUrl.includes("github.com")) {
23932
+ const ghIndex = urlParts.findIndex((p) => p.includes("github.com"));
23933
+ if (ghIndex !== -1 && urlParts.length > ghIndex + 1) {
23934
+ repoOwner = urlParts[ghIndex + 1].toLowerCase();
23935
+ }
23936
+ }
23937
+ if (myUsername && repoOwner && repoOwner === myUsername) {
23938
+ setTimeout(() => {
23939
+ onSuccess(clonedPath, "keep");
23940
+ }, 1e3);
23941
+ } else {
23942
+ setTimeout(() => {
23943
+ setIsLoading(false);
23944
+ setShowOptions(true);
23945
+ }, 1e3);
23946
+ }
23947
+ } catch (e) {
23948
+ setTimeout(() => {
23949
+ setIsLoading(false);
23950
+ setShowOptions(true);
23951
+ }, 1e3);
23952
+ }
23953
+ } catch (e) {
23954
+ setError(e.message || "Failed to clone repository");
23955
+ setIsLoading(false);
23956
+ setCloneProgress(null);
23957
+ }
23958
+ };
23959
+ const effectiveProgress = cloneProgress || (isLoading ? { percentage: 5, eta: "Initializing..." } : null);
23960
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-[100] p-4 animate-in fade-in duration-300", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-surface/95 border border-border w-full max-w-[600px] rounded-2xl shadow-2xl flex flex-col overflow-hidden max-h-[90vh]", children: [
23961
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 border-b border-border/50 bg-canvas/30", children: [
23962
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-2xl font-bold text-primary flex items-center gap-3", children: [
23963
+ /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-6 h-6 text-brand", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2" }) }),
23964
+ "Clone Repository"
23965
+ ] }),
23966
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-secondary mt-2 text-sm", children: "Download an existing Git repository to your computer" })
23967
+ ] }),
23968
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-6 overflow-y-auto", children: isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12", children: [
23969
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
23970
+ MassivePushLoader,
23971
+ {
23972
+ percentage: effectiveProgress?.percentage || 0,
23973
+ eta: effectiveProgress?.eta || "Cloning..."
23974
+ }
23975
+ ),
23976
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-8 text-secondary text-center max-w-[300px] text-sm animate-pulse", children: "Please wait while GitElectron clones the repository. This might take a while depending on the repository size." })
23977
+ ] }) : showOptions ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-8 space-y-6 text-center animate-in zoom-in-95 duration-300", children: [
23978
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-16 h-16 rounded-full bg-brand/10 text-brand flex items-center justify-center mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-8 h-8", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) }),
23979
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
23980
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-xl font-bold text-primary", children: "Clone Successful!" }),
23981
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-secondary text-sm mt-2 max-w-sm mx-auto", children: "This repository belongs to someone else. What would you like to do with it?" })
23982
+ ] }),
23983
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4 w-full mt-4", children: [
23984
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
23985
+ "button",
23986
+ {
23987
+ onClick: () => onSuccess(clonedPathState, "keep"),
23988
+ className: "flex flex-col items-center p-4 rounded-xl border border-border bg-canvas hover:bg-surface-hover transition-all text-left gap-3",
23989
+ children: [
23990
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-10 h-10 rounded-full bg-blue-500/10 text-blue-400 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
23991
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" }),
23992
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" })
23993
+ ] }) }),
23994
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center", children: [
23995
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-primary", children: "Keep as View-Only" }),
23996
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-secondary mt-1", children: "Leave the original remote intact." })
23997
+ ] })
23998
+ ]
23999
+ }
24000
+ ),
24001
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
24002
+ "button",
24003
+ {
24004
+ onClick: () => onSuccess(clonedPathState, "new"),
24005
+ className: "flex flex-col items-center p-4 rounded-xl border border-brand/30 bg-brand/5 hover:bg-brand/10 transition-all text-left gap-3 relative overflow-hidden",
24006
+ children: [
24007
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-0 right-0 px-2 py-0.5 bg-brand text-[10px] font-bold text-white rounded-bl-lg", children: "RECOMMENDED" }),
24008
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-10 h-10 rounded-full bg-brand/20 text-brand flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 6v6m0 0v6m0-6h6m-6 0H6" }) }) }),
24009
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center", children: [
24010
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-brand", children: "Create My Own Copy" }),
24011
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-secondary mt-1", children: "Strip original data to create your own repo." })
24012
+ ] })
24013
+ ]
24014
+ }
24015
+ )
24016
+ ] })
24017
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
24018
+ error && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-danger/10 border border-danger/30 text-danger px-4 py-3 rounded-lg text-sm flex items-start gap-3", children: [
24019
+ /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-5 h-5 flex-shrink-0 mt-0.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
24020
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "break-words", children: error })
24021
+ ] }),
24022
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
24023
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
24024
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-secondary mb-1.5", children: "Repository URL (HTTPS / SSH)" }),
24025
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
24026
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
24027
+ "input",
24028
+ {
24029
+ type: "text",
24030
+ className: "w-full bg-canvas border border-border rounded-lg px-4 py-2.5 text-primary focus:border-brand focus:ring-1 focus:ring-brand outline-none transition-all pl-10",
24031
+ placeholder: "https://github.com/user/repo.git",
24032
+ value: repoUrl,
24033
+ onChange: (e) => setRepoUrl(e.target.value)
24034
+ }
24035
+ ),
24036
+ /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-5 h-5 absolute left-3 top-3 text-secondary", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) })
24037
+ ] })
24038
+ ] }),
24039
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
24040
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-secondary mb-1.5", children: "Destination Base Folder" }),
24041
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
24042
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
24043
+ "input",
24044
+ {
24045
+ type: "text",
24046
+ className: "flex-1 bg-canvas border border-border rounded-lg px-4 py-2.5 text-primary opacity-70 cursor-not-allowed text-sm",
24047
+ placeholder: "Select a folder...",
24048
+ value: destFolder,
24049
+ readOnly: true
24050
+ }
24051
+ ),
24052
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
24053
+ "button",
24054
+ {
24055
+ onClick: handleSelectFolder,
24056
+ className: "bg-surface-hover border border-border hover:border-brand/50 text-primary px-4 rounded-lg font-medium transition-all",
24057
+ children: "Browse"
24058
+ }
24059
+ )
24060
+ ] }),
24061
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-secondary mt-1.5", children: "The folder where the cloned repository directory will be placed." })
24062
+ ] }),
24063
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
24064
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-secondary mb-1.5", children: "Folder Name (Optional)" }),
24065
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
24066
+ "input",
24067
+ {
24068
+ type: "text",
24069
+ className: "w-full bg-canvas border border-border rounded-lg px-4 py-2.5 text-primary focus:border-brand focus:ring-1 focus:ring-brand outline-none transition-all",
24070
+ placeholder: "E.g. my-awesome-project",
24071
+ value: folderName,
24072
+ onChange: (e) => setFolderName(e.target.value)
24073
+ }
24074
+ ),
24075
+ destFolder && folderName && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-brand mt-1.5 font-mono bg-brand/10 p-2 rounded inline-block", children: [
24076
+ "Will clone to: ",
24077
+ destFolder,
24078
+ "\\",
24079
+ folderName
24080
+ ] })
24081
+ ] })
24082
+ ] })
24083
+ ] }) }),
24084
+ !isLoading && !showOptions && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 border-t border-border bg-canvas/30 flex justify-end gap-3", children: [
24085
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
24086
+ "button",
24087
+ {
24088
+ onClick: onClose,
24089
+ className: "px-5 py-2.5 rounded-lg border border-border text-secondary hover:text-primary hover:bg-surface transition-all font-medium",
24090
+ children: "Cancel"
24091
+ }
24092
+ ),
24093
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
24094
+ "button",
24095
+ {
24096
+ onClick: handleClone,
24097
+ disabled: !repoUrl || !destFolder,
24098
+ className: "px-6 py-2.5 rounded-lg bg-brand hover:bg-brand-hover text-white font-medium transition-all shadow-lg shadow-brand/20 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
24099
+ children: [
24100
+ /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" }) }),
24101
+ "Clone Repository"
24102
+ ]
24103
+ }
24104
+ )
24105
+ ] })
24106
+ ] }) });
24107
+ }
23665
24108
  const AmongUsBackground = () => {
23666
24109
  const canvasRef = reactExports.useRef(null);
23667
24110
  reactExports.useEffect(() => {
@@ -23785,7 +24228,9 @@ const CollaborationRepoView = ({
23785
24228
  onRepoCardClick,
23786
24229
  onRefresh,
23787
24230
  isRefreshing,
23788
- onOpenExternal
24231
+ onOpenExternal,
24232
+ onUnlinkMapping,
24233
+ onChangeFolder
23789
24234
  }) => {
23790
24235
  const filteredRepos = collaboratedRepos.filter((repo) => {
23791
24236
  if (!collabSearch.trim()) return true;
@@ -24050,21 +24495,52 @@ const CollaborationRepoView = ({
24050
24495
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-secondary/40" }),
24051
24496
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Not cloned yet" })
24052
24497
  ] }) }),
24053
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2 flex-shrink-0 self-end sm:self-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
24054
- "button",
24055
- {
24056
- type: "button",
24057
- onClick: (e) => {
24058
- e.stopPropagation();
24059
- onRepoCardClick(repo);
24060
- },
24061
- className: `px-3.5 py-1.5 text-xs font-semibold rounded-xl transition-all shadow-xs flex items-center gap-1.5 ${savedPath ? isMissing ? "bg-danger/20 hover:bg-danger/30 text-danger border border-danger/40" : "bg-brand hover:bg-brand-hover text-white shadow-brand/20" : "bg-brand hover:bg-brand-hover text-white shadow-brand/20"}`,
24062
- children: [
24063
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: savedPath ? isMissing ? "Re-Clone" : "Open Repo" : "Clone / Connect" }),
24064
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: isMissing ? "☁️" : savedPath ? "→" : "☁️" })
24065
- ]
24066
- }
24067
- ) })
24498
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 flex-shrink-0 self-end sm:self-center", children: [
24499
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
24500
+ "button",
24501
+ {
24502
+ type: "button",
24503
+ onClick: (e) => {
24504
+ e.stopPropagation();
24505
+ onChangeFolder?.(repo);
24506
+ },
24507
+ className: "px-2.5 py-1.5 text-xs font-medium rounded-xl transition-all shadow-xs flex items-center gap-1 bg-surface hover:bg-surface-hover text-secondary hover:text-primary border border-border",
24508
+ title: savedPath ? "Change connected local folder" : "Select existing local folder on disk",
24509
+ children: [
24510
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "📁" }),
24511
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: savedPath ? "Change Folder" : "Choose Folder" })
24512
+ ]
24513
+ }
24514
+ ),
24515
+ savedPath && /* @__PURE__ */ jsxRuntimeExports.jsx(
24516
+ "button",
24517
+ {
24518
+ type: "button",
24519
+ onClick: (e) => {
24520
+ e.stopPropagation();
24521
+ onUnlinkMapping?.(repo.full_name);
24522
+ },
24523
+ className: "p-1.5 text-xs rounded-xl transition-all bg-surface hover:bg-danger/10 text-secondary hover:text-danger border border-border",
24524
+ title: "Clear connection",
24525
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) })
24526
+ }
24527
+ ),
24528
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
24529
+ "button",
24530
+ {
24531
+ type: "button",
24532
+ onClick: (e) => {
24533
+ e.stopPropagation();
24534
+ onRepoCardClick(repo);
24535
+ },
24536
+ className: `px-3.5 py-1.5 text-xs font-semibold rounded-xl transition-all shadow-xs flex items-center gap-1.5 ${savedPath ? isMissing ? "bg-danger/20 hover:bg-danger/30 text-danger border border-danger/40" : "bg-brand hover:bg-brand-hover text-white shadow-brand/20" : "bg-brand hover:bg-brand-hover text-white shadow-brand/20"}`,
24537
+ children: [
24538
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: savedPath ? isMissing ? "Re-Clone" : "Open Repo" : "Clone" }),
24539
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: isMissing ? "☁️" : savedPath ? "→" : "☁️" })
24540
+ ]
24541
+ }
24542
+ )
24543
+ ] })
24068
24544
  ] })
24069
24545
  ]
24070
24546
  },
@@ -24165,70 +24641,6 @@ const CommitReceiptPrinter = ({ commit, onClose }) => {
24165
24641
  ] }) })
24166
24642
  ] });
24167
24643
  };
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
- };
24232
24644
  const translations = {
24233
24645
  en: {
24234
24646
  settings: "Settings",
@@ -24802,6 +25214,7 @@ function App() {
24802
25214
  return () => document.removeEventListener("click", handleClick);
24803
25215
  }, []);
24804
25216
  const [showDropModal, setShowDropModal] = reactExports.useState(false);
25217
+ const [showCloneWizard, setShowCloneWizard] = reactExports.useState(false);
24805
25218
  const [droppedFiles, setDroppedFiles] = reactExports.useState([]);
24806
25219
  const [showConflictModal, setShowConflictModal] = reactExports.useState(false);
24807
25220
  const [conflictFile, setConflictFile] = reactExports.useState(null);
@@ -25004,32 +25417,8 @@ function App() {
25004
25417
  const exists = await window.api.checkPathExists(targetPath);
25005
25418
  if (!exists) {
25006
25419
  console.warn("Target path does not exist on disk:", targetPath);
25007
- const currentMappings = JSON.parse(localStorage.getItem("gitelectron_collab_mappings") || "{}");
25008
- const matching = Object.entries(currentMappings).find(([_, p]) => p === targetPath);
25009
- if (matching) {
25010
- const [fullName] = matching;
25011
- let repo = collaboratedRepos.find((r) => r.full_name === fullName);
25012
- if (!repo) {
25013
- try {
25014
- const allCollabs = await window.api.getCollaboratedRepos();
25015
- setCollaboratedRepos(allCollabs);
25016
- repo = allCollabs.find((r) => r.full_name === fullName);
25017
- } catch (e) {
25018
- }
25019
- }
25020
- if (repo) {
25021
- showToast(`The local folder for ${fullName} was deleted. You can re-clone it now.`, "warning");
25022
- setShowCollabActionModal({
25023
- repo,
25024
- url: repo.clone_url,
25025
- name: repo.name,
25026
- fullName: repo.full_name,
25027
- missingPreviousPath: targetPath
25028
- });
25029
- setChangesTab("collaboration-repo");
25030
- return;
25031
- }
25032
- }
25420
+ showToast(`Folder not found on disk: ${targetPath}`, "warning");
25421
+ return;
25033
25422
  }
25034
25423
  } catch (e) {
25035
25424
  console.error("Error checking target path existence:", e);
@@ -25048,24 +25437,72 @@ function App() {
25048
25437
  }
25049
25438
  }).catch((err) => console.error("Failed to load repo", err));
25050
25439
  };
25440
+ const getCandidateDirs = () => {
25441
+ const list = [];
25442
+ if (repoPath) {
25443
+ const p1 = repoPath.replace(/\\/g, "/").split("/").slice(0, -1).join("/");
25444
+ if (p1 && !list.includes(p1)) list.push(p1);
25445
+ const p2 = p1 ? p1.split("/").slice(0, -1).join("/") : "";
25446
+ if (p2 && !list.includes(p2)) list.push(p2);
25447
+ }
25448
+ const standard = [
25449
+ "D:/DRDO_ProjectX1",
25450
+ "D:/DRDO_ProjectX1/DRDO_Project",
25451
+ "D:/My Projects",
25452
+ "D:/My Projects/PushGitX"
25453
+ ];
25454
+ standard.forEach((d) => {
25455
+ if (!list.includes(d)) list.push(d);
25456
+ });
25457
+ Object.values(collabMappings).forEach((p) => {
25458
+ if (p) {
25459
+ const pParent = p.replace(/\\/g, "/").split("/").slice(0, -1).join("/");
25460
+ if (pParent && !list.includes(pParent)) list.push(pParent);
25461
+ }
25462
+ });
25463
+ return list;
25464
+ };
25051
25465
  reactExports.useEffect(() => {
25052
25466
  const checkAllPaths = async () => {
25053
25467
  const results = {};
25054
- for (const [fullName, path] of Object.entries(collabMappings)) {
25055
- if (path) {
25468
+ const candidateDirs = getCandidateDirs();
25469
+ for (const repo of collaboratedRepos) {
25470
+ const fullName = repo.full_name;
25471
+ const currentPath = collabMappings[fullName];
25472
+ let valid = false;
25473
+ if (currentPath) {
25056
25474
  try {
25057
- results[fullName] = await window.api.checkPathExists(path);
25475
+ const exists = await window.api.checkPathExists(currentPath);
25476
+ if (exists) {
25477
+ const gitInfo = await window.api.getDirectoryGitInfo(currentPath);
25478
+ const detectedName = (gitInfo.repoName || "").toLowerCase();
25479
+ const expectedName = (repo.name || fullName.split("/").pop() || "").toLowerCase();
25480
+ if (!detectedName || detectedName === expectedName) {
25481
+ valid = true;
25482
+ }
25483
+ }
25058
25484
  } catch {
25059
- results[fullName] = false;
25485
+ valid = false;
25060
25486
  }
25061
25487
  }
25488
+ if (!valid) {
25489
+ try {
25490
+ const found = await window.api.scanForRepoFolder(repo.name, candidateDirs);
25491
+ if (found) {
25492
+ saveMapping(fullName, found);
25493
+ valid = true;
25494
+ }
25495
+ } catch {
25496
+ }
25497
+ }
25498
+ results[fullName] = valid;
25062
25499
  }
25063
25500
  setPathExistenceMap(results);
25064
25501
  };
25065
25502
  if (changesTab === "collaboration-repo" || collaboratedRepos.length > 0) {
25066
25503
  checkAllPaths();
25067
25504
  }
25068
- }, [collabMappings, changesTab, collaboratedRepos.length]);
25505
+ }, [changesTab, collaboratedRepos.length]);
25069
25506
  reactExports.useEffect(() => {
25070
25507
  if (authStatus.status === "Verified") {
25071
25508
  window.api.getCollaboratedRepos().then((repos) => {
@@ -25223,13 +25660,24 @@ function App() {
25223
25660
  return updated;
25224
25661
  });
25225
25662
  };
25663
+ const removeMapping = (repoFullName) => {
25664
+ setCollabMappings((prev) => {
25665
+ const updated = { ...prev };
25666
+ delete updated[repoFullName];
25667
+ localStorage.setItem("gitelectron_collab_mappings", JSON.stringify(updated));
25668
+ return updated;
25669
+ });
25670
+ };
25226
25671
  const openCollabRepoPath = async (targetPath) => {
25227
25672
  localStorage.setItem("gitelectron-last-repo", targetPath);
25228
25673
  setRepoPath(targetPath);
25229
- setIsRepo(true);
25230
- await window.api.setRepoPath(targetPath);
25231
- window.api.toggleAutoSync(targetPath, true);
25232
- await refreshRepoState();
25674
+ const result = await window.api.setRepoPath(targetPath);
25675
+ const isValidRepo = result ? result.isRepo : false;
25676
+ setIsRepo(isValidRepo);
25677
+ if (isValidRepo) {
25678
+ window.api.toggleAutoSync(targetPath, true);
25679
+ await refreshRepoState();
25680
+ }
25233
25681
  setChangesTab("changes");
25234
25682
  };
25235
25683
  const handleCollabRefresh = async () => {
@@ -25245,50 +25693,114 @@ function App() {
25245
25693
  setIsRefreshing(false);
25246
25694
  }
25247
25695
  };
25696
+ const handleSelectCollabFolder = async (repo) => {
25697
+ let defaultDir = void 0;
25698
+ if (repoPath) {
25699
+ defaultDir = repoPath.replace(/\\/g, "/").split("/").slice(0, -1).join("/");
25700
+ }
25701
+ const result = await window.api.selectDirectory(defaultDir);
25702
+ if (!result) return;
25703
+ const targetRepoName = (repo.name || repo.full_name?.split("/").pop() || "").toLowerCase();
25704
+ const gitInfo = await window.api.getDirectoryGitInfo(result.path);
25705
+ const detectedRepoName = (gitInfo.repoName || "").toLowerCase();
25706
+ if (detectedRepoName && targetRepoName && detectedRepoName !== targetRepoName) {
25707
+ const confirmUse = window.confirm(
25708
+ `Notice: Folder Remote Mismatch!
25709
+
25710
+ The folder you selected appears to belong to repository "${gitInfo.repoName}", but this card is for "${repo.name}".
25711
+
25712
+ Do you want to connect "${repo.name}" to this folder anyway?`
25713
+ );
25714
+ if (!confirmUse) return;
25715
+ }
25716
+ const pathToUse = gitInfo.rootPath || result.path;
25717
+ saveMapping(repo.full_name, pathToUse);
25718
+ await openCollabRepoPath(pathToUse);
25719
+ showToast(`Connected ${repo.name} to ${pathToUse.split("\\").pop() || pathToUse}`, "success");
25720
+ };
25248
25721
  const handleRepoCardClick = async (repo) => {
25722
+ const targetRepoName = (repo.name || repo.full_name?.split("/").pop() || "").toLowerCase();
25249
25723
  const savedPath = collabMappings[repo.full_name];
25250
25724
  if (savedPath) {
25251
25725
  const exists = await window.api.checkPathExists(savedPath);
25252
25726
  if (exists) {
25253
- await openCollabRepoPath(savedPath);
25254
- return;
25255
- } else {
25256
- setShowCollabActionModal({
25257
- repo,
25258
- url: repo.clone_url,
25259
- name: repo.name,
25260
- fullName: repo.full_name,
25261
- missingPreviousPath: savedPath
25262
- });
25727
+ const gitInfo = await window.api.getDirectoryGitInfo(savedPath);
25728
+ const detectedRepoName = (gitInfo.repoName || "").toLowerCase();
25729
+ const isMatch = !detectedRepoName || detectedRepoName === targetRepoName || gitInfo.remoteUrl && (gitInfo.remoteUrl.toLowerCase().includes(targetRepoName) || gitInfo.remoteUrl.toLowerCase().includes((repo.full_name || "").toLowerCase()));
25730
+ if (isMatch) {
25731
+ await openCollabRepoPath(gitInfo.rootPath || savedPath);
25732
+ return;
25733
+ }
25734
+ console.warn(
25735
+ `Collab mapping mismatch for ${repo.full_name}: savedPath is ${detectedRepoName}, expected ${targetRepoName}`
25736
+ );
25737
+ }
25738
+ }
25739
+ const candidateDirs = getCandidateDirs();
25740
+ try {
25741
+ const autoFound = await window.api.scanForRepoFolder(repo.name, candidateDirs);
25742
+ if (autoFound) {
25743
+ saveMapping(repo.full_name, autoFound);
25744
+ showToast(
25745
+ `Auto-connected to local folder: ${autoFound.split("\\").pop() || autoFound}`,
25746
+ "success"
25747
+ );
25748
+ await openCollabRepoPath(autoFound);
25263
25749
  return;
25264
25750
  }
25751
+ } catch (e) {
25752
+ console.warn("Auto-scan error:", e);
25265
25753
  }
25266
25754
  setShowCollabActionModal({
25267
25755
  repo,
25268
25756
  url: repo.clone_url,
25269
25757
  name: repo.name,
25270
- fullName: repo.full_name
25758
+ fullName: repo.full_name,
25759
+ missingPreviousPath: savedPath
25271
25760
  });
25272
25761
  };
25273
25762
  const handleCollabMap = async () => {
25274
25763
  if (!showCollabActionModal) return;
25275
- const { fullName } = showCollabActionModal;
25764
+ const { fullName, name, repo } = showCollabActionModal;
25276
25765
  setShowCollabActionModal(null);
25277
- const result = await window.api.selectDirectory();
25766
+ let defaultDir = void 0;
25767
+ if (repoPath) {
25768
+ defaultDir = repoPath.replace(/\\/g, "/").split("/").slice(0, -1).join("/");
25769
+ }
25770
+ const result = await window.api.selectDirectory(defaultDir);
25278
25771
  if (result) {
25279
- if (fullName) {
25280
- saveMapping(fullName, result.path);
25772
+ const repoName = name || repo?.name || (fullName ? fullName.split("/").pop() : "");
25773
+ const selectedBasename = result.path.replace(/\\/g, "/").split("/").pop();
25774
+ const gitInfo = await window.api.getDirectoryGitInfo(result.path);
25775
+ const detectedRepoName = (gitInfo.repoName || "").toLowerCase();
25776
+ const targetRepoName = (repoName || "").toLowerCase();
25777
+ if (detectedRepoName && targetRepoName && detectedRepoName !== targetRepoName) {
25778
+ const confirmed = window.confirm(
25779
+ `Notice: Remote Mismatch!
25780
+
25781
+ The folder you selected appears to be for repository "${gitInfo.repoName}", but this card is "${repoName}".
25782
+
25783
+ Are you sure you want to connect "${repoName}" to this folder?`
25784
+ );
25785
+ if (!confirmed) return;
25786
+ } else if (!detectedRepoName && repoName && selectedBasename && targetRepoName !== selectedBasename.toLowerCase()) {
25787
+ const confirmed = window.confirm(
25788
+ `Warning: Folder Name Mismatch!
25789
+
25790
+ You selected the folder "${selectedBasename}", but the repository is named "${repoName}".
25791
+
25792
+ Because the folder picker often opens in the last folder you viewed, you might have accidentally selected the wrong folder.
25793
+
25794
+ Are you SURE you want to link "${repoName}" to this folder?`
25795
+ );
25796
+ if (!confirmed) return;
25281
25797
  }
25282
- localStorage.setItem("gitelectron-last-repo", result.path);
25283
- setRepoPath(result.path);
25284
- setIsRepo(result.isRepo);
25285
- if (result.isRepo) {
25286
- await window.api.setRepoPath(result.path);
25287
- await refreshRepoState();
25288
- window.api.toggleAutoSync(result.path, true);
25798
+ const pathToUse = gitInfo.rootPath || result.path;
25799
+ if (fullName) {
25800
+ saveMapping(fullName, pathToUse);
25289
25801
  }
25290
- setChangesTab("changes");
25291
- showToast(`Linked repository to ${result.path}`, "success");
25802
+ await openCollabRepoPath(pathToUse);
25803
+ showToast(`Linked repository to ${pathToUse.split("\\").pop() || pathToUse}`, "success");
25292
25804
  }
25293
25805
  };
25294
25806
  const handleCollabClone = async () => {
@@ -25462,23 +25974,7 @@ function App() {
25462
25974
  try {
25463
25975
  const exists = await window.api.checkPathExists(repoPath);
25464
25976
  if (!exists) {
25465
- const currentMappings = JSON.parse(localStorage.getItem("gitelectron_collab_mappings") || "{}");
25466
- const matching = Object.entries(currentMappings).find(([_, p]) => p === repoPath);
25467
- if (matching) {
25468
- const [fullName] = matching;
25469
- const repo = collaboratedRepos.find((r) => r.full_name === fullName);
25470
- if (repo) {
25471
- showToast(`Repository folder was deleted on disk: ${fullName}. Prompting to re-clone.`, "warning");
25472
- setShowCollabActionModal({
25473
- repo,
25474
- url: repo.clone_url,
25475
- name: repo.name,
25476
- fullName: repo.full_name,
25477
- missingPreviousPath: repoPath
25478
- });
25479
- setChangesTab("collaboration-repo");
25480
- }
25481
- }
25977
+ console.warn("Repository path does not exist on disk:", repoPath);
25482
25978
  }
25483
25979
  } catch (err) {
25484
25980
  }
@@ -26601,7 +27097,7 @@ function App() {
26601
27097
  onClick: handleCollabMap,
26602
27098
  className: "w-full py-3 px-4 bg-surface-hover hover:bg-surface-hover/80 border border-border rounded-xl text-primary text-sm font-medium transition-colors text-left flex items-center justify-between",
26603
27099
  children: [
26604
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Already have this project folder" }),
27100
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Select Existing Folder (Already on my computer)" }),
26605
27101
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-base", children: "📁" })
26606
27102
  ]
26607
27103
  }
@@ -26657,6 +27153,24 @@ function App() {
26657
27153
  }
26658
27154
  ),
26659
27155
  showUniversalWizard && /* @__PURE__ */ jsxRuntimeExports.jsx(UniversalPushWizard, { isOpen: showUniversalWizard, onClose: () => setShowUniversalWizard(false) }),
27156
+ showCloneWizard && /* @__PURE__ */ jsxRuntimeExports.jsx(
27157
+ CloneRepoWizard,
27158
+ {
27159
+ onClose: () => setShowCloneWizard(false),
27160
+ onSuccess: async (clonedPath, action) => {
27161
+ setShowCloneWizard(false);
27162
+ if (action === "new") {
27163
+ await window.api.removeGitMetadata(clonedPath);
27164
+ localStorage.setItem("gitelectron-last-repo", clonedPath);
27165
+ setRepoPath(clonedPath);
27166
+ setIsRepo(false);
27167
+ setShowSetupWizard(true);
27168
+ } else {
27169
+ openCollabRepoPath(clonedPath);
27170
+ }
27171
+ }
27172
+ }
27173
+ ),
26660
27174
  showSetupWizard && repoPath && /* @__PURE__ */ jsxRuntimeExports.jsx(
26661
27175
  RepositoryWizard,
26662
27176
  {
@@ -26895,6 +27409,26 @@ function App() {
26895
27409
  ]
26896
27410
  }
26897
27411
  ),
27412
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
27413
+ "button",
27414
+ {
27415
+ onClick: () => setShowCloneWizard(true),
27416
+ className: "w-full bg-surface-hover hover:brightness-110 text-primary font-medium py-2 px-4 rounded-md transition-all border border-border text-sm flex items-center justify-center gap-2",
27417
+ children: [
27418
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
27419
+ "svg",
27420
+ {
27421
+ className: "w-4 h-4 text-secondary",
27422
+ fill: "none",
27423
+ stroke: "currentColor",
27424
+ viewBox: "0 0 24 24",
27425
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" })
27426
+ }
27427
+ ),
27428
+ "Clone Repository"
27429
+ ]
27430
+ }
27431
+ ),
26898
27432
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
26899
27433
  "button",
26900
27434
  {
@@ -26914,19 +27448,53 @@ function App() {
26914
27448
  const saved = collabMappings[repo.full_name];
26915
27449
  const isMissing = saved && pathExistenceMap[repo.full_name] === false;
26916
27450
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
26917
- "button",
27451
+ "div",
26918
27452
  {
26919
- onClick: () => handleRepoCardClick(repo),
26920
- className: `w-full text-left bg-canvas hover:bg-surface-hover text-primary py-2 px-3 rounded-md transition-all border text-sm truncate flex flex-col group ${isMissing ? "border-danger/40 bg-danger/5" : "border-border"}`,
26921
- title: repo.name,
27453
+ className: `relative w-full text-left bg-canvas hover:bg-surface-hover text-primary py-2 px-3 rounded-md transition-all border text-sm flex flex-col group ${isMissing ? "border-danger/40 bg-danger/5" : "border-border"}`,
26922
27454
  children: [
26923
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between w-full", children: [
26924
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium truncate group-hover:text-brand transition-colors", children: repo.name }),
26925
- isMissing && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] bg-danger/20 text-danger px-1 rounded font-bold", children: "Deleted" })
26926
- ] }),
26927
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-secondary truncate", children: [
26928
- "by @",
26929
- repo.owner?.login
27455
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
27456
+ "button",
27457
+ {
27458
+ className: "w-full text-left flex flex-col truncate",
27459
+ onClick: () => handleRepoCardClick(repo),
27460
+ title: repo.name,
27461
+ children: [
27462
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between w-full pr-6", children: [
27463
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium truncate group-hover:text-brand transition-colors", children: repo.name }),
27464
+ isMissing && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] bg-danger/20 text-danger px-1 rounded font-bold", children: "Deleted" })
27465
+ ] }),
27466
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-secondary truncate", children: [
27467
+ "by @",
27468
+ repo.owner?.login
27469
+ ] })
27470
+ ]
27471
+ }
27472
+ ),
27473
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute right-1 top-1.5 flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-all", children: [
27474
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
27475
+ "button",
27476
+ {
27477
+ onClick: (e) => {
27478
+ e.stopPropagation();
27479
+ handleSelectCollabFolder(repo);
27480
+ },
27481
+ className: "p-1 rounded-md text-secondary hover:text-primary hover:bg-surface-hover transition-colors",
27482
+ title: saved ? "Change local folder" : "Select local folder on disk",
27483
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs", children: "📁" })
27484
+ }
27485
+ ),
27486
+ saved && /* @__PURE__ */ jsxRuntimeExports.jsx(
27487
+ "button",
27488
+ {
27489
+ onClick: (e) => {
27490
+ e.stopPropagation();
27491
+ removeMapping(repo.full_name);
27492
+ },
27493
+ className: "p-1 rounded-md text-secondary hover:text-danger hover:bg-danger/10 transition-colors",
27494
+ title: "Clear saved link",
27495
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) })
27496
+ }
27497
+ )
26930
27498
  ] })
26931
27499
  ]
26932
27500
  },
@@ -27045,7 +27613,7 @@ function App() {
27045
27613
  )
27046
27614
  ] })
27047
27615
  ] }),
27048
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 p-6 flex flex-col overflow-hidden relative z-10", children: isRepo && status && branches ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-4 mb-6 relative z-20", children: [
27616
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 p-6 flex flex-col overflow-y-auto custom-scrollbar min-h-0 relative z-10", children: isRepo && status && branches ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col min-h-0 gap-4 mb-6 relative z-20", children: [
27049
27617
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap justify-between items-center bg-surface/70 backdrop-blur-md border border-border p-3 rounded-xl transition-colors duration-300 gap-4 relative z-50", children: [
27050
27618
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-4 text-sm", children: [
27051
27619
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 relative", children: [
@@ -27083,7 +27651,7 @@ function App() {
27083
27651
  ] })
27084
27652
  }
27085
27653
  ),
27086
- showAccountDropdown && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute top-full left-0 mt-2 w-64 max-w-[90vw] bg-surface backdrop-blur-xl border border-border rounded-lg shadow-xl py-2 z-[60]", children: [
27654
+ showAccountDropdown && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute top-full left-0 mt-2 w-64 max-w-[90vw] bg-surface backdrop-blur-xl border border-border rounded-lg shadow-2xl py-2 z-[60] account-dropdown-glass", children: [
27087
27655
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-1.5 text-xs font-semibold text-secondary uppercase tracking-wider mb-1", children: "Your Accounts" }),
27088
27656
  accounts.map((acc) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
27089
27657
  "div",
@@ -27537,12 +28105,14 @@ function App() {
27537
28105
  onRepoCardClick: handleRepoCardClick,
27538
28106
  onRefresh: handleCollabRefresh,
27539
28107
  isRefreshing,
27540
- onOpenExternal: (url) => window.api.openExternal(url)
28108
+ onOpenExternal: (url) => window.api.openExternal(url),
28109
+ onUnlinkMapping: removeMapping,
28110
+ onChangeFolder: handleSelectCollabFolder
27541
28111
  }
27542
28112
  )
27543
28113
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
27544
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { id: "split-pane-container", className: "flex-1 overflow-hidden flex flex-col lg:flex-row pb-2", children: [
27545
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: leftPanelWidth }, className: "bg-surface/70 backdrop-blur-md rounded-xl border border-border flex flex-col transition-colors duration-300 overflow-hidden min-h-[250px]", children: [
28114
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { id: "split-pane-container", className: "flex-1 overflow-hidden min-h-0 flex flex-col lg:flex-row pb-2", children: [
28115
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: leftPanelWidth }, className: "bg-surface/70 backdrop-blur-md rounded-xl border border-border flex flex-col transition-colors duration-300 overflow-hidden min-h-[250px] min-w-0 min-h-0", children: [
27546
28116
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-nowrap overflow-x-auto custom-scrollbar items-center border-b border-border px-4 pt-3 pb-1 gap-y-2 gap-x-1", children: [
27547
28117
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
27548
28118
  "button",
@@ -27609,9 +28179,9 @@ function App() {
27609
28179
  MassivePushLoader,
27610
28180
  {
27611
28181
  percentage: massivePushData?.percentage || 0,
27612
- eta: massivePushData?.eta || "calculating..."
28182
+ eta: gitProgress > 0 && gitProgress < 100 ? `Uploading Chunk: ${Math.round(gitProgress)}%` : massivePushData?.eta || "calculating..."
27613
28183
  }
27614
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-auto p-4 custom-scrollbar", children: [
28184
+ ) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto min-h-0 p-4 custom-scrollbar", children: [
27615
28185
  changesTab === "changes" && /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "space-y-1", children: [
27616
28186
  status.conflicted.map((f) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
27617
28187
  "li",
@@ -27782,9 +28352,9 @@ function App() {
27782
28352
  children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `h-12 w-1 rounded-full transition-colors ${isResizing ? "bg-accent" : "bg-border group-hover:bg-accent/50"}` })
27783
28353
  }
27784
28354
  ),
27785
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: 100 - leftPanelWidth }, className: "bg-surface/70 backdrop-blur-md rounded-xl p-4 border border-border flex flex-col transition-colors duration-300 min-h-[250px]", children: [
27786
- /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "font-semibold mb-4 text-primary text-sm", children: "Staged Changes" }),
27787
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-auto pr-2 custom-scrollbar", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "space-y-1", children: [
28355
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: 100 - leftPanelWidth }, className: "bg-surface/70 backdrop-blur-md rounded-xl p-4 border border-border flex flex-col transition-colors duration-300 overflow-hidden min-h-0 min-w-0", children: [
28356
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "font-semibold mb-4 text-primary text-sm shrink-0", children: "Staged Changes" }),
28357
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto min-h-0 pr-2 custom-scrollbar", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "space-y-1", children: [
27788
28358
  status.staged.map((f) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
27789
28359
  "li",
27790
28360
  {
@@ -27824,7 +28394,7 @@ function App() {
27824
28394
  ] }) })
27825
28395
  ] })
27826
28396
  ] }),
27827
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 bg-surface/70 backdrop-blur-md p-4 rounded-xl border border-border flex gap-3 items-center transition-colors duration-300", children: [
28397
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 shrink-0 bg-surface/70 backdrop-blur-md p-4 rounded-xl border border-border flex flex-col sm:flex-row gap-3 items-center transition-colors duration-300", children: [
27828
28398
  /* @__PURE__ */ jsxRuntimeExports.jsx(
27829
28399
  "input",
27830
28400
  {
@@ -27877,7 +28447,9 @@ function App() {
27877
28447
  onRepoCardClick: handleRepoCardClick,
27878
28448
  onRefresh: handleCollabRefresh,
27879
28449
  isRefreshing,
27880
- onOpenExternal: (url) => window.api.openExternal(url)
28450
+ onOpenExternal: (url) => window.api.openExternal(url),
28451
+ onUnlinkMapping: removeMapping,
28452
+ onChangeFolder: handleSelectCollabFolder
27881
28453
  }
27882
28454
  )
27883
28455
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center text-secondary relative z-10", children: [