Browse Source

init window tabs, init gemtext parser, refactor app sceleton

main
yggverse 3 months ago
parent
commit
ad04be61cb
  1. 133
      config.json
  2. 70
      src/Abstract/Window.php
  3. 273
      src/Controller/Browser.php
  4. 30
      src/Entity/Box/Menu.php
  5. 123
      src/Entity/Box/Navigation.php
  6. 71
      src/Entity/Box/Tab.php
  7. 18
      src/Entity/Button/Back.php
  8. 18
      src/Entity/Button/Forward.php
  9. 18
      src/Entity/Button/Go.php
  10. 18
      src/Entity/Button/Home.php
  11. 18
      src/Entity/Button/Reload.php
  12. 29
      src/Entity/Entry/Address.php
  13. 37
      src/Entity/Label/Content.php
  14. 33
      src/Entity/Label/Tray.php
  15. 23
      src/Entity/Menu/Bar/Main.php
  16. 30
      src/Entity/Menu/Item/Quit.php
  17. 29
      src/Entity/Menu/Item/Yoda.php
  18. 525
      src/Tab/Page.php
  19. 52
      src/Yoda.php

133
config.json

@ -1,56 +1,99 @@ @@ -1,56 +1,99 @@
{
"homepage":"yoda://welcome",
"interface":
"window":
{
"title":"Yoda",
"theme":"Default",
"window":
"header":
{
"header":
"enabled":true,
"button":
{
"enabled":true,
"button":
{
"close":true
}
},
"navigation":
{
"button":
{
"home":true,
"back":true,
"forward":true,
"reload":true,
"go":true
}
},
"width":640,
"height":480
}
},
"resolver":
{
"enabled":true,
"request":
{
"timeout":1,
"host":
[
"1.1.1.1",
"8.8.8.8"
],
"record":
[
"A",
"AAAA"
]
"close":true
}
},
"result":
"width":640,
"height":480,
"tab":
{
"shuffle":false,
"cache":
"page":
{
"timeout":3600
"resolver":
{
"enabled":true,
"request":
{
"timeout":1,
"host":
[
"1.1.1.1",
"8.8.8.8"
],
"record":
[
"A",
"AAAA"
]
},
"result":
{
"shuffle":false,
"cache":
{
"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"
}
}
}
}
}
}

70
src/Abstract/Window.php

@ -1,70 +0,0 @@ @@ -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
);
}
}

273
src/Controller/Browser.php

@ -1,273 +0,0 @@ @@ -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)
);
}
}
}

30
src/Entity/Box/Menu.php

@ -1,30 +0,0 @@ @@ -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
);
}
}

123
src/Entity/Box/Navigation.php

@ -1,123 +0,0 @@ @@ -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
);
}
}
}

71
src/Entity/Box/Tab.php

@ -1,71 +0,0 @@ @@ -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
);
}
}

18
src/Entity/Button/Back.php

@ -1,18 +0,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
);
}
}

18
src/Entity/Button/Forward.php

@ -1,18 +0,0 @@ @@ -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
);
}
}

18
src/Entity/Button/Go.php

@ -1,18 +0,0 @@ @@ -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
);
}
}

18
src/Entity/Button/Home.php

@ -1,18 +0,0 @@ @@ -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
);
}
}

18
src/Entity/Button/Reload.php

@ -1,18 +0,0 @@ @@ -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
);
}
}

29
src/Entity/Entry/Address.php

@ -1,29 +0,0 @@ @@ -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
);
}
}

37
src/Entity/Label/Content.php

@ -1,37 +0,0 @@ @@ -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
);
}
}

33
src/Entity/Label/Tray.php

@ -1,33 +0,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
);
}
}

23
src/Entity/Menu/Bar/Main.php

@ -1,23 +0,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
);
}
}

30
src/Entity/Menu/Item/Quit.php

@ -1,30 +0,0 @@ @@ -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();
}
);
}
}

29
src/Entity/Menu/Item/Yoda.php

@ -1,29 +0,0 @@ @@ -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

@ -0,0 +1,525 @@ @@ -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

@ -9,6 +9,56 @@ require_once __DIR__ . @@ -9,6 +9,56 @@ require_once __DIR__ .
// Init app
\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();
Loading…
Cancel
Save