mirror of https://github.com/YGGverse/Yoda.git
yggverse
8 months ago
16 changed files with 541 additions and 0 deletions
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
/vendor/ |
||||
/composer.lock |
||||
/db.sqlite |
||||
/config.json |
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
{ |
||||
"name": "yggverse/yoda", |
||||
"description": "PHP-GTK Client for Gemini Protocol", |
||||
"keywords": [ "php-gtk", "gtk", "gtk3", "gemini", "gemini-protocol", "client", "browser", "altweb" ], |
||||
"homepage": "https://github.com/YGGverse/Yoda", |
||||
"type": "project", |
||||
"require": { |
||||
"yggverse/gemini": "^0.7.0", |
||||
"yggverse/net": "^1.7" |
||||
}, |
||||
"license": "MIT", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Yggverse\\Yoda\\": "src/" |
||||
} |
||||
}, |
||||
"authors": [ |
||||
{ |
||||
"name": "YGGverse" |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,145 @@
@@ -0,0 +1,145 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\Box; |
||||
|
||||
class Main |
||||
{ |
||||
public \GtkBox $box; |
||||
|
||||
public \Yggverse\Yoda\Box\Menu $menu; |
||||
public \Yggverse\Yoda\Box\Navigation $navigation; |
||||
public \Yggverse\Yoda\Label\Content $content; |
||||
public \Yggverse\Yoda\Label\Tray $tray; |
||||
|
||||
public function __construct( |
||||
string $name = 'boxMain' |
||||
) { |
||||
$this->box = new \GtkBox( |
||||
\GtkOrientation::VERTICAL |
||||
); |
||||
|
||||
$this->box->set_name( |
||||
$name |
||||
); |
||||
|
||||
// Init dependencies |
||||
$this->menu = new \Yggverse\Yoda\Box\Menu(); |
||||
|
||||
$this->box->pack_start( |
||||
$this->menu->box, |
||||
false, |
||||
true, |
||||
0 |
||||
); |
||||
|
||||
$this->navigation = new \Yggverse\Yoda\Box\Navigation(); |
||||
|
||||
$this->box->pack_start( |
||||
$this->navigation->box, |
||||
false, |
||||
true, |
||||
0 |
||||
); |
||||
|
||||
$this->content = new \Yggverse\Yoda\Label\Content(); |
||||
|
||||
$scroll = new \GtkScrolledWindow(); |
||||
|
||||
$scroll->add( |
||||
$this->content->label |
||||
); |
||||
|
||||
$this->box->pack_start( |
||||
$scroll, |
||||
true, |
||||
true, |
||||
10 |
||||
); |
||||
|
||||
$this->tray = new \Yggverse\Yoda\Label\Tray(); |
||||
|
||||
$this->box->pack_start( |
||||
$this->tray->label, |
||||
false, |
||||
true, |
||||
0 |
||||
); |
||||
|
||||
$this->navigation->address->entry->connect( |
||||
'activate', |
||||
function ($entry) |
||||
{ |
||||
global $config; |
||||
|
||||
$host = null; |
||||
|
||||
if ($config->resolver->enabled) |
||||
{ |
||||
$resolve = new \Yggverse\Net\Resolve( |
||||
$config->resolver->request->record, |
||||
$config->resolver->request->host, |
||||
$config->resolver->request->timeout, |
||||
$config->resolver->result->shuffle |
||||
); |
||||
|
||||
$address = new \Yggverse\Net\Address( |
||||
$entry->get_text() |
||||
); |
||||
|
||||
$resolved = $resolve->address( |
||||
$address |
||||
); |
||||
|
||||
if ($resolved) |
||||
{ |
||||
$host = $resolved->getHost(); // @TODO memory cache |
||||
} |
||||
} |
||||
|
||||
$request = new \Yggverse\Gemini\Client\Request( |
||||
$entry->get_text(), |
||||
$host |
||||
); |
||||
|
||||
$this->tray->label->set_text( |
||||
sprintf( |
||||
'Open %s...', |
||||
$entry->get_text() |
||||
) |
||||
); |
||||
|
||||
$start = microtime(true); |
||||
|
||||
$raw = $request->getResponse(); |
||||
|
||||
$end = microtime(true); |
||||
|
||||
$response = new \Yggverse\Gemini\Client\Response( |
||||
$raw |
||||
); |
||||
|
||||
$this->content->label->set_markup( |
||||
$response->getBody() |
||||
); |
||||
|
||||
$this->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 |
||||
) |
||||
) |
||||
); |
||||
} |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\Box; |
||||
|
||||
class Menu |
||||
{ |
||||
public \GtkBox $box; |
||||
|
||||
public \Yggverse\Yoda\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\Menu\Bar\Main(); |
||||
|
||||
$this->box->add( |
||||
$this->main->bar |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\Box; |
||||
|
||||
class Navigation |
||||
{ |
||||
public \GtkBox $box; |
||||
|
||||
public \Yggverse\Yoda\Entry\Address $address; |
||||
|
||||
public function __construct( |
||||
string $name = 'boxNavigation' |
||||
) { |
||||
global $config; |
||||
|
||||
$this->box = new \GtkBox( |
||||
\GtkOrientation::VERTICAL |
||||
); |
||||
|
||||
$this->box->set_name( |
||||
$name |
||||
); |
||||
|
||||
$this->address = new \Yggverse\Yoda\Entry\Address( |
||||
$config->homepage |
||||
); |
||||
|
||||
$this->box->add( |
||||
$this->address->entry |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\Entry; |
||||
|
||||
class Address |
||||
{ |
||||
public \GtkEntry $entry; |
||||
|
||||
public function __construct( |
||||
?string $value = null |
||||
) { |
||||
$this->entry = new \GtkEntry(); |
||||
|
||||
$this->entry->set_text( |
||||
$value |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\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_xalign( |
||||
0 |
||||
); |
||||
|
||||
$this->label->set_yalign( |
||||
0 |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\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 |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\Menu\Bar; |
||||
|
||||
class Main |
||||
{ |
||||
public \GtkMenuBar $bar; |
||||
|
||||
public \Yggverse\Yoda\Menu\Item\Yoda $yoda; |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->bar = new \GtkMenuBar(); |
||||
|
||||
$this->yoda = new \Yggverse\Yoda\Menu\Item\Yoda(); |
||||
|
||||
$this->bar->append( |
||||
$this->yoda->item |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\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(); |
||||
} |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\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\Menu\Item\Quit(); |
||||
|
||||
$children->append( |
||||
$quit->item |
||||
); |
||||
|
||||
$this->item->set_submenu( |
||||
$children |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\Model; |
||||
|
||||
class Database |
||||
{ |
||||
public function __construct() |
||||
{} |
||||
} |
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\Model; |
||||
|
||||
class File |
||||
{ |
||||
public static function getConfig(): object |
||||
{ |
||||
$filename = __DIR__ . |
||||
DIRECTORY_SEPARATOR . '..' . |
||||
DIRECTORY_SEPARATOR . '..' . |
||||
DIRECTORY_SEPARATOR . 'config.json'; |
||||
|
||||
if (file_exists($filename) && is_readable($filename)) |
||||
{ |
||||
$result = json_decode( |
||||
file_get_contents( |
||||
$filename |
||||
) |
||||
); |
||||
} |
||||
|
||||
if (empty($result)) |
||||
{ |
||||
throw new \Exception(); // @TODO |
||||
} |
||||
|
||||
return $result; |
||||
} |
||||
|
||||
public static function getTheme(string $name): string |
||||
{ |
||||
$filename = __DIR__ . |
||||
DIRECTORY_SEPARATOR . '..' . |
||||
DIRECTORY_SEPARATOR . 'Theme' . |
||||
DIRECTORY_SEPARATOR . $name . '.css'; |
||||
|
||||
if (file_exists($filename) && is_readable($filename)) |
||||
{ |
||||
$result = file_get_contents( |
||||
$filename |
||||
); |
||||
} |
||||
|
||||
if (empty($result)) |
||||
{ |
||||
throw new \Exception(); // @TODO |
||||
} |
||||
|
||||
return $result; |
||||
} |
||||
} |
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Yggverse\Yoda\Model; |
||||
|
||||
class Memory |
||||
{ |
||||
public function __construct() |
||||
{} |
||||
} |
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
#boxMenu {} |
||||
#boxNavigation {} |
||||
#boxMain {} |
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
<?php |
||||
|
||||
// Load dependencies |
||||
require_once __DIR__ . |
||||
DIRECTORY_SEPARATOR . '..'. |
||||
DIRECTORY_SEPARATOR . 'vendor' . |
||||
DIRECTORY_SEPARATOR . 'autoload.php'; |
||||
|
||||
// Init config |
||||
$config = \Yggverse\Yoda\Model\File::getConfig(); |
||||
|
||||
// Init GTK |
||||
\Gtk::init(); |
||||
|
||||
// Init theme |
||||
$css = new \GtkCssProvider(); |
||||
|
||||
$css->load_from_data( |
||||
\Yggverse\Yoda\Model\File::getTheme( |
||||
$config->theme |
||||
) |
||||
); |
||||
|
||||
$style = new \GtkStyleContext(); |
||||
|
||||
$style->add_provider_for_screen( |
||||
$css, |
||||
600 |
||||
); |
||||
|
||||
// Init app window |
||||
$window = new \GtkWindow(); |
||||
|
||||
$window->set_size_request( |
||||
600, |
||||
480 |
||||
); |
||||
|
||||
$window->set_title( |
||||
'Yoda' |
||||
); |
||||
|
||||
$window->connect( |
||||
'destroy', |
||||
function() |
||||
{ |
||||
\Gtk::main_quit(); |
||||
} |
||||
); |
||||
|
||||
$main = new \Yggverse\Yoda\Box\Main(); |
||||
|
||||
$window->add( |
||||
$main->box |
||||
); |
||||
|
||||
$window->show_all(); |
||||
|
||||
\Gtk::main(); |
Loading…
Reference in new issue