10 Commits

Author SHA1 Message Date
0f09b2de71 layer with it own size with positioning X and Y by canvas 2026-06-06 15:46:32 +00:00
3ef75a5814 stroke position fix 2026-06-04 15:47:12 +00:00
4d2e419018 dragdrop 2026-06-03 18:55:28 +00:00
91d5883885 dots 2026-05-31 13:19:05 +05:00
4203b1e9f8 ssh port 2026-05-31 00:34:53 +05:00
658a95877c improved the nginx section 2026-05-31 00:16:17 +05:00
3ce62f13e2 small fixes 2026-05-30 22:19:02 +05:00
1361f8cd5e corners 2026-05-30 16:58:45 +00:00
323beeb886 headers 2026-05-30 21:48:37 +05:00
9378f022b4 instruction 2026-05-30 21:45:50 +05:00
8 changed files with 118 additions and 40 deletions

View File

@@ -1,2 +1,51 @@
# pechatalka # Pechatalka
Chat-robot constructor for the Svoboda typography Site and chat-robot constructor for the Svoboda typography
# Installation
Before process any command think about **what it does** and whether the **paths** are specified correctly<br>
## NGINX
### Create the NGINX server
You can copy an example of the server file from here: `/examples/nginx/pechatalka.conf`<br>
<small><i>I prefer to rename nginx config files to domain names. For example: `pechatalka.kodorvan.tech`</i></small><br>
<i>The file will be half commented out specifically to start the server for generating the TLS/SSL certificate</i><br>
1. `cd /examples/nginx`<br>
2. `sudo cp pechatalka.conf /etc/nginx/sites-avaiable/pechatalka.conf`<br>
3. `sudo nvim /etc/nginx/sites-avaiable/pechatalka.conf`<br>
<small>3.1. <i>Customize the file according to your requirements</i></small><br>
4. `sudo ln -s /etc/nginx/sites-avaiable/pechatalka.conf /etc/nginx/sites-enabled/pechatalka.conf`<br>
5. `sudo nginx -t`<br>
<small>5.1. <i>Make sure that <b>NGINX does not throw errors</b>, otherwise proceed to the instructions for generate a TLS/SSL certificate</i></small><br>
6. `sudo service nginx restart`<br>
### Add mime-type recognition for javascript modules
<small>Edit the file: `/etc/nginx/mime.types`</small><br>
**From:** `application/javascript js;`<br>
**To:** `application/javascript js mjs;`
### Generate a TLS/SSL sertificate (via [certbot](http://certbot.eff.org/) for [ubuntu](https://ubuntu.com/))
1. `sudo apt install certbot python3-certbot-nginx`<br>
2. `sudo certbot certonly --nginx`<br>
<small><i>The **domain** must already be **bound** to the **IP-address** of the server by `CNAME`, `A` or `AAAA` record</i></small><br>
3. Uncomment and reconfigure the nginx server file
4. `sudo nginx -t`<br>
<small>4.1. <i>Make sure that <b>NGINX does not throw errors</b></i></small><br>
5. `sudo service nginx restart`
### Set up firewall rules for HTTP and HTTPS requests (for [ubuntu](https://ubuntu.com/))
1. `sudo ufw allow "NGINX Full"`<br>
<small>1.1. <i>Make sure that the <b>port for SSH connection</b> is open</i></small><br>
2. `sudo ufw allow 22`<br>
<small>2.1. <i>Use your SSH port instead of 22</i></small><br>
3. `sudo ufw enable`
## SystemD (or any alternative you like)
You can copy an example of the systemd file from here: `/examples/systemd/arming.service`<br>
1. `cd examples/systemd`<br>
2. `sudo cp pechatalka.service /etc/systemd/system/pechatalka.service && sudo chmod +x /etc/systemd/system/pechatalka.service`<br>
3. `sudo nvim /etc/systemd/system/pechatalka.service`<br>
<small>3.1. <i>Customize the file according to your requirements</i></small><br>
4. `sudo systemctl daemon-reload`<br>
3. `sudo systemctl enable pechatalka`<br>

View File

@@ -151,18 +151,19 @@ final class paper extends core
$image->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER); $image->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
$image->setimagematte(true); $image->setimagematte(true);
// Initializing the layer image height before resizing
$before = $image->getImageHeight();
// Resizing the layer image // Resizing the layer image
$image->adaptiveResizeImage((int) round($blank['width'] * $layer['scale']), 0); $image->adaptiveResizeImage((int) round($blank['width'] * $layer['scale']), 0);
$image->roundCornersImage($layer['corners'], $layer['corners']);
if (!empty($layer['corners'])) {
// Received the layer image corners
// Masking the layer image with corners
$image->roundCornersImage($layer['corners'], $layer['corners']);
}
// Calculating the layer image coordinates by the layer image mask // Calculating the layer image coordinates by the layer image mask
$vertical = $blank['height'] - $before; $layer['x'] = (int) round(($layer['x'] - ($canvas['width'] - $layer['width']) / 2) * $ratio['width'] + ($blank['width'] - $image->getImageWidth()) / 2);
$layer['x'] = (int) round($layer['x'] * $ratio['width'] + ($blank['width'] - $image->getImageWidth()) / 2); $layer['y'] = (int) round(($layer['y'] - ($canvas['height'] - $layer['height']) / 2) * $ratio['height'] + ($blank['height'] - $image->getImageHeight()) / 2);
$layer['y'] = (int) round($layer['y'] * $ratio['height'] + ($blank['height'] - $image->getImageHeight() + ($vertical > 0 ? $vertical : 0)) / 2);
unset($before, $vertical);
// Compositing the layer image mask with the layer image // Compositing the layer image mask with the layer image
$image->compositeImage( $image->compositeImage(
@@ -175,15 +176,15 @@ final class paper extends core
// Drawing the cutting line // Drawing the cutting line
$draw = new imagick_draw(); $draw = new imagick_draw();
$draw->setfillcolor($canvas['background'] ?? '#fff'); $draw->setfillcolor($canvas['background'] ?? '#fff');
$stroke = 1; $stroke = 2;
$draw->setStrokeOpacity($stroke); $draw->setStrokeOpacity(1);
$draw->setStrokeColor('#000'); $draw->setStrokeColor('#000');
$draw->setStrokeWidth(2); $draw->setStrokeWidth($stroke);
$draw->circle( $draw->circle(
$place['x'] + $blank['width'] / 2, $place['x'] + $blank['width'] / 2,
$place['y'] + $blank['height'] / 2, $place['y'] + $blank['height'] / 2,
round($place['x'] + $blank['width'] / 2 - $stroke), round($place['x'] + $blank['width'] / 2 + $stroke),
round($place['y'] + $blank['height']) round($place['y'] + $blank['height'] + $stroke)
); );
$paper->drawimage($draw); $paper->drawimage($draw);

View File

@@ -148,15 +148,20 @@ Object.assign(
if (typeof index === "number") { if (typeof index === "number") {
// Initialized the layer index // Initialized the layer index
// Initializing the layer // Calculating the difference between the canvas and the layer
product[index] ??= {}; const difference = {
width: canvas.offsetWidth - layer.offsetWidth,
height: canvas.offsetHeight - layer.offsetHeight
};
// Writing the layer parameters // Initializing the layer
product[index].x = product[index] = {
parseInt(layer.style.getPropertyValue("left")) || 0; x: parseInt(layer.style.getPropertyValue("left")) || (difference.width > 0 ? difference.width / 2 : 0),
product[index].y = y: parseInt(layer.style.getPropertyValue("top")) || (difference.height > 0 ? difference.height / 2 : 0),
parseInt(layer.style.getPropertyValue("top")) || 0; width: parseInt(layer.offsetWidth),
product[index].scale = parseFloat(layer.style.getPropertyValue("scale") || 1); height: parseInt(layer.offsetHeight),
scale: parseFloat(layer.style.getPropertyValue("scale") || 1)
};
// Initializing the layer type // Initializing the layer type
const type = layer.getAttribute("data-layer-type"); const type = layer.getAttribute("data-layer-type");

View File

@@ -13,6 +13,12 @@ core.modules.connect(["generator", "pechatalka"])
]), ]),
); );
// Activating the keyboard function
instance.keyboard();
// Activating the drag and drop function
instance.dragdrop();
// instence.layers.set('interface', true) // instence.layers.set('interface', true)
// Reinitializing the `layer create` event // Reinitializing the `layer create` event

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

View File

@@ -93,14 +93,31 @@ div#pechatalka {
position: relative; position: relative;
width: var(--diameter-cut, 300px); width: var(--diameter-cut, 300px);
height: var(--diameter-cut, 300px); height: var(--diameter-cut, 300px);
box-sizing: border-box;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
overflow: clip; overflow: clip;
border-radius: 100%; border-radius: 100%;
border: 2px solid var(--background-color-inverted); outline: 2px solid var(--background-color-inverted);
background-color: var(--paper, var(--white, #fff)); background-color: var(--paper, var(--white, #fff));
&:is(.drag) {
&:before {
opacity: 1;
background: radial-gradient(1px,
transparent calc(var(--diameter-display, 77.08%) / 2),
#53decbab);
transition: opacity 0s, background 0s;
}
}
&:not(.drag) {
&:before {
transition: opacity 0.1s ease-out, background 0.1s ease-out;
}
}
&:before { &:before {
z-index: 500; z-index: 500;
position: absolute; position: absolute;
@@ -112,7 +129,6 @@ div#pechatalka {
background: radial-gradient(1px, background: radial-gradient(1px,
transparent calc(var(--diameter-display, 77.08%) / 2), transparent calc(var(--diameter-display, 77.08%) / 2),
#000a); #000a);
transition: opacity 0.1s ease-out;
} }
&:has(div.layer) { &:has(div.layer) {
@@ -153,7 +169,7 @@ div#pechatalka {
/* min-width: 50%; /* min-width: 50%;
max-width: 200%; */ max-width: 200%; */
width: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px)); width: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px));
height: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px)); /* height: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px)); */
cursor: grab; cursor: grab;
display: flex; display: flex;
place-items: center; place-items: center;
@@ -171,28 +187,29 @@ div#pechatalka {
} }
>button { >button {
&:is(:disabled, [disabled="true"], .disabled) {
display: none !important;
pointer-events: none !important;
}
&:is(.delete) { &:is(.delete) {
--offset: 5px; --offset: 5px;
--size: 40px; --size: 40px;
z-index: 1500; z-index: 1500;
position: fixed; position: absolute;
margin-top: var(--offset); top: calc(var(--vertical-difference, 0px) / 2 + var(--offset, 5px));
margin-left: calc((var(--size, 40px) + var(--offset)) * -1); right: calc(var(--image-right, 0px) + var(--offset, 5px));
width: var(--size, 40px); width: var(--size, 40px);
height: var(--size, 40px); height: var(--size, 40px);
display: inline-flex; display: inline-flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
mix-blend-mode: overlay; opacity: 1;
pointer-events: all;
border: unset;
background: unset;
transition: pointer-events 0s, opacity 0.1s ease-in;
}
&:hover { &:is(:disabled, [disabled="true"], .disabled) {
mix-blend-mode: normal; opacity: 0;
} pointer-events: none !important;
transition: pointer-events 0s linear 0.1s, opacity 0.1s ease-out;
} }
} }
} }

View File

@@ -1,5 +1,5 @@
{% block js %} {% block js %}
<script src="https://telegram.org/js/telegram-web-app.js"></script> <!-- <script src="https://telegram.org/js/telegram-web-app.js"></script> -->
<script src="/js/modules/damper.mjs" type="module"></script> <script src="/js/modules/damper.mjs" type="module"></script>
<script src="/js/core.js"></script> <script src="/js/core.js"></script>
<script src="/js/modules/telegram.mjs" type="module"></script> <script src="/js/modules/telegram.mjs" type="module"></script>