From 49a4ed3ad9df751b0f1132f82a778d32243699b4 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Mon, 28 Jul 2025 10:09:42 +0330 Subject: [PATCH] propmt input in mobile + print email + ltr and rtl new message + najva token --- src/App.tsx | 2 + src/components/NajvaToken.tsx | 33 +++++++ src/components/newMessage/EmailEditor.tsx | 87 ++++++++++++++++--- src/components/newMessage/NewMessage.tsx | 2 +- .../newMessage/hooks/useNewMessage.ts | 11 ++- src/hooks/useEmailWebSocket.ts | 2 +- src/index.css | 8 +- src/main.tsx | 1 + src/pages/Trash/service/TrashService.ts | 2 - src/pages/archive/service/ArchiveService.ts | 2 - src/pages/draft/service/DraftService.ts | 2 - src/pages/favorite/service/FavoriteService.ts | 2 - src/pages/profile/types/ProfileTypes.ts | 1 + src/pages/received/Components/Header.tsx | 80 ++++++++++++++++- src/pages/received/Detail.tsx | 6 +- src/pages/received/List.tsx | 12 --- src/pages/received/service/EmailService.ts | 2 - src/pages/sent/service/SentService.ts | 2 - src/pages/spam/service/SpamService.ts | 2 - 19 files changed, 216 insertions(+), 43 deletions(-) create mode 100644 src/components/NajvaToken.tsx diff --git a/src/App.tsx b/src/App.tsx index d1f2bfd..95da014 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,6 +18,7 @@ import { Paths } from './utils/Paths'; import Login from './pages/auth/Login'; import { EmailWebSocketProvider } from './contexts/EmailWebSocketContext'; import SocketManagment from './lib/SocketManagment'; +import NajvaToken from './components/NajvaToken'; declare global { interface Window { @@ -135,6 +136,7 @@ const App: FC = () => {
+ ) : isLogin === 'isNotLogin' ? ( diff --git a/src/components/NajvaToken.tsx b/src/components/NajvaToken.tsx new file mode 100644 index 0000000..0642df1 --- /dev/null +++ b/src/components/NajvaToken.tsx @@ -0,0 +1,33 @@ +import { FC, useEffect } from 'react' +import { updateProfile } from '../pages/profile/service/ProfileService' + +declare global { + interface Window { + NAJVA: { + getUserToken: () => Promise + najvaUserSubscribed: (najvaUserToken: string) => void + } + } +} +const NajvaToken: FC = () => { + + const handleNajvaToken = async () => { + const userToken = await window.NAJVA?.getUserToken() + if (userToken) { + updateProfile({ + pushToken: userToken, + }) + } + } + + useEffect(() => { + handleNajvaToken() + // window.NAJVA.najvaUserSubscribed = function (najvaUserToken) { + // console.log('najvaUserToken', najvaUserToken) + // } + }, []) + + return null +} + +export default NajvaToken \ No newline at end of file diff --git a/src/components/newMessage/EmailEditor.tsx b/src/components/newMessage/EmailEditor.tsx index 6d43999..1a38ff4 100644 --- a/src/components/newMessage/EmailEditor.tsx +++ b/src/components/newMessage/EmailEditor.tsx @@ -1,5 +1,6 @@ -import { FC } from 'react' +import { FC, useMemo } from 'react' import ReactQuill from 'react-quill-new' +import 'react-quill-new/dist/quill.snow.css' interface EmailEditorProps { value: string @@ -10,19 +11,85 @@ interface EmailEditorProps { const EmailEditor: FC = ({ value, onChange, - placeholder = '' + placeholder = 'متن پیام خود را وارد کنید...' }) => { + const modules = useMemo(() => ({ + toolbar: [ + ['bold', 'italic', 'underline'], + [{ 'list': 'ordered' }, { 'list': 'bullet' }], + [{ 'align': [] }], + [{ 'direction': 'rtl' }], + ['link'], + [{ 'color': [] }, { 'background': [] }], + [{ 'font': [] }, { 'size': ['small', false, 'large', 'huge'] }], + ['clean'] + ], + }), []) + const formats = [ + 'bold', 'italic', 'underline', + 'list', 'bullet', + 'align', 'direction', + 'link', + 'color', 'background', + 'font', 'size' + ] return ( - +
+ + +
) } diff --git a/src/components/newMessage/NewMessage.tsx b/src/components/newMessage/NewMessage.tsx index af6c74f..5387525 100644 --- a/src/components/newMessage/NewMessage.tsx +++ b/src/components/newMessage/NewMessage.tsx @@ -146,7 +146,7 @@ const NewMessage: FC = () => {
-
+
{ const draftUpdateData = { to: parseEmailAddresses(toEmails), subject, - html: ensureString(content), + html: `
${ensureString( + content + )}
`, text: ensureString(content).replace(/<[^>]*>/g, ""), ...(attachments.length > 0 && { attachments }), }; @@ -170,6 +172,9 @@ export const useNewMessage = () => { messageId: editingDraftId.toString(), draftData: { ...draftUpdateData, + html: `
${ensureString( + content + )}
`, isDraft: true, uploadOnly: true, }, @@ -195,7 +200,9 @@ export const useNewMessage = () => { from: { address: userEmail || "sender@example.com" }, to: parseEmailAddresses(toEmails), subject, - html: ensureString(content), + html: `
${ensureString( + content + )}
`, text: ensureString(content).replace(/<[^>]*>/g, ""), ...(attachments.length > 0 && { attachments }), ...(isDraft && { isDraft: true, uploadOnly: true }), diff --git a/src/hooks/useEmailWebSocket.ts b/src/hooks/useEmailWebSocket.ts index d5a8ea5..2885d0f 100644 --- a/src/hooks/useEmailWebSocket.ts +++ b/src/hooks/useEmailWebSocket.ts @@ -40,7 +40,7 @@ export const useEmailWebSocket = ({ }); newSocket.on("connection_established", (data) => { - console.log("🎉 اتصال WebSocket ایمیل تأیید شد:", data); + console.log("🎉 اتصال We bSocket ایمیل تأیید شد:", data); }); newSocket.on("connection_error", (error) => { diff --git a/src/index.css b/src/index.css index 1aec8aa..dad22e3 100644 --- a/src/index.css +++ b/src/index.css @@ -238,7 +238,13 @@ textarea::placeholder { @apply rounded-t-xl; } .ql-editor { - @apply !text-right; + text-align: start !important; + unicode-bidi: plaintext !important; +} +.ql-editor p { + unicode-bidi: plaintext !important; + text-align: start !important; + direction: auto !important; } .dltr { diff --git a/src/main.tsx b/src/main.tsx index bef5202..573630b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,7 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import './index.css' +import './assets/fonts/irancell/style.css' import App from './App.tsx' createRoot(document.getElementById('root')!).render( diff --git a/src/pages/Trash/service/TrashService.ts b/src/pages/Trash/service/TrashService.ts index 82689b6..35af6cc 100644 --- a/src/pages/Trash/service/TrashService.ts +++ b/src/pages/Trash/service/TrashService.ts @@ -6,8 +6,6 @@ import { MessageListQueryDto, TrashResponse } from "../types/TrashTypes"; export const getTrashMessages = async ( query: MessageListQueryDto ): Promise => { - console.log("query", query); - const isSearch = !!query.search || !!query.datestart || query.dateend || query.from; const url = isSearch ? "search" : "messages/trash"; diff --git a/src/pages/archive/service/ArchiveService.ts b/src/pages/archive/service/ArchiveService.ts index 4679da7..93bb681 100644 --- a/src/pages/archive/service/ArchiveService.ts +++ b/src/pages/archive/service/ArchiveService.ts @@ -5,8 +5,6 @@ import { MessageListQueryDto, ArchiveResponse } from "../types/ArchiveTypes"; export const getArchiveMessages = async ( query: MessageListQueryDto ): Promise => { - console.log("query", query); - const isSearch = !!query.search || !!query.datestart || query.dateend || query.from; const url = isSearch ? "search" : "messages/archive"; diff --git a/src/pages/draft/service/DraftService.ts b/src/pages/draft/service/DraftService.ts index 56ebf55..6591cfc 100644 --- a/src/pages/draft/service/DraftService.ts +++ b/src/pages/draft/service/DraftService.ts @@ -10,8 +10,6 @@ import { export const getDrafts = async ( query: MessageListQueryDto ): Promise => { - console.log("query", query); - const isSearch = !!query.search || !!query.datestart || query.dateend || query.from; const url = isSearch ? "search" : "messages/drafts"; diff --git a/src/pages/favorite/service/FavoriteService.ts b/src/pages/favorite/service/FavoriteService.ts index ad232b6..4890f28 100644 --- a/src/pages/favorite/service/FavoriteService.ts +++ b/src/pages/favorite/service/FavoriteService.ts @@ -5,8 +5,6 @@ import { MessageListQueryDto, FavoriteResponse } from "../types/FavoriteTypes"; export const getFavoriteMessages = async ( query: MessageListQueryDto ): Promise => { - console.log("query", query); - const isSearch = !!query.search || !!query.datestart || query.dateend || query.from; const url = isSearch ? "search" : "messages/favorite"; diff --git a/src/pages/profile/types/ProfileTypes.ts b/src/pages/profile/types/ProfileTypes.ts index 44bc527..ada9745 100644 --- a/src/pages/profile/types/ProfileTypes.ts +++ b/src/pages/profile/types/ProfileTypes.ts @@ -12,6 +12,7 @@ export type UpdateProfileType = { cityId?: string; postalCode?: string; userAddress?: string; + pushToken?: string; }; export type UpdateEmailType = { diff --git a/src/pages/received/Components/Header.tsx b/src/pages/received/Components/Header.tsx index f305d64..9c10643 100644 --- a/src/pages/received/Components/Header.tsx +++ b/src/pages/received/Components/Header.tsx @@ -9,12 +9,89 @@ import MessageSpam from './MessageSpam' import { MailboxEnum } from '../enum/Enum' import MessageFavorite from './MessageFavorite' import MessageTrash from './MessageTrash' +import { MessageDetail } from '../types/Types' +import { sanitizeEmailHTML, detectTextDirection } from '@/config/func' -const Header: FC<{ mailBoxName: MailboxEnum, flagged: boolean }> = ({ mailBoxName, flagged }) => { +const Header: FC<{ + mailBoxName: MailboxEnum, + flagged: boolean, + messageDetail?: MessageDetail +}> = ({ mailBoxName, flagged, messageDetail }) => { const navigate = useNavigate() const { t } = useTranslation() + const handlePrint = () => { + if (!messageDetail) return + + // Create a new window for printing + const printWindow = window.open('', '_blank', 'width=800,height=600') + if (!printWindow) return + + // Get the email content + let content = '' + if (messageDetail.html && messageDetail.html.length > 0) { + content = sanitizeEmailHTML(messageDetail.html.join('')) + } else { + content = messageDetail.text || 'محتوای پیام' + } + + // Detect text direction + const direction = detectTextDirection(content) + + // Create print content + const printContent = ` + + + + + پرینت ایمیل + + + + + + + + ` + + // Write content and print + printWindow.document.write(printContent) + printWindow.document.close() + + // Wait for content to load then print + printWindow.onload = () => { + printWindow.print() + printWindow.close() + } + } + return (
@@ -42,6 +119,7 @@ const Header: FC<{ mailBoxName: MailboxEnum, flagged: boolean }> = ({ mailBoxNam