forked from 77media/video-flow
feat:授权回调修改
This commit is contained in:
parent
d3db6388e1
commit
8e1901f72c
@ -7,10 +7,37 @@ export default function TwitterAuthCallbackPage() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 此页面主要是为了 Next.js 路由捕获回调 URL。
|
// 解析回调参数
|
||||||
// 在 ShareModal 检测到参数后会打开 TwitterCallbackModal。
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
// 重定向到主页面或相关仪表板页面。
|
const state = searchParams.get('state');
|
||||||
// 参数将由 ShareModal 接收处理。
|
const code = searchParams.get('code');
|
||||||
|
|
||||||
|
// 将回调参数写入 localStorage,供原窗口读取
|
||||||
|
if (state && code) {
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
state,
|
||||||
|
code,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
};
|
||||||
|
localStorage.setItem('twitterAuthCallbackPayload', JSON.stringify(payload));
|
||||||
|
// 通过变化一个随机标记键,确保触发其它窗口的 storage 事件
|
||||||
|
localStorage.setItem('twitterAuthCallbackFlag', Math.random().toString(36).slice(2));
|
||||||
|
} catch {
|
||||||
|
// 忽略本地存储异常
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通过 postMessage 通知打开者(如果存在且同源策略允许)
|
||||||
|
try {
|
||||||
|
if (window.opener) {
|
||||||
|
window.opener.postMessage({ type: 'TWITTER_AUTH_CALLBACK', state, code }, window.location.origin);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳回应用页面(原窗口会通过 storage 事件弹出处理弹框)
|
||||||
router.push('/movies?twitterCallback=true');
|
router.push('/movies?twitterCallback=true');
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
|
|||||||
@ -103,16 +103,53 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
const state = urlParams.get('state');
|
const state = urlParams.get('state');
|
||||||
const code = urlParams.get('code');
|
const code = urlParams.get('code');
|
||||||
|
|
||||||
// 检查是否是 Twitter 授权回调
|
// 当前就在回调路径(同窗口授权)
|
||||||
if (state && code && window.location.pathname.includes('/api/video-share/x/auth/callback')) {
|
if (state && code && window.location.pathname.includes('/api/video-share/x/auth/callback')) {
|
||||||
setTwitterCallbackParams({ state, code });
|
setTwitterCallbackParams({ state, code });
|
||||||
setTwitterCallbackVisible(true);
|
setTwitterCallbackVisible(true);
|
||||||
|
|
||||||
// 清理 URL 参数
|
|
||||||
const newUrl = window.location.pathname;
|
const newUrl = window.location.pathname;
|
||||||
window.history.replaceState({}, document.title, newUrl);
|
window.history.replaceState({}, document.title, newUrl);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 新窗口授权,回到非回调路径,比如 /movies?twitterCallback=true
|
||||||
|
const hasFlag = urlParams.get('twitterCallback') === 'true';
|
||||||
|
const cached = localStorage.getItem('twitterAuthCallbackPayload');
|
||||||
|
if (hasFlag && cached) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(cached);
|
||||||
|
if (parsed?.state && parsed?.code) {
|
||||||
|
setTwitterCallbackParams({ state: parsed.state, code: parsed.code });
|
||||||
|
setTwitterCallbackVisible(true);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
|
||||||
|
}
|
||||||
|
// 清理 URL 中的 twitterCallback 标记
|
||||||
|
const cleanUrl = window.location.pathname;
|
||||||
|
window.history.replaceState({}, document.title, cleanUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听 storage 事件(跨窗口通知)
|
||||||
|
const onStorage = (e: StorageEvent) => {
|
||||||
|
if (e.key === 'twitterAuthCallbackFlag') {
|
||||||
|
const cachedPayload = localStorage.getItem('twitterAuthCallbackPayload');
|
||||||
|
if (cachedPayload) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(cachedPayload);
|
||||||
|
if (parsed?.state && parsed?.code) {
|
||||||
|
setTwitterCallbackParams({ state: parsed.state, code: parsed.code });
|
||||||
|
setTwitterCallbackVisible(true);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener('storage', onStorage);
|
||||||
|
return () => window.removeEventListener('storage', onStorage);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -306,6 +343,11 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
onClose={() => {
|
onClose={() => {
|
||||||
setTwitterCallbackVisible(false);
|
setTwitterCallbackVisible(false);
|
||||||
setTwitterCallbackParams(null);
|
setTwitterCallbackParams(null);
|
||||||
|
// 关闭时清理临时缓存
|
||||||
|
try {
|
||||||
|
localStorage.removeItem('twitterAuthCallbackPayload');
|
||||||
|
localStorage.removeItem('twitterAuthCallbackFlag');
|
||||||
|
} catch {}
|
||||||
}}
|
}}
|
||||||
project={project}
|
project={project}
|
||||||
urlParams={twitterCallbackParams}
|
urlParams={twitterCallbackParams}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import type { MouseEvent } from 'react';
|
import type { MouseEvent } from 'react';
|
||||||
import { Loader2, Download, Share } from 'lucide-react';
|
import { Loader2, Download, Send } from 'lucide-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import './style/create-to-video2.css';
|
import './style/create-to-video2.css';
|
||||||
|
|
||||||
@ -382,7 +382,7 @@ export default function CreateToVideo2() {
|
|||||||
className="w-[2.5rem] h-[2.5rem] rounded-full items-center justify-center p-0 hidden group-hover:flex transition-all duration-300 hover:bg-white/15"
|
className="w-[2.5rem] h-[2.5rem] rounded-full items-center justify-center p-0 hidden group-hover:flex transition-all duration-300 hover:bg-white/15"
|
||||||
onClick={(e) => handleShareClick(e, project)}
|
onClick={(e) => handleShareClick(e, project)}
|
||||||
>
|
>
|
||||||
<Share className="w-4 h-4 text-white" />
|
<Send className="w-4 h-4 text-white" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{/* 下载按钮 */}
|
{/* 下载按钮 */}
|
||||||
|
|||||||
@ -155,9 +155,6 @@ export const validateEnvConfig = (): { isValid: boolean; errors: string[] } => {
|
|||||||
errors.push('NEXT_PUBLIC_JAVA_URL is required');
|
errors.push('NEXT_PUBLIC_JAVA_URL is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!baseUrl) {
|
|
||||||
errors.push('NEXT_PUBLIC_SHARE_API_URL is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!googleClientId) {
|
if (!googleClientId) {
|
||||||
errors.push('NEXT_PUBLIC_GOOGLE_CLIENT_ID is required');
|
errors.push('NEXT_PUBLIC_GOOGLE_CLIENT_ID is required');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user