refactor: split directory and image rendering into viewer.directory, viewer.image; add viewer.common for shared helpers
This commit is contained in:
221
viewer/common.py
Normal file
221
viewer/common.py
Normal file
@@ -0,0 +1,221 @@
|
||||
# Standard library imports.
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlencode
|
||||
from functools import cmp_to_key
|
||||
|
||||
# Django imports.
|
||||
from django.conf import settings
|
||||
|
||||
# Project imports.
|
||||
from .utils import make_thumbnail, is_image_file
|
||||
|
||||
###########################################################################################
|
||||
# Constants. #
|
||||
###########################################################################################
|
||||
|
||||
SORT_OPTIONS = [
|
||||
("abc", "Alphabetical A-Z"),
|
||||
("cba", "Alphabetical Z-A"),
|
||||
("old", "Creation date old to new"),
|
||||
("new", "Creation date new to old"),
|
||||
("recent", "Modification date most recent"),
|
||||
("tnecer", "Modification date least recent"),
|
||||
]
|
||||
|
||||
SORT_LABELS = dict(SORT_OPTIONS)
|
||||
|
||||
|
||||
def normalize_sort(sort_value):
|
||||
return sort_value if sort_value in SORT_LABELS else "abc"
|
||||
|
||||
|
||||
def normalize_theme(theme_value):
|
||||
return theme_value if theme_value in ("dark", "light") else "dark"
|
||||
|
||||
|
||||
def get_creation_timestamp(path_obj):
|
||||
try:
|
||||
stat_data = path_obj.stat()
|
||||
return getattr(stat_data, "st_birthtime", stat_data.st_ctime)
|
||||
except OSError:
|
||||
return 0
|
||||
|
||||
|
||||
def get_modification_timestamp(path_obj):
|
||||
try:
|
||||
return path_obj.stat().st_mtime
|
||||
except OSError:
|
||||
return 0
|
||||
|
||||
|
||||
def build_query(search_text, sort_key, theme):
|
||||
query = {"sort": sort_key, "theme": theme}
|
||||
|
||||
if search_text != "":
|
||||
query["search"] = search_text
|
||||
|
||||
return query
|
||||
|
||||
|
||||
def append_query(url, query_dict):
|
||||
if len(query_dict) == 0:
|
||||
return url
|
||||
|
||||
return url + "?" + urlencode(query_dict)
|
||||
|
||||
|
||||
def gallery_url(path_obj=None, is_dir=False, query_dict=None):
|
||||
if query_dict is None:
|
||||
query_dict = {}
|
||||
|
||||
if path_obj is None:
|
||||
base_url = "/gallery/"
|
||||
else:
|
||||
path_text = str(path_obj).replace("\\", "/")
|
||||
base_url = "/gallery/" + path_text
|
||||
|
||||
if is_dir and not base_url.endswith("/"):
|
||||
base_url += "/"
|
||||
|
||||
return append_query(base_url, query_dict)
|
||||
|
||||
|
||||
def sort_images(images, sort_key):
|
||||
def compare(img_a, img_b):
|
||||
name_a = img_a.name.lower()
|
||||
name_b = img_b.name.lower()
|
||||
rel_a = str(img_a.relative_to(settings.GALLERY_ROOT)).lower()
|
||||
rel_b = str(img_b.relative_to(settings.GALLERY_ROOT)).lower()
|
||||
|
||||
if sort_key == "abc":
|
||||
if name_a < name_b:
|
||||
return -1
|
||||
if name_a > name_b:
|
||||
return 1
|
||||
|
||||
elif sort_key == "cba":
|
||||
if name_a > name_b:
|
||||
return -1
|
||||
if name_a < name_b:
|
||||
return 1
|
||||
|
||||
elif sort_key == "old":
|
||||
created_a = get_creation_timestamp(img_a)
|
||||
created_b = get_creation_timestamp(img_b)
|
||||
|
||||
if created_a < created_b:
|
||||
return -1
|
||||
if created_a > created_b:
|
||||
return 1
|
||||
|
||||
elif sort_key == "new":
|
||||
created_a = get_creation_timestamp(img_a)
|
||||
created_b = get_creation_timestamp(img_b)
|
||||
|
||||
if created_a > created_b:
|
||||
return -1
|
||||
if created_a < created_b:
|
||||
return 1
|
||||
|
||||
elif sort_key == "recent":
|
||||
modified_a = get_modification_timestamp(img_a)
|
||||
modified_b = get_modification_timestamp(img_b)
|
||||
|
||||
if modified_a > modified_b:
|
||||
return -1
|
||||
if modified_a < modified_b:
|
||||
return 1
|
||||
|
||||
elif sort_key == "tnecer":
|
||||
modified_a = get_modification_timestamp(img_a)
|
||||
modified_b = get_modification_timestamp(img_b)
|
||||
|
||||
if modified_a < modified_b:
|
||||
return -1
|
||||
if modified_a > modified_b:
|
||||
return 1
|
||||
|
||||
if name_a < name_b:
|
||||
return -1
|
||||
if name_a > name_b:
|
||||
return 1
|
||||
if rel_a < rel_b:
|
||||
return -1
|
||||
if rel_a > rel_b:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
return sorted(images, key=cmp_to_key(compare))
|
||||
|
||||
|
||||
def build_breadcrumbs(path_text, query_dict):
|
||||
breadcrumbs = [{"label": "Gallery", "path": gallery_url(None, True, query_dict)}]
|
||||
|
||||
if path_text == "":
|
||||
return breadcrumbs
|
||||
|
||||
segments = Path(path_text).parts
|
||||
current = Path("")
|
||||
|
||||
for segment in segments:
|
||||
current = current.joinpath(segment)
|
||||
breadcrumbs.append(
|
||||
{"label": segment, "path": gallery_url(current, True, query_dict)}
|
||||
)
|
||||
|
||||
return breadcrumbs
|
||||
|
||||
|
||||
def build_sort_options(request, search_text, sort_key, theme):
|
||||
options = []
|
||||
|
||||
for option_key, label in SORT_OPTIONS:
|
||||
query = {"sort": option_key, "theme": theme}
|
||||
|
||||
if search_text != "":
|
||||
query["search"] = search_text
|
||||
|
||||
options.append(
|
||||
{
|
||||
"key": option_key,
|
||||
"label": label,
|
||||
"url": append_query(request.path, query),
|
||||
"is_active": option_key == sort_key,
|
||||
}
|
||||
)
|
||||
|
||||
return options
|
||||
|
||||
|
||||
def get_first_image_thumbnail_url(subdir):
|
||||
try:
|
||||
images = sorted(
|
||||
[
|
||||
entry
|
||||
for entry in subdir.iterdir()
|
||||
if entry.is_file() and not entry.is_symlink() and is_image_file(entry)
|
||||
],
|
||||
key=lambda item: (
|
||||
item.name.lower(),
|
||||
str(item.relative_to(settings.GALLERY_ROOT)).lower(),
|
||||
),
|
||||
)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
if len(images) == 0:
|
||||
return None
|
||||
|
||||
first_image = images[0]
|
||||
|
||||
try:
|
||||
make_thumbnail(first_image)
|
||||
rel_path = first_image.relative_to(settings.GALLERY_ROOT)
|
||||
thumb_path = settings.THUMBNAILS_ROOT.joinpath(rel_path)
|
||||
|
||||
if thumb_path.exists():
|
||||
return "/thumbs/" + str(rel_path).replace("\\", "/")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return None
|
||||
Reference in New Issue
Block a user