Refactor proxyFetch and enhance MediaProviderDetailPage layout

- Removed the isCloud check from proxyFetch.js, simplifying the fetch patching logic.
- Updated MediaProviderDetailPage to include a new section for API key retrieval, improving user experience with clearer layout and additional notice text.
- Enhanced ConnectionRow to better handle email display names.
- Improved ProviderDetailPage to conditionally render provider notices and API key links.
- Refactored localDb, requestDetailsDb, and usageDb to remove unnecessary isCloud checks, streamlining database interactions.
- Updated OAuthModal to combine waiting and manual input steps for a more cohesive user flow.
- Added API key URLs to several providers in providers.js for better accessibility.
This commit is contained in:
decolua
2026-05-01 17:03:13 +07:00
parent f8d2a9ff76
commit f410061e70
9 changed files with 144 additions and 147 deletions

View File

@@ -1408,7 +1408,20 @@ export default function MediaProviderDetailPage() {
/>
</div>
<div className="flex-1">
<h1 className="text-3xl font-semibold tracking-tight">{provider.name}</h1>
<div className="flex items-center gap-3 flex-wrap">
<h1 className="text-3xl font-semibold tracking-tight">{provider.name}</h1>
{!isCustom && provider.notice?.apiKeyUrl && (
<a
href={provider.notice.apiKeyUrl}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-primary hover:underline inline-flex items-center gap-1"
>
<span className="material-symbols-outlined text-sm">open_in_new</span>
Get API Key
</a>
)}
</div>
<div className="flex items-center gap-1.5 mt-1 flex-wrap">
{isCustom && <Badge variant="default" size="sm">Custom · {customNode?.prefix}</Badge>}
{kinds.map((k) => (
@@ -1439,6 +1452,24 @@ export default function MediaProviderDetailPage() {
</div>
)}
{/* Provider notice text (only when there's actual text content) */}
{!isCustom && provider.notice?.text && !provider.deprecated && (
<div className="flex flex-col gap-2 rounded-lg border border-blue-500/30 bg-blue-500/10 px-3 py-2 sm:flex-row sm:items-center">
<span className="material-symbols-outlined text-[16px] text-blue-500 shrink-0">info</span>
<p className="min-w-0 flex-1 text-xs leading-relaxed text-blue-600 dark:text-blue-400">{provider.notice.text}</p>
{provider.notice.apiKeyUrl && (
<a
href={provider.notice.apiKeyUrl}
target="_blank"
rel="noopener noreferrer"
className="inline-flex justify-center rounded bg-blue-500 px-2 py-1 text-xs font-medium text-white transition-colors hover:bg-blue-600 sm:py-0.5"
>
Get API Key →
</a>
)}
</div>
)}
{/* Connections */}
{!isCustom && provider.noAuth ? (
<NoAuthProxyCard providerId={id} />

View File

@@ -65,8 +65,9 @@ export default function ConnectionRow({ connection, proxyPools, isOAuth, isFirst
}
};
const isEmail = (v) => typeof v === "string" && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);
const displayName = isOAuth
? connection.name || connection.email || connection.displayName || "OAuth Account"
? (isEmail(connection.email) ? connection.email : (isEmail(connection.name) ? connection.name : (connection.name || connection.email || connection.displayName || "OAuth Account")))
: connection.name;
// Use useState + useEffect for impure Date.now() to avoid calling during render

View File

@@ -760,7 +760,20 @@ export default function ProviderDetailPage() {
)}
</div>
<div className="min-w-0">
<h1 className="truncate text-2xl font-semibold tracking-tight sm:text-3xl">{providerInfo.name}</h1>
<div className="flex items-center gap-3 flex-wrap">
<h1 className="truncate text-2xl font-semibold tracking-tight sm:text-3xl">{providerInfo.name}</h1>
{providerInfo.notice?.apiKeyUrl && !providerInfo.deprecated && (
<a
href={providerInfo.notice.apiKeyUrl}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-primary hover:underline inline-flex items-center gap-1"
>
<span className="material-symbols-outlined text-sm">open_in_new</span>
Get API Key
</a>
)}
</div>
<p className="text-text-muted">
{connections.length} connection{connections.length === 1 ? "" : "s"}
</p>
@@ -775,7 +788,7 @@ export default function ProviderDetailPage() {
</div>
)}
{providerInfo.notice && !providerInfo.deprecated && (
{providerInfo.notice?.text && !providerInfo.deprecated && (
<div className="flex flex-col gap-2 rounded-lg border border-blue-500/30 bg-blue-500/10 px-3 py-2 sm:flex-row sm:items-center">
<span className="material-symbols-outlined text-[16px] text-blue-500 shrink-0">info</span>
<p className="min-w-0 flex-1 text-xs leading-relaxed text-blue-600 dark:text-blue-400">{providerInfo.notice.text}</p>