diff --git a/apps/desktop/changelog/0.3.13.md b/apps/desktop/changelog/0.3.13.md index 48ed46019..eabfafb6a 100644 --- a/apps/desktop/changelog/0.3.13.md +++ b/apps/desktop/changelog/0.3.13.md @@ -3,6 +3,7 @@ ## New Features - New Action Language setting +- Export entry content to a PDF file ## Improvements diff --git a/apps/desktop/locales/app/ar-DZ.json b/apps/desktop/locales/app/ar-DZ.json index 0e9fc14c0..f97018a92 100644 --- a/apps/desktop/locales/app/ar-DZ.json +++ b/apps/desktop/locales/app/ar-DZ.json @@ -15,6 +15,8 @@ "discover.rss_url": "رابط RSS", "discover.select_placeholder": "اختر", "entry_actions.copy_link": "نسخ الرابط", + "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.", + "entry_actions.export_as_pdf": "تصدير كملف PDF", "entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.", "entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.", "entry_actions.failed_to_save_to_obsidian": "فشل في الحفظ إلى Obsidian.", diff --git a/apps/desktop/locales/app/ar-IQ.json b/apps/desktop/locales/app/ar-IQ.json index 607a076fd..5765b22f9 100644 --- a/apps/desktop/locales/app/ar-IQ.json +++ b/apps/desktop/locales/app/ar-IQ.json @@ -15,6 +15,8 @@ "discover.rss_url": "رابط RSS", "discover.select_placeholder": "اختر", "entry_actions.copy_link": "نسخ الرابط", + "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.", + "entry_actions.export_as_pdf": "تصدير كملف PDF", "entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.", "entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.", "entry_actions.failed_to_save_to_obsidian": "فشل في الحفظ إلى Obsidian.", diff --git a/apps/desktop/locales/app/ar-KW.json b/apps/desktop/locales/app/ar-KW.json index f1b0b4d42..e20e1000f 100644 --- a/apps/desktop/locales/app/ar-KW.json +++ b/apps/desktop/locales/app/ar-KW.json @@ -15,6 +15,8 @@ "discover.rss_url": "رابط RSS", "discover.select_placeholder": "اختر", "entry_actions.copy_link": "نسخ الرابط", + "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.", + "entry_actions.export_as_pdf": "تصدير كملف PDF", "entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.", "entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.", "entry_actions.failed_to_save_to_obsidian": "فشل في الحفظ إلى Obsidian", diff --git a/apps/desktop/locales/app/ar-MA.json b/apps/desktop/locales/app/ar-MA.json index ad7a5fe0d..e3fcc656f 100644 --- a/apps/desktop/locales/app/ar-MA.json +++ b/apps/desktop/locales/app/ar-MA.json @@ -15,6 +15,8 @@ "discover.rss_url": "رابط RSS", "discover.select_placeholder": "اختر", "entry_actions.copy_link": "نسخ الرابط", + "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.", + "entry_actions.export_as_pdf": "تصدير كملف PDF", "entry_actions.failed_to_save_to_eagle": "فشل الحفظ إلى Eagle.", "entry_actions.failed_to_save_to_instapaper": "فشل الحفظ إلى Instapaper.", "entry_actions.failed_to_save_to_obsidian": "فشل الحفظ في Obsidian", diff --git a/apps/desktop/locales/app/ar-SA.json b/apps/desktop/locales/app/ar-SA.json index 3058725ee..a6359d1c5 100644 --- a/apps/desktop/locales/app/ar-SA.json +++ b/apps/desktop/locales/app/ar-SA.json @@ -15,6 +15,8 @@ "discover.rss_url": "عنوان URL لخلاصة RSS", "discover.select_placeholder": "اختيار", "entry_actions.copy_link": "نسخ الرابط", + "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.", + "entry_actions.export_as_pdf": "تصدير كملف PDF", "entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.", "entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.", "entry_actions.failed_to_save_to_readwise": "فشل في الحفظ إلى Readwise.", diff --git a/apps/desktop/locales/app/ar-TN.json b/apps/desktop/locales/app/ar-TN.json index de9223186..703d068f6 100644 --- a/apps/desktop/locales/app/ar-TN.json +++ b/apps/desktop/locales/app/ar-TN.json @@ -15,6 +15,8 @@ "discover.rss_url": "رابط RSS", "discover.select_placeholder": "اختر", "entry_actions.copy_link": "نسخ الرابط", + "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.", + "entry_actions.export_as_pdf": "تصدير كملف PDF", "entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.", "entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.", "entry_actions.failed_to_save_to_readwise": "فشل في الحفظ إلى Readwise.", diff --git a/apps/desktop/locales/app/de.json b/apps/desktop/locales/app/de.json index 84394d8a0..f27733a69 100644 --- a/apps/desktop/locales/app/de.json +++ b/apps/desktop/locales/app/de.json @@ -15,6 +15,8 @@ "discover.rss_url": "RSS-URL", "discover.select_placeholder": "Auswählen", "entry_actions.copy_link": "Link kopieren", + "entry_actions.exported_notify": "Artikel als PDF exportiert.", + "entry_actions.export_as_pdf": "Als PDF exportieren", "entry_actions.failed_to_save_to_eagle": "Speichern in Eagle fehlgeschlagen.", "entry_actions.failed_to_save_to_instapaper": "Speichern in Instapaper fehlgeschlagen.", "entry_actions.failed_to_save_to_obsidian": "Speichern in Obsidian fehlgeschlagen", diff --git a/apps/desktop/locales/app/en.json b/apps/desktop/locales/app/en.json index 12d82f49e..f4f567110 100644 --- a/apps/desktop/locales/app/en.json +++ b/apps/desktop/locales/app/en.json @@ -108,6 +108,8 @@ "entry_actions.image_gallery": "Image Gallery", "entry_actions.copied_notify": "{{which}} copied to clipboard.", "entry_actions.copy_link": "Copy Link", + "entry_actions.exported_notify": "Exported article as PDF.", + "entry_actions.export_as_pdf": "Export as PDF", "entry_actions.copy_title": "Copy Title", "entry_actions.delete": "Delete", "entry_actions.deleted": "Deleted.", diff --git a/apps/desktop/locales/app/es.json b/apps/desktop/locales/app/es.json index 686c08687..c299baf2a 100644 --- a/apps/desktop/locales/app/es.json +++ b/apps/desktop/locales/app/es.json @@ -15,6 +15,8 @@ "discover.rss_url": "RSS URL", "discover.select_placeholder": "Seleccionar", "entry_actions.copy_link": "Copiar enlace", + "entry_actions.exported_notify": "Artículo exportado como PDF.", + "entry_actions.export_as_pdf": "Exportar como PDF", "entry_actions.failed_to_save_to_obsidian": "Error al guardar en Obsidian", "entry_actions.mark_as_read": "Marcar como leído", "entry_actions.mark_as_unread": "Marcar como no leído", diff --git a/apps/desktop/locales/app/fi.json b/apps/desktop/locales/app/fi.json index 9e4abfe47..baa90f112 100644 --- a/apps/desktop/locales/app/fi.json +++ b/apps/desktop/locales/app/fi.json @@ -15,6 +15,8 @@ "discover.rss_url": "RSS-URL", "discover.select_placeholder": "Valitse", "entry_actions.copy_link": "Kopioi linkki", + "entry_actions.exported_notify": "Artikkeli vietiin PDF-muodossa.", + "entry_actions.export_as_pdf": "Vie PDF:nä", "entry_actions.failed_to_save_to_eagle": "Tallennus Eagleen epäonnistui.", "entry_actions.failed_to_save_to_instapaper": "Tallennus Instapaperiin epäonnistui.", "entry_actions.failed_to_save_to_readwise": "Tallennus Readwiseen epäonnistui.", diff --git a/apps/desktop/locales/app/fr.json b/apps/desktop/locales/app/fr.json index 81047be3d..d973e5cad 100644 --- a/apps/desktop/locales/app/fr.json +++ b/apps/desktop/locales/app/fr.json @@ -15,6 +15,8 @@ "discover.rss_url": "URL du RSS", "discover.select_placeholder": "Sélectionner", "entry_actions.copy_link": "Copier le lien", + "entry_actions.exported_notify": "Article exporté en PDF.", + "entry_actions.export_as_pdf": "Exporter en PDF", "entry_actions.failed_to_save_to_eagle": "Échec de l'enregistrement sur Eagle.", "entry_actions.failed_to_save_to_instapaper": "Échec de l'enregistrement sur Instapaper.", "entry_actions.failed_to_save_to_readwise": "Échec de l'enregistrement sur Readwise.", diff --git a/apps/desktop/locales/app/it.json b/apps/desktop/locales/app/it.json index 03e47a391..a227a30f1 100644 --- a/apps/desktop/locales/app/it.json +++ b/apps/desktop/locales/app/it.json @@ -15,6 +15,8 @@ "discover.rss_url": "URL RSS", "discover.select_placeholder": "Seleziona", "entry_actions.copy_link": "Copia link", + "entry_actions.exported_notify": "Articolo esportato come PDF.", + "entry_actions.export_as_pdf": "Esporta come PDF", "entry_actions.failed_to_save_to_eagle": "Salvataggio su Eagle non riuscito.", "entry_actions.failed_to_save_to_instapaper": "Salvataggio su Instapaper non riuscito.", "entry_actions.failed_to_save_to_readwise": "Salvataggio su Readwise non riuscito.", diff --git a/apps/desktop/locales/app/ja.json b/apps/desktop/locales/app/ja.json index 068f9bd71..d1073451e 100644 --- a/apps/desktop/locales/app/ja.json +++ b/apps/desktop/locales/app/ja.json @@ -107,6 +107,8 @@ "discover.target.lists": "リスト", "entry_actions.copied_notify": "{{which}} をクリップボードにコピーしました。", "entry_actions.copy_link": "リンクをコピー", + "entry_actions.exported_notify": "記事をPDFとしてエクスポートしました。", + "entry_actions.export_as_pdf": "PDFとしてエクスポート", "entry_actions.copy_title": "タイトルをコピー", "entry_actions.delete": "削除", "entry_actions.deleted": "削除済み", diff --git a/apps/desktop/locales/app/ko.json b/apps/desktop/locales/app/ko.json index 5e98a327f..c93b82272 100644 --- a/apps/desktop/locales/app/ko.json +++ b/apps/desktop/locales/app/ko.json @@ -107,6 +107,8 @@ "discover.target.lists": "목록", "entry_actions.copied_notify": "{{which}}이(가) 클립보드에 복사되었습니다", "entry_actions.copy_link": "링크 복사", + "entry_actions.exported_notify": "PDF로 기사 내보내기 완료.", + "entry_actions.export_as_pdf": "PDF로 내보내기", "entry_actions.copy_title": "제목 복사", "entry_actions.delete": "삭제", "entry_actions.deleted": "삭제됨", diff --git a/apps/desktop/locales/app/pt.json b/apps/desktop/locales/app/pt.json index 1ad2fd980..8cdd99d1c 100644 --- a/apps/desktop/locales/app/pt.json +++ b/apps/desktop/locales/app/pt.json @@ -15,6 +15,8 @@ "discover.rss_url": "RSS URL", "discover.select_placeholder": "選択", "entry_actions.copy_link": "リンクをコピー", + "entry_actions.exported_notify": "Artigo exportado como PDF.", + "entry_actions.export_as_pdf": "Exportar como PDF", "entry_actions.failed_to_save_to_eagle": "Eagle への保存に失敗しました。", "entry_actions.failed_to_save_to_instapaper": "Instapaper への保存に失敗しました。", "entry_actions.failed_to_save_to_readwise": "Readwise への保存に失敗しました。", diff --git a/apps/desktop/locales/app/ru.json b/apps/desktop/locales/app/ru.json index 1481cc068..8f8f8f6b4 100644 --- a/apps/desktop/locales/app/ru.json +++ b/apps/desktop/locales/app/ru.json @@ -103,6 +103,8 @@ "discover.target.lists": "Списки", "entry_actions.copied_notify": "{{which}} скопировано в буфер обмена.", "entry_actions.copy_link": "Копировать ссылку", + "entry_actions.exported_notify": "Статья экспортирована в PDF.", + "entry_actions.export_as_pdf": "Экспортировать в PDF", "entry_actions.copy_title": "Копировать заголовок", "entry_actions.delete": "Удалить", "entry_actions.deleted": "Удалено.", diff --git a/apps/desktop/locales/app/tr.json b/apps/desktop/locales/app/tr.json index 4ffe75fc7..726367e8c 100644 --- a/apps/desktop/locales/app/tr.json +++ b/apps/desktop/locales/app/tr.json @@ -28,6 +28,8 @@ "discover.target.label": "Arama hedefi", "discover.target.lists": "Listeler", "entry_actions.copy_link": "Bağlantıyı kopyala", + "entry_actions.exported_notify": "Makale PDF olarak dışa aktarıldı.", + "entry_actions.export_as_pdf": "PDF olarak dışa aktar", "entry_actions.failed_to_save_to_eagle": "Eagle'a kaydetme başarısız oldu.", "entry_actions.failed_to_save_to_instapaper": "Instapaper'a kaydetme başarısız oldu.", "entry_actions.failed_to_save_to_readwise": "Readwise'a kaydetme başarısız oldu.", diff --git a/apps/desktop/locales/app/zh-CN.json b/apps/desktop/locales/app/zh-CN.json index e26fa4c0e..b94c9ba28 100644 --- a/apps/desktop/locales/app/zh-CN.json +++ b/apps/desktop/locales/app/zh-CN.json @@ -108,6 +108,8 @@ "entry_actions.image_gallery": "图片库", "entry_actions.copied_notify": "{{which}}已复制到剪贴板。", "entry_actions.copy_link": "复制链接", + "entry_actions.exported_notify": "文章已导出为 PDF。", + "entry_actions.export_as_pdf": "导出为 PDF", "entry_actions.copy_title": "复制标题", "entry_actions.delete": "删除", "entry_actions.deleted": "已删除", diff --git a/apps/desktop/locales/app/zh-HK.json b/apps/desktop/locales/app/zh-HK.json index e2ea1d741..c4425cec6 100644 --- a/apps/desktop/locales/app/zh-HK.json +++ b/apps/desktop/locales/app/zh-HK.json @@ -108,6 +108,8 @@ "entry_actions.image_gallery": "圖片庫", "entry_actions.copied_notify": "{{which}}已複製到剪貼簿", "entry_actions.copy_link": "複製連結", + "entry_actions.exported_notify": "文章已匯出為 PDF。", + "entry_actions.export_as_pdf": "匯出為 PDF", "entry_actions.copy_title": "複製標題", "entry_actions.delete": "刪除", "entry_actions.deleted": "已刪除", diff --git a/apps/desktop/locales/app/zh-TW.json b/apps/desktop/locales/app/zh-TW.json index d9ddca9b0..7490e9116 100644 --- a/apps/desktop/locales/app/zh-TW.json +++ b/apps/desktop/locales/app/zh-TW.json @@ -104,6 +104,8 @@ "discover.target.lists": "列表", "entry_actions.copied_notify": "{{which}}已複製到剪貼簿", "entry_actions.copy_link": "複製連結", + "entry_actions.exported_notify": "文章已匯出為 PDF。", + "entry_actions.export_as_pdf": "匯出為 PDF", "entry_actions.copy_title": "複製標題", "entry_actions.delete": "刪除", "entry_actions.deleted": "已刪除。", diff --git a/apps/desktop/src/renderer/src/hooks/biz/useEntryActions.tsx b/apps/desktop/src/renderer/src/hooks/biz/useEntryActions.tsx index b92a58e80..3f2d2b4af 100644 --- a/apps/desktop/src/renderer/src/hooks/biz/useEntryActions.tsx +++ b/apps/desktop/src/renderer/src/hooks/biz/useEntryActions.tsx @@ -146,6 +146,10 @@ export const useEntryActions = ({ entryId, view }: { entryId: string; view?: Fee hide: !entry?.entries.url, shortcut: shortcuts.entry.copyLink.key, }, + { + id: COMMAND_ID.entry.exportAsPDF, + onClick: runCmdFn(COMMAND_ID.entry.exportAsPDF, [{ entryId }]), + }, { id: COMMAND_ID.entry.openInBrowser, onClick: runCmdFn(COMMAND_ID.entry.openInBrowser, [{ entryId }]), diff --git a/apps/desktop/src/renderer/src/modules/command/commands/entry.tsx b/apps/desktop/src/renderer/src/modules/command/commands/entry.tsx index 60d95a1d1..8aa3fc1f7 100644 --- a/apps/desktop/src/renderer/src/modules/command/commands/entry.tsx +++ b/apps/desktop/src/renderer/src/modules/command/commands/entry.tsx @@ -175,6 +175,25 @@ export const useRegisterEntryCommands = () => { }) }, }, + { + id: COMMAND_ID.entry.exportAsPDF, + label: t("entry_actions.export_as_pdf"), + icon: , + run: ({ entryId }) => { + const entry = useEntryStore.getState().flatMapEntries[entryId] + + if (!entry) { + toast.error("Failed to export as pdf: entry is not available", { duration: 3000 }) + return + } + + window.print() + + toast(t("entry_actions.exported_notify"), { + duration: 1000, + }) + }, + }, { id: COMMAND_ID.entry.copyTitle, label: t("entry_actions.copy_title"), diff --git a/apps/desktop/src/renderer/src/modules/command/commands/id.ts b/apps/desktop/src/renderer/src/modules/command/commands/id.ts index ce5611051..dc68451b7 100644 --- a/apps/desktop/src/renderer/src/modules/command/commands/id.ts +++ b/apps/desktop/src/renderer/src/modules/command/commands/id.ts @@ -11,6 +11,7 @@ export const COMMAND_ID = { read: "entry:read", toggleAISummary: "entry:toggle-ai-summary", toggleAITranslation: "entry:toggle-ai-translation", + exportAsPDF: "entry:export-as-pdf", }, integration: { saveToEagle: "integration:save-to-eagle", diff --git a/apps/desktop/src/renderer/src/modules/command/commands/types.ts b/apps/desktop/src/renderer/src/modules/command/commands/types.ts index dabd5a6fb..dd3d83653 100644 --- a/apps/desktop/src/renderer/src/modules/command/commands/types.ts +++ b/apps/desktop/src/renderer/src/modules/command/commands/types.ts @@ -25,6 +25,11 @@ export type CopyLinkCommand = Command<{ fn: (data: { entryId: string }) => void }> +export type ExportAsPDFCommand = Command<{ + id: typeof COMMAND_ID.entry.exportAsPDF + fn: (data: { entryId: string }) => void +}> + export type CopyTitleCommand = Command<{ id: typeof COMMAND_ID.entry.copyTitle fn: (data: { entryId: string }) => void @@ -65,6 +70,7 @@ export type EntryCommand = | StarCommand | DeleteCommand | CopyLinkCommand + | ExportAsPDFCommand | CopyTitleCommand | OpenInBrowserCommand | ViewSourceContentCommand diff --git a/apps/desktop/src/renderer/src/modules/customize-toolbar/constant.ts b/apps/desktop/src/renderer/src/modules/customize-toolbar/constant.ts index d92c4f85a..199091925 100644 --- a/apps/desktop/src/renderer/src/modules/customize-toolbar/constant.ts +++ b/apps/desktop/src/renderer/src/modules/customize-toolbar/constant.ts @@ -21,6 +21,7 @@ export const DEFAULT_ACTION_ORDER: ToolbarActionOrder = { [ COMMAND_ID.entry.copyLink, COMMAND_ID.entry.openInBrowser, + COMMAND_ID.entry.exportAsPDF, COMMAND_ID.entry.read, ] as string[] ).includes(id), diff --git a/apps/desktop/src/renderer/src/styles/main.css b/apps/desktop/src/renderer/src/styles/main.css index 2df451951..0ca4475ed 100644 --- a/apps/desktop/src/renderer/src/styles/main.css +++ b/apps/desktop/src/renderer/src/styles/main.css @@ -2,3 +2,13 @@ @import "./additional.css"; @import "./scrollbar.css"; @import "./cursor.css"; + +@media print { + * { + overflow: visible !important; + page-break-after: avoid; + page-break-before: avoid; + break-inside: avoid; + height: max-content; + } +} diff --git a/apps/mobile/src/icons/pdf_cute_re.tsx b/apps/mobile/src/icons/pdf_cute_re.tsx new file mode 100644 index 000000000..fa13fd1b0 --- /dev/null +++ b/apps/mobile/src/icons/pdf_cute_re.tsx @@ -0,0 +1,25 @@ +import * as React from "react" +import Svg, { Path } from "react-native-svg" + +interface PdfCuteReIconProps { + width?: number + height?: number + color?: string +} + +export const PdfCuteReIcon = ({ + width = 24, + height = 24, + color = "#10161F", +}: PdfCuteReIconProps) => { + return ( + + + + ) +} diff --git a/icons/mgc/pdf_cute_re.svg b/icons/mgc/pdf_cute_re.svg new file mode 100644 index 000000000..cae867576 --- /dev/null +++ b/icons/mgc/pdf_cute_re.svg @@ -0,0 +1 @@ + \ No newline at end of file