mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-08 17:51:20 +02:00
Merge branch 'main' into patch-1
This commit is contained in:
commit
d148f08794
37
build.gradle
37
build.gradle
@ -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'
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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'
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 { }
|
||||
}
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user