ic: something

This commit is contained in:
E. S. 2025-05-03 03:32:13 +03:00
parent 03f79a7550
commit aa909de1de
23 changed files with 159 additions and 71 deletions

View File

@ -1,6 +1,7 @@
domain: example.org
cookie_host: .example.org
admin_email: admin@example.org
ic_email: info@4in1.ws
default_project: 'foreignone'
subdomains:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 664 B

View File

@ -87,6 +87,7 @@ a.head-item {
padding: 6px 10px;
margin: 0 0 0 5px;
vertical-align: middle;
text-transform: lowercase;
&.is-ic {
color: $link-color;

View File

@ -36,11 +36,7 @@ class StringsBase implements ArrayAccess
* @return string|string[]
*/
public function offsetGet(mixed $offset): mixed {
if (!isset($this->data[$offset])) {
logError(__METHOD__.': '.$offset.' not found');
return '{'.$offset.'}';
}
return $this->data[$offset];
return $this->data[$offset] ?? '{'.$offset.'}';
}
/**

View File

@ -32,6 +32,7 @@ abstract class BaseSkin
$this->twig->addExtension(new SkinTwigExtension($this));
$this->strings = Strings::getInstance(); // why singleton here?
$this->strings->load('common');
}
abstract protected function getTwigLoader(): LoaderInterface;

View File

@ -3,6 +3,8 @@
namespace engine\skin;
use app\ThemesUtil;
use engine\http\HtmlResponse;
use engine\http\Response;
use engine\skin\TwigAddons\JsTagRuntime;
use engine\skin\TwigAddons\JsTwigExtension;
@ -79,6 +81,19 @@ abstract class FeaturedSkin
}
}
public function renderPage(string $template, array $vars = []): Response {
$this->applyGlobals();
// render body first (in order for all svgPreload() calls to be executed)
$b = $this->renderBody($template, $vars);
// then everything else
$h = $this->renderHeader();
$f = $this->renderFooter();
return new HtmlResponse($h.$b.$f);
}
public function renderBreadCrumbs(array $items, ?string $style = null, bool $mt = false): string {
static $chevron = '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.47 4.217a.75.75 0 0 0 0 1.06L12.185 10 7.469 14.72a.75.75 0 1 0 1.062 1.06l5.245-5.25a.75.75 0 0 0 0-1.061L8.531 4.218a.75.75 0 0 0-1.061-.001z" fill="currentColor"/></svg>';
$buf = implode(array_map(function (array $i) use ($chevron): string {
@ -211,7 +226,7 @@ HTML;
}
$versions = jsonEncode($versions);
}
$html .= 'StaticManager.init(\''.$config['commit_hash'].'\', '.jsonEncode($this->styleNames).', '.$versions.');';
$html .= 'StaticManager.init(\''.(isDev() ? 'dev' : $config['commit_hash']).'\', '.jsonEncode($this->styleNames).', '.$versions.');';
$html .= 'ThemeSwitcher.init();';
if (!empty($this->exportedStrings)) {

View File

@ -79,3 +79,8 @@ function isAdmin(): bool {
app\Admin::check();
return app\Admin::getId() != 0;
}
function getExecutionTime(): float {
$exec_time = microtime(true) - START_TIME;
return round($exec_time, 4);
}

View File

@ -12,7 +12,7 @@ abstract class BaseHandler
public function __construct() {
$this->skin = new InvisibleCollegeSkin();
// $this->skin->strings->load('ic');
$this->skin->strings->load('ic');
$this->skin->addStatic(
'css/common.css',
'js/common.js'

View File

@ -4,7 +4,7 @@ namespace app\ic;
use engine\http\errors\NotFound;
use engine\http\HtmlResponse;
use engine\http\PlainTextResponse;
use engine\http\HTTPCode;
class MainHandler
extends BaseHandler
@ -16,8 +16,16 @@ class MainHandler
public function GET_index() {
if (!isAdmin())
return new HtmlResponse($this->skin->render('soon.twig'));
return new HtmlResponse($this->skin->render('soon.twig'), code: HTTPCode::NotFound);
return new PlainTextResponse('hello world');
$this->skin->meta->title = lang('meta_index_title');
$this->skin->meta->description = lang('meta_index_description');
$this->skin->meta->url = 'https://'.$_SERVER['HTTP_HOST'].'/';
// $this->skin->meta->image = 'https://'.$config['domain'].'/img/4in1-preview.jpg';
$this->skin->meta->setSocial('og:type', 'website');
$this->skin->options->isIndex = true;
return $this->skin->renderPage('index.twig');
}
}

View File

@ -71,6 +71,7 @@ class ForeignOneSkin
'static_html' => $this->getHeaderStaticTags(),
'svg_html' => $this->getSVGTags(),
'render_options' => $this->options->getOptions(),
'ic_url' => 'https://ic'.(isDev() ? 'dev' : '').'.'.$config['domain'],
'app_config' => [
'domain' => $config['domain'],
'devMode' => isDev(),
@ -89,18 +90,11 @@ class ForeignOneSkin
protected function renderFooter(): string {
global $config;
$exec_time = microtime(true) - START_TIME;
$exec_time = round($exec_time, 4);
$footer_vars = [
'exec_time' => $exec_time,
'exec_time' => getExecutionTime(),
'render_options' => $this->options->getOptions(),
'admin_email' => $config['admin_email'],
// 'lang_json' => json_encode($this->getLangKeys(), JSON_UNESCAPED_UNICODE),
// 'static_config' => $this->getStaticConfig(),
'script_html' => $this->getFooterScriptTags(),
'this_page_url' => $_SERVER['REQUEST_URI'],
'theme' => ThemesUtil::getUserTheme(),
];
return $this->doRender('footer.twig', $footer_vars);

View File

@ -2,8 +2,8 @@
namespace app\ic;
use app\foreignone\ForeignOneSkinOptions;
use app\ThemesUtil;
use engine\http\HtmlResponse;
use engine\http\Response;
use Twig\Loader\FilesystemLoader;
use Twig\Loader\LoaderInterface;
@ -11,9 +11,23 @@ use Twig\Loader\LoaderInterface;
class InvisibleCollegeSkin
extends \engine\skin\FeaturedSkin
{
public InvisibleCollegeSkinOptions $options;
public string $title {
get {
$title = isset($this->title) && $this->title ? $this->title : lang('site_title');
if (!$this->options->isIndex)
$title = $title.' - '.lang('invisible_college');
return $title;
}
set(string $title) {
$this->title = $title;
}
}
public function __construct() {
parent::__construct();
$this->options = new InvisibleCollegeSkinOptions();
}
protected function getTwigLoader(): LoaderInterface {
@ -27,42 +41,21 @@ class InvisibleCollegeSkin
return $config['skin_cache_'.(isDev() ? 'dev' : 'prod').'_dir'].'/ic';
}
/*
public function renderPage(string $template, array $vars = []): Response {
$this->exportStrings(['4in1']);
$this->applyGlobals();
// render body first
$b = $this->renderBody($template, $vars);
// then everything else
$h = $this->renderHeader();
$f = $this->renderFooter();
return new HtmlResponse($h.$b.$f);
}
protected function renderHeader(): string {
global $config;
$body_class = [];
if ($this->options->fullWidth)
$body_class[] = 'full-width';
else if ($this->options->wide)
$body_class[] = 'wide';
$vars = [
'title' => $this->title,
'meta_html' => $this->meta->getHtml(),
'static_html' => $this->getHeaderStaticTags(),
'svg_html' => $this->getSVGTags(),
'render_options' => $this->options->getOptions(),
'home_url' => 'https://'.(isDev() ? 'dev.' : '').$config['domain'],
'app_config' => [
'domain' => $config['domain'],
'devMode' => $config['is_dev'],
'devMode' => isDev(),
'cookieHost' => $config['cookie_host'],
],
'body_class' => $body_class,
'theme' => ThemesUtil::getUserTheme(),
];
@ -75,21 +68,13 @@ class InvisibleCollegeSkin
protected function renderFooter(): string {
global $config;
$exec_time = microtime(true) - START_TIME;
$exec_time = round($exec_time, 4);
$footer_vars = [
'exec_time' => $exec_time,
'exec_time' => getExecutionTime(),
'render_options' => $this->options->getOptions(),
'admin_email' => $config['admin_email'],
// 'lang_json' => json_encode($this->getLangKeys(), JSON_UNESCAPED_UNICODE),
// 'static_config' => $this->getStaticConfig(),
'admin_email' => $config['ic_email'],
'script_html' => $this->getFooterScriptTags(),
'this_page_url' => $_SERVER['REQUEST_URI'],
'theme' => ThemesUtil::getUserTheme(),
];
return $this->doRender('footer.twig', $footer_vars);
}
*/
}

View File

@ -0,0 +1,9 @@
<?php
namespace app\ic;
class InvisibleCollegeSkinOptions
extends \engine\skin\Options
{
public bool $isIndex = false;
}

View File

@ -18,22 +18,8 @@
{{ script_html|raw }}
{% if not render_options.inside_admin_interface %}
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(96032069, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/96032069" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
{% if not render_options.inside_admin_interface and not is_dev %}
{% include 'metrika.twig' %}
{% endif %}
</body>

View File

@ -38,7 +38,7 @@
about
</a>
{%- if is_admin -%}
<a class="head-item is-ic" href="https://ic.4in1.ws">
<a class="head-item is-ic" href="{{ ic_url }}">
invisible college {{ svgInPlace('college_20') }}
</a>
{%- endif -%}

View File

@ -0,0 +1,15 @@
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(96032069, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/96032069" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->

24
src/skins/ic/footer.twig Normal file
View File

@ -0,0 +1,24 @@
</div>
<div class="footer">
<div class="footer-right">
Email: <a href="mailto:{{ admin_email }}">{{ admin_email }}</a>
</div>
<div class="footer-left">
Theme: <a id="switch-theme" href="javascript:void(0)" onclick="return ThemeSwitcher.next(event)">{{ theme }}</a>
</div>
</div>
</div>
{{ script_html|raw }}
{% if not render_options.inside_admin_interface and not is_dev %}
{% include '@foreignone/metrika.twig' %}
{% endif %}
</body>
</html>
{% if is_admin %}
<!-- {{ exec_time }} s -->
{% endif %}

39
src/skins/ic/header.twig Normal file
View File

@ -0,0 +1,39 @@
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/favicon.png?v=2" type="image/png">
<link rel="icon" href="/favicon.ico?v=2" type="image/x-icon">
<title>{{ title }}</title>
<script type="text/javascript">window.appConfig = {{ app_config|json_encode|raw }};</script>
{{ meta_html|raw }}
{{ static_html|raw }}
</head>
<body>
{{ svg_html|raw }}
<div class="page-content base-width">
<div class="head{% if not render_options.is_index %} no-subtitle{% endif %}">
<div class="head-inner">
<div class="head-logo-wrap">
<div class="head-logo">
<a href="/">
<div class="head-logo-title">{{ "invisible_college"|lang }}</div>
</a>
</div>
</div>
<div class="head-items">
<a class="head-item {% if render_options.head_section == 'books' %} is-selected{% endif %}" href="/books/">
books
</a>
{%- if is_admin -%}
<a class="head-item is-ic" href="{{ home_url }}">
foreign one {{ svgInPlace('riverbank_eagle_20') }}
</a>
{%- endif -%}
</div>
</div>
</div>
<div class="page-content-inner">

3
src/skins/ic/index.twig Normal file
View File

@ -0,0 +1,3 @@
<div class="page is-index">
hello, world
</div>

View File

@ -0,0 +1 @@
<path d="M9.24,15.19c-.66.76-1.65,1.37-2.24,1.37s-.41.51.23.76c.76.3.84.24,1.07,0,.07-.06.14-.11.36-.13.3-.04.48-.18.79-.51.33-.36.43-.56.43-.64,0-.2,0-.28.2-.61.64-.97-.05-1.17-.84-.25ZM16.09,11.56c-1.07.3-1.57.6-1.65.91-.08.25-.46.61-.86.79-.41.18-.74.51-.74.76,0,.23-.2.48-.48.58-.69.2-1.21,1.12-1.06,1.58.18.43.84.51,1.09.1.1-.18.51-.23,1.02-.15.81.13.84.1.99-.91.28-1.65,1.02-2.64,2.44-3.25.69-.31,1.22-.61,1.14-.66-.05-.08-1.02,0-1.89.26ZM13.28,10.72c.71,0,.81-.43.31-1.47-.33-.71-.61-.94-1.12-.97-.36-.03-.86-.15-1.14-.3-.41-.25-.38-.28.31-.15.74.15.79.13.66-.61-.08-.64.03-.79.69-1.09.92-.41,1.17-.92.74-1.42-.56-.69-2.26-1.37-3.71-1.53-.79-.08-1.55-.23-1.7-.33-.43-.3-8.01-.53-8.01-.23,0,.48,1.23,1.92,2.24,2.01.84.07,1.92.88,1.92.88,2.44,1.11,2.9,2.04,3.72,3.69.1.2.41.89.89,1.45.48.58.89,1.17.89,1.32s.15.51.31.79c.36.58.76.69.66.18-.1-.46,1.78-2.21,2.36-2.21ZM18.52,7.49c-.28-.25-1.93,1.04-1.96,1.53,0,.1.18.18.38.18s.38-.1.38-.25c0-.13.18-.25.38-.25.38,0,1.04-.97.81-1.19Z"/>

1
src/strings/common.yaml Normal file
View File

@ -0,0 +1 @@
error: Error

5
src/strings/ic.yaml Normal file
View File

@ -0,0 +1,5 @@
# common
invisible_college: Invisible College
site_title: Invisible College
meta_index_title: ""
meta_index_description: ""

View File

@ -9,7 +9,6 @@ articles: Articles
recent_articles: Recent articles
view_all_articles: View all
unknown_error: Unknown error
error: Error
write: Write
submit: submit
sign_in: Sign in