Skip to content

Commit

Permalink
chore(base): module federation working
Browse files Browse the repository at this point in the history
  • Loading branch information
antonstjernquist committed Sep 16, 2024
1 parent ece7ff7 commit 66b87bf
Show file tree
Hide file tree
Showing 21 changed files with 435 additions and 125 deletions.
24 changes: 24 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/client/services/PhoneService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class PhoneService {
this.state = 'open';
global.SendNUIMessage({ type: 'SET_PHONE_OPEN', payload: true });
SetNuiFocus(true, true);
SetNuiFocusKeepInput(true);
// SetNuiFocusKeepInput(true);
await this.animate.openPhone();
}

Expand Down
32 changes: 16 additions & 16 deletions src/server/router/contacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ const contactIdSchema = z.object({
contactId: z.coerce.number(),
});

contactsRouter.add('/:contactId', async (ctx, next) => {
try {
const { contactId } = contactIdSchema.parse(ctx.params);
const contact = await ContactService.getContactById(ctx, contactId);

ctx.status = 200;
ctx.body = {
ok: true,
payload: contact,
};
} catch (error) {
handleError(error, ctx);
}

await next();
});
// contactsRouter.add('/:contactId', async (ctx, next) => {
// try {
// const { contactId } = contactIdSchema.parse(ctx.params);
// const contact = await ContactService.getContactById(ctx, contactId);

// ctx.status = 200;
// ctx.body = {
// ok: true,
// payload: contact,
// };
// } catch (error) {
// handleError(error, ctx);
// }

// await next();
// });

contactsRouter.add('/add', async (ctx, next) => {
try {
Expand Down
27 changes: 22 additions & 5 deletions src/server/services/MessageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import {
} from '../../shared/Errors';
import DeviceRepository from '../repositories/DeviceRepository';
import { Message } from '../../shared/Types';
import { getPlayerSrcBySid } from '../utils/player';
import { parseObjectToIsoString } from '../utils/date';
import { handleError } from '../utils/errors';

class MessageService {
private readonly messageRepository: typeof MessageRepository;
Expand All @@ -27,15 +30,15 @@ class MessageService {
}

public async sendMessage(
{ device }: RouterContext,
ctx: RouterContext,
content: string,
receiverPhoneNumber: string,
): Promise<Message> {
if (!device.sim_card_id) {
if (!ctx.device.sim_card_id) {
throw new SimcardNotFoundError('SENDER');
}

if (!device.sim_card_is_active) {
if (!ctx.device.sim_card_is_active) {
throw new SimCardNotActiveError('SENDER');
}

Expand All @@ -52,14 +55,29 @@ class MessageService {
}

const message = await this.messageRepository.createMessage({
sender_id: device.sim_card_id,
sender_id: ctx.device.sim_card_id,
receiver_id: receiverSimcard.id,
content,
});

this.broadcastNewMessage(ctx, message);

return message;
}

public async broadcastNewMessage(ctx: RouterContext, message: Message): Promise<void> {
try {
const callerSrc = await getPlayerSrcBySid(message.sender_id);
const receiverSrc = await getPlayerSrcBySid(message.receiver_id);

ctx.emitToNui(callerSrc, 'message:new-message', parseObjectToIsoString(message));
ctx.emitToNui(receiverSrc, 'message:new-message', parseObjectToIsoString(message));
} catch (error) {
console.error('Failed to broadcast call update', error);
handleError(error, ctx);
}
}

public async getMessages(ctx: RouterContext): Promise<Message[]> {
const device = await this.deviceRepository.getDeviceById(ctx.device.id);

Expand All @@ -72,7 +90,6 @@ class MessageService {
}

const messages = await this.messageRepository.getMessagesBySid(device.sim_card_id);
console.log({ messages });

return messages;
}
Expand Down
2 changes: 1 addition & 1 deletion src/shared/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export interface Call extends Record<string, unknown> {
acknowledged_at?: Date;
}

export interface Message {
export interface Message extends Record<string, unknown> {
id: number;
sender_id: number;
receiver_id: number;
Expand Down
1 change: 1 addition & 0 deletions src/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@originjs/vite-plugin-federation": "^1.3.6",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@tanstack/react-query": "^5.55.1",
Expand Down
10 changes: 9 additions & 1 deletion src/ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Outlet, useNavigate } from 'react-router-dom';
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import { Frame } from './Frame';

import { useEffect } from 'react';
Expand All @@ -14,6 +14,7 @@ import { useCurrentDevice } from './api/hooks/useCurrentDevice';
import { motion, useMotionValue, useTransform } from 'framer-motion';
import { useKeys } from './hooks/useKeys';
import { useThemeType } from './hooks/useTheme';
import { Message } from '../../shared/Types';

export const lightTheme: Theme = {
type: 'light',
Expand All @@ -40,6 +41,7 @@ export const darkTheme: Theme = {
};

function App() {
const location = useLocation();
const navigate = useNavigate();
const currentDevice = useCurrentDevice();
const y = useMotionValue(0);
Expand Down Expand Up @@ -82,6 +84,12 @@ function App() {
},
});

useEffect(() => {
if (location.pathname === '/') {
navigate('/home');
}
}, [location.pathname]);

/**
* If there is no device, we should not render anything.
* This is a safety check to ensure that the app does not render
Expand Down
3 changes: 1 addition & 2 deletions src/ui/src/Apps/Calls/Contacts/New/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ export const NewContactView = () => {
<Drawer modal open onClose={handleBack}>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Are you absolutely sure?</DrawerTitle>
<DrawerDescription>This action cannot be undone.</DrawerDescription>
<DrawerTitle>Create a new contact</DrawerTitle>
</DrawerHeader>

<NewContactForm onContactCreated={handleBack} />
Expand Down
19 changes: 8 additions & 11 deletions src/ui/src/Apps/Calls/Messages/Conversation/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { useQuery } from '@tanstack/react-query';
import { TopNavigation } from '../../../../components/Navigation/TopNavigation';
import { useNavigate, useParams } from 'react-router';
import { Message } from '../../../../../../shared/Types';
import { instance } from '../../../../utils/fetch';
import { useCurrentDevice } from '../../../../api/hooks/useCurrentDevice';
import { clsx } from 'clsx';
import { queryClient } from '../../../../Providers';
import { Fragment, useEffect, useRef } from 'react';
import { useConversationMessages } from '../../../../api/hooks/useConversation';
import { Send, UserCheck } from 'react-feather';
import { useThemeType } from '../../../../hooks/useTheme';
import { Send } from 'react-feather';
import { DateTime } from 'luxon';
import { AlignVerticalSpaceAround } from 'lucide-react';

export const Conversation = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -78,13 +76,10 @@ export const Conversation = () => {
messagesList.scrollTo(0, messagesList.scrollHeight);
}, [messages.length]);

const themeType = useThemeType();
const bgColor = themeType === 'dark' ? 'bg-cyan-800' : 'bg-cyan-100';

return (
<div className="flex flex-col h-full">
<TopNavigation
title={phoneNumber}
title={<AlignVerticalSpaceAround />}
left={
<button onClick={() => navigate(-1)} className="text-primary">
Back
Expand Down Expand Up @@ -115,12 +110,14 @@ export const Conversation = () => {

<li
className={clsx(
'p-4 rounded-lg max-w-[80%] shadow-sm text-ellipsis flex-1 overflow-clip break-words',
'p-4 rounded-lg max-w-[80%] shadow-sm text-ellipsis flex-1 break-words',
{
'self-end': message.sender_id === device?.sim_card_id,
'self-start': message.receiver_id === device?.sim_card_id,
},
message.sender_id === device?.sim_card_id ? bgColor : 'bg-secondary',
message.sender_id === device?.sim_card_id
? 'dark:bg-cyan-800 bg-cyan-100'
: 'bg-secondary',
!shouldDisplayDate && isPreviousMessageDifferentSender && 'mt-2',
)}
>
Expand All @@ -141,7 +138,7 @@ export const Conversation = () => {
ref={textAreaRef}
autoFocus
onKeyDown={(e) => {
if (e.key === 'Enter' && e.ctrlKey) {
if (e.key === 'Enter' && !e.shiftKey) {
formRef.current?.requestSubmit();
}
}}
Expand Down
10 changes: 7 additions & 3 deletions src/ui/src/Providers.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { PropsWithChildren } from 'react';
import { PropsWithChildren, useContext } from 'react';
import { NuiProvider } from 'react-fivem-hooks';
import { RouterProvider } from './RouterContext';
import { routes } from './routes';

export const queryClient = new QueryClient({
defaultOptions: {
Expand All @@ -21,8 +23,10 @@ export const Providers = ({ children }: PropsWithChildren) => {
return (
<QueryClientProvider client={queryClient}>
<NuiProvider>
{/* <ReactQueryDevtools initialIsOpen={false} /> */}
{children}
<RouterProvider initialRoutes={routes}>
{/* <ReactQueryDevtools initialIsOpen={false} /> */}
{children}
</RouterProvider>
</NuiProvider>
</QueryClientProvider>
);
Expand Down
29 changes: 29 additions & 0 deletions src/ui/src/RouterContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createContext, PropsWithChildren, useState } from 'react';
import { RouteObject, RouteProps } from 'react-router';
import { createHashRouter, RouterProvider as ReactRouterProvider } from 'react-router-dom';

export const RouterContext = createContext<{
routes: RouteObject[];
setRoutes: (routes: RouteObject[]) => void;
}>({
routes: [],
setRoutes: () => {},
});

interface RouterProviderProps extends PropsWithChildren {
initialRoutes?: RouteObject[];
}

export const RouterProvider = ({ initialRoutes = [] }: RouterProviderProps) => {
const [routes, setRoutes] = useState(initialRoutes);

if (!routes?.length) {
throw new Error('No routes provided to RouterProvider');
}

return (
<RouterContext.Provider value={{ routes, setRoutes }}>
<ReactRouterProvider router={createHashRouter(routes)} />
</RouterContext.Provider>
);
};
9 changes: 9 additions & 0 deletions src/ui/src/api/hooks/useConversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { useQuery } from '@tanstack/react-query';
import { instance } from '../../utils/fetch';
import { Message } from '../../../../shared/Types';
import { StringifyDates } from '../../../../shared/TypeUtils';
import { useBroadcastEvent } from '@/hooks/useBroadcastEvent';
import { queryClient } from '@/Providers';

export const useConversationMessages = (phoneNumber?: string) => {
const { data } = useQuery({
Expand All @@ -18,5 +20,12 @@ export const useConversationMessages = (phoneNumber?: string) => {
},
});

useBroadcastEvent('message:new-message', (data) => {
console.log('new message', { data });
queryClient.invalidateQueries({
queryKey: ['conversation', phoneNumber],
});
});

return data?.payload || [];
};
4 changes: 3 additions & 1 deletion src/ui/src/components/Contacts/NewContactForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ export const NewContactForm = ({ onContactCreated }: NewContactFormProps) => {

{error && <div className="text-red-500">{error}</div>}

<Button type="submit">Create new contact</Button>
<Button type="submit" variant="outline">
Create
</Button>
</form>
);
};
Loading

0 comments on commit 66b87bf

Please sign in to comment.