summaryrefslogtreecommitdiff
path: root/src/application/templates/modern/base.twig
diff options
context:
space:
mode:
Diffstat (limited to 'src/application/templates/modern/base.twig')
-rw-r--r--src/application/templates/modern/base.twig222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/application/templates/modern/base.twig b/src/application/templates/modern/base.twig
new file mode 100644
index 0000000..819af80
--- /dev/null
+++ b/src/application/templates/modern/base.twig
@@ -0,0 +1,222 @@
+{%- if title -%}
+ {%- set title = title ~ " | " -%}
+{%- endif -%}
+{%- set title = title ~ (g.env.MYSTIC_FORUM_TITLE|default("Forum")) -%}
+{%- set nextParam = "" -%}
+{%- if g.globals.action in ["login", "register"] -%}
+ {%- set nextParam = g.get.next|default("") -%}
+{%- else -%}
+ {%- set nextParam = g.server.REQUEST_URI -%}
+{%- endif -%}
+<!DOCTYPE html>
+<html lang="{{ __("en", context: "HTML language") }}">
+<head>
+ <meta charset="utf-8">
+ <meta name="color-scheme" content="light dark">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+ <meta name="generator" content="mysticBB {{ constant("MYSTICBB_VERSION") }}">
+ <title>{{ title }}</title>
+ <link rel="stylesheet" href=".?_action=ctheme">
+ <script src=".?_action=ji18n"></script>
+ {% block head_after %}{% endblock %}
+</head>
+<body>
+
+{% block nav %}
+<header>
+ <a id="brand" href=".">{{ g.env.MYSTIC_FORUM_TITLE|default("Forum") }}</a>
+ <nav>
+ {% block navbar %}
+ {% if currentUser %}
+ <a aria-label="{{ __("Search") }}" href="?_action=search"{{ g.globals.action == "search" ? ' class="active"'|raw : '' }}>
+ <svg viewBox="0 0 24 24" class="icon"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
+ </a>
+ <a aria-label="{{ __("View profile") }}" href="?_action=viewuser&amp;user={{ currentUser.id|url_encode }}"{{ (g.globals.action == "viewuser" and g.get.user == currentUser.id) ? ' class="active"'|raw : '' }}>
+ <svg viewBox="0 0 24 24" class="icon"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
+ </a>
+ <a aria-label="{{ __("Log out") }}" href="?_action=logout&amp;next={{ g.server.REQUEST_URI|url_encode }}">
+ <svg viewBox="0 0 24 24" class="icon"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" x2="9" y1="12" y2="12"/></svg>
+ </a>
+ {% else %}
+ <a aria-label="{{ __("Search") }}" href="?_action=search"{{ g.globals.action == "search" ? ' class="active"'|raw : '' }}>
+ <svg viewBox="0 0 24 24" class="icon"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
+ </a>
+ <a href="?_action=auth&amp;next={{ nextParam|url_encode }}"{{ g.globals.action == "auth" ? ' class="active"'|raw : '' }}>{{ __("Log in") }}</a>
+ {% if constant("REGISTRATION_ENABLED") %}
+ <a href="?_action=register&amp;next={{ nextParam|url_encode }}"{{ g.globals.action == "register" ? ' class="active"'|raw : '' }}>{{ __("Register") }}</a>
+ {% endif %}
+ {% endif %}
+ {% endblock %}
+ </nav>
+</header>
+{% endblock %}
+
+{% block main %}
+<main>
+ {% block content %}{% endblock %}
+</main>
+{% endblock %}
+
+{% block footer %}
+<footer>
+ <div id="about">
+ &copy; {{ "now"|date("Y") }} {{ g.env.MYSTIC_FORUM_COPYRIGHT|default(g.env.MYSTIC_FORUM_TITLE)|default("Forum") }}.
+ Powered by <a href="https://git.jkohl.link/mystic-forum.git/tag/?h=v{{ constant("MYSTICBB_VERSION")|url_encode }}">mysticBB v{{ constant("MYSTICBB_VERSION") }}</a>.
+ </div>
+ <div id="preferences">
+ <form action="?_action=settheme" class="form-inline" method="post">
+ <input type="hidden" name="next" value="{{ g.server.REQUEST_URI }}">
+ <div class="form-group">
+ <label for="theme-select">{{ __("Theme:") }}</label>
+ <select id="theme-select" name="theme" onchange="this.form.submit()">
+ {% for themeKey, themeInfo in availableThemes %}
+ <option value="{{ themeKey }}"{{ themeKey == currentTheme ? " selected" : "" }}>{{ themeInfo.name }}</option>
+ {% endfor %}
+ </select>
+ </div>
+ </form>
+ <form action="?_action=setlang" class="form-inline" method="post">
+ <input type="hidden" name="next" value="{{ g.server.REQUEST_URI }}">
+ <div class="form-group">
+ <label for="lang-select">{{ __("Language:") }}</label>
+ <select id="lang-select" name="lang" onchange="this.form.submit()">
+ {% for langKey, langName in availableLangs %}
+ <option value="{{ langKey }}"{{ langKey == currentLang ? " selected" : "" }}>{{ langName }}</option>
+ {% endfor %}
+ </select>
+ </div>
+ </form>
+ </div>
+</footer>
+{% endblock %}
+
+{% block scripts %}
+<script type="text/javascript">
+ (function() {
+ function insertAroundSelection(textarea, before, after) {
+ var start = textarea.selectionStart;
+ var end = textarea.selectionEnd;
+ var text = textarea.value;
+ var pre = text.substring(0, start);
+ var inner = text.substring(start, end);
+ var post = text.substring(end);
+ start += before.length;
+ end += before.length;
+ text = pre + before + inner + after + post;
+ textarea.value = text;
+ textarea.focus();
+ textarea.selectionStart = start;
+ textarea.selectionEnd = end;
+ }
+
+ function getTextarea(btn) {
+ return document.querySelector(btn.dataset.area);
+ }
+
+ var commands = {
+ bold: function(textarea) {
+ insertAroundSelection(textarea, "[b]", "[/b]");
+ },
+ italic: function(textarea) {
+ insertAroundSelection(textarea, "[i]", "[/i]");
+ },
+ underline: function(textarea) {
+ insertAroundSelection(textarea, "[u]", "[/u]");
+ },
+ strikethrough: function(textarea) {
+ insertAroundSelection(textarea, "[s]", "[/s]");
+ },
+ sup: function(textarea) {
+ insertAroundSelection(textarea, "[^]", "[/^]");
+ },
+ sub: function(textarea) {
+ insertAroundSelection(textarea, "[_]", "[/_]");
+ },
+ quote: function(textarea) {
+ insertAroundSelection(textarea, "> ", "");
+ },
+ spoiler: function(textarea) {
+ insertAroundSelection(textarea, "[spoiler]", "[/spoiler]");
+ }
+ }
+
+ document.querySelectorAll("button[data-editor-command]").forEach(e => {
+ e.addEventListener("click", function() {
+ const command = e.dataset.editorCommand;
+ const textarea = getTextarea(e);
+ commands[command](textarea);
+ });
+ });
+ })();
+</script>
+
+<script>
+ document.querySelectorAll("._time").forEach(e => {
+ const date = new Date(e.textContent.trim());
+ e.textContent = date.toLocaleString();
+ });
+ document.querySelectorAll("._date").forEach(e => {
+ const date = new Date(e.textContent.trim());
+ e.textContent = date.toLocaleDateString();
+ });
+ document.querySelectorAll("._time-only").forEach(e => {
+ const date = new Date(e.textContent.trim());
+ e.textContent = date.toLocaleTimeString();
+ });
+ document.querySelectorAll("[data-dismiss='modal']").forEach(e => {
+ e.addEventListener("click", () => {
+ const modal = e.closest(".modal");
+ if (!modal)
+ return;
+ modal.classList.add("fade");
+ modal.dispatchEvent(new Event("hidemodal"));
+ });
+ })
+</script>
+
+<script>
+ // feature detection
+ (function() {
+ var unsupportedFeatures = [];
+
+ function notSupported(feat) {
+ unsupportedFeatures.push("- " + feat);
+ }
+
+ var supports = {
+ cssNesting: ((function() {
+ try {
+ document.querySelector("&");
+ return true;
+ } catch (e) {
+ return false;
+ }
+ })()),
+ es6Syntax: ((function() {
+ try {
+ Function("() => {};");
+ return true;
+ } catch (e) {
+ return false;
+ }
+ })())
+ };
+
+ if (!supports.cssNesting) notSupported("CSS nesting");
+ if (!supports.es6Syntax) notSupported("ECMAScript 6 Syntax");
+
+ if (unsupportedFeatures.length > 0) {
+ alert(
+ "ATTENTION: This site might not work properly because your " +
+ "browser does not support some required features: \n\n" +
+ unsupportedFeatures.join("\n") +
+ "\n\n" +
+ "Please try chaning the theme to something else!"
+ );
+ }
+ })();
+</script>
+{% endblock %}
+
+</body>
+</html>