diff --git a/packages/insomnia/src/main/git-service.ts b/packages/insomnia/src/main/git-service.ts index 732d630f18..8155c2e87f 100644 --- a/packages/insomnia/src/main/git-service.ts +++ b/packages/insomnia/src/main/git-service.ts @@ -2886,6 +2886,7 @@ async function getCurrentBranchByRepositoryId({ export interface MigrationSummary { logs: string[]; failedProjects: { id: string; name: string }[]; + totalProjects: number; } export async function runAllGitRepoMigrations(): Promise { @@ -2895,7 +2896,7 @@ export async function runAllGitRepoMigrations(): Promise { const allProjects = await services.project.all(); const gitProjects = allProjects.filter((p): p is GitProject => models.project.isConnectedGitProject(p)); - if (gitProjects.length === 0) return { logs, failedProjects }; + if (gitProjects.length === 0) return { logs, failedProjects, totalProjects: 0 }; // Batch-fetch all git repositories in one query instead of N individual lookups. const repoIds = gitProjects.map(p => models.project.getEffectiveRepoId(p)).filter(Boolean) as string[]; @@ -2913,6 +2914,8 @@ export async function runAllGitRepoMigrations(): Promise { `${ts()} [INFO] Starting migration v${CURRENT_MIGRATION_VERSION} for ${gitProjects.length} repo(s): ${projectList}`, ); + let migratedCount = 0; + await Promise.all( gitProjects.map(async project => { const gitRepository = repoById.get(models.project.getEffectiveRepoId(project)!); @@ -2933,6 +2936,8 @@ export async function runAllGitRepoMigrations(): Promise { const success = await migrateRepoStructureIfNeeded(baseDir, project._id, repoId, logger); if (!success) { failedProjects.push({ id: project._id, name: project.name }); + } else { + migratedCount++; } }), ); @@ -2965,7 +2970,7 @@ export async function runAllGitRepoMigrations(): Promise { }), ); - return { logs, failedProjects }; + return { logs, failedProjects, totalProjects: migratedCount }; } export interface GitServiceAPI { diff --git a/packages/insomnia/src/routes/git-migration.$.tsx b/packages/insomnia/src/routes/git-migration.$.tsx index d589a6fa6e..c340f06ff9 100644 --- a/packages/insomnia/src/routes/git-migration.$.tsx +++ b/packages/insomnia/src/routes/git-migration.$.tsx @@ -9,24 +9,37 @@ import git_migration from '~/ui/images/git-migration/git.png'; type MigrationStatus = 'default' | 'running' | 'completed' | 'partiallyCompleted' | 'error'; +const MIN_DISPLAY_MS = 3000; + const MigrationView = () => { const [status, setStatus] = useState('default'); const [migrationLogs, setMigrationLogs] = useState([]); const [failedProjects, setFailedProjects] = useState<{ id: string; name: string }[]>([]); + const [migratedCount, setMigratedCount] = useState(0); const handleMigration = () => { setStatus('running'); + const startTime = Date.now(); window.main.git .runAllGitRepoMigrations() - .then((result: { logs: string[]; failedProjects: { id: string; name: string }[] }) => { - setMigrationLogs(result.logs); - setFailedProjects(result.failedProjects); - setStatus(result.failedProjects.length > 0 ? 'partiallyCompleted' : 'completed'); + .then((result: { logs: string[]; failedProjects: { id: string; name: string }[]; totalProjects: number }) => { + const elapsed = Date.now() - startTime; + const remaining = Math.max(0, MIN_DISPLAY_MS - elapsed); + setTimeout(() => { + setMigrationLogs(result.logs); + setFailedProjects(result.failedProjects); + setMigratedCount(result.totalProjects); + setStatus(result.failedProjects.length > 0 ? 'partiallyCompleted' : 'completed'); + }, remaining); }) .catch((err: unknown) => { + const elapsed = Date.now() - startTime; + const remaining = Math.max(0, MIN_DISPLAY_MS - elapsed); const errorMsg = err instanceof Error ? err.message : 'An unexpected error occurred.'; - setMigrationLogs(prev => [...prev, `[ERROR] ${errorMsg}`]); - setStatus('error'); + setTimeout(() => { + setMigrationLogs(prev => [...prev, `[ERROR] ${errorMsg}`]); + setStatus('error'); + }, remaining); }); }; @@ -39,7 +52,8 @@ const MigrationView = () => {
-

+

+ {isUpdateCompletedSuccessfully && } {isUpdateCompletedSuccessfully ? 'Update Successful' : isUpdateErrored @@ -51,8 +65,9 @@ const MigrationView = () => { {isUpdateCompletedSuccessfully ? (

- Your file system has been successfully updated. Now you can explore all of your Insomnia files on your - local system and use git on your CLI to manage changes. + All {migratedCount} Insomnia git project{migratedCount !== 1 ? 's' : ''} on your local system have been + updated. You can now explore them, use git from your favourite CLI, or modify them from any other tool of + your choice.

) : isUpdateCompletedWithErrors ? ( <> @@ -73,7 +88,7 @@ const MigrationView = () => { <>

We hit an unexpected error while updating your file system. Please try again.

- Having trouble and need to contact us, or back up to an old version? See our docs + Having trouble and need to contact us, or back up to an old version? See our{' '} docs. @@ -82,23 +97,20 @@ const MigrationView = () => { ) : ( <>

- In order to continue with this update, we need to adjust your local file system. This is required to - enable managing Insomnia changes using git on the CLI. + In order to continue with this update, we need to adjust your local projects. This is required to enable + managing Insomnia changes using git on the CLI.

{isUpdateRunning ? 'Note: Your data is safe and the update only takes seconds.' - : 'Note: This update does NOT change your data and only affects how your local Insomnia files are stored.'} + : 'Note: This update does NOT affect any ongoing work or pending changes, and only affects how your local Insomnia files are stored.'}

)}
{isUpdateCompletedSuccessfully ? ( - + Open Insomnia ) : isUpdateCompletedWithErrors ? ( @@ -111,10 +123,7 @@ const MigrationView = () => { Copy Error Logs - + Open Insomnia
@@ -128,20 +137,12 @@ const MigrationView = () => { Copy Error Logs -

) : ( - )} @@ -181,7 +182,7 @@ const Component = () => {
+ + + You can now browse Git Sync project files on your local file system and manage changes using your normal + Git workflows.{' '} + + Learn more ↗ + + + +
-

- You can now browse Git Sync project files on your local file system and manage changes using your normal Git - workflows.{' '} - - Learn more ↗ - -

-

Path to this project:

-
+

Path to this project:

+
{repoPath} + + + + Open in file system + +
-
); @@ -1370,8 +1399,8 @@ const OriginalGitProjectStagingModal: FC<

)} -
-
+
+
{isGenerateCommitMessagesWithAIEnabled && (

diff --git a/packages/insomnia/src/ui/components/modals/git-staging-modal.tsx b/packages/insomnia/src/ui/components/modals/git-staging-modal.tsx index ec6185298e..11df335e14 100644 --- a/packages/insomnia/src/ui/components/modals/git-staging-modal.tsx +++ b/packages/insomnia/src/ui/components/modals/git-staging-modal.tsx @@ -148,7 +148,7 @@ export const GitStagingModal: FC<{ onClose: () => void }> = ({ onClose }) => {

-
+
{ diff --git a/packages/insomnia/src/ui/components/modals/sync-staging-modal.tsx b/packages/insomnia/src/ui/components/modals/sync-staging-modal.tsx index ed41914b42..f9fb6851e2 100644 --- a/packages/insomnia/src/ui/components/modals/sync-staging-modal.tsx +++ b/packages/insomnia/src/ui/components/modals/sync-staging-modal.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { Button, Dialog, @@ -176,7 +176,7 @@ export const SyncStagingModal = ({ onClose, status, syncItems }: Props) => {
-
+
{ diff --git a/packages/insomnia/src/ui/components/project/project-settings-form.tsx b/packages/insomnia/src/ui/components/project/project-settings-form.tsx index 22f5148682..f070148134 100644 --- a/packages/insomnia/src/ui/components/project/project-settings-form.tsx +++ b/packages/insomnia/src/ui/components/project/project-settings-form.tsx @@ -11,6 +11,8 @@ import { Select, SelectValue, TextField, + Tooltip, + TooltipTrigger, } from 'react-aria-components'; import { useParams } from 'react-router'; @@ -33,6 +35,7 @@ import { useActiveView } from '~/ui/components/project/utils'; import { useIsLightTheme } from '~/ui/hooks/theme'; import { useIsGitSyncEnabled } from '~/ui/hooks/use-organization-features'; +import { platform } from '../../../common/platform'; import { useProjectUpdateActionFetcher } from '../../../routes/organization.$organizationId.project.$projectId.update'; import { Icon } from '../icon'; @@ -323,35 +326,40 @@ export const ProjectSettingsForm: FC = ({ Learn more ↗
-
- +
+ {repoPath} - + + + + Open in file system + +