()
| 122 | // Load all plugins from all marketplaces |
| 123 | useEffect(() => { |
| 124 | async function loadAllPlugins() { |
| 125 | try { |
| 126 | const config = await loadKnownMarketplacesConfig(); |
| 127 | |
| 128 | // Load marketplaces with graceful degradation |
| 129 | const { |
| 130 | marketplaces, |
| 131 | failures |
| 132 | } = await loadMarketplacesWithGracefulDegradation(config); |
| 133 | |
| 134 | // Collect all plugins from all marketplaces |
| 135 | const allPlugins: InstallablePlugin[] = []; |
| 136 | for (const { |
| 137 | name, |
| 138 | data: marketplace |
| 139 | } of marketplaces) { |
| 140 | if (marketplace) { |
| 141 | for (const entry of marketplace.plugins) { |
| 142 | const pluginId = createPluginId(entry.name, name); |
| 143 | allPlugins.push({ |
| 144 | entry, |
| 145 | marketplaceName: name, |
| 146 | pluginId, |
| 147 | // Only block when globally installed (user/managed scope). |
| 148 | // Project/local-scope installs don't block — user may want to |
| 149 | // promote to user scope so it's available everywhere (gh-29997). |
| 150 | isInstalled: isPluginGloballyInstalled(pluginId) |
| 151 | }); |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | // Filter out installed and policy-blocked plugins |
| 157 | const uninstalledPlugins = allPlugins.filter(p => !p.isInstalled && !isPluginBlockedByPolicy(p.pluginId)); |
| 158 | |
| 159 | // Fetch install counts and sort by popularity |
| 160 | try { |
| 161 | const counts = await getInstallCounts(); |
| 162 | setInstallCounts(counts); |
| 163 | if (counts) { |
| 164 | // Sort by install count (descending), then alphabetically |
| 165 | uninstalledPlugins.sort((a_0, b_0) => { |
| 166 | const countA = counts.get(a_0.pluginId) ?? 0; |
| 167 | const countB = counts.get(b_0.pluginId) ?? 0; |
| 168 | if (countA !== countB) return countB - countA; |
| 169 | return a_0.entry.name.localeCompare(b_0.entry.name); |
| 170 | }); |
| 171 | } else { |
| 172 | // No counts available - sort alphabetically |
| 173 | uninstalledPlugins.sort((a_1, b_1) => a_1.entry.name.localeCompare(b_1.entry.name)); |
| 174 | } |
| 175 | } catch (error_0) { |
| 176 | // Log the error, then gracefully degrade to alphabetical sort |
| 177 | logForDebugging(`Failed to fetch install counts: ${errorMessage(error_0)}`); |
| 178 | uninstalledPlugins.sort((a, b) => a.entry.name.localeCompare(b.entry.name)); |
| 179 | } |
| 180 | setAvailablePlugins(uninstalledPlugins); |
| 181 |
no test coverage detected