diff options
| author | Craig Jennings <c@cjennings.net> | 2025-10-18 00:27:16 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2025-10-18 00:27:16 -0500 |
| commit | 2cfdc0e04e44c52c465091b9a42ad1092f7af7e3 (patch) | |
| tree | 7d88b188af3abb68e88cc9dbf517b32b0e4a98e6 | |
| parent | 6f45c53df973876eb53164e087f0205f11bdf93e (diff) | |
feat: video-capture: Auto-initialize after Emacs startup
- Refactor quick-video-capture to auto-initialize after Emacs startup, removing the need for manual setup.
- Added functions to ensure initialization and defer loading strategies to optimize startup sequence.
- Improved handling of org-protocol and capture templates to be idempotent and prevent redundancy.
| -rw-r--r-- | modules/quick-video-capture.el | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/modules/quick-video-capture.el b/modules/quick-video-capture.el index 05ad70c8..100cf04a 100644 --- a/modules/quick-video-capture.el +++ b/modules/quick-video-capture.el @@ -12,7 +12,7 @@ ;; - Can be triggered manually via org-capture with URL prompt ;; ;; Setup: -;; 1. Load this file and call (cj/setup-video-download) +;; 1. Load this file - it will auto-initialize after Emacs startup ;; 2. Add the bookmarklet from `cj/video-download-bookmarklet' to your browser ;; 3. Click the bookmarklet on any video page to queue a download ;; @@ -20,77 +20,119 @@ ;;; Code: -(require 'org-protocol) -(require 'org-capture) -(require 'media-utils) +;; Declare external functions to avoid warnings +(declare-function org-capture "org-capture" (&optional goto keys)) +(declare-function org-protocol-check-filename-for-protocol "org-protocol" (fname restoffiles client)) +(declare-function cj/yt-dl-it "media-utils" (url)) + +(defvar org-capture-templates) +(defvar org-protocol-protocol-alist) (defconst cj/video-download-bookmarklet "javascript:location.href='org-protocol://video-download?url='+encodeURIComponent(location.href);void(0);" "JavaScript bookmarklet for triggering video downloads from the browser. Add this as a bookmark in your browser to enable one-click video downloads.") +(defvar cj/video-download-current-url nil + "Temporary storage for URL passed via org-protocol.") + +(defvar cj/video-download-initialized nil + "Flag to track if video download has been initialized.") + (defun cj/org-protocol-video-download (info) "Process org-protocol video download requests. INFO is a plist containing :url from the org-protocol call." + ;; Ensure we're initialized when called via protocol + (cj/ensure-video-download-initialized) (let ((url (plist-get info :url))) - (when url - ;; Store the URL for the capture template to use - (setq cj/video-download-current-url url)) - ;; Trigger the capture - (org-capture nil "v") - nil)) ; Return nil to indicate we handled it + (when url + ;; Store the URL for the capture template to use + (setq cj/video-download-current-url url)) + ;; Trigger the capture + (org-capture nil "v") + nil)) ; Return nil to indicate we handled it (defun cj/video-download-capture-handler () "Handle video download during org-capture. This function is called from the capture template." + ;; Ensure media-utils is loaded when we actually need to download + (require 'media-utils) (let ((url (or cj/video-download-current-url - (read-string "Video URL: ")))) - ;; Clear the stored URL after using it - (setq cj/video-download-current-url nil) - (if (string-empty-p url) - (error "No URL provided for download") - (cj/yt-dl-it url) - ;; Return empty string to prevent capture from saving anything - ""))) + (read-string "Video URL: ")))) + ;; Clear the stored URL after using it + (setq cj/video-download-current-url nil) + (if (string-empty-p url) + (error "No URL provided for download") + (cj/yt-dl-it url) + ;; Return empty string to prevent capture from saving anything + ""))) -(defvar cj/video-download-current-url nil - "Temporary storage for URL passed via org-protocol.") +(defun cj/ensure-video-download-initialized () + "Ensure video download is initialized, loading dependencies if needed." + (unless cj/video-download-initialized + (cj/setup-video-download))) -;; register the handler and the capture template after org-protocol is loaded -(with-eval-after-load 'org-protocol - ;; Register the org-protocol handler - (add-to-list 'org-protocol-protocol-alist - '("video-download" - :protocol "video-download" - :function cj/org-protocol-video-download - :kill-client t)) - - ;; Add the capture template - (add-to-list 'org-capture-templates - '("v" "Video Download" entry - (file "") ; No file needed since we're not saving - "%(cj/video-download-capture-handler)" - :immediate-finish t - :jump-to-captured nil))) +(defun cj/setup-video-download () + "Initialize video download functionality. +This function sets up org-protocol handlers and capture templates. +It's designed to be idempotent - safe to call multiple times." + (when (not cj/video-download-initialized) + ;; Load required packages + (require 'org-protocol) + (require 'org-capture) + + ;; Register the org-protocol handler if not already registered + (unless (assoc "video-download" org-protocol-protocol-alist) + (add-to-list 'org-protocol-protocol-alist + '("video-download" + :protocol "video-download" + :function cj/org-protocol-video-download + :kill-client t))) + + ;; Add the capture template if not already added + (unless (assoc "v" org-capture-templates) + (add-to-list 'org-capture-templates + '("v" "Video Download" entry + (file "") ; No file needed since we're not saving + "%(cj/video-download-capture-handler)" + :immediate-finish t + :jump-to-captured nil))) + + (setq cj/video-download-initialized t) + (message "Video download functionality initialized"))) (defun cj/video-download-bookmarklet-instructions () "Display instructions for setting up the browser bookmarklet." (interactive) (let ((buf (get-buffer-create "*Video Download Bookmarklet Setup*"))) - (with-current-buffer buf - (erase-buffer) - (insert "Video Download Bookmarklet Setup\n") - (insert "=================================\n\n") - (insert "1. Create a new bookmark in your browser\n") - (insert "2. Set the name to: Download Video (or your preference)\n") - (insert "3. Set the URL to the following JavaScript code:\n\n") - (insert cj/video-download-bookmarklet) - (insert "\n\n") - (insert "4. Save the bookmark to your bookmarks bar\n") - (insert "5. Click the bookmark when viewing a video to download it\n\n") - (insert "Note: Make sure Emacs server is running (M-x server-start)\n") - (insert "and emacsclient is properly configured for org-protocol.\n")) - (switch-to-buffer buf))) + (with-current-buffer buf + (erase-buffer) + (insert "Video Download Bookmarklet Setup\n") + (insert "=================================\n\n") + (insert "1. Create a new bookmark in your browser\n") + (insert "2. Set the name to: Download Video (or your preference)\n") + (insert "3. Set the URL to the following JavaScript code:\n\n") + (insert cj/video-download-bookmarklet) + (insert "\n\n") + (insert "4. Save the bookmark to your bookmarks bar\n") + (insert "5. Click the bookmark when viewing a video to download it\n\n") + (insert "Note: Make sure Emacs server is running (M-x server-start)\n") + (insert "and emacsclient is properly configured for org-protocol.\n")) + (switch-to-buffer buf))) + +;; Deferred initialization strategy: +;; 1. Try to load shortly after Emacs is idle following init +;; 2. Fallback timer ensures loading within 2 seconds regardless +(add-hook 'after-init-hook + (lambda () + (run-with-idle-timer 0.5 nil #'cj/setup-video-download))) + +;; Fallback: ensure initialization within 2 seconds of loading this file +(run-with-timer 2 nil #'cj/setup-video-download) + +;; If someone manually triggers capture before initialization +(with-eval-after-load 'org-capture + (add-hook 'org-capture-mode-hook #'cj/ensure-video-download-initialized)) ;;; Commentary for bookmarklet: ;; @@ -101,4 +143,4 @@ This function is called from the capture template." ;; the download through yt-dlp and task-spooler. (provide 'quick-video-capture) -;;; quick-video-capture.el ends here. +;;; quick-video-capture.el ends here
\ No newline at end of file |
