diff --git a/plugin.program.autowidget/resources/lib/add.py b/plugin.program.autowidget/resources/lib/add.py index 93087b08..4a1884ee 100644 --- a/plugin.program.autowidget/resources/lib/add.py +++ b/plugin.program.autowidget/resources/lib/add.py @@ -207,7 +207,7 @@ def add_group(target, group_name=""): "id": group_id, "art": folder_sync if target == "widget" else folder_shortcut, "version": settings.get_addon_info("version"), - "content": "files", + "content": None, } utils.write_json(filename, group_def) @@ -257,7 +257,7 @@ def _add_path(group_def, labels, over=False): labels["file"]["filetype"] = "file" labels["file"]["file"] = labels["file"]["file"].split("&")[0] elif labels["target"] == "shortcut" and labels["file"]["filetype"] == "file": - labels["content"] = "files" + labels["content"] = None manage.write_path(group_def, path_def=labels) diff --git a/plugin.program.autowidget/resources/lib/common/cache.py b/plugin.program.autowidget/resources/lib/common/cache.py index 609fa2a1..5dbd7971 100644 --- a/plugin.program.autowidget/resources/lib/common/cache.py +++ b/plugin.program.autowidget/resources/lib/common/cache.py @@ -79,7 +79,8 @@ def next_cache_queue(): # TODO: need to workout if a blocking write is happen while it was queued or right now. # probably need a .lock file to ensure foreground calls can get priority. cache_data = read_history(path, create_if_missing=True) - yield hash, cache_data + widget_id = utils.read_json(queue_path).get("widget_id", None) + yield path, cache_data, widget_id def push_cache_queue(path, widget_id=None): @@ -100,7 +101,7 @@ def push_cache_queue(path, widget_id=None): if os.path.exists(queue_path): pass # Leave original modification date so item is higher priority else: - utils.write_json(queue_path, {"hash": hash, "path": path}) + utils.write_json(queue_path, {"hash": hash, "path": path, "widget_id": widget_id}) def is_cache_queue(hash): @@ -130,63 +131,30 @@ def widgets_for_path(path): return set(widgets) -def cache_and_update(hash, widget_ids, notify=None): +def cache_and_update(path, widget_id, cache_data, notify=None): """a widget might have many paths. Ensure each path is either queued for an update or is expired and if so force it to be refreshed. When going through the queue this could mean we refresh paths that other widgets also use. These will then be skipped. """ - assert widget_ids - affected_widgets = set() + assert widget_id + assert cache_data.get("path") == path + assert widget_id in cache_data["widgets"] - changed = False - path = widget_ids.get("path", "") - # TODO: we might be updating paths used by widgets that weren't initiall queued. - # We need to return those and ensure they get refreshed also. - affected_widgets = affected_widgets.union(widgets_for_path(path)) - for widget_id in affected_widgets: - if is_cache_queue(hash): - # we need to update this path regardless - if notify is not None: - widget_def = manage.get_widget_by_id(widget_id) - notify(widget_def.get("label", ""), path) - new_files, files_changed = cache_files(path, widget_id) - changed = changed or files_changed - remove_cache_queue(hash) - # else: This bit is broken down below - # # double check this hasn't been updated already when updating another widget - # expiry, _ = cache.cache_expiry(hash, widget_id, no_queue=True) - # if expiry <= time.time(): - # cache.cache_files(path, widget_id) - # else: - # pass # Skipping this path because its already been updated - - # TODO: update every widget? - # for widget_id in widget_ids: - # widget_def = manage.get_widget_by_id(widget_id) - # if not widget_def: - # continue - # widget_path = widget_def.get("path", "") - # utils.log( - # "trying to update {} with widget def {}".format(widget_id, widget_def), - # "inspect", - # ) - - # if type(widget_path) != list: - # widget_path = [widget_path] - # for path_id in widget_path: - # # simple compatibility with pre-3.3.0 widgets - # if isinstance(path_id, dict): - # path_id = path_id.get("id", "") - # path = manage.get_path_by_id(path_id) - # if not path: - # continue - - # _label = path["label"] - # path = path["file"]["file"] - # # TODO: only need to do that if a path has changed which we can tell from the history - # if changed: - # _update_strings(widget_def) - return affected_widgets + hash = path2hash(path) + if not is_cache_queue(hash): + return [] + + if notify is not None: + widget_def = manage.get_widget_by_id(widget_id) + if widget_def is not None: + notify(widget_def.get("label", ""), path) + + new_files, files_changed = cache_files(path, widget_id) + remove_cache_queue(hash) + + # TODO: this is all widgets that ever requested this path. do we + # need to update all of them? + return cache_data["widgets"] if files_changed else [] def cache_files(path, widget_id): diff --git a/plugin.program.autowidget/resources/lib/common/router.py b/plugin.program.autowidget/resources/lib/common/router.py index 8cf9dd14..61fd90fd 100644 --- a/plugin.program.autowidget/resources/lib/common/router.py +++ b/plugin.program.autowidget/resources/lib/common/router.py @@ -121,4 +121,6 @@ def dispatch(_handle, _params): if is_dir: directory.add_sort_methods(_handle) - directory.finish_directory(_handle, category, is_type) + directory.finish_directory( + _handle, category, is_type if is_type not in [None, "none"] else "" + ) diff --git a/plugin.program.autowidget/resources/lib/common/utils.py b/plugin.program.autowidget/resources/lib/common/utils.py index 3685e8b5..01b15bff 100644 --- a/plugin.program.autowidget/resources/lib/common/utils.py +++ b/plugin.program.autowidget/resources/lib/common/utils.py @@ -362,6 +362,12 @@ def update_container(reload=False): refresh_time = os.path.join(_addon_data, "refresh.time") in_media = get_active_window() == "media" in_plugin = in_media and get_infolabel("Container.PluginName") == _addon_id + is_scanning = get_condition("Library.IsScanningVideo") or get_condition( + "Library.IsScanningMusic" + ) + if is_scanning: + return + if reload: if in_media: write_file(refresh_time, six.text_type(time.time())) diff --git a/plugin.program.autowidget/resources/lib/edit.py b/plugin.program.autowidget/resources/lib/edit.py index 5c71f54e..1c1c44ae 100644 --- a/plugin.program.autowidget/resources/lib/edit.py +++ b/plugin.program.autowidget/resources/lib/edit.py @@ -351,6 +351,7 @@ def _get_value(edit_def, key): value = utils.set_color() elif key == "content": options = [ + "none", "files", "movies", "tvshows", @@ -364,7 +365,9 @@ def _get_value(edit_def, key): "games", ] type = dialog.select( - utils.get_string(30119), options, preselect=options.index(default) + utils.get_string(30119), + options, + preselect=options.index(default if default in options else "none"), ) value = options[type] else: diff --git a/plugin.program.autowidget/resources/lib/manage.py b/plugin.program.autowidget/resources/lib/manage.py index 07b18ea3..c5e88ded 100644 --- a/plugin.program.autowidget/resources/lib/manage.py +++ b/plugin.program.autowidget/resources/lib/manage.py @@ -7,6 +7,7 @@ from resources.lib.common import utils _addon_data = utils.translate_path(settings.get_addon_info("profile")) +_userdata = utils.translate_path("special://userdata/") _skin_shortcuts = utils.translate_path( settings.get_addon_info("profile", addon="script.skinshortcuts") ) @@ -39,6 +40,9 @@ def clean(widget_id=None, notify=False, all=False): if ext[-1] in ["xml", "properties"]: path = os.path.join(_skin_shortcuts, xml) files.append(path) + favorites = os.path.join(_userdata, "favourites.xml") + if os.path.exists(favorites): + files.append(favorites) remove = [] removed = 0 @@ -148,7 +152,7 @@ def save_path_details(params): def get_group_by_id(group_id): if not group_id: - return + return {} filename = "{}.group".format(group_id) path = os.path.join(_addon_data, filename) @@ -164,7 +168,7 @@ def get_group_by_id(group_id): def get_path_by_id(path_id, group_id=None): if not path_id: - return + return {} for defined in find_defined_paths(group_id): if defined.get("id", "") == path_id: @@ -173,7 +177,7 @@ def get_path_by_id(path_id, group_id=None): def get_widget_by_id(widget_id, group_id=None): if not widget_id: - return + return {} for defined in find_defined_widgets(group_id): if defined.get("id", "") == widget_id: diff --git a/plugin.program.autowidget/resources/lib/menu.py b/plugin.program.autowidget/resources/lib/menu.py index 08620309..c7257612 100644 --- a/plugin.program.autowidget/resources/lib/menu.py +++ b/plugin.program.autowidget/resources/lib/menu.py @@ -54,7 +54,7 @@ def root_menu(): title=30008, params={"mode": "tools"}, art=utils.get_art("tools"), isFolder=True ) - return True, "AutoWidget", "files" + return True, "AutoWidget", None def my_groups_menu(): @@ -87,18 +87,20 @@ def my_groups_menu(): isFolder=False, props={"specialsort": "bottom"}, ) - directory.add_menu_item( - title=30010, - params={"mode": "manage", "action": "add_group", "target": "widget"}, - art=utils.get_art("folder-sync"), - ) directory.add_menu_item( title=30011, params={"mode": "manage", "action": "add_group", "target": "shortcut"}, art=utils.get_art("folder-shortcut"), + props={"specialsort": "bottom"}, + ) + directory.add_menu_item( + title=30010, + params={"mode": "manage", "action": "add_group", "target": "widget"}, + art=utils.get_art("folder-sync"), + props={"specialsort": "bottom"}, ) - return True, utils.get_string(30007), "files" + return True, utils.get_string(30007), None def group_menu(group_id): @@ -111,12 +113,12 @@ def group_menu(group_id): '"{}" is missing, please repoint the widget to fix it.'.format(group_id), "error", ) - return False, "AutoWidget", "files" + return False, "AutoWidget", None group_name = group_def["label"] group_type = group_def["type"] paths = group_def["paths"] - content = group_def.get("content", "files") + content = group_def.get("content") if len(paths) > 0: utils.log( @@ -244,7 +246,7 @@ def active_widgets_menu(): props={"specialsort": "bottom"}, ) - return True, utils.get_string(30052), "files" + return True, utils.get_string(30052), None def tools_menu(): @@ -252,7 +254,6 @@ def tools_menu(): title=30006, params={"mode": "force"}, art=utils.get_art("refresh"), - info={"plot": utils.get_string(30012)}, isFolder=False, ) directory.add_menu_item( @@ -280,7 +281,7 @@ def tools_menu(): isFolder=False, ) - return True, utils.get_string(30008), "files" + return True, utils.get_string(30008), None def show_path( @@ -300,9 +301,9 @@ def show_path( widget_def = manage.get_widget_by_id(widget_id) if not widget_def: - return True, "AutoWidget", "videos" + return True, "AutoWidget", None - content = widget_path.get("content", "videos") + content = widget_path.get("content") action = widget_def.get("action", "") if not titles: titles = [] @@ -476,13 +477,13 @@ def path_menu(group_id, action, widget_id): art=utils.get_art("alert"), isFolder=True, ) - return True, "AutoWidget", "files" + return True, "AutoWidget", None group_name = group_def.get("label", "") paths = group_def.get("paths", []) if len(paths) == 0: directory.add_menu_item(title=30019, art=utils.get_art("alert"), isFolder=True) - return True, group_name, "files" + return True, group_name, None widget_def = manage.get_widget_by_id(widget_id, group_id) if not widget_def: @@ -492,7 +493,7 @@ def path_menu(group_id, action, widget_id): utils.get_string(30088), paths, indices=True, single=True ) if idx == -1: - return True, "AutoWidget", "videos" + return True, "AutoWidget", None widget_def = manage.initialize(group_def, action, widget_id, keep=idx) elif action == "cycling": @@ -502,7 +503,7 @@ def path_menu(group_id, action, widget_id): ) if idx == -1: del dialog - return True, "AutoWidget", "videos" + return True, "AutoWidget", None _action = "random" if idx == 0 else "next" @@ -535,7 +536,7 @@ def path_menu(group_id, action, widget_id): return titles, cat, type else: directory.add_menu_item(title=30045, art=info, isFolder=True) - return True, group_name, "files" + return True, group_name, None def merged_path(group_id, widget_id): @@ -546,7 +547,7 @@ def merged_path(group_id, widget_id): paths = group_def.get("paths", []) if len(paths) == 0: directory.add_menu_item(title=30019, art=utils.get_art("alert"), isFolder=False) - return True, group_name, "files" + return True, group_name, None widget_def = manage.get_widget_by_id(widget_id, group_id) if widget_def and _window != "dialog": @@ -586,7 +587,7 @@ def merged_path(group_id, widget_id): return titles, cat, type else: directory.add_menu_item(title=30045, art=info, isFolder=True) - return True, group_name, "files" + return True, group_name, None def _create_group_context_items(group_id, target): @@ -719,14 +720,25 @@ def _create_action_items(group_def, _id): def _is_page_item(label, next=True): tag_pattern = r"(\[[^\]]*\])" page_count_pattern = r"(?:\W*(?:(?:\d+\D*\d*))\W*)?" - base_pattern = r"^(?:(?:.+)?(?:(?:\b{}\b)|(?:\b{}\b)){{1,2}}{}){{1}}(?:\W+)?$" + # base_pattern = r"^(?:(?:.+)?(?:(?:\b{}\b)|(?:\b{}\b)){{1,2}}{}){{1}}(?:\W+)?$" + base_pattern_prefix = r"^(?:(?:.+)?(?:" + word_pattern = r"(?:\b{}\b)" + base_pattern_suffix = r"){{1,2}}{}){{1}}(?:\W+)?$" cleaned_title = re.sub(tag_pattern, "", label.lower()).strip() next_page_words = [i.lower() for i in re.split(r"\s+", _next_page)] prev_page_words = [i.lower() for i in re.split(r"\s+", _previous_page)] - next_page_pattern = base_pattern.format(*next_page_words, page_count_pattern) - prev_page_pattern = base_pattern.format(*prev_page_words, page_count_pattern) + next_page_pattern = ( + base_pattern_prefix + + "|".join([word_pattern.format(i) for i in next_page_words]) + + base_pattern_suffix.format(page_count_pattern) + ) + prev_page_pattern = ( + base_pattern_prefix + + "|".join([word_pattern.format(i) for i in prev_page_words]) + + base_pattern_suffix.format(page_count_pattern) + ) contains_dir_page = ( re.search(next_page_pattern if next else prev_page_pattern, cleaned_title) @@ -744,7 +756,7 @@ def show_error(id, props=None): isFolder=False, ) - return True, id, "files" + return True, id, None def show_empty(id, props=None): @@ -755,4 +767,4 @@ def show_empty(id, props=None): isFolder=False, ) - return True, id, "files" + return True, id, None diff --git a/plugin.program.autowidget/resources/lib/refresh.py b/plugin.program.autowidget/resources/lib/refresh.py index ecac83a1..d45941fc 100644 --- a/plugin.program.autowidget/resources/lib/refresh.py +++ b/plugin.program.autowidget/resources/lib/refresh.py @@ -108,20 +108,18 @@ def __call__(self, groupname, path): progress = Progress() while queue: - hash, widget_ids = queue.pop(0) + path, cache_data, widget_id = queue.pop(0) + hash = cache.path2hash(path) utils.log("Dequeued cache update: {}".format(hash[:5]), "notice") - affected_widgets = cache.cache_and_update( - hash, widget_ids, notify=progress - ) + affected_widgets = set(cache.cache_and_update( + path, widget_id, cache_data, notify=progress + )) if affected_widgets: updated = True - cache.remove_cache_queue( - hash - ) # Just in queued path's widget defintion has changed and it didn't update this path unrefreshed_widgets = unrefreshed_widgets.union( affected_widgets - ).difference(set(widget_ids)) + ) # # wait 5s or for the skin to reload the widget # # this should reduce churn at startup where widgets take too long too long show up # before_update = time.time() # TODO: have .access file so we can put above update @@ -255,11 +253,11 @@ def refresh(widget_id, widget_def=None, paths=None, force=False, single=False): if not paths: cycle_paths = widget_def.get("cycle_paths") - paths = ( - [p for p in cycle_paths] - if cycle_paths - else manage.find_defined_paths(group_id) - ) + if cycle_paths is None: + cycle_paths = [p.get("id") for p in manage.find_defined_paths(group_id)] + widget_def["cycle_paths"] = cycle_paths + + paths = [p for p in cycle_paths] if action: if len(paths) > 0: