From 491ed9a52143b4d341882d1b4aa8446aec15d54a Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 18 Apr 2024 21:36:43 +0200 Subject: [PATCH] bootstrap 5 template function complete current status: - got expiration and format selections to work - fixed modals (password, QR-code, etc.) - replaced glyphicons with Bootstrap icons (needs CSP relaxation to work) - tested the different settings and combinations - got editor tabs to change active status to be done: - add "Dark Mode" to translation strings - figure out how to change prettify theme when dark mode gets selected - check tab alignment in HTML source --- LICENSE.md | 1 + cfg/conf.sample.php | 8 ++- css/bootstrap5/privatebin.css | 107 ++++++++++++++++++++++++++++++++- img/bootstrap-icons.svg | 1 + js/privatebin.js | 55 ++++++++++------- lib/Configuration.php | 2 +- lib/Controller.php | 8 +-- lib/Persistence/ServerSalt.php | 2 +- tpl/bootstrap.php | 10 +-- tpl/bootstrap5.php | 86 +++++++++++++------------- tpl/page.php | 10 +-- 11 files changed, 204 insertions(+), 86 deletions(-) create mode 100644 img/bootstrap-icons.svg diff --git a/LICENSE.md b/LICENSE.md index 8b88a6d4..0895f586 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -351,6 +351,7 @@ Copyright © 2016 Nils Adermann, Jordi Boggiano Copyright © 2016 Lars Jung (https://larsjung.de) Copyright © 2018 base-x contributors Copyright © 2014-2018 The Bitcoin Core developers +Copyright © 2019-2024 The Bootstrap Authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index 141888f2..cd64a5fa 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -85,8 +85,10 @@ languageselection = false ; scripts or run your site behind certain DDoS-protection services. ; Check the documentation at https://content-security-policy.com/ ; Notes: -; - If you use a bootstrap theme, you can remove the allow-popups from the +; - If you use any bootstrap theme, you can remove the allow-popups from the ; sandbox restrictions. +; - If you use the bootstrap5 theme, you must change default-src to 'self' to +; enable display of the svg icons ; - By default this disallows to load images from third-party servers, e.g. when ; they are embedded in pastes. If you wish to allow that, you can adjust the ; policy here. See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-it-load-embedded-images @@ -242,7 +244,7 @@ dir = PATH "data" ; - AWS_ACCESS_KEY_ID ; - AWS_SECRET_ACCESS_KEY ; - AWS_SESSION_TOKEN (if needed) -; for more details, see https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials.html#default-credential-chain +; for more details, see https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials.html#default-credential-chain ;class = S3Storage ;[model_options] ;region = "eu-central-1" @@ -264,4 +266,4 @@ dir = PATH "data" ; (optional) the "signature" (access key) issued by YOURLS for the using account ; signature = "" ; (optional) the URL of the YOURLS API, called to shorten a PrivateBin URL -; apiurl = "https://yourls.example.com/yourls-api.php" \ No newline at end of file +; apiurl = "https://yourls.example.com/yourls-api.php" diff --git a/css/bootstrap5/privatebin.css b/css/bootstrap5/privatebin.css index cd0604ed..3630049f 100644 --- a/css/bootstrap5/privatebin.css +++ b/css/bootstrap5/privatebin.css @@ -9,4 +9,109 @@ * @version 1.7.1 */ - .hidden { display: none; } + .hidden { display: none !important; } + + #attachmentPreview img { + max-width: 100%; + height: auto; + margin-bottom: 20px; +} + +#attachmentPreview .pdfPreview { + width: 100%; + height: 100vh; + margin-bottom: 20px; +} + +#dropzone { + text-align: center; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + opacity: 0.6; + background-color: #99ccff; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: center; + background-size: 25vh; + outline: 2px dashed #228bff; + outline-offset: -50px; +} + +.dragAndDropFile{ + color: #777; + font-size: 1em; + display: inline; + white-space: normal; +} + +#deletelink { + float: right; + margin-left: 5px; +} + +#qrcodemodalClose { + float: right; +} + +#qrcode-display { + width: 200px; + height: 200px; + margin: auto; +} + +#pastelink { + display: inline; +} + +#pastelink > a { + word-wrap: break-word; +} + +#preview { + margin-bottom: 10px; +} + +#message, .replymessage { + font-family: monospace; + resize: vertical; +} + +#nickname { + margin: 5px 0; +} + +#comments, #comments button { + margin-bottom: 10px; +} + +#filewrap { + transition: background-color 0.75s ease-out; +} + +.comment { + border-left: 1px solid #ccc; + padding: 5px 0 5px 10px; + white-space: pre-wrap; + transition: background-color 0.75s ease-out; +} + +.highlight { + background-color: #ffdd86; + transition: background-color 0.2s ease-in; +} + +li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 { + list-style-type: decimal !important; +} + +.text-right button { + float: right; +} + +html[dir="rtl"] #deletelink, html[dir="rtl"] #qrcodemodalClose { + float: left; +} diff --git a/img/bootstrap-icons.svg b/img/bootstrap-icons.svg new file mode 100644 index 00000000..11afeae1 --- /dev/null +++ b/img/bootstrap-icons.svg @@ -0,0 +1 @@ + diff --git a/js/privatebin.js b/js/privatebin.js index 0a3271c8..f05afa79 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2390,7 +2390,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { let $editorTabs, $messageEdit, + $messageEditLi, $messagePreview, + $messagePreviewLi, $message, isPreview = false; @@ -2431,10 +2433,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { { // toggle buttons $messageEdit.addClass('active'); + $messageEditLi.addClass('active'); $messagePreview.removeClass('active'); + $messagePreviewLi.removeClass('active'); - $('#messageedit').attr('aria-selected','true'); - $('#messagepreview').attr('aria-selected','false'); + $messageEdit.attr('aria-selected','true'); + $messagePreview.attr('aria-selected','false'); PasteViewer.hide(); @@ -2463,10 +2467,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { { // toggle buttons $messageEdit.removeClass('active'); + $messageEditLi.removeClass('active'); $messagePreview.addClass('active'); + $messagePreviewLi.addClass('active'); - $('#messageedit').attr('aria-selected','false'); - $('#messagepreview').attr('aria-selected','true'); + $messageEdit.attr('aria-selected','false'); + $messagePreview.attr('aria-selected','true'); // hide input as now preview is shown $message.addClass('hidden'); @@ -2594,10 +2600,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { // bind events $message.keydown(supportTabs); - // bind click events to tab switchers (a), but save parent of them - // (li) - $messageEdit = $('#messageedit').click(viewEditor).parent(); - $messagePreview = $('#messagepreview').click(viewPreview).parent(); + // bind click events to tab switchers (a), and save parents (li) + $messageEdit = $('#messageedit').click(viewEditor); + $messageEditLi = $messageEdit.parent(); + $messagePreview = $('#messagepreview').click(viewPreview); + $messagePreviewLi = $messagePreview.parent(); }; return me; @@ -2693,15 +2700,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { // otherwise hide the placeholder $placeholder.addClass('hidden'); - switch (format) { - case 'markdown': - $plainText.removeClass('hidden'); - $prettyMessage.addClass('hidden'); - break; - default: - $plainText.addClass('hidden'); - $prettyMessage.removeClass('hidden'); - break; + if (format === 'markdown') { + $plainText.removeClass('hidden'); + $prettyMessage.addClass('hidden'); + } else { + $plainText.addClass('hidden'); + $prettyMessage.removeClass('hidden'); } } @@ -2726,6 +2730,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { format = newFormat; isChanged = true; + + // update preview + if (Editor.isPreview()) { + PasteViewer.run(); + } + }; /** @@ -3712,11 +3722,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { $('#pasteFormatterDisplay').text($target.text()); PasteViewer.setFormat(newFormat); - // update preview - if (Editor.isPreview()) { - PasteViewer.run(); - } - event.preventDefault(); } @@ -3921,6 +3926,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { text: window.location.href }); $('#qrcode-display').html(qrCanvas); + $('#qrcodemodal').modal('show'); } /** @@ -4360,7 +4366,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ me.getExpiration = function() { - return pasteExpiration; + return Model.getExpirationDefault() || pasteExpiration; }; /** @@ -4543,6 +4549,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { // bootstrap template drop downs $('ul.dropdown-menu li a', $('#expiration').parent()).click(updateExpiration); $('ul.dropdown-menu li a', $('#formatter').parent()).click(updateFormat); + $('#pasteFormatter').on('change', function() { + PasteViewer.setFormat(Model.getFormatDefault()); + }); // initiate default state of checkboxes changeBurnAfterReading(); diff --git a/lib/Configuration.php b/lib/Configuration.php index dac6eec3..cf0febe6 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -240,7 +240,7 @@ class Configuration // ensure the basepath ends in a slash, if one is set if ( - strlen($this->_configuration['main']['basepath']) && + !empty($this->_configuration['main']['basepath']) && substr_compare($this->_configuration['main']['basepath'], '/', -1) !== 0 ) { $this->_configuration['main']['basepath'] .= '/'; diff --git a/lib/Controller.php b/lib/Controller.php index c97485a7..316b6b5d 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -114,7 +114,7 @@ class Controller error_log(I18n::_('%s requires php %s or above to work. Sorry.', I18n::_('PrivateBin'), self::MIN_PHP_VERSION)); return; } - if (strlen(PATH) < 0 && substr(PATH, -1) !== DIRECTORY_SEPARATOR) { + if (!empty(PATH) && substr(PATH, -1) !== DIRECTORY_SEPARATOR) { error_log(I18n::_('%s requires the PATH to end in a "%s". Please update the PATH in your index.php.', I18n::_('PrivateBin'), DIRECTORY_SEPARATOR)); return; } @@ -320,10 +320,10 @@ class Controller $this->_error = $e->getMessage(); } if ($this->_request->isJsonApiCall()) { - if (strlen($this->_error)) { - $this->_return_message(1, $this->_error); - } else { + if (empty($this->_error)) { $this->_return_message(0, $dataid); + } else { + $this->_return_message(1, $this->_error); } } } diff --git a/lib/Persistence/ServerSalt.php b/lib/Persistence/ServerSalt.php index a0e2f377..9679b34c 100644 --- a/lib/Persistence/ServerSalt.php +++ b/lib/Persistence/ServerSalt.php @@ -56,7 +56,7 @@ class ServerSalt extends AbstractPersistence */ public static function get() { - if (strlen(self::$_salt)) { + if (!empty(self::$_salt)) { return self::$_salt; } diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 6b08037f..23a06a48 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -34,7 +34,7 @@ if ($SYNTAXHIGHLIGHTING) : ?> - + @@ -437,7 +437,7 @@ endif;