diff --git a/.gitignore b/.gitignore index 712ad9d0dcbc554bb70cb74dfa7218bbd7e502b4..2c2681e14b7f45b0a927e0482da75962781a5cc0 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ dist/ # Bun bun.lockb + +# Local Netlify folder +.netlify diff --git a/netlify.toml b/netlify.toml index 5737a8b04eac8f7b8d08ca8f25446ac189a92957..8e20cb64c4d2e58b35f751ac116d3d803a32a13d 100644 --- a/netlify.toml +++ b/netlify.toml @@ -2,6 +2,14 @@ command = "bun run build" publish = "dist" +[dev] + command = "bun run dev" + port = 3001 + targetPort = 3000 + publish = "dist" + framework = "vite" + autoLaunch = true + # Handle React Router [[redirects]] from = "/*" @@ -16,10 +24,10 @@ X-XSS-Protection = "1; mode=block" X-Content-Type-Options = "nosniff" Referrer-Policy = "strict-origin-when-cross-origin" - Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; connect-src 'self' https:;" + Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; connect-src 'self' https:; worker-src 'self' blob:; child-src 'self' blob:;" # Cache control for static assets [[headers]] for = "/assets/*" [headers.values] - Cache-Control = "public, max-age=31536000, immutable" \ No newline at end of file + Cache-Control = "public, max-age=31536000, immutable" diff --git a/package.json b/package.json index c4f3e6f1852bced211fdd306406c3e55da34a941..4096d5c9cbc23db4943970748e60f85f88a6b95b 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "eslint-plugin-react-hooks": "^latest", "eslint-plugin-simple-import-sort": "^8.0.0", "eslint-plugin-sort-destructure-keys": "^1.4.0", + "netlify-cli": "^19.1.5", "nyc": "^15.1.0", "postcss": "^8.4.47", "prettier": "^3.3.3", diff --git a/src/components/common/Input/index.tsx b/src/components/common/Input/index.tsx index 96558ece4ada580848eae9ac9119b22daccffa1d..73af715634f432674afe06cd1924021229946030 100644 --- a/src/components/common/Input/index.tsx +++ b/src/components/common/Input/index.tsx @@ -19,10 +19,10 @@ const Input: FC<Props> = ({ size = 'md', ...props }) => ( w-full block rounded-[1.5rem] px-4 - bg-transparent - border border-[var(--charcoal-1)] - focus:outline-none focus:border-[var(--primary)] - placeholder:text-sm placeholder:text-[var(--charcoal-1)] + bg-charcoal-4 + border border-charcoal-1 + focus:outline-none focus:border-primary + placeholder:text-sm placeholder:text-charcoal-1 ${sizeMap[size]} ${props.className || ''} `} diff --git a/src/components/modals/CreateChannelView/CreateChannelView.tsx b/src/components/modals/CreateChannelView/CreateChannelView.tsx index ddb25b95a2114b9fe7ae79b4ccf5955f366701d0..a4f3239bc327675cab372cfda7af04f692fa7b8b 100644 --- a/src/components/modals/CreateChannelView/CreateChannelView.tsx +++ b/src/components/modals/CreateChannelView/CreateChannelView.tsx @@ -55,16 +55,44 @@ const CreateChannelView: FC = () => { const onCreate = useCallback(async () => { if (error) { + console.error('Validation error:', error); return; } + const trimmedName = channelName.trim(); + + // Log the actual values for debugging + console.log('Attempting to create channel with:', { + name: trimmedName, + nameLength: trimmedName.length, + description: channelDesc, + privacyLevel, + dmsEnabled + }); + try { - createChannel(channelName, channelDesc, privacyLevel, dmsEnabled); + if (!trimmedName) { + alert({ + type: 'error', + content: t('Channel name is required') + }); + return; + } + + if (!regex.test(trimmedName)) { + alert({ + type: 'error', + content: t('Invalid channel name format') + }); + return; + } + + await createChannel(trimmedName, channelDesc, privacyLevel, dmsEnabled); setChannelName(''); setChannelDesc(''); closeModal(); } catch (e) { - console.error((e as any).message); + console.error('Failed to create channel:', e); alert({ type: 'error', content: t('Something wrong happened, please check your details.') @@ -89,7 +117,17 @@ const CreateChannelView: FC = () => { <ModalTitle>{t('Create New Space')}</ModalTitle> <div className='space-y-4 w-full'> <Input - className={cn({ 'border-red text-red placeholder:text-red': !!nameError })} + autoFocus + className={cn(` + focus:border-primary + focus-visible:outline-none w-full + rounded-2xl bg-charcoal-4 border border-charcoal-1 px-4 py-2 + placeholder-charcoal-1 placeholder:text-sm + transition-all`, + { + 'border-red text-red': !!nameError + } + )} data-testid='channel-name-input' type='text' placeholder={t('Name')} @@ -103,8 +141,7 @@ const CreateChannelView: FC = () => { onChange={onChannelNameChange} /> <textarea - className={cn( - ` + className={cn(` focus:border-primary focus-visible:outline-none resize-none h-10 active:outline-0 w-full rounded-2xl bg-charcoal-4 border border-charcoal-1 px-4 py-2 diff --git a/src/contexts/network-client-context.tsx b/src/contexts/network-client-context.tsx index 5b5f3639ef5909c5bd3fefc769f8c1e659793fbf..e2643722ede5b448839d2a6464f0d8f3143ed6df 100644 --- a/src/contexts/network-client-context.tsx +++ b/src/contexts/network-client-context.tsx @@ -1108,6 +1108,22 @@ export const NetworkProvider: FC<WithChildren> = (props) => { } }, [channelManager, fetchInitialData]); + useEffect(() => { + if (!utils) return; + + const interval = setInterval(() => { + try { + // Try to call a simple WASM function to check if it's still responsive + utils.GetWasmSemanticVersion(); + } catch (error) { + console.error('WASM appears to be non-responsive, refreshing page...', error); + window.location.reload(); + } + }, 10000); // Check every 10 seconds + + return () => clearInterval(interval); + }, [utils]); + const ctx: NetworkContext = { decryptMessageContent: cipher?.decrypt, channelManager,