Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0d22734
Add everyday media tools: compress, merge, slideshow, extract audio, …
cre8ive-marketing Oct 21, 2026
94ec0a7
Put Extract audio on the video donut's back face when upgrading
cre8ive-marketing Oct 21, 2026
756f0a0
Translate the media tools into Brazilian Portuguese
cre8ive-marketing Oct 21, 2026
1c11b1e
Harden the media tools: safe merge copies, slideshow progress, compre…
cre8ive-marketing Oct 21, 2026
cf3beda
Add iCalendar (.ics) to CSV conversion and back
SeoJCalive Oct 22, 2026
d8813c8
Use Moscow in the historical-offset iCalendar test
SeoJCalive Oct 22, 2026
476c0aa
Read .lua scripts and .css style sheets as plain text (#388, #368)
cre8ive-marketing Oct 22, 2026
e9bf173
Snap the crop frame to the picture's centre lines while moving it (#369)
cre8ive-marketing Oct 22, 2026
a54bbfa
Document .lua / .css as text and crop centre snapping
cre8ive-marketing Oct 22, 2026
b3a663a
Address review: safe failed joins, one-file joins, kept originals, ea…
cre8ive-marketing Oct 22, 2026
1c06463
Keep CSV cells from adding their own iCalendar lines
SeoJCalive Oct 22, 2026
eda4b53
Repeat an Excel sheet's print title rows on every PDF page (#407)
cre8ive-marketing Oct 22, 2026
25a8ca1
Read HP-GL plot files (.plt, #410)
cre8ive-marketing Oct 22, 2026
b3a8ce7
Read HP-GL/1 plots that start with any command (#432 review)
cre8ive-marketing Oct 22, 2026
5894b0e
Merge pull request #393: Fix #388, #368, #369: .lua and .css as text,…
KnifeLemon Oct 23, 2026
0cd5f63
Renumber #393's migration to 34; no new strings
KnifeLemon Oct 23, 2026
98875db
Merge pull request #432: Fix #407, #410: repeat Excel print title row…
KnifeLemon Oct 23, 2026
08499ba
Renumber #432's migration to 35; no new strings
KnifeLemon Oct 23, 2026
39538f9
Merge pull request #381: Add iCalendar (.ics) to CSV conversion and b…
KnifeLemon Oct 23, 2026
b5648aa
Renumber #381's migration to 36; iCalendar in the data engine text fo…
KnifeLemon Oct 23, 2026
545c83b
Merge pull request #349: Everyday media tools on 2.0.0, with audit fi…
KnifeLemon Oct 23, 2026
352fe37
Renumber #349's migration to 37; media tool strings for fr, zh-TW, ne
KnifeLemon Oct 23, 2026
c1315c8
Fit #349's images back face, compress into ZIPs, count saved pictures
KnifeLemon Oct 23, 2026
781e618
Keep the released 2.0.0 CHANGELOG section as it shipped
KnifeLemon Oct 23, 2026
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ slides show what's new.
| **Archives**: ZIP, ANSYS Workbench (WBPZ), 7Z, RAR, TAR, TAR.GZ, TAR.BZ2, TAR.XZ, GZ, ISO, CAB, DMG, ALZ, EGG, … | extract, ZIP, 7Z, TAR, TAR.GZ; any files → one ZIP |
| **CAD**: DWG, DXF | PDF, SVG, PNG, DWG ↔ DXF |
| **Fonts**: TTF, OTF, WOFF, WOFF2, EOT | each other |
| **Data**: JSON, JSON Lines, YAML, TOML, XML · vCard | each other, CSV and XLSX (tables); vCard ↔ CSV |
| **Data**: JSON, JSON Lines, YAML, TOML, XML · vCard, iCalendar | each other, CSV and XLSX (tables); vCard, iCalendar ↔ CSV |
| **3D models**: GLB, glTF, STL, OBJ (+ MTL), 3MF, PLY; FBX read | each other, PNG preview |
| **Geospatial vectors**: Shapefile, GeoJSON, KML, KMZ, GPX · CSV with coordinates | each other and CSV / XLSX / JSON; projected data (UTM, Web Mercator, Lambert, Albers) comes out as WGS 84 longitude / latitude |

Expand Down
8 changes: 7 additions & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
same name ("Overwrite"). It frees its names and removes an output folder it made if that is left empty.
"Merge into one PDF" converts each file to PDF and merges with PDFsharp.
"Compress into one archive" packs the dropped files, unconverted, with the archive engine (`IFileCombiner`).
"Merge videos", "Merge audio" and "Video from images" join the files, in the order picked in the merge order
window, into one file with FFmpeg (`IMediaJoiner`); pictures become PNG through the image engines first. Like the
other one-file jobs, the output follows "subfolder only for several files", and a join that fails or is cancelled
is undone by the job's allocator, which deletes only paths that were the job's own.
6. **Report** – progress and results appear in the toast window and in Home → Recent conversions.
Renderers check only the original source for referenced fonts. `ConversionStep.MissingFonts` reports any missing
families to `FileResult.MissingFonts`; the toast card can offer one trusted source, while the CLI and watch jobs
Expand Down Expand Up @@ -136,7 +140,9 @@ multi-frame pictures refused, the EXIF thumbnail dropped), one history entry for
skipped. Every file starts free and whole, its portrait/landscape choice following the picture.
- `Controls/CropCanvas` is the stage: the picture inside `ImagePadding`, the part outside the frame frosted (a copy at
most 40 px across, drawn large) under a veil of the page colour, the frame in the accent colour with round handles,
a rule-of-thirds grid while dragging and a size chip that follows the frame. The preview is downscaled once by
a rule-of-thirds grid while dragging and a size chip that follows the frame. A frame being moved snaps onto the
picture's vertical or horizontal centre line within `CropMath.SnapDistance` (8 px) and shows that line as a dashed
guide until the drag ends. The preview is downscaled once by
`CropService.LoadPreviewAsync`; nothing is decoded again while dragging. Programmatic changes (reset, a ratio, a
new picture) ease in with tweens read against the clock, so a lost frame never leaves one half done; dragging and
arrow-key nudges follow at once, and `PlayAnimations` (from `Motion.Enabled`) turns all of it off.
Expand Down
63 changes: 51 additions & 12 deletions docs/ENGINES.md

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion src/Filee.App/Assets/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"error.cannot_turn": "التدوير والانعكاس متاحان للصور فقط",
"error.no_transparency": "هذا التنسيق لا يدعم الشفافية، لذا لا يوجد ما يُقص",
"error.too_many_frames": "عدد الإطارات كبير جدًا لحفظها كصور. زِد قيمة «كل إطار رقم N»",
"error.too_many_pictures": "عدد الصور كبير جدًا لفيديو واحد، قسّمها على عدة فيديوهات",
"error.not_enough_space": "لا توجد مساحة كافية على القرص لحفظ الصور",
"error.no_motion_photo": "لا تحتوي هذه الصورة على فيديو يستطيع Filee قراءته (صورة Motion Photo من Android، أو Live Photo من iPhone مع ملف MOV بجانبها)",
"error.live_photo_start": "يبدأ المقطع بعد نهاية هذا الفيديو. اختر «بداية المقطع» أبكر",
Expand Down Expand Up @@ -129,7 +130,7 @@
"engine.pdf-text.description": "استخراج نصوص PDF بترتيب القراءة، بما في ذلك الصفحات ذات العمودين (دون تعرّف ضوئي OCR للمستندات الممسوحة).",
"engine.pdf-slides.description": "تحويل PDF إلى شرائح PowerPoint: تصبح كل صفحة صورة على شريحة مستقلة (بنفس مظهر PDF وغير قابلة للتحرير)، مع نص الصفحة في ملاحظات المتحدث.",
"engine.email.description": "تحويل رسائل البريد (EML وOutlook MSG) إلى HTML ونص مع المرسل والمستلمين والتاريخ والصور، وتجميع المرفقات في ZIP.\nتحويل MSG إلى EML، وصفحات الويب المحفوظة (MHTML) إلى ملف HTML واحد مع صورها.",
"engine.data.description": "التحويل بين JSON وJSON Lines وYAML وTOML وXML وCSV.\nتحويل جهات اتصال vCard إلى CSV والعكس.\nتُحذف التعليقات. تدعم CSV البيانات الجدولية فقط.",
"engine.data.description": "التحويل بين JSON وJSON Lines وYAML وTOML وXML وCSV.\nتحويل جهات اتصال vCard وأحداث iCalendar إلى CSV والعكس.\nتُحذف التعليقات. تدعم CSV البيانات الجدولية فقط.",
"engine.vector.description": "تحويل SVG وSVGZ إلى PDF متجهي وصور وDXF؛ وتتبع الصور إلى SVG؛ وقراءة ملفات Illustrator المحفوظة بمحتوى PDF.",
"engine.icns.description": "تحويل أيقونات تطبيقات macOS ‏(ICNS) من الصور وإليها.",
"engine.font.description": "التحويل بين الخطوط: TTF وOTF وWOFF وWOFF2 وEOT.",
Expand Down Expand Up @@ -217,6 +218,14 @@
"preset.extract_motion": "استخراج فيديو Live Photo",
"preset.live_photo_iphone": "Live Photo (iPhone)",
"preset.motion_photo_android": "Motion Photo (Android)",
"preset.compress_image": "ضغط الصورة",
"preset.compress_video": "ضغط الفيديو",
"preset.video_from_images": "فيديو من الصور",
"preset.extract_audio": "استخراج الصوت",
"preset.merge_videos": "دمج الفيديوهات",
"preset.compress_audio": "ضغط الصوت",
"preset.merge_audio": "دمج الصوت",
"preset.remove_metadata": "إزالة البيانات الوصفية",
"format.folder": "مجلد",
"format.category.Image": "صورة",
"format.category.Pdf": "PDF",
Expand Down Expand Up @@ -481,6 +490,9 @@
"presets.frame_estimate": "تنتج دقيقة من فيديو بمعدل 30 إطارًا/ث {0} صورة، بحد أقصى {1} لكل فيديو.",
"presets.extract_motion_photo": "استخراج فيديو Live/Motion Photo",
"presets.extract_motion_photo_hint": "تتحول الصورة إلى الفيديو المحفوظ معها: المضمّن في Motion Photo من Android، أو ملف MOV بجانب Live Photo من iPhone.\nتتحول الصور الأخرى إلى فيديو للصورة الثابتة.",
"presets.slide_seconds": "ثوانٍ لكل صورة",
"presets.crossfade": "تلاشٍ متداخل بين الصور",
"presets.crossfade_hint": "تتلاشى كل صورة في التالية خلال ثانية بدلًا من الانتقال المفاجئ.",
"presets.group.live_photo": "Live / Motion Photo",
"presets.live_photo": "يصبح الفيديو",
"presets.live_photo.None": "إطارًا ثابتًا واحدًا",
Expand Down
14 changes: 13 additions & 1 deletion src/Filee.App/Assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"error.cannot_turn": "Rotate and flip work on images only",
"error.no_transparency": "This format has no transparency, so there's nothing to trim",
"error.too_many_frames": "Too many frames to save as pictures, raise \"Every Nth frame\"",
"error.too_many_pictures": "Too many pictures for one video, split them into several",
"error.not_enough_space": "Not enough free disk space for the pictures",
"error.no_motion_photo": "This photo has no video Filee can read (an Android Motion Photo, or an iPhone Live Photo with its MOV next to it)",
"error.live_photo_start": "The clip starts after the end of this video. Choose an earlier \"Clip start\"",
Expand Down Expand Up @@ -136,7 +137,7 @@
"engine.pdf-text.description": "Extracts the text of PDFs in reading order, also from two-column pages (no OCR for scans).",
"engine.pdf-slides.description": "Turns PDFs into PowerPoint slides: each page becomes a picture on its own slide (looks like the PDF, not editable), with the page text in the speaker notes.",
"engine.email.description": "E-mails (EML, Outlook MSG) to HTML and text with sender, recipients and date, pictures included; attachments into a ZIP.\nMSG to EML. Saved web pages (MHTML) to one HTML file with their pictures.",
"engine.data.description": "JSON, JSON Lines, YAML, TOML, XML and CSV into each other.\nvCard contacts to CSV and back.\nComments are dropped. CSV holds tables only.",
"engine.data.description": "JSON, JSON Lines, YAML, TOML, XML and CSV into each other.\nvCard contacts and iCalendar events to CSV and back.\nComments are dropped. CSV holds tables only.",
"engine.vector.description": "SVG and SVGZ to vector PDF, images and DXF; pictures traced into SVG; Illustrator files saved with PDF content.",
"engine.icns.description": "macOS app icons (ICNS) from and to images.",
"engine.font.description": "Fonts: TTF, OTF, WOFF, WOFF2 and EOT into each other.",
Expand Down Expand Up @@ -227,6 +228,14 @@
"preset.extract_motion": "Extract Live Photo video",
"preset.live_photo_iphone": "Live Photo (iPhone)",
"preset.motion_photo_android": "Motion Photo (Android)",
"preset.compress_image": "Compress image",
"preset.compress_video": "Compress video",
"preset.video_from_images": "Video from images",
"preset.extract_audio": "Extract audio",
"preset.merge_videos": "Merge videos",
"preset.compress_audio": "Compress audio",
"preset.merge_audio": "Merge audio",
"preset.remove_metadata": "Remove metadata",

"format.folder": "Folder",
"format.category.Image": "Image",
Expand Down Expand Up @@ -496,6 +505,9 @@
"presets.frame_estimate": "One minute of 30 fps video gives {0} pictures, at most {1} per video.",
"presets.extract_motion_photo": "Extract Live/Motion Photo video",
"presets.extract_motion_photo_hint": "A photo becomes the video saved with it: the one inside an Android Motion Photo, or the MOV next to an iPhone Live Photo.\nOther pictures become a video of the still picture.",
"presets.slide_seconds": "Seconds per picture",
"presets.crossfade": "Crossfade between pictures",
"presets.crossfade_hint": "Each picture fades into the next over a second instead of cutting to it.",
"presets.group.live_photo": "Live / Motion Photo",
"presets.live_photo": "A video becomes",
"presets.live_photo.None": "One still frame",
Expand Down
14 changes: 13 additions & 1 deletion src/Filee.App/Assets/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"error.cannot_turn": "Rotar y voltear solo funcionan con imágenes",
"error.no_transparency": "Este formato no tiene transparencia, así que no hay nada que recortar",
"error.too_many_frames": "Demasiados fotogramas para guardar como imágenes; aumenta «Cada N fotogramas»",
"error.too_many_pictures": "Demasiadas imágenes para un vídeo; divídelas en varios",
"error.not_enough_space": "Espacio libre en disco insuficiente para las imágenes",
"error.no_motion_photo": "Esta foto no tiene un vídeo que Filee pueda leer (una Motion Photo de Android o una Live Photo de iPhone con su MOV al lado)",
"error.live_photo_start": "El clip empieza después del final de este vídeo. Elige un «Inicio del clip» anterior",
Expand Down Expand Up @@ -129,7 +130,7 @@
"engine.pdf-text.description": "Extrae el texto de los PDF en orden de lectura, también de páginas en dos columnas (sin OCR para escaneos).",
"engine.pdf-slides.description": "Convierte PDF en diapositivas de PowerPoint: cada página pasa a ser una imagen en su propia diapositiva (con el aspecto del PDF, no editable), con el texto de la página en las notas del orador.",
"engine.email.description": "Correos electrónicos (EML, Outlook MSG) a HTML y texto con remitente, destinatarios y fecha, imágenes incluidas; los adjuntos van a un ZIP.\nMSG a EML. Páginas web guardadas (MHTML) a un solo archivo HTML con sus imágenes.",
"engine.data.description": "JSON, JSON Lines, YAML, TOML, XML y CSV entre sí.\nContactos vCard a CSV y viceversa.\nLos comentarios se descartan. CSV solo admite tablas.",
"engine.data.description": "JSON, JSON Lines, YAML, TOML, XML y CSV entre sí.\nContactos vCard y eventos de iCalendar a CSV y viceversa.\nLos comentarios se descartan. CSV solo admite tablas.",
"engine.vector.description": "SVG y SVGZ a PDF vectorial, imágenes y DXF; imágenes trazadas a SVG; archivos de Illustrator guardados con contenido PDF.",
"engine.icns.description": "Iconos de apps de macOS (ICNS) desde y hacia imágenes.",
"engine.font.description": "Tipografías: TTF, OTF, WOFF, WOFF2 y EOT entre sí.",
Expand Down Expand Up @@ -217,6 +218,14 @@
"preset.extract_motion": "Extraer vídeo de Live Photo",
"preset.live_photo_iphone": "Live Photo (iPhone)",
"preset.motion_photo_android": "Motion Photo (Android)",
"preset.compress_image": "Comprimir imagen",
"preset.compress_video": "Comprimir vídeo",
"preset.video_from_images": "Vídeo de imágenes",
"preset.extract_audio": "Extraer audio",
"preset.merge_videos": "Unir vídeos",
"preset.compress_audio": "Comprimir audio",
"preset.merge_audio": "Unir audio",
"preset.remove_metadata": "Quitar metadatos",
"format.folder": "Carpeta",
"format.category.Image": "Imagen",
"format.category.Pdf": "PDF",
Expand Down Expand Up @@ -481,6 +490,9 @@
"presets.frame_estimate": "Un minuto de vídeo a 30 fps genera {0} imágenes, como máximo {1} por vídeo.",
"presets.extract_motion_photo": "Extraer vídeo de Live/Motion Photo",
"presets.extract_motion_photo_hint": "La foto se convierte en el vídeo guardado con ella: el que lleva dentro una Motion Photo de Android o el MOV junto a una Live Photo de iPhone.\nLas demás imágenes se convierten en un vídeo de la imagen fija.",
"presets.slide_seconds": "Segundos por imagen",
"presets.crossfade": "Fundido entre imágenes",
"presets.crossfade_hint": "Cada imagen se funde con la siguiente durante un segundo en lugar de cortar.",
"presets.group.live_photo": "Live Photo / Motion Photo",
"presets.live_photo": "Un vídeo se convierte en",
"presets.live_photo.None": "Un fotograma fijo",
Expand Down
14 changes: 13 additions & 1 deletion src/Filee.App/Assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"error.cannot_turn": "La rotation et le retournement ne s'appliquent qu'aux images",
"error.no_transparency": "Ce format n'a pas de transparence : il n'y a rien à rogner",
"error.too_many_frames": "Trop d'images à enregistrer, augmentez « Une image sur N »",
"error.too_many_pictures": "Trop d'images pour une seule vidéo, répartissez-les en plusieurs",
"error.not_enough_space": "Pas assez d'espace disque libre pour les images",
"error.no_motion_photo": "Cette photo ne contient aucune vidéo lisible par Filee (une Motion Photo Android, ou une Live Photo d'iPhone avec son MOV à côté)",
"error.live_photo_start": "L'extrait commence après la fin de cette vidéo. Choisissez un « Début de l'extrait » plus tôt",
Expand Down Expand Up @@ -136,7 +137,7 @@
"engine.pdf-text.description": "Extrait le texte des PDF dans l'ordre de lecture, y compris sur deux colonnes (pas d'OCR pour les numérisations).",
"engine.pdf-slides.description": "Convertit les PDF en diapositives PowerPoint : chaque page devient une image sur sa propre diapositive (fidèle au PDF, non modifiable), avec le texte de la page dans les notes du présentateur.",
"engine.email.description": "E-mails (EML, MSG Outlook) en HTML et texte avec expéditeur, destinataires et date, images comprises ; pièces jointes dans un ZIP.\nMSG en EML. Pages web enregistrées (MHTML) en un seul fichier HTML avec leurs images.",
"engine.data.description": "JSON, JSON Lines, YAML, TOML, XML et CSV entre eux.\nContacts vCard en CSV et inversement.\nLes commentaires sont supprimés. Le CSV ne contient que des tableaux.",
"engine.data.description": "JSON, JSON Lines, YAML, TOML, XML et CSV entre eux.\nContacts vCard et événements iCalendar en CSV et inversement.\nLes commentaires sont supprimés. Le CSV ne contient que des tableaux.",
"engine.vector.description": "SVG et SVGZ en PDF vectoriel, images et DXF ; images vectorisées en SVG ; fichiers Illustrator enregistrés avec contenu PDF.",
"engine.icns.description": "Icônes d'apps macOS (ICNS) depuis et vers des images.",
"engine.font.description": "Polices : TTF, OTF, WOFF, WOFF2 et EOT entre eux.",
Expand Down Expand Up @@ -227,6 +228,14 @@
"preset.extract_motion": "Vidéo Live",
"preset.live_photo_iphone": "Live Photo (iPhone)",
"preset.motion_photo_android": "Motion Photo (Android)",
"preset.compress_image": "Compresser l'image",
"preset.compress_video": "Compresser la vidéo",
"preset.video_from_images": "Vidéo à partir d'images",
"preset.extract_audio": "Extraire l'audio",
"preset.merge_videos": "Fusionner les vidéos",
"preset.compress_audio": "Compresser l'audio",
"preset.merge_audio": "Fusionner l'audio",
"preset.remove_metadata": "Supprimer les métadonnées",

"format.folder": "Dossier",
"format.category.Image": "Image",
Expand Down Expand Up @@ -496,6 +505,9 @@
"presets.frame_estimate": "Une minute de vidéo à 30 i/s donne {0} images, au plus {1} par vidéo.",
"presets.extract_motion_photo": "Extraire la vidéo Live/Motion Photo",
"presets.extract_motion_photo_hint": "Une photo devient la vidéo enregistrée avec elle : celle contenue dans une Motion Photo Android, ou le MOV à côté d'une Live Photo d'iPhone.\nLes autres images deviennent une vidéo de l'image fixe.",
"presets.slide_seconds": "Secondes par image",
"presets.crossfade": "Fondu enchaîné entre les images",
"presets.crossfade_hint": "Chaque image se fond dans la suivante en une seconde au lieu d'y passer d'un coup.",
"presets.group.live_photo": "Live / Motion Photo",
"presets.live_photo": "Une vidéo devient",
"presets.live_photo.None": "Une image fixe",
Expand Down
Loading
Loading