{%- import "components.html" as components -%} {%- import "macros.html" as macros -%} <!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <meta http-equiv="content-security-policy" content="default-src 'self' blob:; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' blob: *; script-src 'self' 'unsafe-inline' blob: *; object-src 'self' blob: *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' blob: data: *" /> <link rel="icon" href="/public/favicon.svg" /> <link rel="stylesheet" href="/css/style.css" /> {% if user %} <script> window.localStorage.setItem( "tetratto:theme", "{{ user.settings.theme_preference }}", ); </script> {% endif %} <script src="/js/loader.js"></script> <script defer async src="/js/atto.js"></script> <script> globalThis.ns_verbose = false; globalThis.ns_config = { root: "/js/", verbose: globalThis.ns_verbose, version: "cache-breaker-{{ random_cache_breaker }}", }; globalThis._app_base = { name: "tetratto", ns_store: {}, classes: {}, }; globalThis.no_policy = false; </script> <meta name="theme-color" content="{{ config.color }}" /> <meta name="description" content="{{ config.description }}" /> <meta property="og:type" content="website" /> <meta property="og:site_name" content="{{ config.name }}" /> <meta name="turbo-prefetch" content="false" /> <meta name="turbo-refresh-method" content="morph" /> <meta name="turbo-refresh-scroll" content="preserve" /> <script src="https://unpkg.com/@hotwired/turbo@8.0.5/dist/turbo.es2017-esm.js" type="module" async defer ></script> {% block head %}{% endblock %} </head> <body> <div id="toast_zone"></div> <div id="page" style="display: contents"> <!-- prettier-ignore --> {% if user and user.id == 0 %} <article> <main> <div class="card-nest"> <div class="card small flex items-center gap-2 red"> {{ icon "frown" }} <span >{{ text "general:label.account_banned" }}</span > </div> <div class="card"> <span >{{ text "general:label.account_banned_body" }}</span > </div> </div> </main> </article> {% else %} {% block body %}{% endblock %} {% endif %} </div> <script data-turbo-permanent="true" id="init-script"> document.documentElement.addEventListener("turbo:load", () => { const atto = ns("atto"); atto.disconnect_observers(); atto.remove_false_options(); atto.clean_date_codes(); atto.link_filter(); atto["hooks::scroll"](document.body, document.documentElement); atto["hooks::dropdown.init"](window); atto["hooks::character_counter.init"](); atto["hooks::long_text.init"](); atto["hooks::alt"](); atto["hooks::online_indicator"](); atto["hooks::ips"](); atto["hooks::check_reactions"](); atto["hooks::tabs"](); atto["hooks::partial_embeds"](); if (document.getElementById("tokens")) { trigger("me::render_token_picker", [ document.getElementById("tokens"), ]); } }); </script> {% if user %} <script data-turbo-permanent="true" id="update-seen-script"> document.documentElement.addEventListener("turbo:load", () => { trigger("me::seen"); }); </script> {% endif %} <!-- dialogs --> <dialog id="link_filter"> <div class="inner flex flex-col gap-2"> <p>Pressing continue will bring you to the following URL:</p> <pre><code id="link_filter_url"></code></pre> <p>Are sure you want to go there?</p> <hr class="margin" /> <div class="flex gap-2"> <a class="button primary" id="link_filter_continue" rel="noopener noreferrer" target="_blank" onclick="document.getElementById('link_filter').close()" > {{ icon "external-link" }} <span>{{ text "dialog:action.continue" }}</span> </a> <button class="secondary" type="button" onclick="document.getElementById('link_filter').close()" > {{ icon "x" }} <span>{{ text "dialog:action.cancel" }}</span> </button> </div> </div> </dialog> <dialog id="web_api_prompt"> <div class="inner flex flex-col gap-2"> <form class="flex gap-2 flex-col" onsubmit="event.preventDefault()" > <label for="prompt" id="web_api_prompt:msg"></label> <input id="prompt" name="prompt" /> <div class="flex justify-between"> <div></div> <div class="flex gap-2"> <button class="primary bold circle" onclick="globalThis.web_api_prompt_submit(document.getElementById('prompt').value); document.getElementById('prompt').value = ''" type="button" > {{ icon "check" }} {{ text "dialog:action.okay" }} </button> <button class="bold red camo" onclick="globalThis.web_api_prompt_submit('')" type="button" > {{ icon "x" }} {{ text "dialog:action.cancel" }} </button> </div> </div> </form> </div> </dialog> <dialog id="web_api_prompt_long"> <div class="inner flex flex-col gap-2"> <form class="flex gap-2 flex-col" onsubmit="event.preventDefault()" > <label for="prompt_long" id="web_api_prompt_long:msg" ></label> <textarea id="prompt_long" name="prompt_long"></textarea> <div class="flex justify-between"> <div></div> <div class="flex gap-2"> <button class="primary bold circle" onclick="globalThis.web_api_prompt_long_submit(document.getElementById('prompt_long').value); document.getElementById('prompt_long').value = ''" type="button" > {{ icon "check" }} {{ text "dialog:action.okay" }} </button> <button class="bold red camo" onclick="globalThis.web_api_prompt_long_submit('')" type="button" > {{ icon "x" }} {{ text "dialog:action.cancel" }} </button> </div> </div> </form> </div> </dialog> <dialog id="web_api_confirm"> <div class="inner flex flex-col gap-2"> <form class="flex gap-2 flex-col" onsubmit="event.preventDefault()" > <label id="web_api_confirm:msg"></label> <div class="flex justify-between"> <div></div> <div class="flex gap-2"> <button class="primary bold circle" onclick="globalThis.web_api_confirm_submit(true)" type="button" > {{ icon "check" }} {{ text "dialog:action.yes" }} </button> <button class="bold red camo" onclick="globalThis.web_api_confirm_submit(false)" type="button" > {{ icon "x" }} {{ text "dialog:action.no" }} </button> </div> </div> </form> </div> </dialog> {% if user %} <dialog id="tokens_dialog"> <div class="inner flex flex-col gap-2"> <form class="flex gap-2 flex-col" onsubmit="event.preventDefault()" > <div id="tokens" style="display: contents"></div> <a href="/auth/login" class="button" data-turbo="false"> {{ icon "plus" }} <span>{{ text "general:action.add_account" }}</span> </a> <div class="flex justify-between"> <div></div> <div class="flex gap-2"> <button class="quaternary" onclick="document.getElementById('tokens_dialog').close()" type="button" > {{ icon "check" }} <span>{{ text "dialog:action.okay" }}</span> </button> </div> </div> </form> </div> </dialog> <dialog id="town_square_post_dialog"> <div class="inner flex flex-col gap-2"> {{ components::town_square_post_form() }} <div class="flex justify-between"> <div></div> <div class="flex gap-2"> <button class="bold red quaternary" onclick="document.getElementById('town_square_post_dialog').close()" type="button" > {{ icon "x" }} {{ text "dialog:action.close" }} </button> </div> </div> </div> </dialog> <dialog id="quote_dialog"> <div class="inner flex flex-col gap-2"> {{ components::quote_form() }} <div class="flex justify-between"> <div></div> <div class="flex gap-2"> <button class="bold red quaternary" onclick="document.getElementById('quote_dialog').close()" type="button" > {{ icon "x" }} {{ text "dialog:action.close" }} </button> </div> </div> </div> </dialog> {% endif %} {% if user and use_user_theme %} {{ components::theme(user=user) }} {% endif %} </body> </html>