Features ------------- Custom application name via APP_NAME docker env (These next 3 are done with OCRMyPDF) Extra features to OCR for scanned page cleanup (tilt/noise fixing) Adding OCR ability to read and output to text file Added Dedicated PDF/A conversion page Bug fixes -------------- Fix concurrent calls on Libre and OCRMyPDF jbig fix for compressions Fix for compression metadata issues due to forced conversions to PDF/A Other -------- Removal of UK US language and just using "English" due to extra development time Still issue with concurrent files for PDF to image... will fix later sorry
274 lines
16 KiB
HTML
274 lines
16 KiB
HTML
<div th:fragment="navbar" class="mx-auto">
|
|
<script>
|
|
document
|
|
.addEventListener(
|
|
'DOMContentLoaded',
|
|
function() {
|
|
// Get the dropdown items
|
|
var dropdownItems = document
|
|
.querySelectorAll('.lang_dropdown-item');
|
|
|
|
// Loop through the dropdown items
|
|
for (var i = 0; i < dropdownItems.length; i++) {
|
|
dropdownItems[i].classList
|
|
.remove('active');
|
|
if (dropdownItems[i].dataset.languageCode === localStorage
|
|
.getItem('languageCode')) {
|
|
dropdownItems[i].classList
|
|
.add('active');
|
|
}
|
|
|
|
// Add a click event listener to each dropdown item
|
|
dropdownItems[i]
|
|
.addEventListener(
|
|
'click',
|
|
function(event) {
|
|
|
|
// Prevent the default link behavior
|
|
event
|
|
.preventDefault();
|
|
|
|
// Get the language code
|
|
var languageCode = this.dataset.languageCode;
|
|
|
|
// Save the language code to local storage
|
|
localStorage
|
|
.setItem(
|
|
'languageCode',
|
|
languageCode);
|
|
|
|
// Get the current URL
|
|
var currentUrl = window.location.href;
|
|
|
|
// Check if the URL already contains a "?lang" query parameter
|
|
if (currentUrl
|
|
.indexOf('?lang=') === -1) {
|
|
// Update the URL with the "?lang" query parameter
|
|
window.location.href = currentUrl
|
|
+ '?lang='
|
|
+ languageCode;
|
|
} else {
|
|
// Replace the "?lang" query parameter with the new value
|
|
window.location.href = currentUrl
|
|
.replace(
|
|
/\?lang=\w{2,}/,
|
|
'?lang='
|
|
+ languageCode);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<script th:inline="javascript">
|
|
function compareVersions(version1, version2) {
|
|
const v1 = version1.split('.');
|
|
const v2 = version2.split('.');
|
|
|
|
for (let i = 0; i < v1.length || i < v2.length; i++) {
|
|
const n1 = parseInt(v1[i]) || 0;
|
|
const n2 = parseInt(v2[i]) || 0;
|
|
|
|
if (n1 > n2) {
|
|
return 1;
|
|
} else if (n1 < n2) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
async function getLatestReleaseVersion() {
|
|
const url = "https://api.github.com/repos/Frooodle/Stirling-PDF/releases/latest";
|
|
const response = await fetch(url);
|
|
const data = await response.json();
|
|
return data.tag_name.substring(1);
|
|
}
|
|
|
|
const currentVersion = /*[[${@appVersion}]]*/ ''; // Replace with your current version number
|
|
|
|
async function checkForUpdate() {
|
|
const latestVersion = await getLatestReleaseVersion();
|
|
console.log("latestVersion=" + latestVersion)
|
|
console.log("currentVersion=" + currentVersion)
|
|
console.log("compareVersions(latestVersion, currentVersion) > 0)=" + compareVersions(latestVersion, currentVersion))
|
|
if (latestVersion != null && latestVersion != "" && compareVersions(latestVersion, currentVersion) > 0) {
|
|
document.getElementById("update-btn").style.visibility = "visible";
|
|
console.log("visible")
|
|
} else {
|
|
document.getElementById("update-btn").style.visibility = "hidden";
|
|
console.log("hidden")
|
|
}
|
|
}
|
|
|
|
checkForUpdate();
|
|
</script>
|
|
|
|
|
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
|
<div class="container ">
|
|
|
|
<a class="navbar-brand" href="#" th:href="@{/}" th:text="${@appName}"></a>
|
|
|
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
|
|
<div class="collapse navbar-collapse" id="navbarNav">
|
|
|
|
<ul class="navbar-nav mr-auto flex-nowrap">
|
|
|
|
<li class="nav-item"><a class="nav-link" href="#" th:href="@{merge-pdfs}" th:classappend="${currentPage}=='merge-pdfs' ? 'active' : ''" th:text="#{home.merge.title}"></a></li>
|
|
|
|
<li class="nav-item"><a class="nav-link" href="#" th:href="@{split-pdfs}" th:classappend="${currentPage}=='split-pdfs' ? 'active' : ''" th:text="#{home.split.title}"></a></li>
|
|
|
|
<li class="nav-item"><a class="nav-link" href="#" th:href="@{pdf-organizer}" th:classappend="${currentPage}=='pdf-organizer' ? 'active' : ''" th:text="#{home.pdfOrganiser.title}"></a></li>
|
|
|
|
<li class="nav-item"><a class="nav-link" href="#" th:href="@{rotate-pdf}" th:classappend="${currentPage}=='rotate-pdf' ? 'active' : ''" th:text="#{home.rotate.title}"></a></li>
|
|
|
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='pdf-to-img' OR ${currentPage}=='img-to-pdf' OR ${currentPage}=='pdf-to-pdfa' OR ${currentPage}=='file-to-pdf' OR ${currentPage}=='xlsx-to-pdf' ? 'active' : ''"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
|
|
aria-haspopup="true" aria-expanded="false" th:text="#{navbar.convert}"></a>
|
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
|
<a class="dropdown-item" href="#" th:href="@{pdf-to-img}" th:classappend="${currentPage}=='pdf-to-img' ? 'active' : ''" th:text="#{home.pdfToImage.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{img-to-pdf}" th:classappend="${currentPage}=='img-to-pdf' ? 'active' : ''" th:text="#{home.imageToPdf.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{file-to-pdf}" th:classappend="${currentPage}=='file-to-pdf' ? 'active' : ''" th:text="#{home.fileToPDF.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{pdf-to-pdfa}" th:classappend="${currentPage}=='pdf-to-pdfa' ? 'active' : ''" th:text="#{home.pdfToPDFA.title}"></a>
|
|
</div>
|
|
</li>
|
|
|
|
|
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='add-password' OR ${currentPage}=='remove-password' OR ${currentPage}=='change-permissions' OR ${currentPage}=='add-watermark' OR ${currentPage}=='remove-watermark' ? 'active' : ''">
|
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:text="#{navbar.security}"></a>
|
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
|
<a class="dropdown-item" href="#" th:href="@{add-password}" th:classappend="${currentPage}=='add-password' ? 'active' : ''" th:text="#{home.addPassword.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{remove-password}" th:classappend="${currentPage}=='remove-password' ? 'active' : ''" th:text="#{home.removePassword.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{change-permissions}" th:classappend="${currentPage}=='change-permissions' ? 'active' : ''" th:text="#{home.permissions.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{add-watermark}" th:classappend="${currentPage}=='add-watermark' ? 'active' : ''" th:text="#{home.watermark.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{change-metadata}" th:classappend="${currentPage}=='change-metadata' ? 'active' : ''" th:text="#{home.changeMetadata.title}"></a>
|
|
</div>
|
|
</li>
|
|
|
|
|
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='add-image' OR ${currentPage}=='ocr-pdf' OR ${currentPage}=='extract-images' OR ${currentPage}=='compress-pdf' ? 'active' : ''"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
|
|
aria-haspopup="true" aria-expanded="false" th:text="#{navbar.other}"></a>
|
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
|
<a class="dropdown-item" href="#" th:href="@{ocr-pdf}" th:classappend="${currentPage}=='ocr-pdf' ? 'active' : ''" th:text="#{home.ocr.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{add-image}" th:classappend="${currentPage}=='add-image' ? 'active' : ''" th:text="#{home.addImage.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{compress-pdf}" th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''" th:text="#{home.compressPdfs.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{remove-pages}" th:classappend="${currentPage}=='remove-pages' ? 'active' : ''" th:text="#{home.removePages.title}"></a>
|
|
<a class="dropdown-item" href="#" th:href="@{extract-images}" th:classappend="${currentPage}=='extract-images' ? 'active' : ''" th:text="#{home.extractImages.title}"></a>
|
|
</div></li>
|
|
|
|
|
|
|
|
<input type="checkbox" id="toggle-dark-mode" checked="true" th:onclick="javascript:toggleDarkMode()">
|
|
<a class="nav-link" href="#" for="toggle-dark-mode" th:text="#{navbar.darkmode}" ></a>
|
|
|
|
|
|
<li class="nav-item dropdown">
|
|
<a class="nav-link dropdown-toggle" href="#" id="languageDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-globe2" viewBox="0 0 20 20">
|
|
<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.539c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.035.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.312.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.282.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a13.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.258-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.694.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.418.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"/>
|
|
</svg>
|
|
</a>
|
|
<div class="dropdown-menu" aria-labelledby="languageDropdown">
|
|
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_GB">English</a>
|
|
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="ar_AR">العربية</a>
|
|
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="de_DE">Deutsch</a>
|
|
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="fr_FR">Français</a>
|
|
</div>
|
|
</li>
|
|
|
|
<li class="nav-item">
|
|
<!-- Settings Button -->
|
|
<button type="button" class="btn btn-secondary float-right" data-toggle="modal" data-target="#settingsModal">
|
|
<span class="glyphicon glyphicon-cog"></span><span th:text="#{navbar.settings}"></span>
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</nav>
|
|
<div th:insert="~{fragments/errorBanner.html :: errorBanner}"></div>
|
|
|
|
<div class="modal fade" id="settingsModal" tabindex="-1" role="dialog" aria-labelledby="settingsModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
|
<div class="modal-content dark-card">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="settingsModalLabel" th:text="#{settings.title}"></h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<p class="mb-0" th:utext="#{settings.appVersion} + ' ' + ${@appVersion}"></p>
|
|
<a href="https://github.com/Frooodle/Stirling-PDF/releases" target="_blank">
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="update-btn" th:utext="#{settings.update}"></button>
|
|
</a>
|
|
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="downloadOption" th:utext="#{settings.downloadOption.title}"></label>
|
|
<select class="form-control" id="downloadOption">
|
|
<option value="sameWindow" th:utext="#{settings.downloadOption.1}"></option>
|
|
<option value="newWindow" th:utext="#{settings.downloadOption.2}"></option>
|
|
<option value="downloadFile" th:utext="#{settings.downloadOption.3}"></option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="zipThreshold" th:utext="#{settings.zipThreshold}"></label>
|
|
<input type="range" class="custom-range" min="0" max="9" step="1" id="zipThreshold" value="4">
|
|
<span id="zipThresholdValue" class="ml-2"></span>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal" th:text="#{close}"></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script>
|
|
// Get the download option from local storage, or set it to 'sameWindow' if it doesn't exist
|
|
var downloadOption = localStorage.getItem('downloadOption')
|
|
|| 'sameWindow';
|
|
|
|
// Set the selected option in the dropdown
|
|
document.getElementById('downloadOption').value = downloadOption;
|
|
|
|
// Save the selected option to local storage when the dropdown value changes
|
|
document.getElementById('downloadOption').addEventListener(
|
|
'change',
|
|
function() {
|
|
downloadOption = this.value;
|
|
localStorage.setItem('downloadOption',
|
|
downloadOption);
|
|
});
|
|
|
|
|
|
// Get the zipThreshold value from local storage, or set it to 0 if it doesn't exist
|
|
var zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4;
|
|
|
|
// Set the value of the slider and the display span
|
|
document.getElementById('zipThreshold').value = zipThreshold;
|
|
document.getElementById('zipThresholdValue').textContent = zipThreshold;
|
|
|
|
// Save the selected value to local storage when the slider value changes
|
|
document.getElementById('zipThreshold').addEventListener('input', function () {
|
|
zipThreshold = this.value;
|
|
document.getElementById('zipThresholdValue').textContent = zipThreshold;
|
|
localStorage.setItem('zipThreshold', zipThreshold);
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
</div>
|