Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NextGen Image Formats #43

Merged
merged 50 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
de72ffe
Image Optimization
arunshenoy99 Nov 18, 2024
94bdc81
Add a /
arunshenoy99 Nov 26, 2024
8389b85
Gracefully handle original file deletion
arunshenoy99 Nov 26, 2024
375664b
Update text copy
arunshenoy99 Nov 26, 2024
f15b138
Fix webp generation
arunshenoy99 Nov 26, 2024
0846116
Lazy Load Images
arunshenoy99 Nov 27, 2024
cd0703b
Exclude build folder from lint workflow
arunshenoy99 Nov 27, 2024
f9eda1e
Bulk Image Optimization of Media Library
arunshenoy99 Dec 9, 2024
36ce5d3
Update attachment and URL
arunshenoy99 Dec 9, 2024
b976bf1
Fix delete original logic
arunshenoy99 Dec 10, 2024
9ac1865
Auto delete toggle fix
arunshenoy99 Dec 10, 2024
dbb78c0
Lazy load block renders
arunshenoy99 Dec 10, 2024
d990074
Merge branch 'enhance/PRESS7-76-lazy-load-images' of https://github.c…
arunshenoy99 Dec 10, 2024
30fae45
Fix media link
arunshenoy99 Dec 10, 2024
d0d6992
Merge branch 'main' of https://github.com/newfold-labs/wp-module-perf…
arunshenoy99 Dec 18, 2024
d68b44b
Merge branch 'enhance/PRESS7-81-intercept-media-upload' of https://gi…
arunshenoy99 Dec 18, 2024
6c7e409
Add ImageManager
arunshenoy99 Dec 18, 2024
7763e93
Merge branch 'enhance/PRESS7-76-lazy-load-images' of https://github.c…
arunshenoy99 Dec 18, 2024
982b8b4
Mark Optimized Images
arunshenoy99 Dec 19, 2024
fbe020f
Fix lint
arunshenoy99 Dec 19, 2024
6f3f629
Configure .htaccess to Serve WebP Images When Available
arunshenoy99 Dec 21, 2024
4fdb648
Merge branch 'main' of https://github.com/newfold-labs/wp-module-perf…
arunshenoy99 Dec 23, 2024
7d4ce4c
Merge branch 'enhance/PRESS7-81-intercept-media-upload' of https://gi…
arunshenoy99 Dec 23, 2024
afab43f
Remove duplicate import and move Constants before ImageManager
arunshenoy99 Dec 23, 2024
8bf75d7
Merge branch 'enhance/PRESS7-76-lazy-load-images' of https://github.c…
arunshenoy99 Dec 23, 2024
2a0b620
Move Bulk Optimization above and also localize strings
arunshenoy99 Dec 23, 2024
4284dee
Add a new results screen
arunshenoy99 Dec 23, 2024
2a09574
Update build
arunshenoy99 Dec 23, 2024
8ec4c1b
Merge branch 'enhance/PRESS7-75-bulk-image-optimization' of https://g…
arunshenoy99 Dec 23, 2024
1b1d100
Merge branch 'enhance/PRESS7-131-annotate-opt-images' of https://gith…
arunshenoy99 Dec 23, 2024
d5fa3c8
Merge pull request #42 from newfold-labs/enhance/PRESS7-130-server-pr…
arunshenoy99 Dec 23, 2024
c00555b
Merge pull request #40 from newfold-labs/enhance/PRESS7-131-annotate-…
arunshenoy99 Dec 23, 2024
1859ac3
Merge pull request #35 from newfold-labs/enhance/PRESS7-75-bulk-image…
arunshenoy99 Dec 23, 2024
1b54280
Merge pull request #32 from newfold-labs/enhance/PRESS7-76-lazy-load-…
arunshenoy99 Dec 23, 2024
6f15b8a
Merge pull request #28 from newfold-labs/enhance/PRESS7-81-intercept-…
arunshenoy99 Dec 23, 2024
d68f537
Separate out CSS from bulk optimizer
arunshenoy99 Dec 25, 2024
a4ced5a
Update build and naming conventions for consistency
arunshenoy99 Dec 25, 2024
14b4557
Remove unnecessary scripts
arunshenoy99 Dec 25, 2024
6db04ef
Fix character encoding warning
arunshenoy99 Dec 27, 2024
7f05382
Disable Image Optimization by default
arunshenoy99 Dec 27, 2024
b3c5c0e
Handle postmeta updates when auto delete is enabled
arunshenoy99 Dec 27, 2024
6ad5993
Fix accesibility test on Hostgator
arunshenoy99 Dec 27, 2024
5def7a1
Auto reload the page when the modal closes
arunshenoy99 Dec 27, 2024
459e887
Auto enable all settings when image optimization is turned on
arunshenoy99 Dec 27, 2024
3b0d347
Improve text clarity
arunshenoy99 Dec 27, 2024
62cfcf5
Center modal content
arunshenoy99 Dec 27, 2024
774774b
Add MutationObserver to auto select bulk optimize based on URL param
arunshenoy99 Dec 27, 2024
9b311a5
Conditionally render media library link and update to add url param
arunshenoy99 Dec 27, 2024
10526b5
Update filetype when replacing original image
arunshenoy99 Dec 27, 2024
c16980d
Merge branch 'release/v2.2.0' of https://github.com/newfold-labs/wp-m…
arunshenoy99 Dec 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ on:
push:
paths:
- '**.php'
- '!build/**'
pull_request:
types: [opened, edited, reopened, ready_for_review]
paths:
- '**.php'
- '!build/**'
workflow_dispatch:

concurrency:
Expand Down Expand Up @@ -36,6 +38,11 @@ jobs:
**/*.php
!build/**/*.php

- name: Exclude build folder from diff
run: |
export GIT_DIFF=$(echo "$GIT_DIFF" | grep -v '^build/')
echo "Filtered diff: $GIT_DIFF"

- name: Get Composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
vendor
node_modules
vendor
.DS_Store
.vscode
56 changes: 56 additions & 0 deletions assets/image-bulk-optimizer/image-bulk-optimizer.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.nfd-performance-image-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}

.nfd-performance-image-modal-content {
background: #fff;
padding: 2rem;
border-radius: 8px;
text-align: center;
width: 400px;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

.nfd-performance-image-progress-container {
width: 100%;
height: 20px;
background: #eee;
border-radius: 10px;
margin: 1rem 0;
overflow: hidden;
position: relative;
}

.nfd-performance-image-progress-bar {
height: 100%;
width: 0;
background: #007cba;
transition: width 0.3s ease;
}

.nfd-performance-image-result-list {
text-align: center;
margin: 1rem auto;
max-height: 200px;
overflow-y: auto;
}

.nfd-performance-image-done-button {
margin-top: 1rem;
margin-left: auto;
margin-right: auto;
display: block;
}
304 changes: 304 additions & 0 deletions assets/image-bulk-optimizer/image-bulk-optimizer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
import './image-bulk-optimizer.css';

document.addEventListener( 'DOMContentLoaded', () => {
const { __ } = wp.i18n;

const bulkOptimizeButtonId = 'nfd-bulk-optimize-btn';
let cancelRequested = false;

const bulkSelectButtonClasses = [
'button',
'media-button',
'select-mode-toggle-button',
];
const deletePermanentlyButtonClasses = [
'button',
'media-button',
'button-primary',
'button-large',
'delete-selected-button',
];

const removeBulkOptimizeButton = () => {
const bulkOptimizeButton =
document.getElementById( bulkOptimizeButtonId );
if ( bulkOptimizeButton ) bulkOptimizeButton.remove();
};

const createModal = () => {
const modal = document.createElement( 'div' );
modal.id = 'nfd-bulk-modal';
modal.className = 'nfd-performance-image-modal';

const modalContent = document.createElement( 'div' );
modalContent.className = 'nfd-performance-image-modal-content';

const modalTitle = document.createElement( 'h2' );
modalTitle.id = 'nfd-modal-title';
modalTitle.textContent = __(
'Optimizing Images…',
'wp-module-performance'
);

const currentFileName = document.createElement( 'p' );
currentFileName.id = 'nfd-current-file';
currentFileName.textContent = __(
'Preparing files…',
'wp-module-performance'
);

const progressContainer = document.createElement( 'div' );
progressContainer.id = 'nfd-progress-container';
progressContainer.className =
'nfd-performance-image-progress-container';

const progressBar = document.createElement( 'div' );
progressBar.id = 'nfd-progress-bar';
progressBar.className = 'nfd-performance-image-progress-bar';

const resultList = document.createElement( 'ul' );
resultList.id = 'nfd-result-list';
resultList.className = 'nfd-performance-image-result-list';

const doneButton = document.createElement( 'button' );
doneButton.textContent = __( 'Done', 'wp-module-performance' );
doneButton.className =
'button button-secondary nfd-performance-image-done-button';
doneButton.style.display = 'none'; // Hidden initially
doneButton.addEventListener( 'click', () => {
modal.remove();
window.location.reload();
} );

progressContainer.appendChild( progressBar );
modalContent.append(
modalTitle,
currentFileName,
progressContainer,
resultList,
doneButton
);
modal.appendChild( modalContent );
document.body.appendChild( modal );

return {
modal,
progressBar,
modalTitle,
currentFileName,
resultList,
doneButton,
progressContainer,
};
};

const openModal = () => {
cancelRequested = false;
const {
progressBar,
modalTitle,
currentFileName,
resultList,
doneButton,
progressContainer,
} = createModal();
progressBar.style.width = '0%';
currentFileName.textContent = '';
return {
progressBar,
modalTitle,
currentFileName,
resultList,
doneButton,
progressContainer,
};
};

const getFileName = ( attachment ) => {
return attachment.getAttribute( 'aria-label' );
};

const handleBulkOptimize = async () => {
const selectedItems = Array.from(
document.querySelectorAll( '.attachment.selected' )
).map( ( attachment ) => ( {
id: attachment.getAttribute( 'data-id' ),
name: getFileName( attachment ),
} ) );

if ( ! selectedItems.length ) return;

const apiUrl =
window.nfdPerformance?.imageOptimization?.bulkOptimizer?.apiUrl;

if ( ! apiUrl ) {
return;
}

const {
progressBar,
modalTitle,
currentFileName,
resultList,
doneButton,
progressContainer,
} = openModal();
const results = [];

try {
for ( let i = 0; i < selectedItems.length; i++ ) {
if ( cancelRequested ) {
modalTitle.textContent = __(
'Optimization Canceled',
'wp-module-performance'
);
break;
}

const { id: mediaId, name: fileName } = selectedItems[ i ];
currentFileName.textContent =
__( 'Optimizing:', 'wp-module-performance' ) +
` ${ fileName }`;

try {
await wp.apiFetch( {
url: apiUrl,
method: 'POST',
data: { media_id: parseInt( mediaId, 10 ) },
} );

results.push( { name: fileName, status: 'passed' } );
} catch ( error ) {
results.push( { name: fileName, status: 'failed' } );
}

const progress = ( ( i + 1 ) / selectedItems.length ) * 100;
progressBar.style.width = `${ progress }%`;
}

modalTitle.textContent = __(
'Optimization Complete!',
'wp-module-performance'
);
progressContainer.style.display = 'none';
currentFileName.style.display = 'none';

results.forEach( ( { name, status } ) => {
const listItem = document.createElement( 'li' );
const statusText =
status === 'passed'
? __( 'Passed', 'wp-module-performance' )
: __( 'Failed', 'wp-module-performance' );

listItem.textContent = `${ name } - ${ statusText }`;
resultList.appendChild( listItem );
} );

doneButton.style.display = 'block';
} catch ( error ) {
modalTitle.textContent = __(
'An error occurred.',
'wp-module-performance'
);
}
};

const createBulkOptimizeButton = () => {
const bulkOptimizeButton = document.createElement( 'button' );
bulkOptimizeButton.id = bulkOptimizeButtonId;
bulkOptimizeButton.className =
'button media-button button-large button-primary';
bulkOptimizeButton.textContent = __(
'Optimize',
'wp-module-performance'
);
bulkOptimizeButton.disabled = true;
bulkOptimizeButton.addEventListener( 'click', handleBulkOptimize );
return bulkOptimizeButton;
};

const addBulkOptimizeButton = () => {
if ( document.getElementById( bulkOptimizeButtonId ) ) return;

const deletePermanentlyButton = document.querySelector(
'.button.media-button.button-primary.button-large.delete-selected-button'
);

if (
! hasExactClassList(
deletePermanentlyButton,
deletePermanentlyButtonClasses
)
)
return;

const bulkOptimizeButton = createBulkOptimizeButton();
deletePermanentlyButton.parentElement.insertBefore(
bulkOptimizeButton,
deletePermanentlyButton.nextSibling
);

monitorSelectedItems( bulkOptimizeButton );
};

const monitorSelectedItems = ( bulkOptimizeButton ) => {
const updateButtonState = () => {
const hasSelectedItems =
document.querySelectorAll( '.attachment.selected' ).length > 0;
bulkOptimizeButton.disabled = ! hasSelectedItems;
};

const mediaFrameContent = document.querySelector(
'.media-frame-content'
);
if ( mediaFrameContent ) {
const observer = new MutationObserver( updateButtonState );
observer.observe( mediaFrameContent, {
childList: true,
subtree: true,
} );
updateButtonState();
}
};

const hasExactClassList = ( element, classList ) =>
element?.classList.length === classList.length &&
classList.every( ( cls ) => element.classList.contains( cls ) );

// Automatically select the Bulk Select button if the URL parameter is set
const urlParams = new URLSearchParams( window.location.search );
const autoSelect = urlParams.get( 'autoSelectBulk' );

if ( autoSelect === 'true' ) {
const observer = new MutationObserver( () => {
const bulkSelectButton = document.querySelector(
'.button.media-button.select-mode-toggle-button'
);

if ( bulkSelectButton ) {
bulkSelectButton.click();
observer.disconnect();
}
} );

observer.observe( document.body, { childList: true, subtree: true } );
}

const observer = new MutationObserver( () => {
const bulkSelectButton = document.querySelector(
'.button.media-button.select-mode-toggle-button'
);

const isBulkSelectButtonVisible = hasExactClassList(
bulkSelectButton,
bulkSelectButtonClasses
);
if ( isBulkSelectButtonVisible ) {
removeBulkOptimizeButton();
} else {
addBulkOptimizeButton();
}
} );

observer.observe( document.body, { childList: true, subtree: true } );
} );
Loading
Loading