M5 — תיקון אוטומטי בעת Reload של DWG

"החשש של היועץ פתור" · אם היועץ דורס את ה-DWG, הפלאגין מתקן בלי שתעשה כלום
VITRUVIUS · SESSION 0027 · 2026-05-25
למה זה היה צריך להיות מילסטון

בלי M5, התרחיש הזה שובר את הזרימה:

  • אתה מתקן את הקישור עם "תקן ג'יבריש" — עברית קריאה, מצוין.
  • היועץ שולח DWG מעודכן. אתה דורס את הקובץ הישן בתיקיית הפרויקט.
  • פותח את Manage Links → Reload. הג'יבריש חזר.
  • צריך ללחוץ שוב "תקן ג'יבריש" ידנית. בכל reload. מהיום עד אחרון ימי הפרויקט.

אדריכל לא ילך אחורה לכפתור בכל פעם. M5 מבטל את הצעד הזה לגמרי.

מה נבנה
  • קובץ אחד חדש: src\Vitruvius.Revit2024\Events\DwgReloadHandler.cs
  • refactor ב-FixGibberishCommand: הצינור עצמו (fontmap → SHX archive → reverse → reload) הופק ל-RunSilently(doc, paths) כדי שגם ה-handler האוטומטי יוכל לקרוא לו, לא רק הכפתור.
  • רישום אירוע ב-VitruviusApp: ב-startup רושמים DocumentChanged, ב-shutdown משחררים.

DLL גדל מ-54KB ל-59KB. שום שינוי ב-UI שאתה רואה — רק יוצא לדרך לבד כשצריך.

איך זה עובד — צעד אחר צעד
1
היועץ דורס את הקובץ
DWG חדש נכתב לדיסק במקום הישן. mtime של הקובץ מתעדכן לזמן הנוכחי.
2
אתה עושה Reload (או פותח את המודל)
Revit קורא את הקובץ מהדיסק, ומפעיל אירוע פנימי בשם DocumentChanged שאומר "ה-CADLinkType הזה השתנה".
3
DwgReloadHandler קולט את האירוע
מסנן רק שינויים על CADLinkType (בלי הרעש של כל אלפי האלמנטים שמשתנים בעת רינדור).
4
בודק בזיכרון: האם תיקנו את הקובץ הזה פעם?
קורא את %APPDATA%\Vitruvius\state.json. אם הקובץ לא רשום שם — אין מה לעשות, יוצאים.
5
ה-guard הקריטי — האם הקובץ חדש יותר ממה שתיקנו?
משווים mtime של הדיסק מול FixedAt שב-cache. רק אם mtime > FixedAt — היועץ דרס. אחרת — זה הקובץ שלנו, מתעלמים. (ראה למה זה קריטי בהמשך.)
6
דוחפים את הנתיב ל-buffer ומבקשים מ-Revit "תתקשר אלינו כשתוכל"
קוראים ל-ExternalEvent.Raise(). זה לא מריץ כלום עכשיו — רק שם בתור.
7
Revit חוזר אלינו ב-idle
כשהוא לא באמצע אירוע, הוא קורא לפונקציה Execute שלנו. כאן מותר לשנות את המסמך.
8
מריצים את כל הצינור בלי דיאלוג
FixGibberishCommand.RunSilently — fontmap, ארכוב SHX, היפוך עברית, ועושה Reload תכנותי על הקישור.
9
רושמים את התיקון ומראים toast
אחרי שכתבנו את הקובץ — מעדכנים FixedAt ל-now. צץ ה-toast: "תוקנו אוטומטית X קישורים שעודכנו". סה"כ ~5 שניות מ-Reload עד "נגמר".
למה ה-mtime guard הוא הלב של הסיפור

ה-Reload התכנותי שאנחנו עושים בשלב 8 — גם הוא יורה את DocumentChanged. בלי שום הגנה, היינו נכנסים ללולאה כזאת:

  1. תיקנו → reload → DocumentChanged → handler רץ → תיקנו שוב → reload → DocumentChanged → ...

Revit היה קורס תוך 30 שניות, או שהמשתמש היה מקבל "טוסט סיים" אינסופי.

🛡 ההגנה

הצינור עושה cache.Record אחרי שכתב את הקובץ.
אז FixedAt תמיד מאוחר יותר מ-mtime של הקובץ שלנו.

כש-DocumentChanged יחזור מה-Reload התכנותי שלנו, ה-handler יראה mtime ≤ FixedAt ויפסיק שם. לא יחזיר. הלולאה נשברת.

רק כתיבה חיצונית (היועץ) שדוחפת את ה-mtime קדימה מעבר ל-FixedAt הישן — עוברת. בדיוק מה שרצינו.

למה ExternalEvent ולא לרוץ ישר מ-DocumentChanged

Revit אוסר על שינוי המסמך מתוך אירועי DB.Events. אם תקרא ל-cadType.Reload() בתוך ה-DocumentChanged callback ישירות, אתה מקבל exception ובאיזשהו מקום למעלה במחסנית התוכנית קורסת.

הדפוס המאושר של Revit הוא ExternalEvent:

  • בתוך ה-event שלך, אסור לשנות מסמך → אז רק מבקשים ש-Revit יחזור אלינו.
  • Revit חוזר ב-idle loop, קורא ל-Execute(UIApplication) שלנו.
  • שם — main thread, לא בתוך event, context בטוח. הכל מותר.

זה גם הסיבה שיש _pendingPaths כ-buffer — בין הצתת האירוע לבין הריצה בפועל יכולים לעבור כמה אירועים, וצריך לאסוף את כולם למקום אחד.

איך לבדוק שזה באמת עובד
  1. פתח את A_Mivne roi.rvt.
  2. אם עוד לא תוקן בסשן הזה — לחץ "תקן ג'יבריש" פעם אחת.
  3. סגור את Revit.
  4. בתיקייה של הקישור, מצא את ה-backup הישן ביותר ב-OLD\ (זה הקובץ המקורי מהיועץ).
  5. העתק אותו על הקובץ הראשי — זה מדמה "היועץ שלח עדכון".
  6. פתח את Revit, תן לו לטעון.
  7. Manage Links → Reload (או פשוט לחץ על הקישור → Reload).
  8. תוך 5 שניות — toast: "תוקנו אוטומטית X קישורים שעודכנו". עברית קריאה. לא לחצת על שום כפתור של Vitruvius.

אם משהו השתבש — לוג ב-%APPDATA%\Vitruvius\diagnostic.log מראה כל תג של reload.detect / reload.skip / reload.exec.

הצעד הבא

M6 — UI מלא. כרגע יש כפתור אחד (SplitButton) עם dropdown. M6 הוא: ScanResultsWindow, SettingsWindow, RestoreWindow מעוצבים — חוויה מקצועית במקום TaskDialog. אומדן: 2-3 ימים.

אחרי M6: M7 update checker · M8 license stub · M9 installer · M10 tests · M11 בטא.