2025-12-01
This commit is contained in:
@@ -8,21 +8,21 @@ The original method is then called from the new method, with the same arguments,
|
||||
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
|
||||
from . import icons
|
||||
|
||||
import bpy
|
||||
import bl_pkg.bl_extension_ui as exui
|
||||
from . import icons
|
||||
from bl_ui.space_userpref import (
|
||||
USERPREF_PT_addons,
|
||||
USERPREF_PT_extensions,
|
||||
USERPREF_MT_extensions_active_repo,
|
||||
)
|
||||
from bpy.props import EnumProperty
|
||||
from bpy.props import StringProperty, IntProperty
|
||||
from bpy.props import IntProperty, StringProperty
|
||||
from bpy.types import Operator
|
||||
import time
|
||||
|
||||
|
||||
EXTENSIONS_API_URL = "https://www.blenderkit.com/api/v1/extensions/"
|
||||
|
||||
bk_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# --- New Modal Operator ---
|
||||
class BK_OT_buy_extension_and_watch(Operator):
|
||||
@@ -59,7 +59,7 @@ class BK_OT_buy_extension_and_watch(Operator):
|
||||
# Open the URL
|
||||
try:
|
||||
bpy.ops.wm.url_open(url=self.url)
|
||||
print(f"BlenderKit: Opening buy URL: {self.url}")
|
||||
bk_logger.info("Opening buy URL: %s.", self.url)
|
||||
except Exception as e:
|
||||
self.report({"ERROR"}, f"Could not open URL: {e}")
|
||||
# Don't cancel, maybe the user still wants the refresh?
|
||||
@@ -75,10 +75,11 @@ class BK_OT_buy_extension_and_watch(Operator):
|
||||
self._last_refresh_time = (
|
||||
self._start_time
|
||||
) # Initialize to avoid immediate refresh
|
||||
print(
|
||||
f"BlenderKit: Started watching repository index {self.repo_index} for updates."
|
||||
bk_logger.info(
|
||||
"Started watching repository index %s for updates.", self.repo_index
|
||||
)
|
||||
context.area.tag_redraw() # Update UI to show operator is running if needed
|
||||
if context and context.area:
|
||||
context.area.tag_redraw() # Update UI to show operator is running if needed
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def modal(self, context, event):
|
||||
@@ -87,19 +88,19 @@ class BK_OT_buy_extension_and_watch(Operator):
|
||||
# --- Exit Conditions ---
|
||||
# 1. User closed Preferences or changed area
|
||||
if context.area is None or context.area.type != "PREFERENCES":
|
||||
print("BlenderKit: Preferences window closed or changed, stopping watcher.")
|
||||
bk_logger.info("Preferences window closed or changed, stopping watcher.")
|
||||
self.cancel(context)
|
||||
return {"CANCELLED"}
|
||||
|
||||
# 2. Timeout
|
||||
if current_time - self._start_time > self._max_duration:
|
||||
print("BlenderKit: Watcher timed out, stopping.")
|
||||
bk_logger.info("Watcher timed out, stopping.")
|
||||
self.cancel(context)
|
||||
return {"CANCELLED"}
|
||||
|
||||
# 3. User cancellation
|
||||
if event.type in {"RIGHTMOUSE", "ESC"}:
|
||||
print("BlenderKit: Watcher cancelled by user.")
|
||||
bk_logger.info("Watcher cancelled by user.")
|
||||
self.cancel(context)
|
||||
return {"CANCELLED"}
|
||||
|
||||
@@ -107,24 +108,25 @@ class BK_OT_buy_extension_and_watch(Operator):
|
||||
if event.type == "TIMER":
|
||||
# Check if refresh interval has passed
|
||||
if current_time - self._last_refresh_time >= self._refresh_interval:
|
||||
print(
|
||||
f"BlenderKit: Refresh interval reached, attempting sync for repo index {self.repo_index}..."
|
||||
bk_logger.info(
|
||||
"Refresh interval reached, attempting sync for repo index %s...",
|
||||
self.repo_index,
|
||||
)
|
||||
try:
|
||||
# Check if repo still exists at that index
|
||||
if self.repo_index < len(context.preferences.extensions.repos):
|
||||
bpy.ops.extensions.repo_sync(repo_index=self.repo_index)
|
||||
print(
|
||||
f"BlenderKit: repo_sync called for index {self.repo_index}."
|
||||
bk_logger.info(
|
||||
"repo_sync called for index %s.", self.repo_index
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f"BlenderKit: Repository index {self.repo_index} no longer valid."
|
||||
bk_logger.info(
|
||||
"Repository index %s no longer valid.", self.repo_index
|
||||
)
|
||||
# Optionally cancel here if repo is gone
|
||||
except Exception as e:
|
||||
except:
|
||||
# This might fail if another operation is in progress
|
||||
print(f"BlenderKit: extensions.repo_sync failed: {e}")
|
||||
bk_logger.exception("extensions.repo_sync failed.")
|
||||
finally:
|
||||
self._last_refresh_time = (
|
||||
current_time # Reset timer regardless of success
|
||||
@@ -137,13 +139,32 @@ class BK_OT_buy_extension_and_watch(Operator):
|
||||
wm = context.window_manager
|
||||
wm.event_timer_remove(self._timer)
|
||||
self._timer = None
|
||||
print("BlenderKit: Watcher timer removed.")
|
||||
context.area.tag_redraw() # Update UI
|
||||
bk_logger.info("Watcher timer removed.")
|
||||
if context and context.area:
|
||||
context.area.tag_redraw() # Update UI
|
||||
|
||||
|
||||
# --- End New Modal Operator ---
|
||||
|
||||
|
||||
def redraw_preferences_once():
|
||||
"""Tag the redraw on the Blender preferences.
|
||||
Meant to be registered as a timer, runs just once.
|
||||
"""
|
||||
for window in bpy.context.window_manager.windows:
|
||||
screen = window.screen
|
||||
if not screen:
|
||||
continue
|
||||
for area in screen.areas:
|
||||
if area.type != "PREFERENCES":
|
||||
continue
|
||||
for region in area.regions:
|
||||
if region.type in {"UI", "WINDOW"}:
|
||||
region.tag_redraw()
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def extension_draw_item_blenderkit(
|
||||
layout,
|
||||
*,
|
||||
@@ -166,14 +187,17 @@ def extension_draw_item_blenderkit(
|
||||
cache_reloaded = ensure_repo_cache()
|
||||
if cache_reloaded:
|
||||
# If cache was just reloaded, tag UI for redraw
|
||||
layout.tag_redraw()
|
||||
print("BlenderKit: Cache reloaded, tagging layout for redraw.")
|
||||
# as UILayout doesn't have tag_redraw we call a custom function
|
||||
if bpy.app.timers.is_registered(redraw_preferences_once):
|
||||
bpy.app.timers.unregister(redraw_preferences_once)
|
||||
bpy.app.timers.register(redraw_preferences_once, first_interval=0.01)
|
||||
bk_logger.info("Cache reloaded, tagging preferences for redraw.")
|
||||
|
||||
# check if the cache is already in the window manager
|
||||
if "blenderkit_extensions_repo_cache" not in bpy.context.window_manager:
|
||||
# Log if cache is missing after trying to ensure it
|
||||
print(
|
||||
"BlenderKit: Extension cache not available in window_manager after ensure_repo_cache call."
|
||||
bk_logger.info(
|
||||
"Extension cache not available in window_manager after ensure_repo_cache call."
|
||||
)
|
||||
# Optionally draw a minimal representation or return early to avoid errors
|
||||
# For now, just return to avoid potential errors accessing bk_ext_cache
|
||||
@@ -330,6 +354,7 @@ def extension_draw_item_blenderkit(
|
||||
|
||||
if show:
|
||||
import os
|
||||
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
|
||||
col = layout.column()
|
||||
@@ -432,7 +457,6 @@ def extension_draw_item_override(
|
||||
extensions_warnings, # `dict[str, list[str]]`
|
||||
show_developer_ui=False, # `bool`
|
||||
):
|
||||
print("BlenderKit Debug: ENTERING extension_draw_item_override")
|
||||
# filter by verification state, only for blenderkit repository
|
||||
if repo_item.remote_url == EXTENSIONS_API_URL:
|
||||
extension_draw_item_blenderkit(
|
||||
@@ -513,7 +537,7 @@ def clear_repo_cache():
|
||||
|
||||
|
||||
def ensure_repo_cache():
|
||||
"""
|
||||
r"""
|
||||
Reads the .json file blender stores in \extensions\www_blenderkit_com\.blender_ext
|
||||
and parses it to a dict from json, we can use it then for drawing purposes and have the extra data BlenderKit api provides.
|
||||
Checks the modification time of the cache file and reloads it if necessary.
|
||||
@@ -528,10 +552,10 @@ def ensure_repo_cache():
|
||||
# If repo doesn't exist, clear cache if it exists in window manager
|
||||
if cache_key in wm:
|
||||
del wm[cache_key]
|
||||
print(f"BlenderKit: Cleared stale extension cache for missing repository.")
|
||||
bk_logger.info("Cleared stale extension cache for missing repository.")
|
||||
if mtime_key in wm:
|
||||
del wm[mtime_key]
|
||||
print(f"BlenderKit Debug: Repository not found, exiting check.")
|
||||
bk_logger.debug("Repository not found, exiting check.")
|
||||
return False # No repo, nothing loaded
|
||||
|
||||
# get the path to the cache file which is in repository directory under /.blender_ext/index.json
|
||||
@@ -544,13 +568,11 @@ def ensure_repo_cache():
|
||||
if os.path.exists(cache_file):
|
||||
current_mtime = os.path.getmtime(cache_file)
|
||||
except OSError as e: # Handle potential race condition or permission issue
|
||||
print(
|
||||
f"BlenderKit: Warning - Could not get modification time for {cache_file}: {e}"
|
||||
)
|
||||
bk_logger.exception("Could not get modification time for %s.", cache_file)
|
||||
# Clear cache if we can't verify its freshness? Safer approach.
|
||||
if cache_key in wm:
|
||||
del wm[cache_key]
|
||||
print(f"BlenderKit: Cleared extension cache due to mtime access error.")
|
||||
bk_logger.info("Cleared extension cache due to mtime access error.")
|
||||
if mtime_key in wm:
|
||||
del wm[mtime_key]
|
||||
return False # Error, nothing loaded
|
||||
@@ -604,7 +626,7 @@ def ensure_repo_cache():
|
||||
): # Ensure pkg is a dict and 'id' key exists
|
||||
new_cache[pkg["id"][:32]] = pkg
|
||||
else:
|
||||
print(f"BlenderKit: Skipping invalid package entry in cache: {pkg}")
|
||||
bk_logger.info("Skipping invalid package entry in cache: %s.", pkg)
|
||||
|
||||
wm[cache_key] = new_cache
|
||||
wm[mtime_key] = current_mtime # Update mtime only on successful load
|
||||
@@ -612,21 +634,21 @@ def ensure_repo_cache():
|
||||
reloaded_flag = True # Mark that we reloaded successfully
|
||||
|
||||
except json.JSONDecodeError:
|
||||
print(
|
||||
f"BlenderKit: Error decoding JSON from {cache_file}. Cache not loaded/updated."
|
||||
bk_logger.warning(
|
||||
"Error decoding JSON from %s. Cache not loaded/updated.", cache_file
|
||||
)
|
||||
# Clear potentially corrupt cache? Or leave old one? Clearing is safer.
|
||||
if cache_key in wm:
|
||||
del wm[cache_key]
|
||||
print("BlenderKit: Cleared cache due to JSON error.")
|
||||
bk_logger.info("Cleared cache due to JSON error.")
|
||||
if mtime_key in wm:
|
||||
del wm[mtime_key]
|
||||
except Exception as e:
|
||||
print(f"BlenderKit: Error reading or processing cache file {cache_file}: {e}")
|
||||
except Exception:
|
||||
bk_logger.exception("Error reading or processing cache file %s.", cache_file)
|
||||
# Clear potentially corrupt cache?
|
||||
if cache_key in wm:
|
||||
del wm[cache_key]
|
||||
print("BlenderKit: Cleared cache due to file processing error.")
|
||||
bk_logger.info("Cleared cache due to file processing error.")
|
||||
if mtime_key in wm:
|
||||
del wm[mtime_key]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user