דילוג לתוכן
0
  • דף הבית
  • חוקי הפורום
  • מדריכים
  • פוסטים אחרונים
  • לא נפתר
  • תגיות
  • פופולרי
  • משתמשים
  • תרומות לאוצריא
  • צור קשר
  • דף הבית
  • חוקי הפורום
  • מדריכים
  • פוסטים אחרונים
  • לא נפתר
  • תגיות
  • פופולרי
  • משתמשים
  • תרומות לאוצריא
  • צור קשר
עיצובים
  • בהיר
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • כהה
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • ברירת מחדל (ללא עיצוב (ברירת מחדל))
  • ללא עיצוב (ברירת מחדל)
כיווץ
לוגו אתר

פורום אוצריא

אוצריא - דף הבית
|
קח שותפות בהוספת ספרים
|
תרום לאוצריא
  1. דף הבית
  2. מדריכים ותוכנות עזר לאוצריא
  3. להורדה | ~~רציתם תוספים לתוכנה? קיבלתם!...~~

להורדה | ~~רציתם תוספים לתוכנה? קיבלתם!...~~

מתוזמן נעוץ נעול הועבר מדריכים ותוכנות עזר לאוצריא
תוספיםתכנותמדריך
52 פוסטים 13 כותבים 2.4k צפיות 11 עוקבים
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
    תגובה
    • תגובה כנושא
    התחברו כדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • יאיר דניאלי יאיר דניאל

      @דבש אולי אוסיף זאת עוד מעט, כעת זה בהרצה, בודק באגים מסויימים שקורים בנטפרי.

      עריכה:
      אולי אוסיף זאת עוד מעט
      נוסף!

      בודק באגים מסויימים שקורים בנטפרי
      נפתר!

      שמואל5ש
      שמואל5ש
      שמואל5
      כתב ב נערך לאחרונה על ידי
      #18

      @יאיר-דניאל יש לך צפי מתי זה ישוחרר?

      יאיר דניאלי תגובה 1 תגובה אחרונה
      0
      • שמואל5ש שמואל5

        @יאיר-דניאל יש לך צפי מתי זה ישוחרר?

        יאיר דניאלי
        יאיר דניאלי
        יאיר דניאל
        תורם לאוצריא ניהול תוספים
        כתב ב נערך לאחרונה על ידי
        #19

        @שמואל5 מקווה שבשעה הקרובה- עוד לא הוספתי את המאגר שלך, אחרי שזה יעבוד טוב, אוסיף בל"נ

        חד בדראח תגובה 1 תגובה אחרונה
        1
        • חנניהח
          חנניהח
          חנניה
          כתב ב נערך לאחרונה על ידי
          #20

          @יאיר-דניאל הוא יוריד כל פעם מחדש את כל המאגר, או שהוא יסנכרן כמו אוצריא עצמה?

          יאיר דניאלי תגובה 1 תגובה אחרונה
          0
          • חנניהח חנניה

            @יאיר-דניאל הוא יוריד כל פעם מחדש את כל המאגר, או שהוא יסנכרן כמו אוצריא עצמה?

            יאיר דניאלי
            יאיר דניאלי
            יאיר דניאל
            תורם לאוצריא ניהול תוספים
            כתב ב נערך לאחרונה על ידי
            #21

            @חנניה לא עד כדי כך...
            בלחיצה על הכפתור יפתח לך רשימה של כל התיקיות הקיימות בגיטאב- ותוכל לבחור מה להוריד.

            חנניהח תגובה 1 תגובה אחרונה
            0
            • יאיר דניאלי יאיר דניאל

              @חנניה לא עד כדי כך...
              בלחיצה על הכפתור יפתח לך רשימה של כל התיקיות הקיימות בגיטאב- ותוכל לבחור מה להוריד.

              חנניהח
              חנניהח
              חנניה
              כתב ב נערך לאחרונה על ידי
              #22

              @יאיר-דניאל א"א לעשות את זה כסינכרון?

              תגובה 1 תגובה אחרונה
              0
              • ד
                ד
                דבש
                כתב ב נערך לאחרונה על ידי
                #23

                עניין של נראות: הייתי מציע להזיז את הכפתור ללמעלה ליד הסנכרון

                תגובה 1 תגובה אחרונה
                1
                • שמואל5ש שמואל5

                  @הבל-הבלים @יאיר-דניאל לי מופיע המיקום הזה... (איפסתי הגדרות בהתקנה, זה הגרסה האחרונה 0.9.86)
                  3381b715-d99a-47d1-8165-32e7869d21be-image.jpeg

                  A
                  A
                  asz
                  מפתח
                  כתב ב נערך לאחרונה על ידי
                  #24

                  > @שמואל5 כתב:

                  @הבל-הבלים @יאיר-דניאל לי מופיע המיקום הזה... (איפסתי הגדרות בהתקנה, זה הגרסה האחרונה 0.9.86)
                  3381b715-d99a-47d1-8165-32e7869d21be-image.jpeg

                  כי התקנת ללא הרשאות ניהול, (בחירה בהתקנה רק למשתמש נוכחי)

                  תגובה 1 תגובה אחרונה
                  1
                  • יאיר דניאלי יאיר דניאל

                    @שמואל5 מקווה שבשעה הקרובה- עוד לא הוספתי את המאגר שלך, אחרי שזה יעבוד טוב, אוסיף בל"נ

                    חד בדראח
                    חד בדראח
                    חד בדרא
                    כתב ב נערך לאחרונה על ידי
                    #25
                    פוסט זה נמחק!
                    יאיר דניאלי תגובה 1 תגובה אחרונה
                    0
                    • חד בדראח חד בדרא
                      [[topic:post-is-deleted]]
                      יאיר דניאלי
                      יאיר דניאלי
                      יאיר דניאל
                      תורם לאוצריא ניהול תוספים
                      כתב ב נערך לאחרונה על ידי יאיר דניאל
                      #26

                      @חד-בדרא כתב:

                      מקווה שבשעה הקרובה

                      לא הכל תלוי בי - יש לי גם בית אשה וילדים... אה, וגם ערב פסח עכשיו.
                      בכ"א יש לי איזה באג מטופש שאני בינתיים מנסה לפתור באוטומציה בגיטאב - בכדי שיוכלו לבחור אילו ספרים להוריד. מקווה שאגמור בהקדם, כי אם לא זה ידחה ל2 -3 בלילה

                      י. פל.י חד בדראח 2 תגובות תגובה אחרונה
                      1
                      • יאיר דניאלי יאיר דניאל

                        @חד-בדרא כתב:

                        מקווה שבשעה הקרובה

                        לא הכל תלוי בי - יש לי גם בית אשה וילדים... אה, וגם ערב פסח עכשיו.
                        בכ"א יש לי איזה באג מטופש שאני בינתיים מנסה לפתור באוטומציה בגיטאב - בכדי שיוכלו לבחור אילו ספרים להוריד. מקווה שאגמור בהקדם, כי אם לא זה ידחה ל2 -3 בלילה

                        י. פל.י
                        י. פל.י
                        י. פל.
                        כתב ב נערך לאחרונה על ידי
                        #27

                        @יאיר-דניאל כתב:

                        לא הכל תלוי בי - יש לי גם בית אשה וילדים... אה, וגם ערב פסח עכשיו.

                        מהקל לקשה, או הפוך?

                        פלמנמוניפ יאיר דניאלי 2 תגובות תגובה אחרונה
                        2
                        • י. פל.י י. פל.

                          @יאיר-דניאל כתב:

                          לא הכל תלוי בי - יש לי גם בית אשה וילדים... אה, וגם ערב פסח עכשיו.

                          מהקל לקשה, או הפוך?

                          פלמנמוניפ
                          פלמנמוניפ
                          פלמנמוני
                          כתב ב נערך לאחרונה על ידי
                          #28

                          > @י.-פל. כתב:

                          מהקל לקשה, או הפוך?

                          לכאו' 'בית' זה הכי קל, תפשוט מינה...

                          תגובה 1 תגובה אחרונה
                          0
                          • י. פל.י י. פל.

                            @יאיר-דניאל כתב:

                            לא הכל תלוי בי - יש לי גם בית אשה וילדים... אה, וגם ערב פסח עכשיו.

                            מהקל לקשה, או הפוך?

                            יאיר דניאלי
                            יאיר דניאלי
                            יאיר דניאל
                            תורם לאוצריא ניהול תוספים
                            כתב ב נערך לאחרונה על ידי יאיר דניאל
                            #29

                            > @י.-פל. כתב:

                            מהקל לקשה, או הפוך

                            האמת, לא יודע...

                            > @פלמנמוני כתב:

                            לכאו' 'בית' זה הכי קל

                            ומנין לך?
                            אחרי הכל כבר אמרנו - ער"פ עכשיו

                            תגובה 1 תגובה אחרונה
                            0
                            • יאיר דניאלי יאיר דניאל

                              @חד-בדרא כתב:

                              מקווה שבשעה הקרובה

                              לא הכל תלוי בי - יש לי גם בית אשה וילדים... אה, וגם ערב פסח עכשיו.
                              בכ"א יש לי איזה באג מטופש שאני בינתיים מנסה לפתור באוטומציה בגיטאב - בכדי שיוכלו לבחור אילו ספרים להוריד. מקווה שאגמור בהקדם, כי אם לא זה ידחה ל2 -3 בלילה

                              חד בדראח
                              חד בדראח
                              חד בדרא
                              כתב ב נערך לאחרונה על ידי חד בדרא
                              #30

                              @יאיר-דניאל כתב:

                              אה, וגם ערב פסח עכשיו.

                              ובין לבין,
                              רוצים להתרענן, כותבים כאן....
                              כל אחד והתחביב שלו..

                              תגובה 1 תגובה אחרונה
                              0
                              • י. פל.י
                                י. פל.י
                                י. פל.
                                כתב ב נערך לאחרונה על ידי
                                #31

                                אולי נחליט שאת הדברים הרציניים כותבים בספויילר...
                                יאללה, נסחפנו.

                                תגובה 1 תגובה אחרונה
                                3
                                • יאיר דניאלי יאיר דניאל

                                  בעקבות בקשות ודיונים שונים בפורום - בנוגע לכך האם אפשר שיהיה תוספים לתוכנה - שדרכם יוכלו להוריד מאגרים חיצוניים כמו שלי ושל @שמואל5 - בניתי (-כמובן בעזרת AI...) סוג של תוסף לתוכנה - היא כעת בהרצה, ועוד מעט תעלה.
                                  פרטים בספויילר הראשון:

                                  אין אפשרות להוסיף תוספים חיצוניים לתוכנה שכתובה בפלאטר ודארט, מה שכן ישנם 3 אפשרויות:

                                  **1. שימוש ב-Dynamic Loading (טעינה דינמית)
                                  זו הדרך הנפוצה ביותר בתוכנות שולחניות (Desktop). ניתן לבנות את האפליקציה כך שהיא תחפש קבצי ספרייה חיצוניים (כמו .dll בחלונות או .so בלינוקס) בתיקייה מסוימת בזמן ריצה.

                                  איך זה עובד: משתמשים בחבילת dart:ffi כדי לקרוא לפונקציות מתוך קבצי ה-C/C++ החיצוניים.

                                  הוספת כפתורים: התוסף יכול להחזיר נתונים שהתוכנה הראשית מפרשת כהוראה להציג כפתור או פונקציה חדשה.

                                  1. הזרקת קוד באמצעות מנוע Scripting
                                    זוהי הדרך הגמישה ביותר להוספת פונקציונליות ושינוי ממשק המשתמש (UI) ללא צורך בקימפול.

                                  שילוב מנוע לואה (Lua) או JavaScript: ניתן להטמיע בתוך אפליקציית ה-Flutter מנוע הרצה שמפרש קבצי טקסט חיצוניים.

                                  דוגמה: התוסף יהיה קובץ .lua המגדיר פונקציות ומיקומים של כפתורים. האפליקציה קוראת את הקובץ ובונה את ה-UI בהתאם.

                                  1. ארכיטקטורת Micro-Frontends (באמצעות נתיבים דינמיים)
                                    אם מדובר בתוספים שאתה מפתח בעצמך ורק רוצה לאפשר למשתמש לבחור אם להתקין אותם:

                                  ניתן להשתמש בטכניקה של Deferred Loading. זה מאפשר להוריד חלקי קוד מהרשת רק כשהמשתמש זקוק להם, מה שחוסך במקום ומאפשר הוספת רכיבים בצורה מודולרית.**

                                  עד כאן תשובותו של הבן הרשע, סליחה של ג'מיני...

                                  למעשה מה שעשיתי זה כך:
                                  ישנה תוכנה בשם AutoHotkey שמאפשרת להזריק סקריפטים מעל תוכנות קיימות, וליצור כפתורים צפים עליהם.
                                  כתבתי בעזרת הAI קוד פייתון וקוד AHK (הקוד שאיתו התוכנה הזו עובדת) שמה שהם עושים ביחד הוא כך - התוכנה רצה ברקע במחשב (היא לא לוקחת זיכרון - בקושי 2M) וכשאוצריא עולה - מיד צץ כפתור חדש בסרגל - עם אייקון של הורדה, וטולטיפ של הסבר על הכפתור.
                                  לחיצה עליו פותחת חלון ששואל האם להוריד את המאגר שלי - לתוך אוצריא, ובלחיצה על אישור - נפתח חלון התקדמות שבסופו ההודעה "הספרים הותקנו בהצלחה"
                                  עיינו בספויילר הבא - לתמונות.

                                  תמונות:

                                  1.png
                                  11.png
                                  2.png
                                  3.png

                                  לאחר שעות ששרפתי על זה - ובאגים בלי סוף - נמאס לי מהעניין והחלטתי שאני פורש.

                                  מצורף הקודים למי שרוצה להמשיך את זה מכאן.

                                  בהצלחה, וסליחה מכל מי שפיתחתי בו ציפיות.
                                  הקודים להורדה:
                                  downloader.py
                                  OtzariaButton (1).ahk
                                  (יש להתקין את הספריה הבאה:)

                                  pip install requests
                                  

                                  קוד הפייתון (- שעליו רץ הקוד השני)

                                  import requests
                                  import sys
                                  import zipfile
                                  import shutil
                                  from pathlib import Path
                                  
                                  # הגדרות מערכת - נשאר בדיוק לפי ההנחיות שלך
                                  API_URL = "https://api.github.com/repos/YairDaniel123/Otzarya-Library/releases/latest"
                                  OTZARIA_LIB = Path(r"C:\ProgramData\otzaria\books")
                                  TEMP_FILE = Path("download.tmp")
                                  HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
                                  CHUNK_SIZE = 1024 * 1024
                                  
                                  def get_remote_assets():
                                      try:
                                          r = requests.get(API_URL, headers=HEADERS, timeout=15)
                                          r.raise_for_status()
                                          data = r.json()
                                          assets = {}
                                          for a in data.get("assets", []):
                                              if not a["name"].endswith(".zip"):
                                                  continue
                                              name = a.get("label") or a["name"]
                                              assets[name] = {
                                                  "url": a["browser_download_url"],
                                                  "updated": a["updated_at"],
                                                  "is_full": (a["name"] == "full-library.zip")
                                              }
                                          return assets
                                      except Exception as e:
                                          print(f"ERROR:LIST|{str(e)}", flush=True)
                                          sys.exit(1)
                                  
                                  def check_updates():
                                      if not OTZARIA_LIB.exists():
                                          try:
                                              OTZARIA_LIB.mkdir(parents=True, exist_ok=True)
                                          except Exception as e:
                                              print(f"ERROR:PERMISSION|{str(e)}", flush=True)
                                              return
                                  
                                      remote = get_remote_assets()
                                      results = []
                                      
                                      for name, info in remote.items():
                                          folder = name.replace(".zip", "")
                                          version_file = OTZARIA_LIB / folder / ".version_info"
                                          
                                          is_up_to_date = version_file.exists() and version_file.read_text(encoding="utf-8").strip() == info["updated"]
                                          
                                          if not is_up_to_date:
                                              type_id = "0" if info["is_full"] else "1"
                                              results.append(f"{type_id}|{name}|{info['url']}|{info['updated']}")
                                      
                                      if results:
                                          results.sort()
                                          print(f"LIST:{';'.join(results)}", flush=True)
                                      else:
                                          print("EMPTY", flush=True)
                                  
                                  def download_and_extract(url, updated_at, display_name):
                                      try:
                                          with requests.get(url, stream=True, headers=HEADERS, timeout=(10, None)) as r:
                                              r.raise_for_status()
                                              total = int(r.headers.get("content-length", 0))
                                              done = 0
                                              with open(TEMP_FILE, "wb") as f:
                                                  for chunk in r.iter_content(CHUNK_SIZE):
                                                      if chunk:
                                                          f.write(chunk)
                                                          done += len(chunk)
                                                          if total:
                                                              print(f"DL_PROGRESS:{int(done/total*100)}", flush=True)
                                          
                                          print("DL_FINISHED", flush=True)
                                          folder_name = display_name.replace(".zip", "")
                                          target_dir = OTZARIA_LIB / folder_name
                                          temp_extract = OTZARIA_LIB / f"temp_{folder_name}"
                                          
                                          if temp_extract.exists(): shutil.rmtree(temp_extract)
                                          temp_extract.mkdir(parents=True)
                                          
                                          with zipfile.ZipFile(TEMP_FILE, "r") as z:
                                              files = [f for f in z.namelist() if not f.endswith(".version_info")]
                                              for i, f in enumerate(files):
                                                  z.extract(f, temp_extract)
                                                  print(f"EX_PROGRESS:{int((i+1)/len(files)*100)}", flush=True)
                                          
                                          if target_dir.exists(): shutil.rmtree(target_dir)
                                          temp_extract.rename(target_dir)
                                          (target_dir / ".version_info").write_text(updated_at, encoding="utf-8")
                                          print("DONE", flush=True)
                                          
                                      except Exception as e:
                                          print(f"ERROR:PROCESS|{str(e)}", flush=True)
                                      finally:
                                          if TEMP_FILE.exists(): TEMP_FILE.unlink()
                                  
                                  if __name__ == "__main__":
                                      if len(sys.argv) < 2: sys.exit()
                                      cmd = sys.argv[1]
                                      if cmd == "CHECK": check_updates()
                                      elif "|" in cmd:
                                          p = cmd.split("|")
                                          if len(p) >= 4: download_and_extract(p[2], p[3], p[1])
                                  

                                  קוד AHK (יש צורך להתקין את התוכנה הזו בשביל להריץ את הקוד, תוכנה קטנה ממש).

                                  #Requires AutoHotkey v2.0
                                  #SingleInstance Force
                                  
                                  global MainColor   := "F8F4E8"   
                                  global AccentColor := "7D5800"   
                                  global BgColor     := "EDE8D5"   
                                  global IsHover     := false
                                  global Queue       := []
                                  global Worker      := ""
                                  global IsCancelled := false
                                  global OurWindows  := Map()      
                                  global SelectGui   := unset
                                  global ProgGui     := unset
                                  global MsgGui      := unset
                                  
                                  ; =====================================================
                                  ;  גרירת חלונות
                                  ; =====================================================
                                  OnMessage(0x0201, WM_LBUTTONDOWN)
                                  WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) {
                                      rootHwnd := DllCall("GetAncestor", "ptr", hwnd, "uint", 2, "ptr")
                                      if !OurWindows.Has(rootHwnd)
                                          return
                                      try {
                                          cls := WinGetClass("ahk_id " hwnd)
                                          if (cls = "Button" || cls = "Edit")
                                              return
                                      }
                                      PostMessage(0xA1, 2,,, "ahk_id " rootHwnd)
                                  }
                                  
                                  ApplyRounding(guiObj) {
                                      guiObj.Opt("+LastFound")
                                      DllCall("dwmapi\DwmSetWindowAttribute", "ptr", guiObj.Hwnd, "uint", 33, "ptr*", 2, "uint", 4)
                                  }
                                  
                                  ; =====================================================
                                  ;  כפתור הורדה צף
                                  ; =====================================================
                                  BtnGui := Gui("+AlwaysOnTop -Caption +ToolWindow +LastFound")
                                  BtnGui.BackColor := "EEAA99"
                                  WinSetTransColor("EEAA99", BtnGui)
                                  BtnGui.SetFont("s22", "Segoe UI Symbol")
                                  global BtnTxt := BtnGui.Add("Text", "x0 y0 w60 h50 Center c" AccentColor, "📥")
                                  BtnTxt.OnEvent("Click", ShowSelectionMenu)
                                  OurWindows[BtnGui.Hwnd] := true
                                  
                                  TipGui := Gui("-Caption +AlwaysOnTop +ToolWindow")
                                  TipGui.BackColor := "2B2B2B"
                                  TipGui.SetFont("s9 w800 cWhite", "Segoe UI")
                                  TipGui.Add("Text", "x8 y4 w80 h44 Center", "הורדת מאגרי ספרים מותאמים")
                                  ApplyRounding(TipGui)
                                  OurWindows[TipGui.Hwnd] := true
                                  
                                  SetTimer(WatchOtzaria, 250)
                                  
                                  WatchOtzaria() {
                                      global IsHover
                                      TargetID := WinExist("ahk_exe otzaria.exe")
                                      ActiveID := WinActive("A")
                                  
                                      SelectHwnd := (IsSet(SelectGui) && IsObject(SelectGui)) ? SelectGui.Hwnd : 0
                                      ProgHwnd   := (IsSet(ProgGui) && IsObject(ProgGui)) ? ProgGui.Hwnd : 0
                                      MsgHwnd    := (IsSet(MsgGui) && IsObject(MsgGui)) ? MsgGui.Hwnd : 0
                                  
                                      ; בדיקה האם אנחנו עובדים כרגע על אוצריא או על אחד החלונות שלנו
                                      IsOtzariaContext := TargetID && (ActiveID = TargetID || ActiveID = SelectHwnd || ActiveID = BtnGui.Hwnd || ActiveID = ProgHwnd || ActiveID = MsgHwnd)
                                  
                                      if IsOtzariaContext {
                                          WinGetPos(&X, &Y, &W, &H, "ahk_id " TargetID)
                                          btnX := X + W - 78
                                          btnY := Y + H - 186
                                          
                                          BtnGui.Show("x" btnX " y" btnY " w60 h50 NoActivate")
                                  
                                          ; החזרת החלונות במידה וחזרנו לאוצריא מתוכנה אחרת
                                          if SelectHwnd
                                              try SelectGui.Show("NoActivate")
                                          if ProgHwnd
                                              try ProgGui.Show("NoActivate")
                                  
                                          MouseGetPos(,, &HoverWin)
                                          if (HoverWin = BtnGui.Hwnd) {
                                              if !IsHover {
                                                  TipGui.Show("x" (btnX - 85) " y" (btnY + 5) " NoActivate")
                                                  IsHover := true
                                              }
                                          } else if IsHover {
                                              TipGui.Hide()
                                              IsHover := false
                                          }
                                      } else {
                                          BtnGui.Hide()
                                          TipGui.Hide()
                                          ; הסתרת חלונות בעת מעבר לתוכנה אחרת (לא סגירה, רק הסתרה)
                                          if SelectHwnd
                                              try SelectGui.Hide()
                                          if ProgHwnd
                                              try ProgGui.Hide()
                                      }
                                  }
                                  
                                  ; =====================================================
                                  ;  חלון בחירת ספרים מעוצב וימין-שמאל (RTL)
                                  ; =====================================================
                                  ShowSelectionMenu(*) {
                                      BtnTxt.Text := "⏳"
                                      try {
                                          shell := ComObject("WScript.Shell")
                                          exec  := shell.Exec("pythonw.exe downloader.py CHECK")
                                          res   := exec.StdOut.ReadAll()
                                      } catch {
                                          BtnTxt.Text := "📥"
                                          CustomMsgBox("שגיאה: לא ניתן להפעיל את פייתון.", "שגיאת הפעלה")
                                          return
                                      }
                                      BtnTxt.Text := "📥"
                                  
                                      if !InStr(res, "LIST:") || InStr(res, "EMPTY") {
                                          CustomMsgBox("המאגר מעודכן!", "עדכון ספריה")
                                          return
                                      }
                                  
                                      global SelectGui := Gui("+AlwaysOnTop -Caption")
                                      SelectGui.BackColor := MainColor
                                      ApplyRounding(SelectGui)
                                      OurWindows[SelectGui.Hwnd] := true
                                  
                                      SelectGui.SetFont("s15 w700 c" AccentColor, "Segoe UI")
                                      SelectGui.Add("Text", "x0 y15 w420 Center", "עדכון ספריה")
                                      
                                      SelectGui.SetFont("s11 w600 cBlack", "Segoe UI")
                                      ; +0x20 ו-Right אחראים על הפיכת הצ'קבוקס לימין שמאלה
                                      cbAll := SelectGui.Add("Checkbox", "x20 y+20 w380 Right +0x20", "בחר / בטל הכל (ללא המאגר המלא)")
                                  
                                      Checkboxes := []
                                      items := StrSplit(StrReplace(res, "LIST:", ""), ";")
                                      for item in items {
                                          if (Trim(item) = "") {
                                              continue 
                                          }
                                          p := StrSplit(item, "|")
                                          isFull := (p[1] = "0")
                                          SelectGui.SetFont("s11 w400 cBlack", "Segoe UI")
                                          cb := SelectGui.Add("Checkbox", (p[1] = "1" ? "Checked " : "") "x20 y+10 w380 Right +0x20", p[2])
                                          Checkboxes.Push({full: item, cb: cb, isFull: isFull})
                                      }
                                  
                                      cbAll.OnEvent("Click", (self, *) => ToggleAll(self.Value, Checkboxes))
                                  
                                      BtnDown   := SelectGui.Add("Button", "Default w160 h35 x40 y+25", "הורד")
                                      BtnCancel := SelectGui.Add("Button", "w160 h35 x+20", "ביטול")
                                  
                                      BtnDown.OnEvent("Click", (*) => StartSelectedDownload(SelectGui, Checkboxes))
                                      BtnCancel.OnEvent("Click", (*) => SelectGui.Destroy())
                                  
                                      SelectGui.Show("w420 Center")
                                  }
                                  
                                  ToggleAll(val, Checkboxes) {
                                      for item in Checkboxes {
                                          if !item.isFull
                                              item.cb.Value := val
                                      }
                                  }
                                  
                                  ; =====================================================
                                  ;  הודעה מעוצבת בסגנון אוצריא
                                  ; =====================================================
                                  CustomMsgBox(txt, title) {
                                      global MsgGui := Gui("-Caption +AlwaysOnTop +Owner")
                                      MsgGui.BackColor := MainColor
                                      ApplyRounding(MsgGui)
                                      OurWindows[MsgGui.Hwnd] := true
                                  
                                      MsgGui.SetFont("s15 w700 c" AccentColor, "Segoe UI")
                                      MsgGui.Add("Text", "x0 y20 w350 Center", title)
                                  
                                      MsgGui.SetFont("s11 w400 cBlack", "Segoe UI")
                                      MsgGui.Add("Text", "x25 y+15 w300 Center +Wrap", txt)
                                  
                                      BtnOk := MsgGui.Add("Button", "Default w120 h35 x115 y+25", "אישור")
                                      BtnOk.OnEvent("Click", (*) => MsgGui.Destroy())
                                  
                                      MsgGui.Show("w350 Center")
                                  }
                                  
                                  ; =====================================================
                                  ;  חלון התקדמות
                                  ; =====================================================
                                  ProgressShow(FileName, Remaining) {
                                      global ProgGui, StatusTxt, Bar, PctLabel
                                  
                                      ProgGui := Gui("-Caption +AlwaysOnTop")
                                      ProgGui.BackColor := MainColor
                                      ApplyRounding(ProgGui)
                                      OurWindows[ProgGui.Hwnd] := true
                                  
                                      ProgGui.SetFont("s14 w700 c" AccentColor, "Segoe UI")
                                      ProgGui.Add("Text", "x0 y20 w400 Center", "הורדה בתהליך")
                                  
                                      ProgGui.SetFont("s11 w600 c" AccentColor, "Segoe UI")
                                      ProgGui.Add("Text", "x25 y+15 w350 Center +Wrap", FileName)
                                  
                                      ProgGui.SetFont("s12 w700 c" AccentColor, "Segoe UI")
                                      StatusTxt := ProgGui.Add("Text", "x0 y+15 w400 Center", "מוריד...")
                                  
                                      Bar := ProgGui.Add("Progress", "x30 y+12 w340 h18 cGreen Background" BgColor, 0)
                                  
                                      ProgGui.SetFont("s11 w700 cBlack", "Segoe UI")
                                      PctLabel := ProgGui.Add("Text", "x0 y+8 w400 Center", "0%")
                                  
                                      CancelBtn := ProgGui.Add("Button", "w120 h35 x140 y+20", "ביטול")
                                      CancelBtn.OnEvent("Click", CancelDownload)
                                  
                                      ProgGui.Show("w400 Center")
                                  }
                                  
                                  ; =====================================================
                                  ;  ניהול תור הורדות
                                  ; =====================================================
                                  StartSelectedDownload(GuiObj, Checkboxes) {
                                      global Queue := [], IsCancelled := false
                                      for item in Checkboxes {
                                          if item.cb.Value
                                              Queue.Push(item.full)
                                      }
                                      GuiObj.Destroy()
                                      if Queue.Length > 0
                                          NextDownload()
                                      else
                                          CustomMsgBox("לא נבחרו ספרים להורדה.", "שים לב")
                                  }
                                  
                                  NextDownload() {
                                      global Queue, IsCancelled, Worker
                                      if IsCancelled || (Queue.Length = 0) {
                                          if !IsCancelled
                                              CustomMsgBox("הספריה עודכנה בהצלחה!", "סיום הורדה")
                                          return
                                      }
                                      CurrentItem := Queue.RemoveAt(1)
                                      p := StrSplit(CurrentItem, "|")
                                      ProgressShow(p[2], Queue.Length)
                                      Worker := ComObject("WScript.Shell").Exec('pythonw.exe downloader.py "' CurrentItem '"')
                                      SetTimer(CheckStatus, 100)
                                  }
                                  
                                  CheckStatus() {
                                      global Worker, ProgGui, StatusTxt, Bar, PctLabel
                                  
                                      if Worker.StdOut.AtEndOfStream {
                                          SetTimer(CheckStatus, 0)
                                          try {
                                              if IsObject(ProgGui) && (ProgGui != "") {
                                                  ProgGui.Destroy()
                                                  ProgGui := unset
                                                  CustomMsgBox("ההורדה נכשלה.`nבדוק חיבור לאינטרנט.", "שגיאה")
                                              }
                                          }
                                          return
                                      }
                                  
                                      line := Worker.StdOut.ReadLine()
                                      if InStr(line, "DL_PROGRESS:") {
                                          pct := StrReplace(line, "DL_PROGRESS:", "")
                                          Bar.Value     := pct
                                          PctLabel.Text := pct "%"
                                      } else if InStr(line, "DL_FINISHED") {
                                          StatusTxt.Text := "מחלץ קבצים..."
                                          Bar.Value := 0
                                      } else if InStr(line, "EX_PROGRESS:") {
                                          pct := StrReplace(line, "EX_PROGRESS:", "")
                                          Bar.Value     := pct
                                          PctLabel.Text := pct "%"
                                      } else if InStr(line, "DONE") {
                                          SetTimer(CheckStatus, 0)
                                          ProgGui.Destroy()
                                          ProgGui := unset
                                          NextDownload()
                                      }
                                  }
                                  
                                  CancelDownload(*) {
                                      global Worker, IsCancelled, ProgGui
                                      IsCancelled := true
                                      SetTimer(CheckStatus, 0)
                                      try Worker.Terminate()
                                      ProgGui.Destroy()
                                      ProgGui := unset
                                      CustomMsgBox("ההורדה בוטלה.", "ביטול")
                                  }
                                  
                                  דנדיד
                                  דנדיד
                                  דנדי
                                  תורם לאוצריא
                                  כתב ב נערך לאחרונה על ידי
                                  #32

                                  @יאיר-דניאל לי נראה שכדאי שלספרים האישיים יהיה מיקום נפרד ולא שיהיה באותה תקיה של כל הספרים

                                  יאיר דניאלי תגובה 1 תגובה אחרונה
                                  0
                                  • דנדיד דנדי

                                    @יאיר-דניאל לי נראה שכדאי שלספרים האישיים יהיה מיקום נפרד ולא שיהיה באותה תקיה של כל הספרים

                                    יאיר דניאלי
                                    יאיר דניאלי
                                    יאיר דניאל
                                    תורם לאוצריא ניהול תוספים
                                    כתב ב נערך לאחרונה על ידי
                                    #33

                                    עניין של טעם.

                                    דנדיד תגובה 1 תגובה אחרונה
                                    0
                                    • יאיר דניאלי יאיר דניאל

                                      עניין של טעם.

                                      דנדיד
                                      דנדיד
                                      דנדי
                                      תורם לאוצריא
                                      כתב ב נערך לאחרונה על ידי
                                      #34

                                      @יאיר-דניאל לטעמי זה לא עניין של טעם 🙂

                                      תגובה 1 תגובה אחרונה
                                      0
                                      • יאיר דניאלי יאיר דניאל

                                        בעקבות בקשות ודיונים שונים בפורום - בנוגע לכך האם אפשר שיהיה תוספים לתוכנה - שדרכם יוכלו להוריד מאגרים חיצוניים כמו שלי ושל @שמואל5 - בניתי (-כמובן בעזרת AI...) סוג של תוסף לתוכנה - היא כעת בהרצה, ועוד מעט תעלה.
                                        פרטים בספויילר הראשון:

                                        אין אפשרות להוסיף תוספים חיצוניים לתוכנה שכתובה בפלאטר ודארט, מה שכן ישנם 3 אפשרויות:

                                        **1. שימוש ב-Dynamic Loading (טעינה דינמית)
                                        זו הדרך הנפוצה ביותר בתוכנות שולחניות (Desktop). ניתן לבנות את האפליקציה כך שהיא תחפש קבצי ספרייה חיצוניים (כמו .dll בחלונות או .so בלינוקס) בתיקייה מסוימת בזמן ריצה.

                                        איך זה עובד: משתמשים בחבילת dart:ffi כדי לקרוא לפונקציות מתוך קבצי ה-C/C++ החיצוניים.

                                        הוספת כפתורים: התוסף יכול להחזיר נתונים שהתוכנה הראשית מפרשת כהוראה להציג כפתור או פונקציה חדשה.

                                        1. הזרקת קוד באמצעות מנוע Scripting
                                          זוהי הדרך הגמישה ביותר להוספת פונקציונליות ושינוי ממשק המשתמש (UI) ללא צורך בקימפול.

                                        שילוב מנוע לואה (Lua) או JavaScript: ניתן להטמיע בתוך אפליקציית ה-Flutter מנוע הרצה שמפרש קבצי טקסט חיצוניים.

                                        דוגמה: התוסף יהיה קובץ .lua המגדיר פונקציות ומיקומים של כפתורים. האפליקציה קוראת את הקובץ ובונה את ה-UI בהתאם.

                                        1. ארכיטקטורת Micro-Frontends (באמצעות נתיבים דינמיים)
                                          אם מדובר בתוספים שאתה מפתח בעצמך ורק רוצה לאפשר למשתמש לבחור אם להתקין אותם:

                                        ניתן להשתמש בטכניקה של Deferred Loading. זה מאפשר להוריד חלקי קוד מהרשת רק כשהמשתמש זקוק להם, מה שחוסך במקום ומאפשר הוספת רכיבים בצורה מודולרית.**

                                        עד כאן תשובותו של הבן הרשע, סליחה של ג'מיני...

                                        למעשה מה שעשיתי זה כך:
                                        ישנה תוכנה בשם AutoHotkey שמאפשרת להזריק סקריפטים מעל תוכנות קיימות, וליצור כפתורים צפים עליהם.
                                        כתבתי בעזרת הAI קוד פייתון וקוד AHK (הקוד שאיתו התוכנה הזו עובדת) שמה שהם עושים ביחד הוא כך - התוכנה רצה ברקע במחשב (היא לא לוקחת זיכרון - בקושי 2M) וכשאוצריא עולה - מיד צץ כפתור חדש בסרגל - עם אייקון של הורדה, וטולטיפ של הסבר על הכפתור.
                                        לחיצה עליו פותחת חלון ששואל האם להוריד את המאגר שלי - לתוך אוצריא, ובלחיצה על אישור - נפתח חלון התקדמות שבסופו ההודעה "הספרים הותקנו בהצלחה"
                                        עיינו בספויילר הבא - לתמונות.

                                        תמונות:

                                        1.png
                                        11.png
                                        2.png
                                        3.png

                                        לאחר שעות ששרפתי על זה - ובאגים בלי סוף - נמאס לי מהעניין והחלטתי שאני פורש.

                                        מצורף הקודים למי שרוצה להמשיך את זה מכאן.

                                        בהצלחה, וסליחה מכל מי שפיתחתי בו ציפיות.
                                        הקודים להורדה:
                                        downloader.py
                                        OtzariaButton (1).ahk
                                        (יש להתקין את הספריה הבאה:)

                                        pip install requests
                                        

                                        קוד הפייתון (- שעליו רץ הקוד השני)

                                        import requests
                                        import sys
                                        import zipfile
                                        import shutil
                                        from pathlib import Path
                                        
                                        # הגדרות מערכת - נשאר בדיוק לפי ההנחיות שלך
                                        API_URL = "https://api.github.com/repos/YairDaniel123/Otzarya-Library/releases/latest"
                                        OTZARIA_LIB = Path(r"C:\ProgramData\otzaria\books")
                                        TEMP_FILE = Path("download.tmp")
                                        HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
                                        CHUNK_SIZE = 1024 * 1024
                                        
                                        def get_remote_assets():
                                            try:
                                                r = requests.get(API_URL, headers=HEADERS, timeout=15)
                                                r.raise_for_status()
                                                data = r.json()
                                                assets = {}
                                                for a in data.get("assets", []):
                                                    if not a["name"].endswith(".zip"):
                                                        continue
                                                    name = a.get("label") or a["name"]
                                                    assets[name] = {
                                                        "url": a["browser_download_url"],
                                                        "updated": a["updated_at"],
                                                        "is_full": (a["name"] == "full-library.zip")
                                                    }
                                                return assets
                                            except Exception as e:
                                                print(f"ERROR:LIST|{str(e)}", flush=True)
                                                sys.exit(1)
                                        
                                        def check_updates():
                                            if not OTZARIA_LIB.exists():
                                                try:
                                                    OTZARIA_LIB.mkdir(parents=True, exist_ok=True)
                                                except Exception as e:
                                                    print(f"ERROR:PERMISSION|{str(e)}", flush=True)
                                                    return
                                        
                                            remote = get_remote_assets()
                                            results = []
                                            
                                            for name, info in remote.items():
                                                folder = name.replace(".zip", "")
                                                version_file = OTZARIA_LIB / folder / ".version_info"
                                                
                                                is_up_to_date = version_file.exists() and version_file.read_text(encoding="utf-8").strip() == info["updated"]
                                                
                                                if not is_up_to_date:
                                                    type_id = "0" if info["is_full"] else "1"
                                                    results.append(f"{type_id}|{name}|{info['url']}|{info['updated']}")
                                            
                                            if results:
                                                results.sort()
                                                print(f"LIST:{';'.join(results)}", flush=True)
                                            else:
                                                print("EMPTY", flush=True)
                                        
                                        def download_and_extract(url, updated_at, display_name):
                                            try:
                                                with requests.get(url, stream=True, headers=HEADERS, timeout=(10, None)) as r:
                                                    r.raise_for_status()
                                                    total = int(r.headers.get("content-length", 0))
                                                    done = 0
                                                    with open(TEMP_FILE, "wb") as f:
                                                        for chunk in r.iter_content(CHUNK_SIZE):
                                                            if chunk:
                                                                f.write(chunk)
                                                                done += len(chunk)
                                                                if total:
                                                                    print(f"DL_PROGRESS:{int(done/total*100)}", flush=True)
                                                
                                                print("DL_FINISHED", flush=True)
                                                folder_name = display_name.replace(".zip", "")
                                                target_dir = OTZARIA_LIB / folder_name
                                                temp_extract = OTZARIA_LIB / f"temp_{folder_name}"
                                                
                                                if temp_extract.exists(): shutil.rmtree(temp_extract)
                                                temp_extract.mkdir(parents=True)
                                                
                                                with zipfile.ZipFile(TEMP_FILE, "r") as z:
                                                    files = [f for f in z.namelist() if not f.endswith(".version_info")]
                                                    for i, f in enumerate(files):
                                                        z.extract(f, temp_extract)
                                                        print(f"EX_PROGRESS:{int((i+1)/len(files)*100)}", flush=True)
                                                
                                                if target_dir.exists(): shutil.rmtree(target_dir)
                                                temp_extract.rename(target_dir)
                                                (target_dir / ".version_info").write_text(updated_at, encoding="utf-8")
                                                print("DONE", flush=True)
                                                
                                            except Exception as e:
                                                print(f"ERROR:PROCESS|{str(e)}", flush=True)
                                            finally:
                                                if TEMP_FILE.exists(): TEMP_FILE.unlink()
                                        
                                        if __name__ == "__main__":
                                            if len(sys.argv) < 2: sys.exit()
                                            cmd = sys.argv[1]
                                            if cmd == "CHECK": check_updates()
                                            elif "|" in cmd:
                                                p = cmd.split("|")
                                                if len(p) >= 4: download_and_extract(p[2], p[3], p[1])
                                        

                                        קוד AHK (יש צורך להתקין את התוכנה הזו בשביל להריץ את הקוד, תוכנה קטנה ממש).

                                        #Requires AutoHotkey v2.0
                                        #SingleInstance Force
                                        
                                        global MainColor   := "F8F4E8"   
                                        global AccentColor := "7D5800"   
                                        global BgColor     := "EDE8D5"   
                                        global IsHover     := false
                                        global Queue       := []
                                        global Worker      := ""
                                        global IsCancelled := false
                                        global OurWindows  := Map()      
                                        global SelectGui   := unset
                                        global ProgGui     := unset
                                        global MsgGui      := unset
                                        
                                        ; =====================================================
                                        ;  גרירת חלונות
                                        ; =====================================================
                                        OnMessage(0x0201, WM_LBUTTONDOWN)
                                        WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) {
                                            rootHwnd := DllCall("GetAncestor", "ptr", hwnd, "uint", 2, "ptr")
                                            if !OurWindows.Has(rootHwnd)
                                                return
                                            try {
                                                cls := WinGetClass("ahk_id " hwnd)
                                                if (cls = "Button" || cls = "Edit")
                                                    return
                                            }
                                            PostMessage(0xA1, 2,,, "ahk_id " rootHwnd)
                                        }
                                        
                                        ApplyRounding(guiObj) {
                                            guiObj.Opt("+LastFound")
                                            DllCall("dwmapi\DwmSetWindowAttribute", "ptr", guiObj.Hwnd, "uint", 33, "ptr*", 2, "uint", 4)
                                        }
                                        
                                        ; =====================================================
                                        ;  כפתור הורדה צף
                                        ; =====================================================
                                        BtnGui := Gui("+AlwaysOnTop -Caption +ToolWindow +LastFound")
                                        BtnGui.BackColor := "EEAA99"
                                        WinSetTransColor("EEAA99", BtnGui)
                                        BtnGui.SetFont("s22", "Segoe UI Symbol")
                                        global BtnTxt := BtnGui.Add("Text", "x0 y0 w60 h50 Center c" AccentColor, "📥")
                                        BtnTxt.OnEvent("Click", ShowSelectionMenu)
                                        OurWindows[BtnGui.Hwnd] := true
                                        
                                        TipGui := Gui("-Caption +AlwaysOnTop +ToolWindow")
                                        TipGui.BackColor := "2B2B2B"
                                        TipGui.SetFont("s9 w800 cWhite", "Segoe UI")
                                        TipGui.Add("Text", "x8 y4 w80 h44 Center", "הורדת מאגרי ספרים מותאמים")
                                        ApplyRounding(TipGui)
                                        OurWindows[TipGui.Hwnd] := true
                                        
                                        SetTimer(WatchOtzaria, 250)
                                        
                                        WatchOtzaria() {
                                            global IsHover
                                            TargetID := WinExist("ahk_exe otzaria.exe")
                                            ActiveID := WinActive("A")
                                        
                                            SelectHwnd := (IsSet(SelectGui) && IsObject(SelectGui)) ? SelectGui.Hwnd : 0
                                            ProgHwnd   := (IsSet(ProgGui) && IsObject(ProgGui)) ? ProgGui.Hwnd : 0
                                            MsgHwnd    := (IsSet(MsgGui) && IsObject(MsgGui)) ? MsgGui.Hwnd : 0
                                        
                                            ; בדיקה האם אנחנו עובדים כרגע על אוצריא או על אחד החלונות שלנו
                                            IsOtzariaContext := TargetID && (ActiveID = TargetID || ActiveID = SelectHwnd || ActiveID = BtnGui.Hwnd || ActiveID = ProgHwnd || ActiveID = MsgHwnd)
                                        
                                            if IsOtzariaContext {
                                                WinGetPos(&X, &Y, &W, &H, "ahk_id " TargetID)
                                                btnX := X + W - 78
                                                btnY := Y + H - 186
                                                
                                                BtnGui.Show("x" btnX " y" btnY " w60 h50 NoActivate")
                                        
                                                ; החזרת החלונות במידה וחזרנו לאוצריא מתוכנה אחרת
                                                if SelectHwnd
                                                    try SelectGui.Show("NoActivate")
                                                if ProgHwnd
                                                    try ProgGui.Show("NoActivate")
                                        
                                                MouseGetPos(,, &HoverWin)
                                                if (HoverWin = BtnGui.Hwnd) {
                                                    if !IsHover {
                                                        TipGui.Show("x" (btnX - 85) " y" (btnY + 5) " NoActivate")
                                                        IsHover := true
                                                    }
                                                } else if IsHover {
                                                    TipGui.Hide()
                                                    IsHover := false
                                                }
                                            } else {
                                                BtnGui.Hide()
                                                TipGui.Hide()
                                                ; הסתרת חלונות בעת מעבר לתוכנה אחרת (לא סגירה, רק הסתרה)
                                                if SelectHwnd
                                                    try SelectGui.Hide()
                                                if ProgHwnd
                                                    try ProgGui.Hide()
                                            }
                                        }
                                        
                                        ; =====================================================
                                        ;  חלון בחירת ספרים מעוצב וימין-שמאל (RTL)
                                        ; =====================================================
                                        ShowSelectionMenu(*) {
                                            BtnTxt.Text := "⏳"
                                            try {
                                                shell := ComObject("WScript.Shell")
                                                exec  := shell.Exec("pythonw.exe downloader.py CHECK")
                                                res   := exec.StdOut.ReadAll()
                                            } catch {
                                                BtnTxt.Text := "📥"
                                                CustomMsgBox("שגיאה: לא ניתן להפעיל את פייתון.", "שגיאת הפעלה")
                                                return
                                            }
                                            BtnTxt.Text := "📥"
                                        
                                            if !InStr(res, "LIST:") || InStr(res, "EMPTY") {
                                                CustomMsgBox("המאגר מעודכן!", "עדכון ספריה")
                                                return
                                            }
                                        
                                            global SelectGui := Gui("+AlwaysOnTop -Caption")
                                            SelectGui.BackColor := MainColor
                                            ApplyRounding(SelectGui)
                                            OurWindows[SelectGui.Hwnd] := true
                                        
                                            SelectGui.SetFont("s15 w700 c" AccentColor, "Segoe UI")
                                            SelectGui.Add("Text", "x0 y15 w420 Center", "עדכון ספריה")
                                            
                                            SelectGui.SetFont("s11 w600 cBlack", "Segoe UI")
                                            ; +0x20 ו-Right אחראים על הפיכת הצ'קבוקס לימין שמאלה
                                            cbAll := SelectGui.Add("Checkbox", "x20 y+20 w380 Right +0x20", "בחר / בטל הכל (ללא המאגר המלא)")
                                        
                                            Checkboxes := []
                                            items := StrSplit(StrReplace(res, "LIST:", ""), ";")
                                            for item in items {
                                                if (Trim(item) = "") {
                                                    continue 
                                                }
                                                p := StrSplit(item, "|")
                                                isFull := (p[1] = "0")
                                                SelectGui.SetFont("s11 w400 cBlack", "Segoe UI")
                                                cb := SelectGui.Add("Checkbox", (p[1] = "1" ? "Checked " : "") "x20 y+10 w380 Right +0x20", p[2])
                                                Checkboxes.Push({full: item, cb: cb, isFull: isFull})
                                            }
                                        
                                            cbAll.OnEvent("Click", (self, *) => ToggleAll(self.Value, Checkboxes))
                                        
                                            BtnDown   := SelectGui.Add("Button", "Default w160 h35 x40 y+25", "הורד")
                                            BtnCancel := SelectGui.Add("Button", "w160 h35 x+20", "ביטול")
                                        
                                            BtnDown.OnEvent("Click", (*) => StartSelectedDownload(SelectGui, Checkboxes))
                                            BtnCancel.OnEvent("Click", (*) => SelectGui.Destroy())
                                        
                                            SelectGui.Show("w420 Center")
                                        }
                                        
                                        ToggleAll(val, Checkboxes) {
                                            for item in Checkboxes {
                                                if !item.isFull
                                                    item.cb.Value := val
                                            }
                                        }
                                        
                                        ; =====================================================
                                        ;  הודעה מעוצבת בסגנון אוצריא
                                        ; =====================================================
                                        CustomMsgBox(txt, title) {
                                            global MsgGui := Gui("-Caption +AlwaysOnTop +Owner")
                                            MsgGui.BackColor := MainColor
                                            ApplyRounding(MsgGui)
                                            OurWindows[MsgGui.Hwnd] := true
                                        
                                            MsgGui.SetFont("s15 w700 c" AccentColor, "Segoe UI")
                                            MsgGui.Add("Text", "x0 y20 w350 Center", title)
                                        
                                            MsgGui.SetFont("s11 w400 cBlack", "Segoe UI")
                                            MsgGui.Add("Text", "x25 y+15 w300 Center +Wrap", txt)
                                        
                                            BtnOk := MsgGui.Add("Button", "Default w120 h35 x115 y+25", "אישור")
                                            BtnOk.OnEvent("Click", (*) => MsgGui.Destroy())
                                        
                                            MsgGui.Show("w350 Center")
                                        }
                                        
                                        ; =====================================================
                                        ;  חלון התקדמות
                                        ; =====================================================
                                        ProgressShow(FileName, Remaining) {
                                            global ProgGui, StatusTxt, Bar, PctLabel
                                        
                                            ProgGui := Gui("-Caption +AlwaysOnTop")
                                            ProgGui.BackColor := MainColor
                                            ApplyRounding(ProgGui)
                                            OurWindows[ProgGui.Hwnd] := true
                                        
                                            ProgGui.SetFont("s14 w700 c" AccentColor, "Segoe UI")
                                            ProgGui.Add("Text", "x0 y20 w400 Center", "הורדה בתהליך")
                                        
                                            ProgGui.SetFont("s11 w600 c" AccentColor, "Segoe UI")
                                            ProgGui.Add("Text", "x25 y+15 w350 Center +Wrap", FileName)
                                        
                                            ProgGui.SetFont("s12 w700 c" AccentColor, "Segoe UI")
                                            StatusTxt := ProgGui.Add("Text", "x0 y+15 w400 Center", "מוריד...")
                                        
                                            Bar := ProgGui.Add("Progress", "x30 y+12 w340 h18 cGreen Background" BgColor, 0)
                                        
                                            ProgGui.SetFont("s11 w700 cBlack", "Segoe UI")
                                            PctLabel := ProgGui.Add("Text", "x0 y+8 w400 Center", "0%")
                                        
                                            CancelBtn := ProgGui.Add("Button", "w120 h35 x140 y+20", "ביטול")
                                            CancelBtn.OnEvent("Click", CancelDownload)
                                        
                                            ProgGui.Show("w400 Center")
                                        }
                                        
                                        ; =====================================================
                                        ;  ניהול תור הורדות
                                        ; =====================================================
                                        StartSelectedDownload(GuiObj, Checkboxes) {
                                            global Queue := [], IsCancelled := false
                                            for item in Checkboxes {
                                                if item.cb.Value
                                                    Queue.Push(item.full)
                                            }
                                            GuiObj.Destroy()
                                            if Queue.Length > 0
                                                NextDownload()
                                            else
                                                CustomMsgBox("לא נבחרו ספרים להורדה.", "שים לב")
                                        }
                                        
                                        NextDownload() {
                                            global Queue, IsCancelled, Worker
                                            if IsCancelled || (Queue.Length = 0) {
                                                if !IsCancelled
                                                    CustomMsgBox("הספריה עודכנה בהצלחה!", "סיום הורדה")
                                                return
                                            }
                                            CurrentItem := Queue.RemoveAt(1)
                                            p := StrSplit(CurrentItem, "|")
                                            ProgressShow(p[2], Queue.Length)
                                            Worker := ComObject("WScript.Shell").Exec('pythonw.exe downloader.py "' CurrentItem '"')
                                            SetTimer(CheckStatus, 100)
                                        }
                                        
                                        CheckStatus() {
                                            global Worker, ProgGui, StatusTxt, Bar, PctLabel
                                        
                                            if Worker.StdOut.AtEndOfStream {
                                                SetTimer(CheckStatus, 0)
                                                try {
                                                    if IsObject(ProgGui) && (ProgGui != "") {
                                                        ProgGui.Destroy()
                                                        ProgGui := unset
                                                        CustomMsgBox("ההורדה נכשלה.`nבדוק חיבור לאינטרנט.", "שגיאה")
                                                    }
                                                }
                                                return
                                            }
                                        
                                            line := Worker.StdOut.ReadLine()
                                            if InStr(line, "DL_PROGRESS:") {
                                                pct := StrReplace(line, "DL_PROGRESS:", "")
                                                Bar.Value     := pct
                                                PctLabel.Text := pct "%"
                                            } else if InStr(line, "DL_FINISHED") {
                                                StatusTxt.Text := "מחלץ קבצים..."
                                                Bar.Value := 0
                                            } else if InStr(line, "EX_PROGRESS:") {
                                                pct := StrReplace(line, "EX_PROGRESS:", "")
                                                Bar.Value     := pct
                                                PctLabel.Text := pct "%"
                                            } else if InStr(line, "DONE") {
                                                SetTimer(CheckStatus, 0)
                                                ProgGui.Destroy()
                                                ProgGui := unset
                                                NextDownload()
                                            }
                                        }
                                        
                                        CancelDownload(*) {
                                            global Worker, IsCancelled, ProgGui
                                            IsCancelled := true
                                            SetTimer(CheckStatus, 0)
                                            try Worker.Terminate()
                                            ProgGui.Destroy()
                                            ProgGui := unset
                                            CustomMsgBox("ההורדה בוטלה.", "ביטול")
                                        }
                                        
                                        u88U
                                        u88U
                                        u88
                                        כתב ב נערך לאחרונה על ידי
                                        #35

                                        @יאיר-דניאל התוסף קיים לציבור או "עתיד לבוא" פשוט הסמל הוא
                                        aae52a03-39e3-42ca-846a-2a14bc9bec5f-image.jpeg
                                        תודה רבה

                                        יאיר דניאלי תגובה 1 תגובה אחרונה
                                        0
                                        • u88U u88

                                          @יאיר-דניאל התוסף קיים לציבור או "עתיד לבוא" פשוט הסמל הוא
                                          aae52a03-39e3-42ca-846a-2a14bc9bec5f-image.jpeg
                                          תודה רבה

                                          יאיר דניאלי
                                          יאיר דניאלי
                                          יאיר דניאל
                                          תורם לאוצריא ניהול תוספים
                                          כתב ב נערך לאחרונה על ידי
                                          #36

                                          @u88 האמת שזה היה מוכן לגמרי - והייתי אמור להעלות אותו שעה - שעתיים אחרי שפרסמתי את הפוסט, אבל שיפרתי כמה דברים בעיצוב שלו, ואז הגיע @דבש עם הרעיון היפה - לאפשר למשתמש לבחור מה להוריד (בברירת המחדל הראשונית זה הוריד את כל המאגר כולו), מה שסיבך אותי מאוד בביצוע - מבחינת יצירת אוטומציה בגיטאב - שתיצור קובץ זיפ להורדה מכל תיקייה בנפרד, ארך לי יומיים לפתור את זה (!), ואחרי שהצלחתי בסייעתא דשמיא, הייתי צריך לסדר את כל העיצוב = UI מחדש, כך שיתאים לפונקציות שנוספו, ואז כבר הגיע ער"פ, בדיקת חמץ ושות' וזה נתקע - עד אחרי החג, בעז"ה.

                                          פלמנמוניפ חד בדראח 3 תגובות תגובה אחרונה
                                          2
                                          • יאיר דניאלי יאיר דניאל

                                            @u88 האמת שזה היה מוכן לגמרי - והייתי אמור להעלות אותו שעה - שעתיים אחרי שפרסמתי את הפוסט, אבל שיפרתי כמה דברים בעיצוב שלו, ואז הגיע @דבש עם הרעיון היפה - לאפשר למשתמש לבחור מה להוריד (בברירת המחדל הראשונית זה הוריד את כל המאגר כולו), מה שסיבך אותי מאוד בביצוע - מבחינת יצירת אוטומציה בגיטאב - שתיצור קובץ זיפ להורדה מכל תיקייה בנפרד, ארך לי יומיים לפתור את זה (!), ואחרי שהצלחתי בסייעתא דשמיא, הייתי צריך לסדר את כל העיצוב = UI מחדש, כך שיתאים לפונקציות שנוספו, ואז כבר הגיע ער"פ, בדיקת חמץ ושות' וזה נתקע - עד אחרי החג, בעז"ה.

                                            פלמנמוניפ
                                            פלמנמוניפ
                                            פלמנמוני
                                            כתב ב נערך לאחרונה על ידי
                                            #37

                                            @יאיר-דניאל אגב, הרב @י.-פל. עמל על אפשרות מובנית לתוספים, יתכן וכדאי לך לחכות ולא להשקיע כ"כ, או לבקש ממנו את התיעוד ולהתחיל לעבוד על התוסף שיעבוד בצורה רשמית

                                            @י.-פל. מתנצל אם היה אסור לגלות...

                                            יאיר דניאלי תגובה 1 תגובה אחרונה
                                            0

                                            שלום! נראה שהשיחה הזו מעניינת אותך, אבל עדיין אין לך חשבון.

                                            נמאס לכם לגלול בין אותם הפוסטים בכל ביקור? כשנרשמים לחשבון, תמיד תחזרו בדיוק למקום שבו הייתם קודם, ותוכלו לבחור לקבל התראות על תגובות חדשות (בין אם במייל, ובין אם בהתראת פוש). תוכלו גם לשמור סימניות ולפרגן ב-upvote לפוסטים כדי להביע הערכה לחברי קהילה אחרים.

                                            בעזרת התרומה שלך, הפוסט הזה יכול להיות אפילו טוב יותר 💗

                                            הרשמה התחברות

                                            • התחברות

                                            • אין לך חשבון עדיין? הרשמה

                                            • התחברו או הירשמו כדי לחפש.
                                            • פוסט ראשון
                                              פוסט אחרון