Skip to content
palmoni5 edited this page Jul 18, 2026 · 2 revisions

קישורי עומק (Deep Links) — סכמת otzaria://

אוצריא רשומה במערכת ההפעלה כמטפלת בסכמת ה־URI ‏otzaria://. כל הפעלה של קישור כזה — מדפדפן, מאפליקציה אחרת, מקיצור דרך או משורת פקודה — פותחת את אוצריא (או מאותתת למופע הרץ) ומבצעת פעולה: ניווט, פתיחת ספר, הפעלת חיפוש, התקנת תוסף.

דף זה מתעד את הכתובות הנתמכות ואת המנגנון הפנימי. המסמך הקנוני במאגר: docs/deep_links.md. למדריך בשפה פשוטה: קישורי עומק למשתמש.

רישום הסכמה במערכת ההפעלה

נייד ו־macOS — רישום סטטי בקונפיגורציית הפלטפורמה:

  • Android — ‏android/app/src/main/AndroidManifest.xml ‏(<intent-filter> עם <data android:scheme="otzaria"/>).
  • iOS / macOS — ‏Info.plist ‏(CFBundleURLSchemes).

דסקטופ (Windows/Linux) — רישום דינמי בזמן ריצה דרך PluginProtocolRegistrationService.ensureRegistered. השם היסטורי ומטעה — השירות רושם את כל סכמת otzaria://, לא רק תוספים:

  • Windows — כתיבה ל־HKCU\Software\Classes\otzaria עם shell\open\command שמכוון ל־exe הפעיל. ‏windows/runner/main.cpp אחראי רק על מה שקורה אחרי שה־OS הפעיל את אוצריא עם הארגומנט.
  • Linux — יצירת ~/.local/share/applications/otzaria.desktop עם MimeType=x-scheme-handler/otzaria; ואז update-desktop-database + ‏xdg-mime default.

כתובות נתמכות

otzaria://open/... — ניווט פנימי

כתובת תוצאה
otzaria://open/library מסך הספרייה
otzaria://open/tools מסך הכלים (הלשונית האחרונה שהיתה פעילה)
otzaria://open/calendar / gematria / notes / shamor_zachor / measurements / aramaic_dictionary / acronyms_dictionary פתיחת כלי מובנה
otzaria://open/search מסך החיפוש (ללא הפעלת חיפוש)
otzaria://open/search?q=<text> לשונית חיפוש חדשה + חיפוש מיידי בכל הספרים
otzaria://open/search?q=<text>&mode=<mode> כנ"ל עם מצב: advanced / exact / fuzzy; ערך לא מוכר → מתקדם
otzaria://open/settings הגדרות (הלשונית הנוכחית)
otzaria://open/settings/<tab> הגדרות בלשונית: design / text / library / tools / shortcuts / system / about
otzaria://open/history דיאלוג ההיסטוריה
otzaria://open/bookmarks דיאלוג הסימניות
otzaria://open/detection דיאלוג איתור מקורות ריק
otzaria://open/detection?q=<text> איתור מקורות עם טקסט מילוי־מראש + חיפוש מיידי
otzaria://open/inspection מסך העיון (הספר האחרון שנפתח)
otzaria://open/sdk דיאלוג ניהול התוספים
otzaria://open/daily_page הדף היומי (PDF תלמוד בבלי בדף הנכון ליום)
otzaria://open/tool/<tool-id> לשונית כלי לפי מזהה מלא (built-in או תוסף מוצמד)
otzaria://open/plugin/<plugin-id> פתיחת תוסף לפי מזהה — גם לא־מוצמד (מצב transient)
otzaria://open/tab/<index> מעבר לטאב פתוח לפי מיקומו (0-based); נבנה אוטומטית ב־Jump List של Windows
otzaria://open/book/<id> ספר טקסט בעיון לפי מזהה DB
otzaria://open/book/<id>?index=<n> פתיחה בסעיף n (לא שלילי)
otzaria://open/book/<id>?q=<text> פתיחה עם מחרוזת חיפוש להדגשה; ניתן לשלב עם index
otzaria://open/book/<id>?index=<n>&mark הדגשת כל רקע המקטע בצהוב
otzaria://open/book/<id>?index=<n>&m=<text> הדגשת טקסט ספציפי בתוך המקטע
otzaria://open/pdf/<id> ספר PDF לפי מזהה משותף עם ה־TextBook
otzaria://open/pdf/<id>?index=<n> פתיחת ה־PDF בעמוד n (חיובי, 1-based)

כללי פרסינג:

  • הסכמה, ה־host ושמות הפעולה — case-insensitive. הערכים (מזהי ספרים/כלים, url=) נשמרים כפי שהם.
  • טקסט עברי ב־q= / m= חייב URL-encoding ‏(UTF-8).
  • index שלילי/לא מספרי, q= ריק, m= ריק — מתעלמים. detection ללא q= נפתח ריק.
  • עדיפות הדגשה ב־book:m > ‏mark > ‏q — אם יש סימון מקומי (m/mark), ‏q מתעלם לחלוטין (לא תיפתח לשונית חיפוש במקביל).
  • כתובת לא מוכרת (otzaria://open/banana) → ‏null, התעלמות שקטה בכוונה. ספר עם ID לא קיים → UiSnack.showError.

otzaria://plugin/install?url=... — התקנת תוסף

פרמטר תיאור
url (חובה) כתובת ההורדה של חבילת .otzplugin; רק http/https
overwrite (אופציונלי) true/1/yes/on — דריסת תוסף קיים בלי לשאול; ברירת מחדל false

otzaria://plugin/install-local?path=<abs> — התקנה מקובץ מקומי

משמש לשיוך קובץ .otzplugin במערכת ההפעלה (לחיצה כפולה). הנתיב חייב להיות מוחלט, להסתיים ב־.otzplugin, ולא נתיב UNC/התקן — ראו "אבטחה" למטה.

תאימות zayit://

הראוטר מנרמל קישורי zayit:// של אפליקציית זַיִת לפורמט המקביל:

  • zayit://book/{id} ← ‏otzaria://open/book/{id}
  • zayit://book/{id}/line/{index} ← ‏otzaria://open/book/{id}?index={index}

בניית קישורים בתוך התוכנה

lib/utils/book_link_builder.dart — לוגיקה טהורה (ללא תלות ב־Flutter) לבניית קישורי ספר/מקטע/הדגשה, שמשמשת את פריטי "העתק קישור ישיר" בתפריטי ההקשר של קורא הטקסט וה־PDF, ואת קיצורי המקלדת המוגדרים ב־shortcut_validator.dart. הוספת סוג קישור חדש שמוצג למשתמש מתחילה שם.

איך זה עובד מאחורי הקלעים

לחיצה על otzaria://...
        ↓
ה-OS מפעיל את אוצריא עם הארגומנט
        ↓
אוצריא כבר רצה?
  לא → הפעלה רגילה + טיפול בארגומנטים
  כן → הפרוסס המשני כותב ל-pending_external_activations.jsonl ויוצא;
       המופע הקיים מזהה את השינוי דרך file watcher
        ↓
_handleExternalActivationUriString(uri)
        ↓
ExternalUriRouter.parseUri → ExternalUriAction (sealed)
        ↓
_dispatchExternalUriAction — switch יחיד → ניווט / פתיחת ספר / התקנה

Single-instance ב־Windows

ב־windows/runner/main.cpp יש Mutex בשם OtzariaAppSingleInstance. מופע שני שמזהה מופע חי: מחלץ מהארגומנטים URIs שמתחילים ב־otzaria:, מוסיף אותם כשורות JSONL ל־%APPDATA%\otzaria\pending_external_activations.jsonl, ויוצא מיד. המופע הראשון מאזין לקובץ דרך ExternalActivationQueue; הקובץ עובר rename ל־.processing בזמן הקריאה כדי לא לאבד URIs אם המופע נסגר באמצע. ב־Android/iOS יש ערוץ פלטפורמה — external_activation_channel.dart.

הראוטר — ExternalUriRouter

ראוטר יחיד — lib/core/external_uri_router.dart — הוא נקודת הכניסה היחידה לפענוח. הוא מנתב את כל הכתובות ל־sealed class ExternalUriAction עם variant לכל סוג פעולה: OpenScreenAction, ‏OpenToolAction, ‏OpenPluginAction, ‏SwitchToTabAction, ‏OpenBookAction, ‏OpenPdfBookAction, ‏OpenSettingsTabAction, ‏OpenHistoryAction, ‏OpenBookmarksAction, ‏RunSearchAction, ‏RunDetectionAction, ‏OpenInspectionAction, ‏OpenSdkAction, ‏OpenDailyPageAction, ‏InstallPluginAction, ‏InstallLocalPluginAction.

לפענוח plugin/install הראוטר מאציל ל־PluginStoreLinkParser.parseUri ועוטף את התוצאה ב־InstallPluginAction.

ל־OpenBookAction/OpenPdfBookAction יש hasExplicitPosition — קישור "חשוף" ללא מיקום לא מזיז טאב שכבר פתוח על הספר.

הדיספצ'ר

ב־main_window_screen.dart הפונקציה _handleExternalActivationUriString: מפענחת (אם null — מתעלמת בשקט), מציפה את החלון (_bringWindowToFront), ואז _dispatchExternalUriAction עם switch יחיד על ה־sealed class. נקודות עדינות:

  • OpenToolAction — ניווט ל־Screen.more ואז requestOpenTool(toolId) עם retry מדורג; ב־ToolsScreen יש תור pending לכלי שה־descriptor שלו עוד לא נטען (תוסף שטרם הגיע מ־PluginSystemBloc). אחרי 5 שניות בלי הצלחה — UiSnack.showError.
  • OpenPluginAction — ממתין גם ל־PluginSystemLoaded, מאתר את התוסף וקורא ל־openPluginTransiently — שמטפל גם במוצמד (ניתוב ל־requestOpenTool) וגם בלא־מוצמד (לשונית transient). תוסף חסר/מושבת → UiSnack.showError.
  • OpenBookAction — ‏await DataRepository.instance.library, איתור לפי b.id, ואז openBook(...) עם index/הדגשות.
  • RunSearchAction — יוצר SearchingTab חדש, מוסיף ל־HistoryBloc + TabsBloc, מנווט ל־Screen.search; החיפוש מופעל מ־TantivyFullTextSearch.initState.
  • InstallLocalPluginAction — ‏InstallPluginRequested ל־PluginSystemBloc; דיאלוג ההרשאות נפתח דרך BlocListener.

הוספת יעד חדש

  1. ראוטר — אם זו פעולה חדשה: variant חדש ב־ExternalUriAction + ענף ב־_parseOpen. אם זה כלי מובנה חדש — מספיק alias ב־_toolAliases.
  2. דיספצ'ר — ‏case חדש ב־_dispatchExternalUriAction. הקומפיילר אוכף exhaustive matching על ה־sealed class.
  3. בדיקות — ‏test/core/external_uri_router_test.dart: כתובת תקינה, כתובות שנדחות, case-insensitivity.
  4. תיעוד — עדכון טבלת הכתובות ב־docs/deep_links.md ובדף זה.

אבטחה

  • אין התקנת תוסף ללא אישור משתמש — גם עם overwrite=true המשתמש רואה קבצים והרשאות לפני ההתקנה.
  • plugin/install מקבל רק http/https; ‏file:// וכל סכמה אחרת נדחות.
  • plugin/install-local — הנתיב חייב מוחלט (ב־Windows כולל אות כונן מפורשת), בסיומת .otzplugin, ולא UNC/התקן (\\server\share, ‏\\.\, ‏\\?\, ‏//host). קישור otzaria:// ניתן להפעלה מדף אינטרנט — נתיב UNC היה גורם לחיבור SMB ודליפת אישורי NTLM; נתיב יחסי נפתר מול תיקיית העבודה ולכן אינו מהימן.
  • כתובת לא מוכרת → התעלמות שקטה (עיצובית, כדי לא להפחיד משתמש שלחץ על קישור מגרסה עתידית); ספר לא קיים → הודעת שגיאה מפורשת.

קבצים מרכזיים

קובץ תפקיד
lib/core/external_uri_router.dart הראוטר האחיד + ‏sealed ‏ExternalUriAction
lib/utils/book_link_builder.dart בניית קישורי ספר לפעולות "העתק קישור ישיר"
lib/plugins/services/plugin_store_link_parser.dart פענוח plugin/install (משמש את הראוטר)
lib/plugins/services/plugin_protocol_registration_service.dart רישום דינמי של הסכמה ב־Windows/Linux
lib/core/external_activation_queue.dart תור JSONL בין מופעים
lib/core/external_activation_channel.dart ערוץ פלטפורמה ל־URIs בזמן ריצה (Android/iOS)
lib/navigation/view/main_window_screen.dart האזנה, פענוח ודיספצ'ר
windows/runner/main.cpp ‏single-instance והעברת ארגומנטים לתור
test/core/external_uri_router_test.dart בדיקות הראוטר

דפים קשורים

Clone this wiki locally