Self-hosting Font Awesome's font files (previous commit) didn't fix it either: every icon in the picker still failed identically. That rules out CDN/network blocking specifically and points to something in the browser blocking custom webfont loading altogether regardless of origin (common with strict anti-fingerprinting protection, e.g. Brave's font blocking or certain privacy extensions — @font-face loading is a well-known fingerprinting vector). Replaced the whole mechanism: each of the 258 curated icons is now a real downloaded SVG file (static/icons/*.svg, sourced from Font Awesome 5 Free's official SVG package) displayed via CSS mask-image (.icon-svg in style.css) instead of a font glyph. A masked SVG isn't a font resource at all, so it isn't subject to webfont-blocking — and it still colors via the existing "color" style property (background-color:currentColor) and sizes via font-size (1em), so no change to how the widget's other controls work. The "Icône" widget now stores just the icon's slug (e.g. "trophy") in a dedicated attribute instead of a full CSS class string, rendered by a new special_render (render_icone.py). Updated the add-gallery and the properties-panel picker modal to use the same mask technique for their previews, and element_add.py to validate the slug against the curated list. Removed the now-unused self-hosted Font Awesome CSS/webfont files and the <link> tags — no font dependency left for icons at all. Verified end to end (gallery renders with real SVG previews, simulated add creates a correctly-attributed element, the SVG file is actually served, the per-element picker reflects the current icon). Full suite green (89).
28 lines
1.4 KiB
Python
28 lines
1.4 KiB
Python
from flask import request, redirect, url_for
|
|
|
|
import screens
|
|
|
|
from core.flask_app import app
|
|
|
|
|
|
@app.route("/game/<slug>/screens/<int:screen_id>/elements/add", methods=["POST"])
|
|
def element_add(slug, screen_id):
|
|
widget = request.form.get("widget", "conteneur")
|
|
from_catalogue = widget == "__catalogue__"
|
|
element_type_id = request.form.get("element_type_id") or None if from_catalogue else None
|
|
if from_catalogue and not element_type_id:
|
|
return redirect(url_for("screen_edit", slug=slug, screen_id=screen_id))
|
|
if from_catalogue:
|
|
types = {t["id"]: t for t in screens.list_element_types(slug)}
|
|
et = types.get(int(element_type_id))
|
|
widget = et["default_widget"] if et else "conteneur"
|
|
new_id = screens.add_element(slug, screen_id, widget, element_type_id)
|
|
icon_slug = request.form.get("icon_class")
|
|
if widget == "icone" and icon_slug in screens.FONTAWESOME_ICONS:
|
|
# Posé depuis la galerie d'icônes (voir le panneau de propriétés,
|
|
# section "Icônes") : l'icône choisie remplace celle posée par
|
|
# défaut à la création plutôt que de repartir d'une icône neutre que
|
|
# l'utilisateur devrait ensuite changer manuellement.
|
|
screens.save_element_controls(slug, new_id, {"ctrl_icon_class": icon_slug})
|
|
return redirect(url_for("screen_edit", slug=slug, screen_id=screen_id, selected=new_id))
|