Skip to content
palmoni5 edited this page Jul 17, 2026 · 1 revision

רצף האתחול והפעלת האפליקציה

דף זה מתאר מה קורה מרגע הפעלת אוצריא ועד שהחלון הראשי מוצג — תחום שבו הושקע מאמץ רב בביצועים (הצגה מהירה של החלון).

נקודת הכניסה — lib/main.dart

הפונקציה main(List<String> args) מבצעת, לפי הסדר:

  1. פקודות CLI_maybeRunCliCommand בודק אם זו הרצת שורת־פקודה (למשל pack-plugin לאריזת תוסף .otzplugin). אם כן — התהליך מסתיים בלי לפתוח חלון.
  2. אתחול BindingsSentryWidgetsFlutterBinding.ensureInitialized().
  3. סמן דטרמיניסטיEditableText.debugDeterministicCursor = true, כדי ש־RtlTextField ינהל את הבהוב הסמן בעצמו.
  4. לוגים מוקדמים — אתחול data root ומטא־דטה של גרסה (PackageInfo).
  5. תור הפעלות חיצוניות — זיהוי otzaria:// וקבצי .otzplugin בארגומנטים והכנסתם לתור.
  6. מטפלי שגיאותFlutterError.onError ו־PlatformDispatcher.onError, כולל סינון "רעש" ידוע (שגיאות AXTree ב־Windows, אסרשן HardwareKeyboard, באג _notifyMissingFonts של pdfrx). בגרסת production השגיאות נכתבות ל־ErrorLogFile (‏logs/errors.txt בתיקיית הנתונים; נמחק בשדרוג גרסה).
  7. Sentry — אתחול אסינכרוני (unawaited); דיווח רק מגרסה שפורסמה, sampling נמוך, ללא PII.
  8. _runAppBootstrap — שומר מופע יחיד (single instance, מדולג ב־macOS/iOS), רושם AppBlocObserver, מאתחל windowManager (החלון נשאר מוסתר!), וקורא runApp.

עץ ה־runApp: SentryWidgetRestartWidgetAppBootstrap.

מסך הפתיחה (Splash) וחשיפת החלון

  • ה־splash הוא נייטיבי — חלק מה־runner של כל פלטפורמת דסקטופ. החלון הראשי של Flutter מוסתר עד הקריאה ל־presentMainWindow().
  • _mainWindowRevealedCompleter מסנכרן: חימומי מטמון כבדים ממתינים לחשיפת החלון כדי לא להתחרות בטעינת הספר הפעיל על ה־main isolate ועל seforim.db.
  • presentMainWindow() מבצע cloak נייטיבי, show/focus, מחיל maximize/fullscreen שנדחו, וסוגר את ה־splash דרך MethodChannel('otzaria/splash').
  • ב־MainWindowScreen: אם המסך ההתחלתי הוא "עיון" עם ספר טקסט שעדיין נטען — החשיפה ממתינה ל־TextBookLoaded/TextBookError. קיים failsafe של 8 שניות.

שלבי האתחול הכבד

_initializeProcessSingletons (רץ בזמן שה־splash מוצג)

מריץ במקביל (Future.wait):

  • RustLib.init() — ‏FFI של מנוע החיפוש (Tantivy).
  • loadCerts() — טעינת תעודת NetFree (רשתות מסוננות).
  • initSettingsAndWindow() — אתחול Settings עם HiveCache, שחזור גבולות חלון.

לאחר מכן: initHive() (פתיחת ה־boxes: ‏tabs, workspaces, history, bookmarks, error_reports_queue), ‏PortablePaths.migrateIfMoved() (מצב נייד — שכתוב נתיבים אם התיקייה הועברה), ושירותים דחויים.

_initializeRestartableRuntime

  • שחזור עדכון ספרייה שנקטע באמצע (_recoverInterruptedLibraryUpdate).
  • SqliteDataProvider.initialize.
  • אתחול מקורות תוספים + PluginCrashGuard.
  • רישום פרוטוקול ו־pre-warm של WebView2 (הכל unawaited).

השלב הזה ניתן להרצה חוזרת — זה מה שמאפשר "restart" של ה־runtime דרך RestartWidget בלי לסגור את התהליך.

_runDeferredCacheWarmups

ממתין לחשיפת החלון (timeout ‏15 שניות) ורק אז מחמם מטמונים: DictionaryLookupRepository, ‏BooksCache, ‏AcronymsCache, ‏GenerationCache, גופני מערכת, ReferenceBooksCache, ספרי HebrewBooks מקומיים.

AppBootstrap — בניית עץ ה־Providers

AppBootstrap (StatefulWidget) מציג SplashApp עד שהאתחול הסתיים (ובמקרה שגיאה — מסך שגיאה RTL). כשמוכן, נבנה:

  • MultiRepositoryProvider — ‏FocusRepository, ‏SettingsRepository.
  • MultiBlocProvider — כל ה־BLoCs הראשיים. שימו לב: LibraryBloc נרשם בלי LoadLibrary — הטעינה נדחית ל־MainWindowScreen כדי לא לחנוק את טעינת הספר הפעיל.

lib/app.dart — ‏App

עוטף את MaterialApp ב־BlocBuilder<SettingsBloc> שנבנה מחדש רק על שינויי צבע ראשי / מצב כהה / תפריט קומפקטי. מגדיר:

  • navigatorKey גלובלי (מ־ui_snack.dart) — משמש את UiSnack.
  • ‏locale קבוע he_IL עם לוקליזציות Global — זה מה שקובע RTL גלובלי.
  • ערכות נושא מ־AppThemeData.light/dark.
  • בדסקטופ — עטיפה ב־VirtualWindowFrame (שורת כותרת מותאמת).
  • home: MainWindowScreen.

שערי Startup — ‏StartupWorkGate

lib/navigation/view/startup_work_gate.dart — מתאם שמונע הרצת עבודות רקע כבדות (סנכרון קבצים, עדכון ספרייה) עד שמתקיימים כל התנאים: הספרייה נטענה, התקבלה החלטת אינדוקס, והאינדוקס אינו רץ. consumeStartPermission() מחזיר true פעם אחת בלבד.

החלטת האינדוקס עצמה היא פונקציה טהורה — decideStartupIndexing ב־lib/navigation/startup_indexing_decision.dart, שמחזירה אחת מ: autoReindexThenStart / promptManualReindex / startIndexing / checkIndexStatus.

ניהול חלון

  • WindowPersistence — שמירה ושחזור של גבולות החלון עם debounce; splashMode מונע שמירת גודל ה־splash בטעות; maximize/fullscreen נדחים עד לחשיפה.
  • AppWindowListener — האזנה לאירועי חלון.
  • FocusRepository — שחזור פוקוס אחרי אירועי חלון (maximize/fullscreen/resize) במודל שתי שכבות: שכבת מסך ושכבת דיאלוג (stack).

דפים קשורים

Clone this wiki locally