diff options
author | Andreas Gohr <andi@splitbrain.org> | 2024-12-18 09:20:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-18 09:20:53 +0100 |
commit | c408a2af01195b7a0821b224bb0e83b4c623ae0f (patch) | |
tree | e857f664e07da0fa5526fd1d40c083f7148579cc | |
parent | 18c84d9d073a64fbf6b23cc76eb9df1df292ecda (diff) | |
parent | f17690f709e1e20933d22a4da15909d879e9aa13 (diff) | |
download | dokuwiki-c408a2af01195b7a0821b224bb0e83b4c623ae0f.tar.gz dokuwiki-c408a2af01195b7a0821b224bb0e83b4c623ae0f.zip |
Merge pull request #4374 from dokuwiki/extensionlabels
Extension Manager: use characters for messages
-rw-r--r-- | lib/plugins/extension/GuiAdmin.php | 12 | ||||
-rw-r--r-- | lib/plugins/extension/GuiExtension.php | 16 | ||||
-rw-r--r-- | lib/plugins/extension/Installer.php | 9 | ||||
-rw-r--r-- | lib/plugins/extension/Notice.php | 34 | ||||
-rw-r--r-- | lib/plugins/extension/Repository.php | 4 | ||||
-rw-r--r-- | lib/plugins/extension/cli.php | 24 | ||||
-rw-r--r-- | lib/plugins/extension/images/error.svg | 1 | ||||
-rw-r--r-- | lib/plugins/extension/images/fire.svg | 4 | ||||
-rw-r--r-- | lib/plugins/extension/images/info.svg | 1 | ||||
-rw-r--r-- | lib/plugins/extension/images/license.txt | 5 | ||||
-rw-r--r-- | lib/plugins/extension/images/security.svg | 1 | ||||
-rw-r--r-- | lib/plugins/extension/images/warning.svg | 1 | ||||
-rw-r--r-- | lib/plugins/extension/style.less | 26 |
13 files changed, 109 insertions, 29 deletions
diff --git a/lib/plugins/extension/GuiAdmin.php b/lib/plugins/extension/GuiAdmin.php index 8480f7553..74499632b 100644 --- a/lib/plugins/extension/GuiAdmin.php +++ b/lib/plugins/extension/GuiAdmin.php @@ -64,6 +64,12 @@ class GuiAdmin extends Gui $html .= '</div>'; $plugins = (new Local())->getPlugins(); + try { + // initialize remote data in one go + Repository::getInstance()->initExtensions(array_keys($plugins)); + } catch (Exception $e) { + msg($e->getMessage(), -1); // this should not happen + } $html .= '<div id="extension__list">'; $html .= '<form action="' . $this->tabURL('plugins') . '" method="post">'; @@ -91,6 +97,12 @@ class GuiAdmin extends Gui $html .= '</div>'; $templates = (new Local())->getTemplates(); + try { + // initialize remote data in one go + Repository::getInstance()->initExtensions(array_keys($templates)); + } catch (Exception $e) { + msg($e->getMessage(), -1); // this should not happen + } $html .= '<div id="extension__list">'; $html .= '<form action="' . $this->tabURL('templates') . '" method="post">'; diff --git a/lib/plugins/extension/GuiExtension.php b/lib/plugins/extension/GuiExtension.php index 1cb848c65..4b8163c60 100644 --- a/lib/plugins/extension/GuiExtension.php +++ b/lib/plugins/extension/GuiExtension.php @@ -75,6 +75,8 @@ class GuiExtension extends Gui $img = [ 'width' => self::THUMB_WIDTH, 'height' => self::THUMB_HEIGHT, + 'class' => 'shot', + 'loading' => 'lazy', 'alt' => '', ]; @@ -144,8 +146,12 @@ class GuiExtension extends Gui foreach ($messages as $message) { $message = hsc($message); $message = nl2br($message); - $message = '<span>' . Notice::ICONS[$type] . '</span> ' . $message; $message = preg_replace('/`([^`]+)`/', '<bdi>$1</bdi>', $message); + $message = sprintf( + '<span class="icon">%s</span><span>%s</span>', + inlineSVG(Notice::icon($type)), + $message + ); $html .= '<li class="' . $type . '"><div class="li">' . $message . '</div></li>'; } } @@ -313,15 +319,17 @@ class GuiExtension extends Gui if (!$popularity) return ''; if ($this->extension->isBundled()) return ''; + $popimg = '<img src="' . DOKU_BASE . 'lib/plugins/extension/images/fire.svg" alt="🔥" />'; + if ($popularity > 0.25) { $title = $this->getLang('popularity_high'); - $emoji = '🔥🔥🔥'; + $emoji = str_repeat($popimg, 3); } elseif ($popularity > 0.15) { $title = $this->getLang('popularity_medium'); - $emoji = '🔥🔥'; + $emoji = str_repeat($popimg, 2); } elseif ($popularity > 0.05) { $title = $this->getLang('popularity_low'); - $emoji = '🔥'; + $emoji = str_repeat($popimg, 1); } else { return ''; } diff --git a/lib/plugins/extension/Installer.php b/lib/plugins/extension/Installer.php index 36fb2937f..7e9483422 100644 --- a/lib/plugins/extension/Installer.php +++ b/lib/plugins/extension/Installer.php @@ -288,10 +288,17 @@ class Installer // download $http = new DokuHTTPClient(); $http->max_bodysize = 0; - $http->timeout = 25; //max. 25 sec $http->keep_alive = false; // we do single ops here, no need for keep-alive $http->agent = 'DokuWiki HTTP Client (Extension Manager)'; + // large downloads may take a while on slow connections, so we try to extend the timeout to 4 minutes + // 4 minutes was chosen, because HTTP servers and proxies often have a 5 minute timeout + if (php_sapi_name() === 'cli' || @set_time_limit(60 * 4)) { + $http->timeout = 60 * 4 - 5; // nearly 4 minutes + } else { + $http->timeout = 25; // max. 25 sec (a bit less than default execution time) + } + $data = $http->get($url); if ($data === false) throw new Exception('error_download', [$url, $http->error, $http->status]); diff --git a/lib/plugins/extension/Notice.php b/lib/plugins/extension/Notice.php index e22aa4044..df5aa805c 100644 --- a/lib/plugins/extension/Notice.php +++ b/lib/plugins/extension/Notice.php @@ -9,11 +9,11 @@ class Notice public const ERROR = 'error'; public const SECURITY = 'security'; - public const ICONS = [ - self::INFO => 'ⓘ', - self::WARNING => '↯', - self::ERROR => '⚠', - self::SECURITY => '☠', + protected const ICONS = [ + self::INFO => 'I', + self::WARNING => 'W', + self::ERROR => 'E', + self::SECURITY => 'S', ]; protected $notices = [ @@ -62,6 +62,30 @@ class Notice } /** + * Return the icon path for a notice type + * + * @param string $type The notice type constant + * @return string + */ + public static function icon($type): string + { + if (!isset(self::ICONS[$type])) throw new \RuntimeException('Unknown notice type: ' . $type); + return __DIR__ . '/images/' . $type . '.svg'; + } + + /** + * Return the character symbol for a notice type used on CLI + * + * @param string $type The notice type constant + * @return string + */ + public static function symbol($type): string + { + if (!isset(self::ICONS[$type])) throw new \RuntimeException('Unknown notice type: ' . $type); + return self::ICONS[$type][0] ?? ''; + } + + /** * Access a language string * * @param string $msg diff --git a/lib/plugins/extension/Repository.php b/lib/plugins/extension/Repository.php index 20130f8fb..2cda2480d 100644 --- a/lib/plugins/extension/Repository.php +++ b/lib/plugins/extension/Repository.php @@ -135,7 +135,7 @@ class Repository // first get all that are cached foreach ($ids as $id) { $data = $this->retrieveCache($id); - if ($data === null) { + if ($data === null || $data === []) { $toload[] = $id; } else { $result[$id] = Extension::createFromRemoteData($data); @@ -147,7 +147,7 @@ class Repository $this->fetchExtensions($toload); foreach ($toload as $id) { $data = $this->retrieveCache($id); - if ($data === null) { + if ($data === null || $data === []) { $result[$id] = null; } else { $result[$id] = Extension::createFromRemoteData($data); diff --git a/lib/plugins/extension/cli.php b/lib/plugins/extension/cli.php index 6100a55be..e163b362e 100644 --- a/lib/plugins/extension/cli.php +++ b/lib/plugins/extension/cli.php @@ -30,10 +30,10 @@ class cli_plugin_extension extends CLIPlugin $options->setHelp( "Manage plugins and templates for this DokuWiki instance\n\n" . "Status codes:\n" . - " i - installed " . Notice::ICONS[Notice::SECURITY] . " - security issue\n" . - " b - bundled with DokuWiki " . Notice::ICONS[Notice::ERROR] . " - extension error\n" . - " g - installed via git " . Notice::ICONS[Notice::WARNING] . " - extension warning\n" . - " d - disabled " . Notice::ICONS[Notice::INFO] . " - extension info\n" . + " i - installed " . Notice::symbol(Notice::SECURITY) . " - security issue\n" . + " b - bundled with DokuWiki " . Notice::symbol(Notice::ERROR) . " - extension error\n" . + " g - installed via git " . Notice::symbol(Notice::WARNING) . " - extension warning\n" . + " d - disabled " . Notice::symbol(Notice::INFO) . " - extension info\n" . " u - update available\n" ); @@ -258,7 +258,11 @@ class cli_plugin_extension extends CLIPlugin */ protected function cmdList($showdetails, $filter) { - $this->listExtensions((new Local())->getExtensions(), $showdetails, $filter); + $extensions = (new Local())->getExtensions(); + // initialize remote data in one go + Repository::getInstance()->initExtensions(array_keys($extensions)); + + $this->listExtensions($extensions, $showdetails, $filter); return 0; } @@ -309,10 +313,10 @@ class cli_plugin_extension extends CLIPlugin } $notices = Notice::list($ext); - if ($notices[Notice::SECURITY]) $status .= Notice::ICONS[Notice::SECURITY]; - if ($notices[Notice::ERROR]) $status .= Notice::ICONS[Notice::ERROR]; - if ($notices[Notice::WARNING]) $status .= Notice::ICONS[Notice::WARNING]; - if ($notices[Notice::INFO]) $status .= Notice::ICONS[Notice::INFO]; + if ($notices[Notice::SECURITY]) $status .= Notice::symbol(Notice::SECURITY); + if ($notices[Notice::ERROR]) $status .= Notice::symbol(Notice::ERROR); + if ($notices[Notice::WARNING]) $status .= Notice::symbol(Notice::WARNING); + if ($notices[Notice::INFO]) $status .= Notice::symbol(Notice::INFO); echo $tr->format( [20, 5, 12, '*'], @@ -347,7 +351,7 @@ class cli_plugin_extension extends CLIPlugin foreach ($msgs as $msg) { echo $tr->format( [7, '*'], - ['', Notice::ICONS[$type] . ' ' . $msg], + ['', Notice::symbol($type) . ' ' . $msg], [null, Colors::C_LIGHTBLUE] ); } diff --git a/lib/plugins/extension/images/error.svg b/lib/plugins/extension/images/error.svg new file mode 100644 index 000000000..5ab8fb2d4 --- /dev/null +++ b/lib/plugins/extension/images/error.svg @@ -0,0 +1 @@ +<svg viewBox="0 0 24 24"><path d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z"/></svg>
\ No newline at end of file diff --git a/lib/plugins/extension/images/fire.svg b/lib/plugins/extension/images/fire.svg new file mode 100644 index 000000000..ee6e8ef41 --- /dev/null +++ b/lib/plugins/extension/images/fire.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"> + <path fill="#f6af62" d="M21.04 20.63s-1.79 8.99-.96 11.47c0 0 1.1-13.6 11.67-24.1 0 0-.34 8.79 5.15 13.25s6.73 11.4 6.73 11.4.62-4.74-1.24-12.33c0 0 11.67 12.12 6.32 25.65 0 0-6.45 14.9-24.92 8.38s-6.05-31.38-2.75-33.72z"/> + <path fill="#fbd872" d="M40.75 32.12c.17 3.81-1.55 4.81-2.94 5.01-.89.13-1.79-.1-2.57-.53-7.65-4.15-3.72-14.29-3.72-14.29-5.01 4.79-2.4 14.74-2.4 14.74s1.55 5.64-1.62 6.13c-1.59.25-2.33-.39-2.67-1.08-.31-.64-.31-1.39-.04-2.05 2.15-5.34.31-8.36.31-8.36-1.03 3.06-2.12 5.08-2.91 6.29-1.12 1.72-1.83 3.68-1.93 5.73-.36 7.64 6.04 10.69 6.04 10.69 10.51 5.36 15.23-4.44 15.23-4.44 5.43-10.44-.78-17.84-.78-17.84z"/> +</svg> diff --git a/lib/plugins/extension/images/info.svg b/lib/plugins/extension/images/info.svg new file mode 100644 index 000000000..307a3403f --- /dev/null +++ b/lib/plugins/extension/images/info.svg @@ -0,0 +1 @@ +<svg viewBox="0 0 24 24"><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z"/></svg>
\ No newline at end of file diff --git a/lib/plugins/extension/images/license.txt b/lib/plugins/extension/images/license.txt index 1feb3467b..d0a36b905 100644 --- a/lib/plugins/extension/images/license.txt +++ b/lib/plugins/extension/images/license.txt @@ -1,7 +1,6 @@ -enabled.png - CC0, (c) Tanguy Ortolo -disabled.png - public domain, (c) Tango Desktop Project http://commons.wikimedia.org/wiki/File:Dialog-information.svg plugin.png - public domain, (c) nicubunu, http://openclipart.org/detail/15093/blue-jigsaw-piece-07-by-nicubunu template.png - public domain, (c) mathec, http://openclipart.org/detail/166596/palette-by-mathec -coffee.png - CC0, (c) Office 31, https://www.svgrepo.com/svg/301068/coffee-cup-coffee +coffee.svg - CC0, (c) Office 31, https://www.svgrepo.com/svg/301068/coffee-cup-coffee bug.svg - PD, (c) Mary Akveo, https://www.svgrepo.com/svg/468140/bug +fire.svg - CC0, (c) SVG Repo, https://www.svgrepo.com/svg/404501/burn-fire-flame-hot diff --git a/lib/plugins/extension/images/security.svg b/lib/plugins/extension/images/security.svg new file mode 100644 index 000000000..2850a9069 --- /dev/null +++ b/lib/plugins/extension/images/security.svg @@ -0,0 +1 @@ +<svg viewBox="0 0 24 24"><path d="M12,12H19C18.47,16.11 15.72,19.78 12,20.92V12H5V6.3L12,3.19M12,1L3,5V11C3,16.55 6.84,21.73 12,23C17.16,21.73 21,16.55 21,11V5L12,1Z"/></svg>
\ No newline at end of file diff --git a/lib/plugins/extension/images/warning.svg b/lib/plugins/extension/images/warning.svg new file mode 100644 index 000000000..baae7bf71 --- /dev/null +++ b/lib/plugins/extension/images/warning.svg @@ -0,0 +1 @@ +<svg viewBox="0 0 24 24"><path d="M12,2L1,21H23M12,6L19.53,19H4.47M11,10V14H13V10M11,16V18H13V16"/></svg>
\ No newline at end of file diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index a74715d8c..5337aea30 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -79,7 +79,7 @@ margin-bottom: 1.5em; // adds space for the detail summary label position: relative; - img { + img.shot { border: 1px solid @ini_border; border-radius: 2px; width: 100%; @@ -104,6 +104,11 @@ .popularity { cursor: default; + img { + vertical-align: middle; + height: 1.2rem; + width: auto; + } } } @@ -166,9 +171,22 @@ margin: 0.5em 0 0 0; padding: 0; - span { - font-weight: bold; - color: @ini_link; + div.li { + display: flex; + line-height: 1.2em; + gap: 0.25em; + align-items: center; + span.icon svg { + fill: @ini_link; + } + } + + &.error div.li span.icon svg { + fill: #f33; + } + &.security div.li span.icon svg, + &.warning div.li span.icon svg { + fill: #f90; } } } |