views/partials/layout_end.php
1 </div><!-- /.wrap -->
2</main>
3
4<?php $stats = forum_stats(); ?>
5<footer class="site-footer">
6 <div class="footer-inner">
7 <div class="footer-stats">
8 <span title="Topics">๐ฌ <strong><?= number_format($stats['topics']) ?></strong> topics</span>
9 <span class="fs-div">ยท</span>
10 <span title="Posts">๐ <strong><?= number_format($stats['posts']) ?></strong> posts</span>
11 <span class="fs-div">ยท</span>
12 <span title="Members">๐ฅ <strong><?= number_format($stats['users']) ?></strong> members</span>
13 <span class="fs-div">ยท</span>
14 <span title="Online now">๐ข <strong><?= $stats['online'] ?></strong> online</span>
15 <?php if ($stats['newest']): ?>
16 <span class="fs-div">ยท</span>
17 <span>Newest: <a href="<?= u('users/profile.php?u='.urlencode($stats['newest']['username'])) ?>">@<?= e($stats['newest']['username']) ?></a></span>
18 <?php endif; ?>
19 </div>
20 <div class="footer-right">
21 <span><?= e(cfg('site_name','Nexus Forum')) ?></span>
22 <?php if ($USER && is_admin()): ?>
23 <a href="<?= u('admin/') ?>">Admin</a>
24 <?php endif; ?>
25 </div>
26 </div>
27</footer>
28
29<script>
30var NX = {
31 base: '<?= BASE ?>',
32 csrf: '<?= csrf() ?>',
33 maxUploadMb: <?= (int)(cfg('max_upload_mb', '5')) ?>,
34 user: <?= $USER ? json_encode(['id'=>(int)$USER['id'],'name'=>$USER['username'],'role'=>$USER['role']]) : 'null' ?>
35};
36</script>
37<!-- Prism.js syntax tokenizer โ loaded lazily only when a code block with a language exists -->
38<!-- We use our own token color theme from main.css, NOT Prism's default theme CSS -->
39<script>
40(function(){
41 if (!document.querySelector('.code-block-wrap pre.code-block code[class]')) return;
42
43 var s = document.createElement('script');
44 s.src = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js';
45 s.onload = function() {
46 var a = document.createElement('script');
47 a.src = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js';
48 a.onload = function() {
49
50 if (Prism.plugins && Prism.plugins.autoloader) {
51 Prism.plugins.autoloader.languages_path =
52 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/';
53 }
54 Prism.highlightAll();
55 };
56 document.body.appendChild(a);
57 };
58 document.body.appendChild(s);
59})();
60</script>
61<script src="<?= asset('js/app.js') ?>"></script>
62
63<script>
64
65(function(){
66 var stored = localStorage.getItem('nexus-theme');
67 var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme:dark)').matches;
68 var dark = stored ? stored === 'dark' : prefersDark;
69 if (dark) document.documentElement.setAttribute('data-theme','dark');
70 updateThemeIcons(dark);
71})();
72
73function toggleTheme(){
74 var isDark = document.documentElement.getAttribute('data-theme') === 'dark';
75 var newDark = !isDark;
76 if (newDark) {
77 document.documentElement.setAttribute('data-theme','dark');
78 localStorage.setItem('nexus-theme','dark');
79 } else {
80 document.documentElement.removeAttribute('data-theme');
81 localStorage.setItem('nexus-theme','light');
82 }
83 updateThemeIcons(newDark);
84}
85
86function updateThemeIcons(dark){
87 var light = document.querySelector('.theme-icon-light');
88 var moon = document.querySelector('.theme-icon-dark');
89 if (light) light.style.display = dark ? 'none' : '';
90 if (moon) moon.style.display = dark ? '' : 'none';
91}
92</script>
93
94</body>
95</html>