Merge branch 'main' into patch-1

This commit is contained in:
吕舒君 2025-07-10 16:15:29 +08:00 committed by GitHub
commit d148f08794
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 596 additions and 108 deletions

View File

@ -15,6 +15,8 @@ plugins {
import com.github.jk1.license.render.*
import org.gradle.internal.os.OperatingSystem
import org.panteleyev.jpackage.ImageType
import java.nio.file.Files
import java.time.Year
@ -43,9 +45,19 @@ bootJar {
enabled = false
}
// Configure main class for the root project
springBoot {
mainClass = 'stirling.software.SPDF.SPDFApplication'
}
repositories {
mavenCentral()
maven { url = 'https://build.shibboleth.net/maven/releases' }
}
allprojects {
group = 'stirling.software'
version = '1.0.1'
version = '1.0.2'
configurations.configureEach {
exclude group: 'commons-logging', module: 'commons-logging'
@ -53,7 +65,6 @@ allprojects {
}
}
tasks.register('writeVersion') {
def propsFile = file("$projectDir/common/src/main/resources/version.properties")
def propsDir = propsFile.parentFile
@ -200,6 +211,14 @@ openApi {
waitTimeInSeconds = 60 // Increase the wait time to 60 seconds
}
// Configure the forked spring boot run task to properly delegate to the stirling-pdf module
tasks.named('forkedSpringBootRun') {
dependsOn ':stirling-pdf:bootRun'
doFirst {
println "Delegating forkedSpringBootRun to :stirling-pdf:bootRun"
}
}
//0.11.5 to 2024.11.5
static def getMacVersion(String version) {
def currentYear = Year.now().getValue()
@ -251,7 +270,7 @@ jpackage {
winUpgradeUuid = "2a43ed0c-b8c2-40cf-89e1-751129b87641" // Unique identifier for updates
winHelpUrl = "https://github.com/Stirling-Tools/Stirling-PDF"
winUpdateUrl = "https://github.com/Stirling-Tools/Stirling-PDF/releases"
type = "exe"
type = ImageType.EXE
installDir = "C:/Program Files/Stirling-PDF"
}
@ -259,7 +278,7 @@ jpackage {
mac {
appVersion = getMacVersion(project.version.toString())
icon = layout.projectDirectory.file("stirling-pdf/src/main/resources/static/favicon.icns")
type = "dmg"
type = ImageType.DMG
macPackageIdentifier = "Stirling PDF"
macPackageName = "Stirling PDF"
macAppCategory = "public.app-category.productivity"
@ -281,7 +300,7 @@ jpackage {
linux {
appVersion = project.version
icon = layout.projectDirectory.file("stirling-pdf/src/main/resources/static/favicon.png")
type = "deb" // Can also use "rpm" for Red Hat-based systems
type = ImageType.DEB // Can also use "rpm" for Red Hat-based systems
// Debian package configuration
//linuxPackageName = "stirlingpdf"
@ -514,6 +533,14 @@ swaggerhubUpload {
}
dependencies {
implementation project(':stirling-pdf')
implementation project(':common')
if (System.getenv('DISABLE_ADDITIONAL_FEATURES') != 'true'
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') != 'true')) {
implementation project(':proprietary')
}
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.12.2'
}

View File

@ -21,6 +21,7 @@ import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;
import org.thymeleaf.spring6.SpringTemplateEngine;
import lombok.Getter;
@ -148,23 +149,11 @@ public class AppConfig {
}
@Bean(name = "activeSecurity")
public boolean activeSecurity() {
String disableAdditionalFeatures = env.getProperty("DISABLE_ADDITIONAL_FEATURES");
if (disableAdditionalFeatures != null) {
// DISABLE_ADDITIONAL_FEATURES=true means security OFF, so return false
// DISABLE_ADDITIONAL_FEATURES=false means security ON, so return true
return !Boolean.parseBoolean(disableAdditionalFeatures);
}
return env.getProperty("DOCKER_ENABLE_SECURITY", Boolean.class, true);
}
@Bean(name = "missingActiveSecurity")
@ConditionalOnMissingClass(
"stirling.software.proprietary.security.configuration.SecurityConfiguration")
public boolean missingActiveSecurity() {
return true;
return ClassUtils.isPresent(
"stirling.software.proprietary.security.configuration.SecurityConfiguration",
this.getClass().getClassLoader()
);
}
@Bean(name = "directoryFilter")

View File

@ -146,5 +146,10 @@ bootJar {
}
}
// Configure main class for Spring Boot
springBoot {
mainClass = 'stirling.software.SPDF.SPDFApplication'
}
bootJar.dependsOn ':common:jar'
bootJar.dependsOn ':proprietary:jar'

View File

@ -98,6 +98,61 @@
font-weight: bold;
}
/* Responsive text sizing for drag & drop area */
#fileInputText {
font-size: 16px;
font-weight: bold;
color: var(--md-sys-color-on-surface);
max-width: 100%;
padding: 0 10px;
box-sizing: border-box;
}
/* Progressive font size reduction for high zoom levels */
@media only screen and (max-width: 1280px) {
#fileInputText {
font-size: 15px;
}
}
@media only screen and (max-width: 960px) {
#fileInputText {
font-size: 14px;
}
}
@media only screen and (max-width: 768px) {
#fileInputText {
font-size: 13px;
}
}
@media only screen and (max-width: 640px) {
#fileInputText {
font-size: 12px;
}
}
@media only screen and (max-width: 480px) {
#fileInputText {
font-size: 11px;
line-height: 1.3;
}
}
@media only screen and (max-width: 384px) {
#fileInputText {
font-size: 10px;
line-height: 1.4;
}
/* Also scale the container at ultra-high zoom */
.input-container {
height: 130px;
padding: 5px;
}
}
.file-input-btn {
display: inline-block;

View File

@ -1,8 +1,11 @@
/* Base Container Styles */
.multi-tool-container {
max-width: 95vw;
margin: 0 auto;
max-width: 100vw;
margin: 0;
padding: 0 20px;
}
/* Form Elements */
label {
text-align: left;
display: block;
@ -17,6 +20,7 @@ label {
flex-grow: 5;
}
/* Action Bar Styles */
.mt-action-bar {
display: flex;
gap: 10px;
@ -28,16 +32,17 @@ label {
padding: 1.25rem;
border-radius: 2rem;
margin: 0px 25px;
justify-content:center;
justify-content: center;
}
.mt-action-bar>* {
.mt-action-bar > * {
padding-bottom: 0.5rem;
}
.mt-file-uploader {
width:100%
width: 100%;
}
.mt-action-bar svg,
.mt-action-btn svg {
width: 20px;
@ -50,20 +55,21 @@ label {
gap: 10px;
}
/* Action Button Styles */
.mt-action-btn {
position: sticky;
bottom: 10%;
margin: auto;
margin-bottom: 25px;
position: fixed;
bottom: 80px;
left: 50%;
transform: translateX(-50%);
border-radius: 2rem;
z-index: 12;
background-color: var(--md-sys-color-surface-container-low) ;
background-color: var(--md-sys-color-surface-container-low);
display: flex;
gap: 10px;
padding: 12px 0px 0px;
width: fit-content;
justify-content: center;
padding: 10px 20px
padding: 10px 20px;
transition: all 0.3s ease-in-out;
}
.mt-action-btn .btn {
@ -71,68 +77,132 @@ label {
height: 3.5rem;
border-radius: 20px;
padding: 0;
position: relative;
}
/* Card and Container Styles */
.bg-card {
background-color: var(--md-sys-color-surface-5);
border-radius: 3rem;
padding: 25px 0;
padding: 15px 0;
margin-left: 55px;
margin-right: 20px;
display: flex;
flex-direction: column;
align-items: stretch;
}
#pages-container-wrapper {
width: 100%;
display: flex;
flex-direction: column;
padding: 1rem;
justify-content: center;
padding: 0.75rem;
border-radius: 25px;
min-height: 275px;
margin: 0 0 30px 0;
margin: 0 0 20px 0;
}
#pages-container {
margin: 0 auto;
width: 95%;
font-size: 0;
display: inline-flex;
flex-wrap: wrap;
gap: 20px;
justify-content: flex-start;
width: fit-content;
max-width: 100%;
}
/* width */
/* Scrollbar Styles */
#pages-container-wrapper::-webkit-scrollbar {
width: 10px;
height: 10px;
}
/* Track */
#pages-container-wrapper::-webkit-scrollbar-track {
background: var(--scroll-bar-color);
}
/* Handle */
#pages-container-wrapper::-webkit-scrollbar-thumb {
border-radius: 10px;
background: var(--scroll-bar-thumb);
}
/* Handle on hover */
#pages-container-wrapper::-webkit-scrollbar-thumb:hover {
background: var(--scroll-bar-thumb-hover);
}
/* Page Container Base Styles */
.page-container {
display: inline-block;
list-style-type: none;
width: 250px;
height: 250px;
width: 260px;
height: 260px;
line-height: 50px;
margin: 15px 25px;
margin-top: 15px;
box-sizing: border-box;
text-align: center;
aspect-ratio: 1;
position: relative;
user-select: none;
transition: width 1s linear;
transition: width 0.3s ease-in-out;
}
/* Responsive Page Container Sizes */
@media only screen and (max-width: 480px) {
.page-container {
width: calc(100vw - 90px);
height: calc(100vw - 90px);
max-width: 300px;
max-height: 300px;
margin: 5px auto;
}
#pages-container { gap: 10px; }
}
@media only screen and (min-width: 481px) and (max-width: 768px) {
.page-container {
width: calc((100vw - 120px - 12px) / 2);
height: calc((100vw - 120px - 12px) / 2);
max-width: 250px;
max-height: 250px;
margin: 6px;
}
#pages-container { gap: 12px; }
}
@media only screen and (min-width: 769px) and (max-width: 1199px) {
.page-container {
width: calc((100vw - 140px - 45px) / 3);
height: calc((100vw - 140px - 45px) / 3);
max-width: 220px;
max-height: 220px;
margin: 7px;
}
#pages-container { gap: 15px; }
}
@media only screen and (min-width: 1200px) and (max-width: 1280px) {
.page-container {
width: calc((100vw - 160px - 60px) / 4);
height: calc((100vw - 160px - 60px) / 4);
max-width: 200px;
max-height: 200px;
margin: 8px;
}
#pages-container { gap: 17px; }
}
@media only screen and (min-width: 1281px) {
.page-container {
width: calc((100vw - 180px - 80px) / 5);
height: calc((100vw - 180px - 80px) / 5);
max-width: 190px;
max-height: 190px;
margin: 10px;
}
#pages-container { gap: 20px; }
}
/* Split Page Styles */
.page-container.split-before {
border-left: 1px dashed var(--md-sys-color-on-surface);
padding-left: -1px;
@ -146,56 +216,35 @@ label {
display: none;
}
/* RTL Language Support */
.page-container:last-child:lang(ar),
/* Arabic */
.page-container:last-child:lang(he),
/* Hebrew */
.page-container:last-child:lang(fa),
/* Persian */
.page-container:last-child:lang(ur),
/* Urdu */
.page-container:last-child:lang(ckb),
/* Sorani Kurdish */
.page-container:last-child:lang(ks),
/* Kashmiri */
.page-container:last-child:lang(kk),
/* Kazakh */
.page-container:last-child:lang(uz),
/* Uzbek */
.page-container:last-child:lang(ky),
/* Kyrgyz */
.page-container:last-child:lang(bal),
/* Baluchi */
.page-container:last-child:lang(dv),
/* Divehi */
.page-container:last-child:lang(ps),
/* Pashto */
.page-container:last-child:lang(sdg),
/* Southern Kurdish */
.page-container:last-child:lang(syr),
/* Syriac */
.page-container:last-child:lang(mzn),
/* Mazanderani */
.page-container:last-child:lang(tgl),
/* Tagalog */
.page-container:last-child:lang(pnb),
/* Western Punjabi */
.page-container:last-child:lang(ug),
/* Uyghur */
.page-container:last-child:lang(nqo),
/* N'Ko */
.page-container:last-child:lang(bqi)
/* Bakhtiari */
{
.page-container:last-child:lang(bqi) {
margin-left: auto !important;
margin-right: 0 !important;
}
/* Page Image Styles */
.page-container img {
max-width: calc(100% - 15px);
max-height: calc(100% - 15px);
max-width: calc(100% - 8px);
max-height: calc(100% - 8px);
display: block;
position: absolute;
left: 50%;
@ -206,10 +255,7 @@ label {
transition: rotate 0.3s;
}
#add-pdf-button {
margin: 0 auto;
}
/* Page Number Styles */
.page-number {
position: absolute;
top: 5px;
@ -224,14 +270,20 @@ label {
font-weight: 450;
}
/* Tool Header and Button Styles */
.tool-header {
margin: 0.5rem 1rem 2rem;
margin: 0.5rem 1rem 1rem;
}
#select-pages-button {
opacity: 0.5;
}
#add-pdf-button {
margin: 0 auto;
}
/* Selected Pages Container Styles */
.selected-pages-container {
background-color: var(--md-sys-color-surface);
border-radius: 16px;
@ -247,12 +299,42 @@ label {
margin-bottom: 10px;
}
.selected-pages-header {
margin-bottom: 15px;
}
.selected-pages-header h5 {
margin: 0 0 8px 0 !important;
font-size: 1.1rem;
font-weight: 600;
color: var(--md-sys-color-on-surface);
}
.selected-pages-header #csv-input {
width: 100%;
height: 2.5rem;
border-radius: 8px;
border: 1px solid var(--md-sys-color-outline);
background-color: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
padding: 0 12px;
font-size: 0.95rem;
}
.selected-pages-header #csv-input:focus {
outline: none;
border-color: var(--md-sys-color-primary);
box-shadow: 0 0 0 2px rgba(var(--md-sys-color-primary-rgb), 0.2);
}
/* Pages List Styles */
.pages-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
padding: 0;
list-style: none;
min-height: 0;
max-height: 10rem;
overflow: auto;
}
@ -293,12 +375,251 @@ label {
font-size: medium;
}
.btn {
position: relative;
/* Zoom Level Responsive Styles */
@media only screen and (min-width: 2000px) {
.mt-action-btn {
gap: 12px;
padding: 12px 24px;
border-radius: 2.5rem;
}
.mt-action-btn .btn {
width: 4rem;
height: 4rem;
border-radius: 22px;
}
.mt-action-btn .btn .material-symbols-rounded {
font-size: 1.7rem;
}
}
@media only screen and (max-width: 767px) { #pages-container { width:300px; } }
@media only screen and (min-width: 768px) and (max-width: 991px) { #pages-container { width: 600px; } }
@media only screen and (min-width: 992px) and (max-width: 1199px) { #pages-container { width: 900px; } }
@media only screen and (min-width: 1200px) and (max-width: 1399px) { #pages-container { width: 900px; } }
@media only screen and (min-width: 1399px) { #pages-container { width: 1200px; } }
@media only screen and (min-width: 2560px) {
.mt-action-btn {
gap: 15px;
padding: 15px 30px;
border-radius: 3rem;
}
.mt-action-btn .btn {
width: 5rem;
height: 5rem;
border-radius: 28px;
}
.mt-action-btn .btn .material-symbols-rounded {
font-size: 2.1rem;
}
}
@media only screen and (min-width: 3840px) {
.mt-action-btn {
gap: 20px;
padding: 20px 40px;
border-radius: 4rem;
}
.mt-action-btn .btn {
width: 7rem;
height: 7rem;
border-radius: 40px;
}
.mt-action-btn .btn .material-symbols-rounded {
font-size: 3rem;
}
}
@media only screen and (min-width: 7680px) {
.mt-action-btn {
gap: 40px;
padding: 40px 80px;
border-radius: 8rem;
}
.mt-action-btn .btn {
width: 14rem;
height: 14rem;
border-radius: 80px;
}
.mt-action-btn .btn .material-symbols-rounded {
font-size: 6rem;
}
}
/* Zoom-responsive Sidebar Styles */
@media only screen and (max-width: 1280px) {
.container {
position: relative;
}
.mt-action-btn {
position: fixed !important;
left: 10px !important;
top: 80px !important;
bottom: 20px !important;
margin: 0 !important;
transform: none !important;
border-radius: 16px !important;
background-color: var(--md-sys-color-surface-container-low);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
backdrop-filter: blur(8px);
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
height: calc(100vh - 100px) !important;
overflow-y: auto !important;
scrollbar-width: none !important;
-ms-overflow-style: none !important;
z-index: 12;
width: 70px !important;
gap: 8px !important;
padding: 12px 8px !important;
box-sizing: border-box !important;
}
.mt-action-btn:has(.btn:nth-last-child(n+7)) {
justify-content: flex-start !important;
}
.mt-action-btn::-webkit-scrollbar {
display: none !important;
}
.mt-action-btn .btn {
width: 48px !important;
height: 48px !important;
border-radius: 12px !important;
padding: 0 !important;
margin: 0 !important;
flex-shrink: 0;
font-size: 16px !important;
box-sizing: border-box !important;
}
.mt-action-btn .btn .material-symbols-rounded {
font-size: 20px !important;
line-height: 1 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 100% !important;
height: 100% !important;
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24 !important;
}
.multi-tool-container {
margin-left: 0 !important;
max-width: 100% !important;
}
.mt-action-bar {
margin-left: 25px !important;
margin-right: 25px !important;
}
.mt-action-btn:not(:has(*:nth-child(6))) {
justify-content: center !important;
}
}
/* Mobile and High Zoom Responsive Styles */
@media only screen and (max-width: 960px) {
.mt-action-btn {
left: 8px !important;
top: 75px !important;
bottom: 15px !important;
height: calc(100vh - 90px) !important;
}
}
@media only screen and (max-width: 768px) {
.mt-action-btn {
left: 5px !important;
width: 60px !important;
top: calc(var(--navbar-height, 60px) + 10px) !important;
bottom: 10px !important;
height: calc(100vh - var(--navbar-height, 60px) - 20px) !important;
}
.mt-action-btn .btn {
width: 40px !important;
height: 40px !important;
box-sizing: border-box !important;
}
.mt-action-btn .btn .material-symbols-rounded {
font-size: 16px !important;
}
#pages-container {
margin: 0 auto !important;
display: flex !important;
flex-wrap: wrap !important;
justify-content: center !important;
width: 100% !important;
}
.page-container {
width: calc(100vw - 55px) !important;
height: calc(100vw - 60px) !important;
max-width: 350px !important;
max-height: 350px !important;
margin: 5px auto !important;
}
}
@media only screen and (max-width: 480px) {
.mt-action-btn {
left: 2px !important;
top: calc(var(--navbar-height, 60px) + 5px) !important;
bottom: 5px !important;
height: calc(100vh - var(--navbar-height, 60px) - 10px) !important;
width: 50px !important;
gap: 6px !important;
padding: 10px 6px !important;
}
.mt-action-btn .btn {
width: 32px !important;
height: 32px !important;
border-radius: 10px !important;
box-sizing: border-box !important;
}
.mt-action-btn .btn .material-symbols-rounded {
font-size: 14px !important;
}
}
@media only screen and (max-width: 384px) {
.mt-action-btn {
left: 2px !important;
top: calc(var(--navbar-height, 60px) + 5px) !important;
bottom: 5px !important;
height: calc(100vh - var(--navbar-height, 60px) - 10px) !important;
width: 40px !important;
gap: 4px !important;
padding: 8px 4px !important;
}
.mt-action-btn .btn {
width: 28px !important;
height: 28px !important;
border-radius: 8px !important;
box-sizing: border-box !important;
}
.mt-action-btn .btn .material-symbols-rounded {
font-size: 12px !important;
}
.page-container {
width: calc(100vw - 55px) !important;
height: calc(100vw - 60px) !important;
max-width: 280px !important;
max-height: 280px !important;
margin: 3px auto !important;
}
.page-container img {
max-width: calc(100% - 4px) !important;
max-height: calc(100% - 4px) !important;
}
}

View File

@ -63,6 +63,79 @@
transform: translateY(-2px);
}
/* Responsive navbar brand - prevent hamburger from wrapping */
.navbar-brand {
display: flex !important;
align-items: center;
gap: 8px;
min-width: 0; /* Allow shrinking */
}
.navbar-brand .icon-text {
font-size: 1.5rem;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Progressive text shrinking to prevent hamburger wrap */
@media only screen and (max-width: 480px) {
.navbar-brand .icon-text {
font-size: 1.3rem;
}
.main-icon {
width: 32px;
height: 32px;
}
}
@media only screen and (max-width: 420px) {
.navbar-brand .icon-text {
font-size: 1.1rem;
}
.main-icon {
width: 28px;
height: 28px;
}
}
@media only screen and (max-width: 380px) {
.navbar-brand .icon-text {
font-size: 1rem;
}
.main-icon {
width: 24px;
height: 24px;
}
}
@media only screen and (max-width: 340px) {
.navbar-brand .icon-text {
font-size: 0.9rem;
}
.main-icon {
width: 20px;
height: 20px;
}
}
/* Ultra-small screens - hide text, keep icon */
@media only screen and (max-width: 320px) {
.navbar-brand .icon-text {
display: none;
}
.main-icon {
width: 24px;
height: 24px;
}
}
.nav-icon {
vertical-align: middle;
font-size: 2rem !important;

View File

@ -2,6 +2,13 @@
if (window.isDownloadScriptInitialized) return; // Prevent re-execution
window.isDownloadScriptInitialized = true;
// Global PDF processing count tracking for survey system
window.incrementPdfProcessingCount = function() {
let pdfProcessingCount = parseInt(localStorage.getItem('pdfProcessingCount') || '0');
pdfProcessingCount++;
localStorage.setItem('pdfProcessingCount', pdfProcessingCount.toString());
};
const {
pdfPasswordPrompt,
multipleInputsForSingleRequest,
@ -312,6 +319,11 @@
pdf_pages: pageCount,
});
}
// Increment PDF processing count for survey tracking
if (success && typeof window.incrementPdfProcessingCount === 'function') {
window.incrementPdfProcessingCount();
}
}
}

View File

@ -271,6 +271,11 @@ class PdfContainer {
pdf_pages: pageCount,
});
}
// Increment PDF processing count for survey tracking
if (success && typeof window.incrementPdfProcessingCount === 'function') {
window.incrementPdfProcessingCount();
}
} catch { }
}

View File

@ -66,19 +66,16 @@ document.addEventListener('DOMContentLoaded', function () {
const dontShowAgain = document.getElementById('dontShowAgain');
const takeSurveyButton = document.getElementById('takeSurvey');
const viewThresholds = [5, 10, 15, 22, 30, 50, 75, 100, 150, 200];
const pdfProcessingThresholds = [8, 15, 22, 35, 50, 75, 100, 150];
// Check if survey version changed and reset page views if it did
// Check if survey version changed and reset PDF processing count if it did
const storedVersion = localStorage.getItem('surveyVersion');
if (storedVersion && storedVersion !== surveyVersion) {
localStorage.setItem('pageViews', '0');
localStorage.setItem('pdfProcessingCount', '0');
localStorage.setItem('surveyVersion', surveyVersion);
}
let pageViews = parseInt(localStorage.getItem('pageViews') || '0');
pageViews++;
localStorage.setItem('pageViews', pageViews.toString());
let pdfProcessingCount = parseInt(localStorage.getItem('pdfProcessingCount') || '0');
function shouldShowSurvey() {
if(!window.showSurvey) {
@ -90,11 +87,11 @@ document.addEventListener('DOMContentLoaded', function () {
}
// If survey version changed and we hit a threshold, show the survey
if (localStorage.getItem('surveyVersion') !== surveyVersion && viewThresholds.includes(pageViews)) {
if (localStorage.getItem('surveyVersion') !== surveyVersion && pdfProcessingThresholds.includes(pdfProcessingCount)) {
return true;
}
return viewThresholds.includes(pageViews);
return pdfProcessingThresholds.includes(pdfProcessingCount);
}
if (shouldShowSurvey()) {

View File

@ -35,7 +35,7 @@
const browserZoom = currentDPR / systemDPR;
// Counter-scale to maintain same visual size
const isMobile = window.innerWidth <= 768 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
const isMobile = window.innerWidth <= 768 && /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
let baseScale = isMobile ? 3 : (isHighDPI ? 2.2 : 1.1); // Prioritize mobile scaling over high DPI
const navScale = baseScale / currentDPR;
// Dropdowns at 80% (20% smaller)
@ -81,6 +81,12 @@
console.log('DPR:', currentDPR, 'isHighDPI:', isHighDPI, 'baseScale:', baseScale, 'navScale:', navScale, 'effective width:', effectiveWidth);
}
// Set CSS custom property for mobile navbar scaling (for sidebar positioning)
// Use the ACTUAL scaled height, not a fixed assumption
const baseHeight = 60;
const actualScaledHeight = baseHeight * navScale;
document.documentElement.style.setProperty('--navbar-height', `${actualScaledHeight}px`);
setTimeout(() => {
const dropdowns = document.querySelectorAll('.dropdown-menu');
dropdowns.forEach(dropdown => {
@ -379,10 +385,10 @@
Browse
</label>
<div class="d-flex flex-column align-items-center">
<div class="d-flex justify-content-start align-items-center" id="fileInputText">
<div th:text="#{fileChooser.click}" style="margin-right: 5px"></div>
<div th:text="#{fileChooser.or}" style="margin-right: 5px"></div>
<div th:text="#{fileChooser.dragAndDrop}" id="dragAndDrop"></div>
<div class="text-center" id="fileInputText" style="word-wrap: break-word; hyphens: auto; line-height: 1.2;">
<span th:text="#{fileChooser.click}"></span>
<span th:text="#{fileChooser.or}" style="margin: 0 5px;"></span>
<span th:text="#{fileChooser.dragAndDrop}" id="dragAndDrop"></span>
</div>
<hr th:if="${@GoogleDriveEnabled == true}" class="horizontal-divider" >
</div>

View File

@ -33,18 +33,16 @@
</div>
<div id="selected-pages-display" class="selected-pages-container hidden">
<div style="display:flex; height:3rem; margin-right:1rem">
<h5 th:text="#{multiTool.selectedPages}" style="white-space: nowrap; margin-right: 1rem;">Selected
Pages</h5>
<input type="text" id="csv-input" class="form-control" style="height:2.5rem" placeholder="1,3,5-10"
value="">
<div class="selected-pages-header">
<h5 th:text="#{multiTool.selectedPages}">Selected Pages</h5>
<input type="text" id="csv-input" class="form-control" placeholder="1,3,5-10" value="">
</div>
<ul id="selected-pages-list" class="pages-list"></ul>
</div>
</div>
<div class="multi-tool-container">
<div class="d-flex flex-wrap" id="pages-container-wrapper">
<div id="pages-container-wrapper">
<div id="pages-container">
</div>
</div>