diff --git a/config.json b/config.json
index 4ccf3826..514ec100 100644
--- a/config.json
+++ b/config.json
@@ -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"
+ }
+ }
+ }
}
}
}
diff --git a/src/Abstract/Window.php b/src/Abstract/Window.php
deleted file mode 100644
index e6dff812..00000000
--- a/src/Abstract/Window.php
+++ /dev/null
@@ -1,70 +0,0 @@
-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
- );
- }
-}
\ No newline at end of file
diff --git a/src/Controller/Browser.php b/src/Controller/Browser.php
deleted file mode 100644
index 28f2641c..00000000
--- a/src/Controller/Browser.php
+++ /dev/null
@@ -1,273 +0,0 @@
-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)
- );
- }
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Box/Menu.php b/src/Entity/Box/Menu.php
deleted file mode 100644
index 66cbf9b3..00000000
--- a/src/Entity/Box/Menu.php
+++ /dev/null
@@ -1,30 +0,0 @@
-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
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Box/Navigation.php b/src/Entity/Box/Navigation.php
deleted file mode 100644
index fcf6e948..00000000
--- a/src/Entity/Box/Navigation.php
+++ /dev/null
@@ -1,123 +0,0 @@
-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
- );
- }
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Box/Tab.php b/src/Entity/Box/Tab.php
deleted file mode 100644
index e9e7e57e..00000000
--- a/src/Entity/Box/Tab.php
+++ /dev/null
@@ -1,71 +0,0 @@
-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
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Button/Back.php b/src/Entity/Button/Back.php
deleted file mode 100644
index e8b961f8..00000000
--- a/src/Entity/Button/Back.php
+++ /dev/null
@@ -1,18 +0,0 @@
-button = \GtkButton::new_with_label(
- $label
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Button/Forward.php b/src/Entity/Button/Forward.php
deleted file mode 100644
index 47416fd0..00000000
--- a/src/Entity/Button/Forward.php
+++ /dev/null
@@ -1,18 +0,0 @@
-button = \GtkButton::new_with_label(
- $label
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Button/Go.php b/src/Entity/Button/Go.php
deleted file mode 100644
index da09c427..00000000
--- a/src/Entity/Button/Go.php
+++ /dev/null
@@ -1,18 +0,0 @@
-button = \GtkButton::new_with_label(
- $label
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Button/Home.php b/src/Entity/Button/Home.php
deleted file mode 100644
index 1c94f1f9..00000000
--- a/src/Entity/Button/Home.php
+++ /dev/null
@@ -1,18 +0,0 @@
-button = \GtkButton::new_with_label(
- $label
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Button/Reload.php b/src/Entity/Button/Reload.php
deleted file mode 100644
index 37b74b04..00000000
--- a/src/Entity/Button/Reload.php
+++ /dev/null
@@ -1,18 +0,0 @@
-button = \GtkButton::new_with_label(
- $label
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Entry/Address.php b/src/Entity/Entry/Address.php
deleted file mode 100644
index 7d037643..00000000
--- a/src/Entity/Entry/Address.php
+++ /dev/null
@@ -1,29 +0,0 @@
-entry = new \GtkEntry();
-
- $this->entry->set_text(
- $text
- );
-
- $this->entry->set_placeholder_text(
- $placeholder
- );
-
- $this->entry->set_max_length(
- 1024
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Label/Content.php b/src/Entity/Label/Content.php
deleted file mode 100644
index e73eafb8..00000000
--- a/src/Entity/Label/Content.php
+++ /dev/null
@@ -1,37 +0,0 @@
-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
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Label/Tray.php b/src/Entity/Label/Tray.php
deleted file mode 100644
index 824a8251..00000000
--- a/src/Entity/Label/Tray.php
+++ /dev/null
@@ -1,33 +0,0 @@
-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
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Menu/Bar/Main.php b/src/Entity/Menu/Bar/Main.php
deleted file mode 100644
index c4c56751..00000000
--- a/src/Entity/Menu/Bar/Main.php
+++ /dev/null
@@ -1,23 +0,0 @@
-bar = new \GtkMenuBar();
-
- $this->yoda = new \Yggverse\Yoda\Entity\Menu\Item\Yoda();
-
- $this->bar->append(
- $this->yoda->item
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Menu/Item/Quit.php b/src/Entity/Menu/Item/Quit.php
deleted file mode 100644
index 58f25e38..00000000
--- a/src/Entity/Menu/Item/Quit.php
+++ /dev/null
@@ -1,30 +0,0 @@
-item = \GtkMenuItem::new_with_label(
- $label
- );
-
- $this->activate();
- }
-
- public function activate(): void
- {
- $this->item->connect(
- 'activate',
- function ()
- {
- \Gtk::main_quit();
- }
- );
- }
-}
\ No newline at end of file
diff --git a/src/Entity/Menu/Item/Yoda.php b/src/Entity/Menu/Item/Yoda.php
deleted file mode 100644
index f51baaae..00000000
--- a/src/Entity/Menu/Item/Yoda.php
+++ /dev/null
@@ -1,29 +0,0 @@
-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
- );
- }
-}
\ No newline at end of file
diff --git a/src/Tab/Page.php b/src/Tab/Page.php
new file mode 100644
index 00000000..e799b53f
--- /dev/null
+++ b/src/Tab/Page.php
@@ -0,0 +1,525 @@
+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(
+ '%s',
+ htmlentities(
+ $h1
+ )
+ );
+
+ $escaped[] = $index;
+ }
+
+ /// Format H2
+ foreach ($body->getH2() as $index => $h2)
+ {
+ $lines[$index] = sprintf(
+ '%s',
+ htmlentities(
+ $h2
+ )
+ );
+
+ $escaped[] = $index;
+ }
+
+ /// Format H3
+ foreach ($body->getH3() as $index => $h3)
+ {
+ $lines[$index] = sprintf(
+ '%s',
+ 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
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/Yoda.php b/src/Yoda.php
index 12d1c134..1c24ded0 100644
--- a/src/Yoda.php
+++ b/src/Yoda.php
@@ -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();
\ No newline at end of file