Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: SonarCloud analysis

on:
push:
branches: ['master']
branches: ["master"]
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const EditorBar = ({ editor, disabled }: ActionBarProps) => {
if (!editor) return;

const previousUrl = editor.getAttributes('link').href;
const url = window.prompt('URL', previousUrl);
const url = globalThis.prompt('URL', previousUrl);

if (url === null) return;

Expand All @@ -116,7 +116,7 @@ export const EditorBar = ({ editor, disabled }: ActionBarProps) => {
const addImage = useCallback(() => {
if (!editor) return;

const url = window.prompt('Image URL');
const url = globalThis.prompt('Image URL');

if (url) {
editor.chain().focus().setImage({ src: url }).run();
Expand Down
21 changes: 19 additions & 2 deletions src/features/welcome/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,22 @@ import { Button } from '@internxt/ui';
import smallLogo from '../../assets/logos/small-logo.svg';
import MailAppImage from '../../assets/images/welcome/welcome-page.webp';
import { useTranslationContext } from '@/i18n';
import { useAuth } from '@/hooks/useAuth';
import { useNavigation } from '@/hooks/useNavigation';

const WelcomePage = () => {
const { translate } = useTranslationContext();
const { goTo } = useNavigation();

const handleOnLogin = () => {
console.log('onLogin');
goTo('/inbox');
};

const { handleWebLogin, handleWebSignup } = useAuth({
onLogin: handleOnLogin,
translate,
});

return (
<div className="flex flex-col w-full h-screen overflow-hidden bg-linear-to-r from-gray-5 to-primary/20">
Expand All @@ -15,8 +28,12 @@ const WelcomePage = () => {
<p>{translate('meet')}</p>
</div>
<div className="flex flex-row gap-4">
<Button variant="secondary">{translate('actions.logIn')}</Button>
<Button variant="primary">{translate('actions.signUp')}</Button>
<Button variant="secondary" onClick={handleWebLogin}>
{translate('actions.logIn')}
</Button>
<Button variant="primary" onClick={handleWebSignup}>
{translate('actions.signUp')}
</Button>
</div>
</div>
<div className="flex flex-row justify-between pt-10">
Expand Down
103 changes: 103 additions & 0 deletions src/hooks/useAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { useCallback, useState } from 'react';
import { LocalStorageService } from '@/services/local-storage';
import { PaymentsService } from '@/services/sdk/payments.service';
import type { LoginCredentials } from '@/types/oauth';
import { OauthService } from '@/services/oauth/oauth.service';

interface UseWebAuthProps {
onLogin?: (token: string) => void
translate: (key: string) => string
}

export function useAuth({ onLogin, translate }: UseWebAuthProps) {
const [webAuthError, setWebAuthError] = useState('');

const saveUserSession = useCallback(
async (credentials: LoginCredentials) => {
LocalStorageService.instance.saveCredentials(
credentials.user,
credentials.mnemonic,
credentials.newToken,
);

try {
const subscription =
await PaymentsService.instance.getUserSubscription();
LocalStorageService.instance.setSubscription(subscription);
} catch (err) {
console.error('Error getting user subscription:', err);
}

onLogin?.(credentials.newToken);
},
[LocalStorageService, onLogin],
);

/**
* Handles web-based login using popup window
*/
const handleWebLogin = async () => {
setWebAuthError('');

try {
const credentials = await OauthService.instance.loginWithWeb();

if (!credentials?.newToken || !credentials?.user) {
throw new Error(translate('meet.auth.modal.error.invalidCredentials'));
}

await saveUserSession(credentials);
} catch (err: unknown) {
errorHandler(err);
}
};

/**
* Handles web-based signup using popup window
*/
const handleWebSignup = async () => {
setWebAuthError('');

try {
const credentials = await OauthService.instance.signupWithWeb();

if (!credentials?.newToken || !credentials?.user) {
throw new Error(translate('meet.auth.modal.error.invalidCredentials'));
}

await saveUserSession(credentials);
} catch (err: unknown) {
errorHandler(err);
}
};

const errorHandler = useCallback(
(err: unknown) => {
if (err instanceof Error) {
if (err.message.includes('popup blocker')) {
setWebAuthError(translate('meet.auth.modal.error.popupBlocked'));
} else if (err.message.includes('cancelled')) {
setWebAuthError(translate('meet.auth.modal.error.authCancelled'));
} else if (err.message.includes('timeout')) {
setWebAuthError(translate('meet.auth.modal.error.authTimeout'));
} else {
setWebAuthError(err.message);
}
} else {
setWebAuthError(translate('meet.auth.modal.error.genericError'));
}
},
[setWebAuthError],
);

const resetState = useCallback(() => {
setWebAuthError('');
}, []);

return {
webAuthError,
handleWebLogin,
handleWebSignup,
resetState,
};
}
2 changes: 1 addition & 1 deletion src/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type RouteObject, Navigate } from 'react-router-dom';
import { lazy } from 'react';
import RootLayout from '@/layouts/RootLayout';
import RootLayout from '@/routes/layouts/RootLayout';

const WelcomePage = lazy(() => import('@/features/welcome'));
const MailView = lazy(() => import('@/features/mail/MailView'));
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions src/routes/paths.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const PATHS = {
welcome: '/welcome',
inbox: '/inbox',
trash: '/trash',
} as const;
Expand Down
43 changes: 43 additions & 0 deletions src/services/oauth/errors/oauth.errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export class MissingAuthParamsToken extends Error {
constructor() {
super('Missing auth params token');

Object.setPrototypeOf(this, MissingAuthParamsToken.prototype);
}
}

export class AuthCancelledByUserError extends Error {
constructor() {
super('Authentication cancelled by user');

Object.setPrototypeOf(this, AuthCancelledByUserError.prototype);
}
}

export class AuthTimeoutError extends Error {
constructor() {
super('Authentication timed out');

Object.setPrototypeOf(this, AuthTimeoutError.prototype);
}
}

export class OpenAuthPopupError extends Error {
constructor() {
super(
'Failed to open authentication popup. Please check your popup blocker settings.',
);

Object.setPrototypeOf(this, OpenAuthPopupError.prototype);
}
}

export class WebAuthProcessingError extends Error {
constructor(cause?: Error) {
super(
`Web authentication processing failed: ${cause instanceof Error ? cause.message : 'Unknown error'}`,
);

Object.setPrototypeOf(this, WebAuthProcessingError.prototype);
}
}
Loading
Loading