mirror of
https://github.com/logos-messaging/OpChan.git
synced 2026-01-05 22:33:07 +00:00
wip
This commit is contained in:
parent
619c914e1b
commit
8d0f86fb2e
@ -1,10 +1,20 @@
|
|||||||
export * from './provider/OpChanProvider';
|
// New v1 exports are namespaced to avoid breaking the app while we migrate.
|
||||||
export { ClientProvider, useClient } from './contexts/ClientContext';
|
// Old API remains available under ./old/index exports.
|
||||||
export { AuthProvider, useAuth } from './contexts/AuthContext';
|
|
||||||
export { ForumProvider, useForum as useForumContext } from './contexts/ForumContext';
|
export * from './old/index';
|
||||||
export { ModerationProvider, useModeration } from './contexts/ModerationContext';
|
|
||||||
export { useIdentity } from './hooks/useIdentity';
|
export {
|
||||||
|
OpChanProvider as OpChanProviderV1,
|
||||||
|
useClient as useClientV1,
|
||||||
|
} from './v1/context/ClientContext';
|
||||||
|
|
||||||
|
export { OpChanProvider as NewOpChanProvider } from './v1/provider/OpChanProvider';
|
||||||
|
|
||||||
|
export { useAuth as useAuthV1 } from './v1/hooks/useAuth';
|
||||||
|
export { useContent as useContentV1 } from './v1/hooks/useContent';
|
||||||
|
export { usePermissions as usePermissionsV1 } from './v1/hooks/usePermissions';
|
||||||
|
export { useNetwork as useNetworkV1 } from './v1/hooks/useNetwork';
|
||||||
|
export { useUserDisplay as useUserDisplayV1 } from './v1/hooks/useUserDisplay';
|
||||||
|
export { useForum as useForumV1 } from './v1/hooks/useForum';
|
||||||
|
|
||||||
export * from './hooks';
|
|
||||||
export { useForumApi as useForum } from './hooks/useForum';
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,15 @@ import { DelegationDuration } from '@opchan/core';
|
|||||||
import { useAppKitAccount } from '@reown/appkit/react';
|
import { useAppKitAccount } from '@reown/appkit/react';
|
||||||
import { useClient } from './ClientContext';
|
import { useClient } from './ClientContext';
|
||||||
|
|
||||||
|
// Extend the base User with convenient, display-focused fields
|
||||||
|
export type CurrentUser = User & {
|
||||||
|
displayName: string;
|
||||||
|
ensName?: string;
|
||||||
|
ordinalDetailsText?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export interface AuthContextValue {
|
export interface AuthContextValue {
|
||||||
currentUser: User | null;
|
currentUser: CurrentUser | null;
|
||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
isAuthenticating: boolean;
|
isAuthenticating: boolean;
|
||||||
verificationStatus: EVerificationStatus;
|
verificationStatus: EVerificationStatus;
|
||||||
@ -31,7 +38,7 @@ const AuthContext = createContext<AuthContextValue | null>(null);
|
|||||||
|
|
||||||
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const [currentUser, setCurrentUser] = useState<User | null>(null);
|
const [currentUser, setCurrentUser] = useState<CurrentUser | null>(null);
|
||||||
const [isAuthenticating, setIsAuthenticating] = useState(false);
|
const [isAuthenticating, setIsAuthenticating] = useState(false);
|
||||||
|
|
||||||
// Get wallet connection status from AppKit
|
// Get wallet connection status from AppKit
|
||||||
@ -42,6 +49,30 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
const connectedAddress = bitcoinAccount.address || ethereumAccount.address;
|
const connectedAddress = bitcoinAccount.address || ethereumAccount.address;
|
||||||
const walletType = bitcoinAccount.isConnected ? 'bitcoin' : 'ethereum';
|
const walletType = bitcoinAccount.isConnected ? 'bitcoin' : 'ethereum';
|
||||||
|
|
||||||
|
// Helper: enrich a base User with identity-derived display fields
|
||||||
|
const enrichUserWithIdentity = useCallback(async (baseUser: User): Promise<CurrentUser> => {
|
||||||
|
const address = baseUser.address;
|
||||||
|
// Resolve identity (debounced) and read display name from service
|
||||||
|
const identity = await client.userIdentityService.getUserIdentity(address);
|
||||||
|
const displayName = client.userIdentityService.getDisplayName(address);
|
||||||
|
|
||||||
|
const ensName = identity?.ensName ?? baseUser.ensDetails?.ensName;
|
||||||
|
const ordinalDetailsText = identity?.ordinalDetails?.ordinalDetails ?? baseUser.ordinalDetails?.ordinalDetails;
|
||||||
|
const callSign = identity?.callSign ?? baseUser.callSign;
|
||||||
|
const displayPreference = identity?.displayPreference ?? baseUser.displayPreference;
|
||||||
|
const verificationStatus = identity?.verificationStatus ?? baseUser.verificationStatus;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...baseUser,
|
||||||
|
callSign,
|
||||||
|
displayPreference,
|
||||||
|
verificationStatus,
|
||||||
|
displayName,
|
||||||
|
ensName,
|
||||||
|
ordinalDetailsText,
|
||||||
|
} as CurrentUser;
|
||||||
|
}, [client]);
|
||||||
|
|
||||||
// ✅ Removed console.log to prevent infinite loop spam
|
// ✅ Removed console.log to prevent infinite loop spam
|
||||||
|
|
||||||
// Define verifyOwnership function early so it can be used in useEffect dependencies
|
// Define verifyOwnership function early so it can be used in useEffect dependencies
|
||||||
@ -56,14 +87,15 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
|
|
||||||
const newVerificationStatus = identity?.verificationStatus ?? EVerificationStatus.WALLET_CONNECTED;
|
const newVerificationStatus = identity?.verificationStatus ?? EVerificationStatus.WALLET_CONNECTED;
|
||||||
|
|
||||||
const updatedUser = {
|
const updatedUser: User = {
|
||||||
...currentUser,
|
...currentUser,
|
||||||
verificationStatus: newVerificationStatus,
|
verificationStatus: newVerificationStatus,
|
||||||
ensDetails: identity?.ensName ? { ensName: identity.ensName } : undefined,
|
ensDetails: identity?.ensName ? { ensName: identity.ensName } : undefined,
|
||||||
ordinalDetails: identity?.ordinalDetails,
|
ordinalDetails: identity?.ordinalDetails,
|
||||||
} as User;
|
} as User;
|
||||||
|
|
||||||
setCurrentUser(updatedUser);
|
const enriched = await enrichUserWithIdentity(updatedUser);
|
||||||
|
setCurrentUser(enriched);
|
||||||
await localDatabase.storeUser(updatedUser);
|
await localDatabase.storeUser(updatedUser);
|
||||||
|
|
||||||
await localDatabase.upsertUserIdentity(currentUser.address, {
|
await localDatabase.upsertUserIdentity(currentUser.address, {
|
||||||
@ -77,11 +109,12 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Verification failed:', error);
|
console.error('❌ Verification failed:', error);
|
||||||
const updatedUser = { ...currentUser, verificationStatus: EVerificationStatus.WALLET_CONNECTED } as User;
|
const updatedUser = { ...currentUser, verificationStatus: EVerificationStatus.WALLET_CONNECTED } as User;
|
||||||
setCurrentUser(updatedUser);
|
const enriched = await enrichUserWithIdentity(updatedUser);
|
||||||
|
setCurrentUser(enriched);
|
||||||
await localDatabase.storeUser(updatedUser);
|
await localDatabase.storeUser(updatedUser);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}, [client, currentUser]);
|
}, [client, currentUser, enrichUserWithIdentity]);
|
||||||
|
|
||||||
// Hydrate user from LocalDatabase on mount
|
// Hydrate user from LocalDatabase on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -90,7 +123,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
try {
|
try {
|
||||||
const user = await localDatabase.loadUser();
|
const user = await localDatabase.loadUser();
|
||||||
if (mounted && user) {
|
if (mounted && user) {
|
||||||
setCurrentUser(user);
|
const enriched = await enrichUserWithIdentity(user);
|
||||||
|
setCurrentUser(enriched);
|
||||||
|
|
||||||
// 🔄 Sync verification status with UserIdentityService
|
// 🔄 Sync verification status with UserIdentityService
|
||||||
await localDatabase.upsertUserIdentity(user.address, {
|
await localDatabase.upsertUserIdentity(user.address, {
|
||||||
@ -118,7 +152,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
return () => {
|
return () => {
|
||||||
mounted = false;
|
mounted = false;
|
||||||
};
|
};
|
||||||
}, []); // Remove verifyOwnership dependency to prevent infinite loops
|
}, [enrichUserWithIdentity]); // Remove verifyOwnership dependency to prevent infinite loops
|
||||||
|
|
||||||
// Auto-connect when wallet is detected
|
// Auto-connect when wallet is detected
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -143,7 +177,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
lastChecked: Date.now(),
|
lastChecked: Date.now(),
|
||||||
};
|
};
|
||||||
|
|
||||||
setCurrentUser(user);
|
const enriched = await enrichUserWithIdentity(user);
|
||||||
|
setCurrentUser(enriched);
|
||||||
await localDatabase.storeUser(user);
|
await localDatabase.storeUser(user);
|
||||||
|
|
||||||
// Also store identity info so UserIdentityService can access it
|
// Also store identity info so UserIdentityService can access it
|
||||||
@ -174,7 +209,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
};
|
};
|
||||||
|
|
||||||
autoConnect();
|
autoConnect();
|
||||||
}, [isWalletConnected, connectedAddress, walletType]); // Remove currentUser and verifyOwnership dependencies
|
}, [isWalletConnected, connectedAddress, walletType, enrichUserWithIdentity]); // Remove currentUser and verifyOwnership dependencies
|
||||||
|
|
||||||
// Ensure verificationStatus reflects a connected wallet even if a user was preloaded
|
// Ensure verificationStatus reflects a connected wallet even if a user was preloaded
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -203,7 +238,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
lastChecked: Date.now(),
|
lastChecked: Date.now(),
|
||||||
} as User;
|
} as User;
|
||||||
|
|
||||||
setCurrentUser(updatedUser);
|
const enriched = await enrichUserWithIdentity(updatedUser);
|
||||||
|
setCurrentUser(enriched);
|
||||||
await localDatabase.storeUser(updatedUser);
|
await localDatabase.storeUser(updatedUser);
|
||||||
await localDatabase.upsertUserIdentity(connectedAddress, {
|
await localDatabase.upsertUserIdentity(connectedAddress, {
|
||||||
ensName: updatedUser.ensDetails?.ensName,
|
ensName: updatedUser.ensDetails?.ensName,
|
||||||
@ -216,7 +252,20 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
|
|
||||||
syncConnectedStatus();
|
syncConnectedStatus();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isWalletConnected, connectedAddress, walletType, currentUser]);
|
}, [isWalletConnected, connectedAddress, walletType, currentUser, enrichUserWithIdentity]);
|
||||||
|
|
||||||
|
// Keep currentUser in sync with identity updates (e.g., profile changes)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!currentUser) return;
|
||||||
|
const off = client.userIdentityService.addRefreshListener(async (addr) => {
|
||||||
|
if (addr !== currentUser.address) return;
|
||||||
|
const enriched = await enrichUserWithIdentity(currentUser as User);
|
||||||
|
setCurrentUser(enriched);
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
try { off && off(); } catch {}
|
||||||
|
};
|
||||||
|
}, [client, currentUser, enrichUserWithIdentity]);
|
||||||
|
|
||||||
const connectWallet = useCallback(async (): Promise<boolean> => {
|
const connectWallet = useCallback(async (): Promise<boolean> => {
|
||||||
if (!isWalletConnected || !connectedAddress) return false;
|
if (!isWalletConnected || !connectedAddress) return false;
|
||||||
@ -231,7 +280,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
verificationStatus: EVerificationStatus.WALLET_CONNECTED,
|
verificationStatus: EVerificationStatus.WALLET_CONNECTED,
|
||||||
lastChecked: Date.now(),
|
lastChecked: Date.now(),
|
||||||
};
|
};
|
||||||
setCurrentUser(user);
|
const enriched = await enrichUserWithIdentity(user);
|
||||||
|
setCurrentUser(enriched);
|
||||||
await localDatabase.storeUser(user);
|
await localDatabase.storeUser(user);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -240,7 +290,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
} finally {
|
} finally {
|
||||||
setIsAuthenticating(false);
|
setIsAuthenticating(false);
|
||||||
}
|
}
|
||||||
}, [currentUser?.displayPreference, isWalletConnected, connectedAddress, walletType]);
|
}, [currentUser?.displayPreference, isWalletConnected, connectedAddress, walletType, enrichUserWithIdentity]);
|
||||||
|
|
||||||
const disconnectWallet = useCallback(() => {
|
const disconnectWallet = useCallback(() => {
|
||||||
setCurrentUser(null);
|
setCurrentUser(null);
|
||||||
@ -6,7 +6,6 @@ export { useForumApi } from './useForum';
|
|||||||
export { useForumData } from './core/useForumData';
|
export { useForumData } from './core/useForumData';
|
||||||
export { usePermissions } from './core/usePermissions';
|
export { usePermissions } from './core/usePermissions';
|
||||||
export { useUserDisplay } from './core/useUserDisplay';
|
export { useUserDisplay } from './core/useUserDisplay';
|
||||||
export { useIdentity } from './useIdentity';
|
|
||||||
|
|
||||||
// Derived hooks (data slicing utilities)
|
// Derived hooks (data slicing utilities)
|
||||||
export { useCell } from './derived/useCell';
|
export { useCell } from './derived/useCell';
|
||||||
9
packages/react/src/old/index.ts
Normal file
9
packages/react/src/old/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export * from './provider/OpChanProvider';
|
||||||
|
export { ClientProvider, useClient } from './contexts/ClientContext';
|
||||||
|
export { AuthProvider, useAuth } from './contexts/AuthContext';
|
||||||
|
export { ForumProvider, useForum as useForumContext } from './contexts/ForumContext';
|
||||||
|
export { ModerationProvider, useModeration } from './contexts/ModerationContext';
|
||||||
|
|
||||||
|
export * from './hooks';
|
||||||
|
export { useForumApi as useForum } from './hooks/useForum';
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user