mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
init window tabs, init gemtext parser, refactor app sceleton
This commit is contained in:
parent
196b30e8d2
commit
ad04be61cb
19 changed files with 664 additions and 884 deletions
79
config.json
79
config.json
|
|
@ -1,10 +1,8 @@
|
||||||
{
|
{
|
||||||
"homepage":"yoda://welcome",
|
|
||||||
"interface":
|
|
||||||
{
|
|
||||||
"theme":"Default",
|
|
||||||
"window":
|
"window":
|
||||||
{
|
{
|
||||||
|
"title":"Yoda",
|
||||||
|
"theme":"Default",
|
||||||
"header":
|
"header":
|
||||||
{
|
{
|
||||||
"enabled":true,
|
"enabled":true,
|
||||||
|
|
@ -13,21 +11,12 @@
|
||||||
"close":true
|
"close":true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"navigation":
|
|
||||||
{
|
|
||||||
"button":
|
|
||||||
{
|
|
||||||
"home":true,
|
|
||||||
"back":true,
|
|
||||||
"forward":true,
|
|
||||||
"reload":true,
|
|
||||||
"go":true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"width":640,
|
"width":640,
|
||||||
"height":480
|
"height":480,
|
||||||
}
|
"tab":
|
||||||
},
|
{
|
||||||
|
"page":
|
||||||
|
{
|
||||||
"resolver":
|
"resolver":
|
||||||
{
|
{
|
||||||
"enabled":true,
|
"enabled":true,
|
||||||
|
|
@ -53,5 +42,59 @@
|
||||||
"timeout":3600
|
"timeout":3600
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"header":
|
||||||
|
{
|
||||||
|
"margin":8,
|
||||||
|
"button":
|
||||||
|
{
|
||||||
|
"home":
|
||||||
|
{
|
||||||
|
"visible":true,
|
||||||
|
"label":"Home",
|
||||||
|
"url":"yoda://welcome"
|
||||||
|
},
|
||||||
|
"back":
|
||||||
|
{
|
||||||
|
"visible":true,
|
||||||
|
"label":"Back"
|
||||||
|
},
|
||||||
|
"forward":
|
||||||
|
{
|
||||||
|
"visible":true,
|
||||||
|
"label":"Forward"
|
||||||
|
},
|
||||||
|
"go":
|
||||||
|
{
|
||||||
|
"visible":true,
|
||||||
|
"label":"Go"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"address":
|
||||||
|
{
|
||||||
|
"placeholder":"URL or any search term...",
|
||||||
|
"length":
|
||||||
|
{
|
||||||
|
"max":1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body":
|
||||||
|
{
|
||||||
|
"margin":8
|
||||||
|
},
|
||||||
|
"footer":
|
||||||
|
{
|
||||||
|
"margin":8,
|
||||||
|
"status":
|
||||||
|
{
|
||||||
|
"open":
|
||||||
|
{
|
||||||
|
"complete":"{TIME_C} | {RESPONSE_META} | {RESPONSE_LENGTH} bytes | {RESPONSE_SECONDS} seconds"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Abstract;
|
|
||||||
|
|
||||||
abstract class Window
|
|
||||||
{
|
|
||||||
public \GtkWindow $window;
|
|
||||||
public \GtkCssProvider $css;
|
|
||||||
public \GtkStyleContext $style;
|
|
||||||
|
|
||||||
public object $config;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
object $config
|
|
||||||
) {
|
|
||||||
$this->config = $config;
|
|
||||||
|
|
||||||
$this->window = new \GtkWindow();
|
|
||||||
|
|
||||||
$this->window->set_size_request(
|
|
||||||
$this->config->interface->window->width,
|
|
||||||
$this->config->interface->window->height
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($this->config->interface->window->header->enabled)
|
|
||||||
{
|
|
||||||
$header = new \GtkHeaderBar();
|
|
||||||
|
|
||||||
$header->set_show_close_button(
|
|
||||||
$this->config->interface->window->header->button->close
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->window->set_titlebar(
|
|
||||||
$header
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->window->set_title(
|
|
||||||
'Yoda'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->window->connect(
|
|
||||||
'destroy',
|
|
||||||
function()
|
|
||||||
{
|
|
||||||
\Gtk::main_quit();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTheme(
|
|
||||||
string $css
|
|
||||||
): void
|
|
||||||
{
|
|
||||||
$this->css = new \GtkCssProvider();
|
|
||||||
|
|
||||||
$this->css->load_from_data(
|
|
||||||
$css
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->style = new \GtkStyleContext();
|
|
||||||
|
|
||||||
$this->style->add_provider_for_screen(
|
|
||||||
$this->css,
|
|
||||||
600
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,273 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Controller;
|
|
||||||
|
|
||||||
class Browser extends \Yggverse\Yoda\Abstract\Window
|
|
||||||
{
|
|
||||||
public \Yggverse\Yoda\Entity\Box\Tab $tab;
|
|
||||||
|
|
||||||
public \Yggverse\Yoda\Model\Memory $memory;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct(
|
|
||||||
\Yggverse\Yoda\Model\File::getConfig()
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->memory = new \Yggverse\Yoda\Model\Memory();
|
|
||||||
|
|
||||||
$this->tab = new \Yggverse\Yoda\Entity\Box\Tab();
|
|
||||||
|
|
||||||
$this->tab->navigation->address->entry->connect(
|
|
||||||
'activate',
|
|
||||||
function ($entry)
|
|
||||||
{
|
|
||||||
$this->navigate(
|
|
||||||
$entry->get_text()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->go)
|
|
||||||
{
|
|
||||||
$this->tab->navigation->go->button->connect(
|
|
||||||
'released',
|
|
||||||
function ($entry)
|
|
||||||
{
|
|
||||||
$this->navigate(
|
|
||||||
$this->tab->navigation->address->entry->get_text()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->reload)
|
|
||||||
{
|
|
||||||
$this->tab->navigation->reload->button->connect(
|
|
||||||
'released',
|
|
||||||
function ($entry)
|
|
||||||
{
|
|
||||||
$this->navigate(
|
|
||||||
$this->tab->navigation->address->entry->get_text()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->home && $this->config->homepage)
|
|
||||||
{
|
|
||||||
$this->tab->navigation->home->button->connect(
|
|
||||||
'released',
|
|
||||||
function ($entry)
|
|
||||||
{
|
|
||||||
$this->tab->navigation->address->entry->set_text(
|
|
||||||
$this->config->homepage
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->navigate(
|
|
||||||
$this->config->homepage
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->tab->navigation->home->button->set_sensitive(
|
|
||||||
!($this->tab->navigation->address->entry->get_text() == $this->config->homepage)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->navigate(
|
|
||||||
$this->tab->navigation->address->entry->get_text()
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->window->add(
|
|
||||||
$this->tab->box
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->window->show_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function navigate(string $url): void
|
|
||||||
{
|
|
||||||
switch (true)
|
|
||||||
{
|
|
||||||
case str_starts_with($url, 'gemini://'):
|
|
||||||
|
|
||||||
$this->_gemini(
|
|
||||||
$url
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case str_starts_with($url, 'yoda://'):
|
|
||||||
|
|
||||||
$this->_yoda(
|
|
||||||
$url
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
$this->_yoda(
|
|
||||||
'yoda://oops'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function _yoda(string $url): void
|
|
||||||
{
|
|
||||||
if ($data = \Yggverse\Yoda\Model\Page::get(str_replace('yoda://', '', $url)))
|
|
||||||
{
|
|
||||||
$response = new \Yggverse\Gemini\Client\Response(
|
|
||||||
$data
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->tab->content->label->set_text(
|
|
||||||
$data
|
|
||||||
);
|
|
||||||
|
|
||||||
$body = new \Yggverse\Gemini\Gemtext\Body(
|
|
||||||
$data
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($h1 = $body->getH1())
|
|
||||||
{
|
|
||||||
$this->window->set_title(
|
|
||||||
$h1[0]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$data = \Yggverse\Yoda\Model\Page::get('Oops');
|
|
||||||
|
|
||||||
$this->tab->content->label->set_text(
|
|
||||||
$data
|
|
||||||
);
|
|
||||||
|
|
||||||
$body = new \Yggverse\Gemini\Gemtext\Body(
|
|
||||||
$data
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($h1 = $body->getH1())
|
|
||||||
{
|
|
||||||
$this->window->set_title(
|
|
||||||
$h1[0]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->home && $this->config->homepage)
|
|
||||||
{
|
|
||||||
$this->tab->navigation->home->button->set_sensitive(
|
|
||||||
!($url == $this->config->homepage)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function _gemini(string $url): void
|
|
||||||
{
|
|
||||||
$this->tab->tray->label->set_text(
|
|
||||||
sprintf(
|
|
||||||
'Open %s...',
|
|
||||||
urldecode(
|
|
||||||
$url
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$start = microtime(true);
|
|
||||||
|
|
||||||
$host = null;
|
|
||||||
|
|
||||||
if ($this->config->resolver->enabled)
|
|
||||||
{
|
|
||||||
$address = new \Yggverse\Net\Address(
|
|
||||||
$url
|
|
||||||
);
|
|
||||||
|
|
||||||
$name = $address->getHost();
|
|
||||||
|
|
||||||
if (!$host = $this->memory->get($name))
|
|
||||||
{
|
|
||||||
$resolve = new \Yggverse\Net\Resolve(
|
|
||||||
$this->config->resolver->request->record,
|
|
||||||
$this->config->resolver->request->host,
|
|
||||||
$this->config->resolver->request->timeout,
|
|
||||||
$this->config->resolver->result->shuffle
|
|
||||||
);
|
|
||||||
|
|
||||||
$resolved = $resolve->address(
|
|
||||||
$address
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($resolved)
|
|
||||||
{
|
|
||||||
$host = $resolved->getHost();
|
|
||||||
|
|
||||||
$this->memory->set(
|
|
||||||
$name,
|
|
||||||
$host
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$request = new \Yggverse\Gemini\Client\Request(
|
|
||||||
$url,
|
|
||||||
$host
|
|
||||||
);
|
|
||||||
|
|
||||||
$raw = $request->getResponse();
|
|
||||||
|
|
||||||
$end = microtime(true);
|
|
||||||
|
|
||||||
$response = new \Yggverse\Gemini\Client\Response(
|
|
||||||
$raw
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->tab->content->label->set_text(
|
|
||||||
$response->getBody()
|
|
||||||
);
|
|
||||||
|
|
||||||
$body = new \Yggverse\Gemini\Gemtext\Body(
|
|
||||||
$response->getBody()
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($h1 = $body->getH1())
|
|
||||||
{
|
|
||||||
$this->window->set_title(
|
|
||||||
sprintf(
|
|
||||||
'%s - Yoda',
|
|
||||||
empty($h1[0]) ? $address->getHost() : $h1[0]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->tab->tray->label->set_text(
|
|
||||||
sprintf(
|
|
||||||
'%s | %s | %d bytes | %s seconds',
|
|
||||||
date('c'),
|
|
||||||
$response->getMeta() ? $response->getMeta() : $response->getCode(),
|
|
||||||
number_format(
|
|
||||||
mb_strlen(
|
|
||||||
$raw
|
|
||||||
)
|
|
||||||
),
|
|
||||||
round(
|
|
||||||
$end - $start, 2
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->home && $this->config->homepage)
|
|
||||||
{
|
|
||||||
$this->tab->navigation->home->button->set_sensitive(
|
|
||||||
!($url == $this->config->homepage)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Box;
|
|
||||||
|
|
||||||
class Menu
|
|
||||||
{
|
|
||||||
public \GtkBox $box;
|
|
||||||
|
|
||||||
public \Yggverse\Yoda\Entity\Menu\Bar\Main $main;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
string $name = 'boxMenu'
|
|
||||||
) {
|
|
||||||
$this->box = new \GtkBox(
|
|
||||||
\GtkOrientation::VERTICAL
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->box->set_name(
|
|
||||||
$name
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->main = new \Yggverse\Yoda\Entity\Menu\Bar\Main();
|
|
||||||
|
|
||||||
$this->box->add(
|
|
||||||
$this->main->bar
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Box;
|
|
||||||
|
|
||||||
class Navigation
|
|
||||||
{
|
|
||||||
public \GtkBox $box;
|
|
||||||
|
|
||||||
public \Yggverse\Yoda\Entity\Entry\Address $address;
|
|
||||||
|
|
||||||
public \Yggverse\Yoda\Entity\Button\Home $home;
|
|
||||||
public \Yggverse\Yoda\Entity\Button\Back $back;
|
|
||||||
public \Yggverse\Yoda\Entity\Button\Forward $forward;
|
|
||||||
public \Yggverse\Yoda\Entity\Button\Reload $reload;
|
|
||||||
public \Yggverse\Yoda\Entity\Button\Go $go;
|
|
||||||
|
|
||||||
public object $config;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
string $name = 'boxNavigation'
|
|
||||||
) {
|
|
||||||
$this->config = \Yggverse\Yoda\Model\File::getConfig();
|
|
||||||
|
|
||||||
$this->box = new \GtkBox(
|
|
||||||
\GtkOrientation::HORIZONTAL
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->box->set_name(
|
|
||||||
$name
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->home && $this->config->homepage)
|
|
||||||
{
|
|
||||||
$this->home = new \Yggverse\Yoda\Entity\Button\Home();
|
|
||||||
|
|
||||||
$this->box->pack_start(
|
|
||||||
$this->home->button,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
8
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->back || $this->config->interface->window->navigation->button->forward)
|
|
||||||
{
|
|
||||||
$boxBackForward = new \GtkButtonBox(
|
|
||||||
\GtkOrientation::HORIZONTAL
|
|
||||||
);
|
|
||||||
|
|
||||||
$boxBackForward->set_layout(
|
|
||||||
\GtkButtonBoxStyle::EXPAND
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->back)
|
|
||||||
{
|
|
||||||
$this->back = new \Yggverse\Yoda\Entity\Button\Back();
|
|
||||||
|
|
||||||
$boxBackForward->pack_start(
|
|
||||||
$this->back->button,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->forward)
|
|
||||||
{
|
|
||||||
$this->forward = new \Yggverse\Yoda\Entity\Button\Forward();
|
|
||||||
|
|
||||||
$boxBackForward->pack_end(
|
|
||||||
$this->forward->button,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->box->pack_start(
|
|
||||||
$boxBackForward,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
8
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->reload)
|
|
||||||
{
|
|
||||||
$this->reload = new \Yggverse\Yoda\Entity\Button\Reload();
|
|
||||||
|
|
||||||
$this->box->pack_start(
|
|
||||||
$this->reload->button,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
8
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->address = new \Yggverse\Yoda\Entity\Entry\Address(
|
|
||||||
$this->config->homepage
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->box->pack_start(
|
|
||||||
$this->address->entry,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
8
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($this->config->interface->window->navigation->button->go)
|
|
||||||
{
|
|
||||||
$this->go = new \Yggverse\Yoda\Entity\Button\Go();
|
|
||||||
|
|
||||||
$this->box->pack_end(
|
|
||||||
$this->go->button,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
8
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Box;
|
|
||||||
|
|
||||||
class Tab
|
|
||||||
{
|
|
||||||
public \GtkBox $box;
|
|
||||||
|
|
||||||
public \Yggverse\Yoda\Entity\Box\Menu $menu;
|
|
||||||
public \Yggverse\Yoda\Entity\Box\Navigation $navigation;
|
|
||||||
public \Yggverse\Yoda\Entity\Label\Content $content;
|
|
||||||
public \Yggverse\Yoda\Entity\Label\Tray $tray;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
string $name = 'boxTab'
|
|
||||||
) {
|
|
||||||
// Init container
|
|
||||||
$this->box = new \GtkBox(
|
|
||||||
\GtkOrientation::VERTICAL
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->box->set_name(
|
|
||||||
$name
|
|
||||||
);
|
|
||||||
|
|
||||||
// Init dependencies
|
|
||||||
$this->menu = new \Yggverse\Yoda\Entity\Box\Menu();
|
|
||||||
|
|
||||||
$this->box->pack_start(
|
|
||||||
$this->menu->box,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->navigation = new \Yggverse\Yoda\Entity\Box\Navigation();
|
|
||||||
|
|
||||||
$this->box->pack_start(
|
|
||||||
$this->navigation->box,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
8
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->content = new \Yggverse\Yoda\Entity\Label\Content();
|
|
||||||
|
|
||||||
$scroll = new \GtkScrolledWindow();
|
|
||||||
|
|
||||||
$scroll->add(
|
|
||||||
$this->content->label
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->box->pack_start(
|
|
||||||
$scroll,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->tray = new \Yggverse\Yoda\Entity\Label\Tray();
|
|
||||||
|
|
||||||
$this->box->pack_start(
|
|
||||||
$this->tray->label,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Button;
|
|
||||||
|
|
||||||
class Back
|
|
||||||
{
|
|
||||||
public \GtkButton $button;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
?string $label = 'Back'
|
|
||||||
) {
|
|
||||||
$this->button = \GtkButton::new_with_label(
|
|
||||||
$label
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Button;
|
|
||||||
|
|
||||||
class Forward
|
|
||||||
{
|
|
||||||
public \GtkButton $button;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
?string $label = 'Forward'
|
|
||||||
) {
|
|
||||||
$this->button = \GtkButton::new_with_label(
|
|
||||||
$label
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Button;
|
|
||||||
|
|
||||||
class Go
|
|
||||||
{
|
|
||||||
public \GtkButton $button;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
?string $label = 'Go'
|
|
||||||
) {
|
|
||||||
$this->button = \GtkButton::new_with_label(
|
|
||||||
$label
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Button;
|
|
||||||
|
|
||||||
class Home
|
|
||||||
{
|
|
||||||
public \GtkButton $button;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
?string $label = 'Home'
|
|
||||||
) {
|
|
||||||
$this->button = \GtkButton::new_with_label(
|
|
||||||
$label
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Button;
|
|
||||||
|
|
||||||
class Reload
|
|
||||||
{
|
|
||||||
public \GtkButton $button;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
?string $label = 'Reload'
|
|
||||||
) {
|
|
||||||
$this->button = \GtkButton::new_with_label(
|
|
||||||
$label
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Entry;
|
|
||||||
|
|
||||||
class Address
|
|
||||||
{
|
|
||||||
public \GtkEntry $entry;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
?string $text = null,
|
|
||||||
?string $placeholder = 'URL or any search term...'
|
|
||||||
) {
|
|
||||||
$this->entry = new \GtkEntry();
|
|
||||||
|
|
||||||
$this->entry->set_text(
|
|
||||||
$text
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->entry->set_placeholder_text(
|
|
||||||
$placeholder
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->entry->set_max_length(
|
|
||||||
1024
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Label;
|
|
||||||
|
|
||||||
class Content
|
|
||||||
{
|
|
||||||
public \GtkLabel $label;
|
|
||||||
|
|
||||||
public function __construct(string $value = '')
|
|
||||||
{
|
|
||||||
$this->label = new \GtkLabel(
|
|
||||||
$value
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_use_markup(
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_selectable(
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_line_wrap(
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_xalign(
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_yalign(
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Label;
|
|
||||||
|
|
||||||
class Tray
|
|
||||||
{
|
|
||||||
public \GtkLabel $label;
|
|
||||||
|
|
||||||
public function __construct(string $value = '')
|
|
||||||
{
|
|
||||||
$this->label = new \GtkLabel(
|
|
||||||
$value
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_use_markup(
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_selectable(
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_xalign(
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->label->set_yalign(
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Menu\Bar;
|
|
||||||
|
|
||||||
class Main
|
|
||||||
{
|
|
||||||
public \GtkMenuBar $bar;
|
|
||||||
|
|
||||||
public \Yggverse\Yoda\Entity\Menu\Item\Yoda $yoda;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->bar = new \GtkMenuBar();
|
|
||||||
|
|
||||||
$this->yoda = new \Yggverse\Yoda\Entity\Menu\Item\Yoda();
|
|
||||||
|
|
||||||
$this->bar->append(
|
|
||||||
$this->yoda->item
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Menu\Item;
|
|
||||||
|
|
||||||
class Quit
|
|
||||||
{
|
|
||||||
public \GtkMenuItem $item;
|
|
||||||
|
|
||||||
public function __construct(string $label = 'Quit')
|
|
||||||
{
|
|
||||||
$this->item = \GtkMenuItem::new_with_label(
|
|
||||||
$label
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->activate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function activate(): void
|
|
||||||
{
|
|
||||||
$this->item->connect(
|
|
||||||
'activate',
|
|
||||||
function ()
|
|
||||||
{
|
|
||||||
\Gtk::main_quit();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Yoda\Entity\Menu\Item;
|
|
||||||
|
|
||||||
class Yoda
|
|
||||||
{
|
|
||||||
public \GtkMenuItem $item;
|
|
||||||
|
|
||||||
public function __construct(string $label = 'Yoda')
|
|
||||||
{
|
|
||||||
$this->item = \GtkMenuItem::new_with_label(
|
|
||||||
$label
|
|
||||||
);
|
|
||||||
|
|
||||||
$children = new \GtkMenu();
|
|
||||||
|
|
||||||
$quit = new \Yggverse\Yoda\Entity\Menu\Item\Quit();
|
|
||||||
|
|
||||||
$children->append(
|
|
||||||
$quit->item
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->item->set_submenu(
|
|
||||||
$children
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
525
src/Tab/Page.php
Normal file
525
src/Tab/Page.php
Normal file
|
|
@ -0,0 +1,525 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Yggverse\Yoda\Tab;
|
||||||
|
|
||||||
|
class Page
|
||||||
|
{
|
||||||
|
public \Yggverse\Yoda\Model\Memory $memory;
|
||||||
|
|
||||||
|
public \GtkBox $box,
|
||||||
|
$header,
|
||||||
|
$body,
|
||||||
|
$footer;
|
||||||
|
|
||||||
|
public \GtkButton $home,
|
||||||
|
$back,
|
||||||
|
$forward,
|
||||||
|
$go;
|
||||||
|
|
||||||
|
public \GtkEntry $address;
|
||||||
|
|
||||||
|
public \GtkLabel $content,
|
||||||
|
$status;
|
||||||
|
|
||||||
|
public \GtkScrolledWindow $container;
|
||||||
|
|
||||||
|
public object $config;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
?string $url = null
|
||||||
|
) {
|
||||||
|
// Init config
|
||||||
|
$this->config = \Yggverse\Yoda\Model\File::getConfig()->window->tab->page;
|
||||||
|
|
||||||
|
// Init memory
|
||||||
|
$this->memory = new \Yggverse\Yoda\Model\Memory();
|
||||||
|
|
||||||
|
// Compose header
|
||||||
|
$this->header = new \GtkBox(
|
||||||
|
\GtkOrientation::HORIZONTAL
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->header->set_margin_top(
|
||||||
|
$this->config->header->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->header->set_margin_bottom(
|
||||||
|
$this->config->header->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->header->set_margin_start(
|
||||||
|
$this->config->header->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->header->set_margin_end(
|
||||||
|
$this->config->header->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->header->set_spacing(
|
||||||
|
$this->config->header->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
// Home button
|
||||||
|
$this->home = \GtkButton::new_with_label(
|
||||||
|
$this->config->header->button->home->label
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->home->set_sensitive(
|
||||||
|
!($url == $this->config->header->button->home->url)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->home->connect(
|
||||||
|
'released',
|
||||||
|
function ($entry)
|
||||||
|
{
|
||||||
|
$this->open(
|
||||||
|
$this->config->header->button->home->url
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->config->header->button->home->visible)
|
||||||
|
{
|
||||||
|
$this->header->add(
|
||||||
|
$this->home
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back button
|
||||||
|
$this->back = \GtkButton::new_with_label(
|
||||||
|
$this->config->header->button->back->label
|
||||||
|
);
|
||||||
|
|
||||||
|
// Forward button
|
||||||
|
$this->forward = \GtkButton::new_with_label(
|
||||||
|
$this->config->header->button->forward->label
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Group buttons
|
||||||
|
if ($this->config->header->button->back->visible || $this->config->header->button->forward->visible)
|
||||||
|
{
|
||||||
|
$buttonGroup = new \GtkButtonBox(
|
||||||
|
\GtkOrientation::HORIZONTAL
|
||||||
|
);
|
||||||
|
|
||||||
|
$buttonGroup->set_layout(
|
||||||
|
\GtkButtonBoxStyle::EXPAND
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->config->header->button->back->visible)
|
||||||
|
{
|
||||||
|
$buttonGroup->add(
|
||||||
|
$this->back
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->config->header->button->forward->visible)
|
||||||
|
{
|
||||||
|
$buttonGroup->add(
|
||||||
|
$this->forward
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->header->add(
|
||||||
|
$buttonGroup
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address field
|
||||||
|
$this->address = new \GtkEntry();
|
||||||
|
|
||||||
|
if ($url)
|
||||||
|
{
|
||||||
|
$this->address->set_text(
|
||||||
|
$url
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->address->set_placeholder_text(
|
||||||
|
$this->config->header->address->placeholder
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->address->set_max_length(
|
||||||
|
$this->config->header->address->length->max
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->address->connect(
|
||||||
|
'activate',
|
||||||
|
function ($entry)
|
||||||
|
{
|
||||||
|
$this->open(
|
||||||
|
$entry->get_text()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->header->pack_start(
|
||||||
|
$this->address,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Go button
|
||||||
|
$this->go = \GtkButton::new_with_label(
|
||||||
|
$this->config->header->button->go->label
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->go->connect(
|
||||||
|
'released',
|
||||||
|
function ($entry)
|
||||||
|
{
|
||||||
|
$this->open(
|
||||||
|
$this->address->get_text()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->config->header->button->go->visible)
|
||||||
|
{
|
||||||
|
$this->header->add(
|
||||||
|
$this->go
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compose body
|
||||||
|
$this->content = new \GtkLabel();
|
||||||
|
|
||||||
|
$this->content->set_use_markup(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->content->set_selectable(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->content->set_line_wrap(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->content->set_xalign(
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->content->set_yalign(
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Init scrolled container
|
||||||
|
$this->container = new \GtkScrolledWindow();
|
||||||
|
|
||||||
|
$this->container->add(
|
||||||
|
$this->content
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->body = new \GtkBox(
|
||||||
|
\GtkOrientation::VERTICAL
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->body->set_margin_start(
|
||||||
|
$this->config->body->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->body->pack_start(
|
||||||
|
$this->container,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Compose footer
|
||||||
|
$this->footer = new \GtkBox(
|
||||||
|
\GtkOrientation::HORIZONTAL
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->footer->set_margin_top(
|
||||||
|
$this->config->footer->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->footer->set_margin_bottom(
|
||||||
|
$this->config->footer->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->footer->set_margin_start(
|
||||||
|
$this->config->footer->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->footer->set_margin_end(
|
||||||
|
$this->config->footer->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->footer->set_spacing(
|
||||||
|
$this->config->footer->margin
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->status = new \GtkLabel();
|
||||||
|
|
||||||
|
$this->footer->add(
|
||||||
|
$this->status
|
||||||
|
);
|
||||||
|
|
||||||
|
// Compose page
|
||||||
|
$this->box = new \GtkBox(
|
||||||
|
\GtkOrientation::VERTICAL
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->box->add(
|
||||||
|
$this->header
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->box->pack_start(
|
||||||
|
$this->body,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->box->add(
|
||||||
|
$this->footer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function open(
|
||||||
|
string $url
|
||||||
|
): void
|
||||||
|
{
|
||||||
|
// Update address field by requested
|
||||||
|
$this->address->set_text(
|
||||||
|
$url
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update home button sensitivity on match requested
|
||||||
|
$this->home->set_sensitive(
|
||||||
|
!($url == $this->config->header->button->home->url)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Open current address
|
||||||
|
switch (true)
|
||||||
|
{
|
||||||
|
case str_starts_with($url, 'gemini://'):
|
||||||
|
|
||||||
|
$this->_gemini(
|
||||||
|
$url
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
$this->_yoda(
|
||||||
|
$url
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _gemini(string $url): void
|
||||||
|
{
|
||||||
|
// Track response time
|
||||||
|
$start = microtime(true);
|
||||||
|
|
||||||
|
// Init custom resolver
|
||||||
|
$host = null;
|
||||||
|
|
||||||
|
if ($this->config->resolver->enabled)
|
||||||
|
{
|
||||||
|
$address = new \Yggverse\Net\Address(
|
||||||
|
$url
|
||||||
|
);
|
||||||
|
|
||||||
|
$name = $address->getHost();
|
||||||
|
|
||||||
|
if (!$host = $this->memory->get($name))
|
||||||
|
{
|
||||||
|
$resolve = new \Yggverse\Net\Resolve(
|
||||||
|
$this->config->resolver->request->record,
|
||||||
|
$this->config->resolver->request->host,
|
||||||
|
$this->config->resolver->request->timeout,
|
||||||
|
$this->config->resolver->result->shuffle
|
||||||
|
);
|
||||||
|
|
||||||
|
$resolved = $resolve->address(
|
||||||
|
$address
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($resolved)
|
||||||
|
{
|
||||||
|
$host = $resolved->getHost();
|
||||||
|
|
||||||
|
$this->memory->set(
|
||||||
|
$name,
|
||||||
|
$host
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = new \Yggverse\Gemini\Client\Request(
|
||||||
|
$url,
|
||||||
|
$host
|
||||||
|
);
|
||||||
|
|
||||||
|
$raw = $request->getResponse();
|
||||||
|
|
||||||
|
$end = microtime(true);
|
||||||
|
|
||||||
|
$response = new \Yggverse\Gemini\Client\Response(
|
||||||
|
$raw
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->content->set_markup(
|
||||||
|
$this->_gemtext(
|
||||||
|
$response->getBody()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* @TODO
|
||||||
|
$body = new \Yggverse\Gemini\Gemtext\Body(
|
||||||
|
$response->getBody()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($h1 = $body->getH1())
|
||||||
|
{
|
||||||
|
$this->window->set_title(
|
||||||
|
sprintf(
|
||||||
|
'%s - Yoda',
|
||||||
|
empty($h1[0]) ? $address->getHost() : $h1[0]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->status->set_text(
|
||||||
|
str_replace( // Custom macros mask from config.json
|
||||||
|
[
|
||||||
|
'{NAVIGATION_ADDRESS}',
|
||||||
|
'{TIME_C}',
|
||||||
|
'{RESPONSE_META}',
|
||||||
|
'{RESPONSE_LENGTH}',
|
||||||
|
'{RESPONSE_SECONDS}'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
urlencode(
|
||||||
|
$url
|
||||||
|
),
|
||||||
|
date(
|
||||||
|
'c'
|
||||||
|
),
|
||||||
|
$response->getMeta() ? $response->getMeta() : $response->getCode(),
|
||||||
|
number_format(
|
||||||
|
mb_strlen(
|
||||||
|
$raw
|
||||||
|
)
|
||||||
|
),
|
||||||
|
round(
|
||||||
|
$end - $start, 2
|
||||||
|
)
|
||||||
|
],
|
||||||
|
$this->config->footer->status->open->complete
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _yoda(
|
||||||
|
string $url
|
||||||
|
): void
|
||||||
|
{
|
||||||
|
// Load local page
|
||||||
|
if (!$data = \Yggverse\Yoda\Model\Page::get(str_replace('yoda://', '', $url)))
|
||||||
|
{
|
||||||
|
$data = \Yggverse\Yoda\Model\Page::get('Oops');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->content->set_markup(
|
||||||
|
$this->_gemtext(
|
||||||
|
$data
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Parse gemtext
|
||||||
|
/* @TODO
|
||||||
|
$body = new \Yggverse\Gemini\Gemtext\Body(
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($h1 = $body->getH1())
|
||||||
|
{
|
||||||
|
$this->window->set_title(
|
||||||
|
$h1[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _gemtext(
|
||||||
|
string $gemtext
|
||||||
|
): string
|
||||||
|
{
|
||||||
|
// Format body
|
||||||
|
$body = new \Yggverse\Gemini\Gemtext\Body(
|
||||||
|
$gemtext
|
||||||
|
);
|
||||||
|
|
||||||
|
$lines = $body->getLines();
|
||||||
|
|
||||||
|
$escaped = [];
|
||||||
|
|
||||||
|
/// Format H1
|
||||||
|
foreach ($body->getH1() as $index => $h1)
|
||||||
|
{
|
||||||
|
$lines[$index] = sprintf(
|
||||||
|
'<span size="xx-large">%s</span>',
|
||||||
|
htmlentities(
|
||||||
|
$h1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$escaped[] = $index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format H2
|
||||||
|
foreach ($body->getH2() as $index => $h2)
|
||||||
|
{
|
||||||
|
$lines[$index] = sprintf(
|
||||||
|
'<span size="x-large">%s</span>',
|
||||||
|
htmlentities(
|
||||||
|
$h2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$escaped[] = $index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format H3
|
||||||
|
foreach ($body->getH3() as $index => $h3)
|
||||||
|
{
|
||||||
|
$lines[$index] = sprintf(
|
||||||
|
'<span size="large">%s</span>',
|
||||||
|
htmlentities(
|
||||||
|
$h3
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$escaped[] = $index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Escape entities
|
||||||
|
foreach ($lines as $index => $line)
|
||||||
|
{
|
||||||
|
if (!in_array($index, $escaped))
|
||||||
|
{
|
||||||
|
$lines[$index] = htmlentities(
|
||||||
|
$line
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @TODO links, code, escape entities
|
||||||
|
|
||||||
|
return implode(
|
||||||
|
PHP_EOL,
|
||||||
|
$lines
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/Yoda.php
52
src/Yoda.php
|
|
@ -9,6 +9,56 @@ require_once __DIR__ .
|
||||||
// Init app
|
// Init app
|
||||||
\Gtk::init();
|
\Gtk::init();
|
||||||
|
|
||||||
new \Yggverse\Yoda\Controller\Browser();
|
$config = \Yggverse\Yoda\Model\File::getConfig(); // @TODO
|
||||||
|
|
||||||
|
$window = new \GtkWindow();
|
||||||
|
|
||||||
|
$window->set_size_request(
|
||||||
|
$config->window->width,
|
||||||
|
$config->window->height
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($config->window->header->enabled)
|
||||||
|
{
|
||||||
|
$header = new \GtkHeaderBar();
|
||||||
|
|
||||||
|
$header->set_title(
|
||||||
|
$config->window->title
|
||||||
|
);
|
||||||
|
|
||||||
|
$header->set_show_close_button(
|
||||||
|
$config->window->header->button->close
|
||||||
|
);
|
||||||
|
|
||||||
|
$window->set_titlebar(
|
||||||
|
$header
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$window->connect(
|
||||||
|
'destroy',
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
\Gtk::main_quit();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$page = new \Yggverse\Yoda\Tab\Page();
|
||||||
|
|
||||||
|
$page->open(
|
||||||
|
'yoda://welcome'
|
||||||
|
);
|
||||||
|
|
||||||
|
$tab = new \GtkNotebook();
|
||||||
|
|
||||||
|
$tab->add(
|
||||||
|
$page->box
|
||||||
|
);
|
||||||
|
|
||||||
|
$window->add(
|
||||||
|
$tab
|
||||||
|
);
|
||||||
|
|
||||||
|
$window->show_all();
|
||||||
|
|
||||||
\Gtk::main();
|
\Gtk::main();
|
||||||
Loading…
Add table
Add a link
Reference in a new issue