container = $container; // Init container $this->gtk = new GtkBox( GtkOrientation::VERTICAL ); // Init title $this->title = new Page\Title( $this ); // Init navbar $this->navbar = new Page\Navbar( $this ); $this->gtk->add( $this->navbar->gtk ); $this->gtk->set_focus_child( $this->navbar->update->gtk // replace autofocus priority ); // Init content $this->content = new Page\Content( $this ); $this->gtk->pack_start( $this->content->gtk, true, true, 0 ); // Init progress bar $this->progressbar = new Page\Progressbar( $this ); $this->gtk->add( $this->progressbar->gtk ); // Init response bar $this->response = new Page\Response( $this ); $this->gtk->pack_end( $this->response->gtk ); // Render $this->gtk->show(); } public function refresh(): void { $this->navbar->refresh(); $this->content->refresh(); } public function init( ?string $request = null, bool $focus = false ): void { if ($request) { $this->navbar->request->setValue( $request ); } if ($focus) { Gtk::timeout_add( 100, function() { $this->navbar->request->focus(); return false; } ); } } public function open( ?string $request = null, bool $history = true ): void { $this->navbar->request->setValue( $request ); $this->update( $history ); } public function update( bool $history = true, int $refresh = 100, int $timeout = 15 ): void { // Request entry should not be empty to update if (empty($this->navbar->request->getValue())) { // return; throw new Exception; } // Update title $this->title->set( _('Loading...') ); // Refresh navbar $this->navbar->refresh(); // Show progressbar $this->progressbar->infinitive(); // Hide response form $this->response->hide(); // Drop previous connection if ($this->connection) { // Free memory $this->connection->close(); } // Update content using multi-protocol driver $this->connection = new Connection( $this->container->browser->database ); // Async request $this->connection->request( $this->navbar->request->getValue(), $timeout ); // Calculate expiration time $expire = time() + $timeout; // Listen response Gtk::timeout_add( $refresh, function() use ($expire, $history) { // Redirect requested if ($location = $this->connection->getRedirect()) { // Follow $this->open( $location ); // Hide progressbar $this->progressbar->hide(); return false; // stop } // Response form requested if ($request = $this->connection->getRequest()) { // Update title $this->title->set( $this->connection->getTitle(), $this->connection->getSubtitle(), $this->connection->getTooltip() ); // Refresh header by new title if current page is active if ($this === $this->container->tab->get()) { $this->container->browser->header->setTitle( $this->title->getValue(), $this->title->getSubtitle() ); } // Show response form $this->response->show( $request['placeholder'], $request['visible'] ); // Hide progressbar $this->progressbar->hide(); return false; // stop } // Stop event loop on request completed if ($this->connection->isCompleted()) { // Update title $this->title->set( $this->connection->getTitle(), $this->connection->getSubtitle(), $this->connection->getTooltip() ); // Refresh header by new title if current page is active if ($this === $this->container->tab->get()) { $this->container->browser->header->setTitle( $this->title->getValue(), $this->title->getSubtitle() ); } // Update content $this->content->set( $this->connection->getMime(), $this->connection->getData() ); // Hide progressbar $this->progressbar->hide(); // Update history if ($history) { // Save request in memory $this->navbar->history->add( $this->navbar->request->getValue() ); // Save request in database (on background) $pid = pcntl_fork(); if ($pid === 0) { $this->container->browser->database->renewHistory( $this->navbar->request->getValue(), $this->title->getValue() ); exit; } } // Stop return false; } // Stop event loop on request expired if (time() > $expire) { // Update title $this->title->set( _('Timeout') ); // Refresh header by new title if current page is active if ($this === $this->container->tab->get()) { $this->container->browser->header->setTitle( $this->title->getValue() ); } // Update content $this->content->set( Filesystem::MIME_TEXT_PLAIN, _('Response time reached') ); // Hide progressbar $this->progressbar->hide(); // Stop return false; } } ); } }