Skip to content

Conversation

@hmacr
Copy link
Contributor

@hmacr hmacr commented Jan 26, 2026

Resolves SER-642

Various improvements to repositories UX

  • Do not list repositories that are not part of the installation.
  • Disable connect button on click
  • Fix GitHub installation links
  • Fix broken navigation of "create function"
  • Race condition in search
  • Opening a modal shows stale data initially

Summary by CodeRabbit

  • Improvements
    • Repository loading is now more efficient with deduplication.
    • Repository search input remains always enabled.
    • Connect button disables while a connection is in progress.
    • Loading indicators display clearly during repository fetches.
    • Pagination and result totals now properly reflect loading states.

✏️ Tip: You can customize this high-level summary in your review settings.

@appwrite
Copy link

appwrite bot commented Jan 26, 2026

Console (appwrite/console)

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code

Tip

Realtime gives you live updates for users, storage, functions, and databases

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 26, 2026

Walkthrough

This PR updates repository and installation handling across multiple components. It introduces request deduplication and improved loading state management in the repositories component, removes navigation tracking in favor of a simplified routing approach in the create-function page, and refactors installation-dependent UI rendering to rely on a reactive store instead of static data properties across two location pages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Improve UX for repositories modal' is partially related to the changeset. While it captures one aspect of the changes, it does not fully reflect the scope, which includes fixes for GitHub installation links, broken navigation in 'create function', race condition handling, and preventing stale modal data.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/components/git/repositories.svelte (1)

121-137: Prevent stale requests from clearing the loading state early.

The stale-response guard prevents old data writes, but isLoadingRepositories is still flipped to false by earlier requests in the callers. That can hide loading while a newer request is still in flight. Consider tying loading-state updates to the same requestId.

🛠️ Suggested fix to tie loading state to the latest request
-    const debouncedLoadRepositories = debounce(
-        async (installationId: string, searchTerm: string) => {
-            isLoadingRepositories = true;
-            try {
-                await loadRepositories(installationId, searchTerm);
-            } finally {
-                isLoadingRepositories = false;
-            }
-        },
-        300
-    );
+    const debouncedLoadRepositories = debounce(
+        async (installationId: string, searchTerm: string) => {
+            await loadRepositories(installationId, searchTerm);
+        },
+        300
+    );

-    const loadRepositoryPage = async () => {
-        isLoadingRepositories = true;
-        try {
-            await loadRepositories(selectedInstallation, search);
-        } finally {
-            isLoadingRepositories = false;
-        }
-    };
+    const loadRepositoryPage = async () => {
+        await loadRepositories(selectedInstallation, search);
+    };

     async function loadRepositories(installationId: string, search: string) {
         const requestId = ++loadRepositoriesRequestId;
+        isLoadingRepositories = true;

-        const result = await sdk
-            .forProject(page.params.region, page.params.project)
-            .vcs.listRepositories({
-                installationId,
-                type:
-                    product === 'functions' ? VCSDetectionType.Runtime : VCSDetectionType.Framework,
-                search: search || undefined,
-                queries: [Query.limit(limit), Query.offset(offset)]
-            });
-
-        // Stale request
-        if (requestId !== loadRepositoriesRequestId) {
-            return;
-        }
-
-        $repositories.repositories =
-            product === 'functions'
-                ? (result as unknown as Models.ProviderRepositoryRuntimeList)
-                      .runtimeProviderRepositories
-                : (result as unknown as Models.ProviderRepositoryFrameworkList)
-                      .frameworkProviderRepositories; //TODO: remove forced cast after backend fixes
-        $repositories.total = result.total;
-        $repositories.search = search;
-        $repositories.installationId = installationId;
-        return $repositories.repositories;
+        try {
+            const result = await sdk
+                .forProject(page.params.region, page.params.project)
+                .vcs.listRepositories({
+                    installationId,
+                    type:
+                        product === 'functions'
+                            ? VCSDetectionType.Runtime
+                            : VCSDetectionType.Framework,
+                    search: search || undefined,
+                    queries: [Query.limit(limit), Query.offset(offset)]
+                });
+
+            // Stale request
+            if (requestId !== loadRepositoriesRequestId) {
+                return;
+            }
+
+            $repositories.repositories =
+                product === 'functions'
+                    ? (result as unknown as Models.ProviderRepositoryRuntimeList)
+                          .runtimeProviderRepositories
+                    : (result as unknown as Models.ProviderRepositoryFrameworkList)
+                          .frameworkProviderRepositories; //TODO: remove forced cast after backend fixes
+            $repositories.total = result.total;
+            $repositories.search = search;
+            $repositories.installationId = installationId;
+            return $repositories.repositories;
+        } finally {
+            if (requestId === loadRepositoriesRequestId) {
+                isLoadingRepositories = false;
+            }
+        }
     }
🤖 Fix all issues with AI agents
In `@src/lib/components/git/repositories.svelte`:
- Around line 276-280: The click handler sets connectingRepositoryId (used to
disable buttons) but never clears it, so failures block all buttons; update the
connect function to return a Promise and ensure connectingRepositoryId is reset
in a finally block (e.g., inside connect or in the caller) so it is cleared
whether connect succeeds or throws; update all callers of connect to
return/await that Promise so the finally runs and the disabled state (tied to
connectingRepositoryId) is released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants