Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ replit.nix
.vscode
.history
cwa-wiki/
docs/

# Test Scripts
test*
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CONTRIBUTORS

This file is automatically generated. DO NOT EDIT MANUALLY.
Generated on: 2025-09-18T08:27:22.533394Z
Generated on: 2025-09-18T17:36:07.319111Z

Upstream project: https://github.com/janeczku/calibre-web
Fork project (Calibre-Web Automated, since 2024): https://github.com/crocodilestick/calibre-web-automated
Expand Down Expand Up @@ -298,7 +298,7 @@ Copyright (C) 2024-2025 Calibre-Web Automated contributors
- zhiyue (1 commits)
# Fork Contributors (crocodilestick/calibre-web-automated)

- crocodilestick (667 commits)
- crocodilestick (669 commits)
- jmarmstrong1207 (73 commits)
- demitrix (30 commits)
- sirwolfgang (22 commits)
Expand Down
2 changes: 1 addition & 1 deletion changelogs/V3.1.0_changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
- Much more **Elegant & Readable** UI, both on **Mobile** & on **Desktop**
- Improved CSS for the Fetch Metadata interface—making it easier and clearer for you to review and select metadata sources.
- **Individually Selectable Elements**
- Say goodbye to having to having all of your book's metadata overwritten simply becuasse you wanted a better looking cover!
- Say goodbye to having to having all of your book's metadata overwritten simply because you wanted a better looking cover!
- As of **V3.1.0**, all metadata elements can be individually updated from multiple sources instead of the only option being to take everything for a single source!

- **Visual Quality Comparison Between the Cover Your Book Already Those Available from Metadata Providers**
Expand Down
34 changes: 34 additions & 0 deletions cps/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,13 @@ def before_request():
# Use per-user theme if available; fallback to global config.config_theme for legacy/anonymous
try:
g.current_theme = getattr(current_user, 'theme', config.config_theme)
g.theme_settings = getattr(current_user, 'theme_settings', {"variant": "dark", "accent_color": "#CC7B19"})
if current_user.is_anonymous and not hasattr(current_user, 'theme'):
g.current_theme = config.config_theme
g.theme_settings = {"variant": "dark", "accent_color": "#CC7B19"}
except Exception:
g.current_theme = getattr(config, 'config_theme', 1)
g.theme_settings = {"variant": "dark", "accent_color": "#CC7B19"}
g.config_authors_max = config.config_authors_max
if '/static/' not in request.path and not config.db_configured and \
request.endpoint not in ('admin.ajax_db_config',
Expand Down Expand Up @@ -2100,6 +2103,8 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support):
try:
# Use global default theme config (acts as default for new users)
content.theme = getattr(config, 'config_theme', 1)
# Set default theme settings for new users
content.theme_settings = {"variant": "dark", "accent_color": "#CC7B19"}
except Exception:
pass
try:
Expand Down Expand Up @@ -2192,6 +2197,35 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
content.theme = theme_val
except Exception:
pass

# Theme settings update
if 'theme_variant' in to_save or 'accent_color' in to_save:
try:
current_settings = content.theme_settings or {"variant": "dark", "accent_color": "#CC7B19"}

# Update variant if provided
if 'theme_variant' in to_save:
variant = to_save.get('theme_variant')
if variant in ('dark', 'light'):
current_settings['variant'] = variant

# Update accent color if provided
if 'accent_color' in to_save:
accent_color = to_save.get('accent_color')
# Basic validation for hex color code
if accent_color and len(accent_color) == 7 and accent_color.startswith('#'):
try:
# Validate it's a proper hex color
int(accent_color[1:], 16)
current_settings['accent_color'] = accent_color
except ValueError:
pass # Invalid hex color, ignore

content.theme_settings = current_settings
flag_modified(content, "theme_settings")
except Exception as e:
log.error(f"Error updating theme settings: {e}")
pass
# Proceed with remaining updates (previously skipped when 'theme' in to_save)
if not ub.session.query(ub.User).filter(ub.User.role.op('&')(constants.ROLE_ADMIN) == constants.ROLE_ADMIN,
ub.User.id != content.id).count() and 'admin_role' not in to_save:
Expand Down
72 changes: 69 additions & 3 deletions cps/cwa_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,31 @@ def validate_and_cleanup_provider_enabled_map(enabled_map, available_provider_id
@switch_theme.route("/cwa-switch-theme", methods=["GET", "POST"])
@login_required_if_no_ano
def cwa_switch_theme():
# Switch theme for current user only
# Enhanced theme switch for current user - now supports variant toggle
try:
# current_user.theme may not exist for old sessions before migration; default to 1 (caliBlur)
current = getattr(current_user, 'theme', 1)
new_theme = 0 if current == 1 else 1
current_theme = getattr(current_user, 'theme', 1)
current_settings = getattr(current_user, 'theme_settings', {"variant": "dark", "accent_color": "#CC7B19"})

# If using legacy theme (0), switch to caliBlur dark mode
if current_theme == 0:
new_theme = 1
new_settings = {"variant": "dark", "accent_color": "#CC7B19"}
else:
# Toggle between light and dark variants of caliBlur
new_theme = 1
if current_settings.get("variant") == "dark":
new_settings = current_settings.copy()
new_settings["variant"] = "light"
else:
new_settings = current_settings.copy()
new_settings["variant"] = "dark"

from . import ub
user = ub.session.query(ub.User).filter(ub.User.id == current_user.id).first()
if user:
user.theme = new_theme
user.theme_settings = new_settings
ub.session_commit()
else:
log.error("Theme switch: user not found in DB")
Expand All @@ -164,6 +180,56 @@ def cwa_switch_theme():
target = url_for("web.index")
return redirect(target, code=302)

@switch_theme.route("/cwa-update-theme-settings", methods=["POST"])
@login_required_if_no_ano
def cwa_update_theme_settings():
"""Update user theme settings via AJAX"""
try:
data = request.get_json()
if not data:
return jsonify({"success": False, "error": "No data provided"}), 400

from . import ub
user = ub.session.query(ub.User).filter(ub.User.id == current_user.id).first()
if not user:
return jsonify({"success": False, "error": "User not found"}), 404

current_settings = user.theme_settings or {"variant": "dark", "accent_color": "#CC7B19"}
updated = False

# Update variant if provided
if 'variant' in data:
variant = data.get('variant')
if variant in ('dark', 'light'):
current_settings['variant'] = variant
updated = True

# Update accent color if provided
if 'accent_color' in data:
accent_color = data.get('accent_color')
# Basic validation for hex color code
if accent_color and len(accent_color) == 7 and accent_color.startswith('#'):
try:
# Validate it's a proper hex color
int(accent_color[1:], 16)
current_settings['accent_color'] = accent_color
updated = True
except ValueError:
return jsonify({"success": False, "error": "Invalid color format"}), 400

if updated:
user.theme_settings = current_settings
from sqlalchemy.orm.attributes import flag_modified
flag_modified(user, "theme_settings")
ub.session_commit()
return jsonify({"success": True, "settings": current_settings})
else:
return jsonify({"success": False, "error": "No valid updates provided"}), 400

except Exception as e:
log.error(f"Error updating theme settings: {e}")
return jsonify({"success": False, "error": "Internal server error"}), 500

##————————————————————————————————————————————————————————————————————————————##
## ##
## CWA LIBRARY REFRESH ##
Expand Down
Loading