From ccd718ada133fa34479df03fbda0f590e8596944 Mon Sep 17 00:00:00 2001 From: Utsav Patel Date: Wed, 24 Dec 2025 13:05:00 +0530 Subject: [PATCH 01/21] chore: fix media sync/edit frame issue with loading --- .../components/browser-uploader.js | 2 + assets/src/admin/media-sharing/index.js | 6 +- assets/src/css/main.scss | 14 ---- inc/Modules/MediaLibrary/Admin.php | 83 ++++++------------- 4 files changed, 29 insertions(+), 76 deletions(-) diff --git a/assets/src/admin/media-sharing/components/browser-uploader.js b/assets/src/admin/media-sharing/components/browser-uploader.js index 824527f..00ee799 100644 --- a/assets/src/admin/media-sharing/components/browser-uploader.js +++ b/assets/src/admin/media-sharing/components/browser-uploader.js @@ -109,6 +109,7 @@ const BrowserUploaderButton = ( { multiple: false, library: { type: ALLOWED_MIME_TYPES, + is_onemedia_sync: false, }, } ); @@ -192,6 +193,7 @@ const BrowserUploaderButton = ( { multiple: false, library: { type: ALLOWED_MIME_TYPES, + is_onemedia_sync: false, }, } ); diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index c4ae2c3..a18ac11 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -199,7 +199,7 @@ const MediaSharingApp = ( { } }; - const handleEditMedia = ( mediaId, currentImageType ) => { + const handleEditMedia = ( mediaId ) => { if ( getFrameProperty( 'wp.media' ) ) { // Create edit media frame. const editFrame = window.wp.media( { @@ -210,8 +210,7 @@ const MediaSharingApp = ( { multiple: false, library: { type: 'image', - onemedia_sync_media_filter: - ONEMEDIA_PLUGIN_TAXONOMY_TERM === currentImageType ? true : false, + is_onemedia_sync: true, }, } ); @@ -516,7 +515,6 @@ const MediaSharingApp = ( { e.stopPropagation(); handleEditMedia( media.id, - imageType, ); } } title={ __( 'Edit Media', 'onemedia' ) } diff --git a/assets/src/css/main.scss b/assets/src/css/main.scss index b62df76..f797db2 100644 --- a/assets/src/css/main.scss +++ b/assets/src/css/main.scss @@ -508,17 +508,3 @@ pointer-events: none; } } - -.onemedia-select-non-sync-media-frame { - - .onemedia-synced-media { - display: none; - } -} - -.onemedia-edit-media-frame { - - .onemedia-non-synced-media { - display: none; - } -} diff --git a/inc/Modules/MediaLibrary/Admin.php b/inc/Modules/MediaLibrary/Admin.php index f4ff0b1..a0427e4 100644 --- a/inc/Modules/MediaLibrary/Admin.php +++ b/inc/Modules/MediaLibrary/Admin.php @@ -11,7 +11,6 @@ use OneMedia\Modules\Core\Assets; use OneMedia\Modules\MediaSharing\Attachment; use OneMedia\Modules\Settings\Settings; -use OneMedia\Modules\Taxonomies\Media; /** * Class Admin @@ -26,7 +25,6 @@ public function register_hooks(): void { add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ], 20 ); add_filter( 'ajax_query_attachments_args', [ $this,'filter_ajax_query_attachments_args' ] ); - add_filter( 'ajax_query_attachments_args', [ $this,'filter_ajax_query_attachments' ] ); } /** @@ -122,63 +120,32 @@ public function filter_ajax_query_attachments_args( array $query ): array { } } - return $query; - } - - /** - * Filter the AJAX query for attachments to include or exclude onemedia_sync based on the onemedia_sync_media_filter parameter. - * - * @param array $query The current query arguments. - * - * @return array Modified query arguments. - */ - public function filter_ajax_query_attachments( array $query ): array { - // Return early if not an AJAX request. - if ( ! wp_doing_ajax() ) { - return $query; - } - - // Nonce verification for AJAX requests. - $nonce = filter_input( INPUT_POST, '_ajax_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); - $nonce = sanitize_text_field( wp_unslash( $nonce ) ); - if ( ! wp_verify_nonce( $nonce, 'onemedia_check_sync_status' ) ) { - return $query; - } - - // Check if this is an AJAX request for attachments. - $post_action = filter_input( INPUT_POST, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); - - if ( ! isset( $post_action ) || empty( $post_action ) || 'query-attachments' !== $post_action ) { - return $query; - } - - $post_query = isset( $_POST['query'] ) && is_array( $_POST['query'] ) ? array_map( 'sanitize_text_field', $_POST['query'] ) : []; - if ( empty( $post_query['onemedia_sync_media_filter'] ) ) { - return $query; - } + // check for is_onemedia_sync meta filter. + if ( ! empty( $request_query['is_onemedia_sync'] ) ) { + $is_onemedia_sync = filter_var( $request_query['is_onemedia_sync'], FILTER_VALIDATE_BOOLEAN ); - $onemedia_sync_media_filter = sanitize_text_field( wp_unslash( $post_query['onemedia_sync_media_filter'] ) ); - - if ( 'true' === $onemedia_sync_media_filter ) { - $query['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query - [ - 'taxonomy' => Media::TAXONOMY, - 'field' => 'slug', - 'terms' => Media::TAXONOMY_TERM, - ], - ]; - } - - // If onemedia_sync_media_filter: false then exclude onemedia. - if ( 'false' === $onemedia_sync_media_filter ) { - $query['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query - [ - 'taxonomy' => Media::TAXONOMY, - 'field' => 'slug', - 'terms' => Media::TAXONOMY_TERM, - 'operator' => 'NOT IN', - ], - ]; + if ( true === $is_onemedia_sync ) { + $query['meta_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query + [ + 'key' => Attachment::IS_SYNC_POSTMETA_KEY, + 'value' => true, + 'compare' => '=', + ], + ]; + } else { + $query['meta_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query + 'relation' => 'OR', + [ + 'key' => Attachment::IS_SYNC_POSTMETA_KEY, + 'value' => false, + 'compare' => '=', + ], + [ + 'key' => Attachment::IS_SYNC_POSTMETA_KEY, + 'compare' => 'NOT EXISTS', + ], + ]; + } } return $query; From 3058ed5180140b1d6ecae4ea2107b3abbf3f480f Mon Sep 17 00:00:00 2001 From: Utsav Patel Date: Wed, 24 Dec 2025 13:25:04 +0530 Subject: [PATCH 02/21] chore: restrict upload media type under onemedia frame --- .../components/browser-uploader.js | 30 +++++++++++++++++++ assets/src/admin/media-sharing/index.js | 18 +++++++++++ 2 files changed, 48 insertions(+) diff --git a/assets/src/admin/media-sharing/components/browser-uploader.js b/assets/src/admin/media-sharing/components/browser-uploader.js index 00ee799..05bd686 100644 --- a/assets/src/admin/media-sharing/components/browser-uploader.js +++ b/assets/src/admin/media-sharing/components/browser-uploader.js @@ -113,6 +113,21 @@ const BrowserUploaderButton = ( { }, } ); + // restrict upload type for our media modal. + frame.once( 'uploader:ready', () => { + const uploader = frame.uploader.uploader.uploader; + uploader.setOption( 'filters', + { + mime_types: [ + { extensions: ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ) }, + ], + }, + ); + + //Trick to reinit field + uploader.setOption( 'multi_selection', false ); + } ); + frame.on( 'open', () => { const frameEl = frame.el; if ( frameEl ) { @@ -197,6 +212,21 @@ const BrowserUploaderButton = ( { }, } ); + // restrict upload type for our media modal. + frame.once( 'uploader:ready', () => { + const uploader = frame.uploader.uploader.uploader; + uploader.setOption( 'filters', + { + mime_types: [ + { extensions: ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ) }, + ], + }, + ); + + //Trick to reinit field + uploader.setOption( 'multi_selection', false ); + } ); + frame.on( 'open', () => { const frameEl = frame.el; if ( frameEl ) { diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index a18ac11..1054af6 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -39,6 +39,9 @@ const MEDIA_PER_PAGE = 12; const ONEMEDIA_PLUGIN_TAXONOMY_TERM = 'onemedia'; const UPLOAD_NONCE = window.OneMediaMediaSharing?.uploadNonce || ''; const ONEMEDIA_MEDIA_SHARING = window.OneMediaMediaSharing || {}; +const ALLOWED_MIME_TYPES = window.OneMediaMediaFrame?.allowedMimeTypes !== 'undefined' + ? Object.values( window.OneMediaMediaFrame?.allowedMimeTypes ) + : []; const MediaSharingApp = ( { imageType = '', @@ -214,6 +217,21 @@ const MediaSharingApp = ( { }, } ); + // restrict upload type for our media modal. + editFrame.once( 'uploader:ready', () => { + const uploader = editFrame.uploader.uploader.uploader; + uploader.setOption( 'filters', + { + mime_types: [ + { extensions: ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ) }, + ], + }, + ); + + //Trick to reinit field + uploader.setOption( 'multi_selection', false ); + } ); + editFrame.on( 'open', function() { // Reset the selection state. editFrame.state().get( 'selection' ).reset(); From 068fb43c1a70d1b20faee8f88eebbbca9e977094 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Wed, 24 Dec 2025 13:25:31 +0530 Subject: [PATCH 03/21] FIX: Filter width --- assets/src/css/main.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/src/css/main.scss b/assets/src/css/main.scss index f797db2..eb87c09 100644 --- a/assets/src/css/main.scss +++ b/assets/src/css/main.scss @@ -252,7 +252,7 @@ } .onemedia_page_onemedia-media-sharing, -.media_page_onemedia-media-sharing { +.toplevel_page_onemedia { .components-tooltip { white-space: pre-line; @@ -270,8 +270,8 @@ } .media-toolbar-secondary .attachment-filters { - width: 100%; - max-width: 100%; + width: 100% !important; + max-width: 100% !important; } } } @@ -502,9 +502,9 @@ } } -.onemedia-selec-sync-media-frame{ +.onemedia-selec-sync-media-frame { - .onemedia-synced-media{ + .onemedia-synced-media { pointer-events: none; } } From 21111c7bc43feacf507867fa58ac801e53d95269 Mon Sep 17 00:00:00 2001 From: Utsav Patel Date: Wed, 24 Dec 2025 13:35:36 +0530 Subject: [PATCH 04/21] added docs comment --- .../components/browser-uploader.js | 18 ++++++++++++++---- assets/src/admin/media-sharing/index.js | 9 +++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/assets/src/admin/media-sharing/components/browser-uploader.js b/assets/src/admin/media-sharing/components/browser-uploader.js index 05bd686..5fd45d9 100644 --- a/assets/src/admin/media-sharing/components/browser-uploader.js +++ b/assets/src/admin/media-sharing/components/browser-uploader.js @@ -113,7 +113,12 @@ const BrowserUploaderButton = ( { }, } ); - // restrict upload type for our media modal. + /** + * Using mine_type will restrict the upload types in media modal, + * Which we don't want as we only need to restrict for OneMedia uploader frame. + * + * @see https://wordpress.stackexchange.com/questions/343320/restrict-file-types-in-the-uploader-of-a-wp-media-frame + */ frame.once( 'uploader:ready', () => { const uploader = frame.uploader.uploader.uploader; uploader.setOption( 'filters', @@ -124,7 +129,7 @@ const BrowserUploaderButton = ( { }, ); - //Trick to reinit field + // Trick to re-init field uploader.setOption( 'multi_selection', false ); } ); @@ -212,7 +217,12 @@ const BrowserUploaderButton = ( { }, } ); - // restrict upload type for our media modal. + /** + * Using mine_type will restrict the upload types in media modal, + * Which we don't want as we only need to restrict for OneMedia uploader frame. + * + * @see https://wordpress.stackexchange.com/questions/343320/restrict-file-types-in-the-uploader-of-a-wp-media-frame + */ frame.once( 'uploader:ready', () => { const uploader = frame.uploader.uploader.uploader; uploader.setOption( 'filters', @@ -223,7 +233,7 @@ const BrowserUploaderButton = ( { }, ); - //Trick to reinit field + // Trick to re-init field uploader.setOption( 'multi_selection', false ); } ); diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index 1054af6..630287a 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -217,7 +217,12 @@ const MediaSharingApp = ( { }, } ); - // restrict upload type for our media modal. + /** + * Using mine_type will restrict the upload types in media modal, + * Which we don't want as we only need to restrict for OneMedia uploader frame. + * + * @see https://wordpress.stackexchange.com/questions/343320/restrict-file-types-in-the-uploader-of-a-wp-media-frame + */ editFrame.once( 'uploader:ready', () => { const uploader = editFrame.uploader.uploader.uploader; uploader.setOption( 'filters', @@ -228,7 +233,7 @@ const MediaSharingApp = ( { }, ); - //Trick to reinit field + // Trick to re-init field uploader.setOption( 'multi_selection', false ); } ); From ce878485e5ed59b9d8abbb434f659ef6fcf8e9e0 Mon Sep 17 00:00:00 2001 From: Utsav Patel Date: Wed, 24 Dec 2025 13:45:54 +0530 Subject: [PATCH 05/21] address PR feedback --- inc/Modules/MediaLibrary/Admin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inc/Modules/MediaLibrary/Admin.php b/inc/Modules/MediaLibrary/Admin.php index a0427e4..1867282 100644 --- a/inc/Modules/MediaLibrary/Admin.php +++ b/inc/Modules/MediaLibrary/Admin.php @@ -121,14 +121,14 @@ public function filter_ajax_query_attachments_args( array $query ): array { } // check for is_onemedia_sync meta filter. - if ( ! empty( $request_query['is_onemedia_sync'] ) ) { + if ( isset( $request_query['is_onemedia_sync'] ) ) { $is_onemedia_sync = filter_var( $request_query['is_onemedia_sync'], FILTER_VALIDATE_BOOLEAN ); if ( true === $is_onemedia_sync ) { $query['meta_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query [ 'key' => Attachment::IS_SYNC_POSTMETA_KEY, - 'value' => true, + 'value' => '1', 'compare' => '=', ], ]; @@ -137,7 +137,7 @@ public function filter_ajax_query_attachments_args( array $query ): array { 'relation' => 'OR', [ 'key' => Attachment::IS_SYNC_POSTMETA_KEY, - 'value' => false, + 'value' => '0', 'compare' => '=', ], [ From e632b9b0f3be32df269016c32c5a6f2f40600dd7 Mon Sep 17 00:00:00 2001 From: Utsav Patel Date: Wed, 24 Dec 2025 13:47:42 +0530 Subject: [PATCH 06/21] check object type --- assets/src/admin/media-sharing/components/browser-uploader.js | 2 +- assets/src/admin/media-sharing/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/src/admin/media-sharing/components/browser-uploader.js b/assets/src/admin/media-sharing/components/browser-uploader.js index 5fd45d9..b06347a 100644 --- a/assets/src/admin/media-sharing/components/browser-uploader.js +++ b/assets/src/admin/media-sharing/components/browser-uploader.js @@ -13,7 +13,7 @@ import { getFrameProperty, showSnackbarNotice } from '../../../js/utils'; // const UPLOAD_NONCE = window.OneMediaMediaFrame?.uploadNonce || ''; -const ALLOWED_MIME_TYPES = window.OneMediaMediaFrame?.allowedMimeTypes !== 'undefined' +const ALLOWED_MIME_TYPES = typeof window.OneMediaMediaFrame?.allowedMimeTypes !== 'undefined' ? Object.values( window.OneMediaMediaFrame?.allowedMimeTypes ) : []; diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index 630287a..7ff7c88 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -39,7 +39,7 @@ const MEDIA_PER_PAGE = 12; const ONEMEDIA_PLUGIN_TAXONOMY_TERM = 'onemedia'; const UPLOAD_NONCE = window.OneMediaMediaSharing?.uploadNonce || ''; const ONEMEDIA_MEDIA_SHARING = window.OneMediaMediaSharing || {}; -const ALLOWED_MIME_TYPES = window.OneMediaMediaFrame?.allowedMimeTypes !== 'undefined' +const ALLOWED_MIME_TYPES = typeof window.OneMediaMediaFrame?.allowedMimeTypes !== 'undefined' ? Object.values( window.OneMediaMediaFrame?.allowedMimeTypes ) : []; From 37d9c325b9b86c422135008af4750c6652cc90d5 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Wed, 24 Dec 2025 14:12:38 +0530 Subject: [PATCH 07/21] FIX: Types issue --- .../components/browser-uploader.js | 42 ++----------------- assets/src/admin/media-sharing/index.js | 22 +--------- assets/src/css/main.scss | 1 - assets/src/js/utils.ts | 39 +++++++++++++++++ 4 files changed, 44 insertions(+), 60 deletions(-) diff --git a/assets/src/admin/media-sharing/components/browser-uploader.js b/assets/src/admin/media-sharing/components/browser-uploader.js index b06347a..d00d7c8 100644 --- a/assets/src/admin/media-sharing/components/browser-uploader.js +++ b/assets/src/admin/media-sharing/components/browser-uploader.js @@ -9,7 +9,7 @@ import { useState, useRef } from '@wordpress/element'; * Internal dependencies */ import { uploadMedia, updateExistingAttachment, checkIfAllSitesConnected, isSyncAttachment as isSyncAttachmentApi } from '../../../components/api'; -import { getFrameProperty, showSnackbarNotice } from '../../../js/utils'; +import { getFrameProperty, restrictMediaFrameUploadTypes, showSnackbarNotice } from '../../../js/utils'; // const UPLOAD_NONCE = window.OneMediaMediaFrame?.uploadNonce || ''; @@ -113,25 +113,7 @@ const BrowserUploaderButton = ( { }, } ); - /** - * Using mine_type will restrict the upload types in media modal, - * Which we don't want as we only need to restrict for OneMedia uploader frame. - * - * @see https://wordpress.stackexchange.com/questions/343320/restrict-file-types-in-the-uploader-of-a-wp-media-frame - */ - frame.once( 'uploader:ready', () => { - const uploader = frame.uploader.uploader.uploader; - uploader.setOption( 'filters', - { - mime_types: [ - { extensions: ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ) }, - ], - }, - ); - - // Trick to re-init field - uploader.setOption( 'multi_selection', false ); - } ); + restrictMediaFrameUploadTypes( frame, ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ).replaceAll( '+xml', '' ) ); frame.on( 'open', () => { const frameEl = frame.el; @@ -217,25 +199,7 @@ const BrowserUploaderButton = ( { }, } ); - /** - * Using mine_type will restrict the upload types in media modal, - * Which we don't want as we only need to restrict for OneMedia uploader frame. - * - * @see https://wordpress.stackexchange.com/questions/343320/restrict-file-types-in-the-uploader-of-a-wp-media-frame - */ - frame.once( 'uploader:ready', () => { - const uploader = frame.uploader.uploader.uploader; - uploader.setOption( 'filters', - { - mime_types: [ - { extensions: ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ) }, - ], - }, - ); - - // Trick to re-init field - uploader.setOption( 'multi_selection', false ); - } ); + restrictMediaFrameUploadTypes( frame, ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ).replaceAll( '+xml', '' ) ); frame.on( 'open', () => { const frameEl = frame.el; diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index 7ff7c88..c106ae1 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -32,7 +32,7 @@ import BrowserUploaderButton from './components/browser-uploader'; import ShareMediaModal from './components/ShareMediaModal'; import VersionModal from './components/VersionModal'; import { fetchSyncedSites as fetchSyncedSitesApi, fetchMediaItems as fetchMediaItemsApi, fetchBrandSites as fetchBrandSitesApi, shareMedia as shareMediaApi, uploadMedia } from '../../components/api'; -import { getNoticeClass, trimTitle, debounce, getFrameProperty } from '../../js/utils'; +import { getNoticeClass, trimTitle, debounce, getFrameProperty, restrictMediaFrameUploadTypes } from '../../js/utils'; import fallbackImage from '../../images/fallback-image.svg'; const MEDIA_PER_PAGE = 12; @@ -217,25 +217,7 @@ const MediaSharingApp = ( { }, } ); - /** - * Using mine_type will restrict the upload types in media modal, - * Which we don't want as we only need to restrict for OneMedia uploader frame. - * - * @see https://wordpress.stackexchange.com/questions/343320/restrict-file-types-in-the-uploader-of-a-wp-media-frame - */ - editFrame.once( 'uploader:ready', () => { - const uploader = editFrame.uploader.uploader.uploader; - uploader.setOption( 'filters', - { - mime_types: [ - { extensions: ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ) }, - ], - }, - ); - - // Trick to re-init field - uploader.setOption( 'multi_selection', false ); - } ); + restrictMediaFrameUploadTypes( editFrame, ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ).replaceAll( '+xml', '' ) ); editFrame.on( 'open', function() { // Reset the selection state. diff --git a/assets/src/css/main.scss b/assets/src/css/main.scss index eb87c09..b7782f1 100644 --- a/assets/src/css/main.scss +++ b/assets/src/css/main.scss @@ -251,7 +251,6 @@ } } -.onemedia_page_onemedia-media-sharing, .toplevel_page_onemedia { .components-tooltip { diff --git a/assets/src/js/utils.ts b/assets/src/js/utils.ts index 3bf441a..a89baee 100644 --- a/assets/src/js/utils.ts +++ b/assets/src/js/utils.ts @@ -4,6 +4,22 @@ import type { NoticeType } from '../admin/settings/page'; +type WPMediaUploader = { + setOption( + key: 'filters' | 'multi_selection' | string, + value: string | object | boolean, + ): void; +}; + +type WPMediaFrame = { + once( event: 'uploader:ready' | string, cb: () => void ): void; + uploader: { + uploader: { + uploader: WPMediaUploader; + }; + }; +}; + /** * Helper function to validate if a string is a well-formed URL. * @@ -194,6 +210,28 @@ const showSnackbarNotice = ( detail: NoticeType ): void => { document.dispatchEvent( event ); }; +const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: string ) => { + /** + * Using mime_type will restrict the upload types in media modal, + * Which we don't want as we only need to restrict for OneMedia uploader frame. + * + * @see https://wordpress.stackexchange.com/questions/343320/restrict-file-types-in-the-uploader-of-a-wp-media-frame + */ + frame.once( 'uploader:ready', () => { + const uploader = frame.uploader.uploader.uploader; + uploader.setOption( 'filters', + { + mime_types: [ + { extensions: allowedTypes }, + ], + }, + ); + + // Trick to re-init field + uploader.setOption( 'multi_selection', false ); + } ); +}; + export { isURL, isValidUrl, @@ -204,4 +242,5 @@ export { observeElement, getFrameProperty, showSnackbarNotice, + restrictMediaFrameUploadTypes, }; From e41f4db6166cf724f5b18d70a6208713db10c203 Mon Sep 17 00:00:00 2001 From: Utsav Patel Date: Wed, 24 Dec 2025 17:20:50 +0530 Subject: [PATCH 08/21] chore: refactor sync/non sync media approach --- assets/src/admin/media-sharing/index.js | 2 +- assets/src/js/media-frame.js | 6 +-- assets/src/js/utils.ts | 53 ++++++++++++++++++- inc/Modules/MediaSharing/Attachment.php | 11 ++++ inc/Modules/MediaSharing/MediaActions.php | 2 +- inc/Modules/MediaSharing/MediaProtection.php | 28 +++++++--- inc/Modules/MediaSharing/UserInterface.php | 17 ++---- inc/Modules/Rest/Media_Sharing_Controller.php | 3 ++ 8 files changed, 96 insertions(+), 26 deletions(-) diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index c106ae1..c8beda2 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -217,7 +217,7 @@ const MediaSharingApp = ( { }, } ); - restrictMediaFrameUploadTypes( editFrame, ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ).replaceAll( '+xml', '' ) ); + restrictMediaFrameUploadTypes( editFrame, ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ).replaceAll( '+xml', '' ), true ); editFrame.on( 'open', function() { // Reset the selection state. diff --git a/assets/src/js/media-frame.js b/assets/src/js/media-frame.js index a966abe..2c3243a 100644 --- a/assets/src/js/media-frame.js +++ b/assets/src/js/media-frame.js @@ -36,7 +36,7 @@ function isSyncAttachment( attachmentOrElement ) { // Handle Backbone model if ( typeof attachmentOrElement.get === 'function' ) { - return isSyncValue( attachmentOrElement.get( 'is_sync_attachment' ) ); + return isSyncValue( attachmentOrElement.get( 'is_onemedia_sync' ) ); } // Not a DOM element @@ -55,7 +55,7 @@ function isSyncAttachment( attachmentOrElement ) { if ( wpMedia && wpMedia.attachment ) { const attachment = wpMedia.attachment( attachmentId ); if ( attachment && attachment.get ) { - return isSyncValue( attachment.get( 'is_sync_attachment' ) ); + return isSyncValue( attachment.get( 'is_onemedia_sync' ) ); } } @@ -80,7 +80,7 @@ function customizeSyncMediaFrame() { originalAttachmentRender.apply( this, arguments ); // Add custom class if synced. - if ( this.model.get( 'is_sync_attachment' ) === true ) { + if ( this.model.get( 'is_onemedia_sync' ) === true ) { // this.el is the native DOM element const element = this.el; diff --git a/assets/src/js/utils.ts b/assets/src/js/utils.ts index a89baee..1cc848a 100644 --- a/assets/src/js/utils.ts +++ b/assets/src/js/utils.ts @@ -5,6 +5,9 @@ import type { NoticeType } from '../admin/settings/page'; type WPMediaUploader = { + settings: { + multipart_params: Record; + } setOption( key: 'filters' | 'multi_selection' | string, value: string | object | boolean, @@ -18,8 +21,29 @@ type WPMediaFrame = { uploader: WPMediaUploader; }; }; + on( event: 'ready' | string, cb: () => void ): void; + state(): { + get( key: 'library' | string ): { + observe( queue: unknown ): void; + } | undefined; + }; }; +declare global { + interface Window { + wp: { + Uploader: { + queue: unknown; + }; + media: { + attachment( id: number ): { + get( key: string ): unknown; + } | undefined; + }; + }; + } +} + /** * Helper function to validate if a string is a well-formed URL. * @@ -210,7 +234,16 @@ const showSnackbarNotice = ( detail: NoticeType ): void => { document.dispatchEvent( event ); }; -const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: string ) => { +/** + * Restrict upload types in a WordPress media frame. + * + * @param {WPMediaFrame} frame - The WordPress media frame to restrict. + * @param {string} allowedTypes - Comma-separated list of allowed file extensions. + * @param {boolean} is_sync - Whether the upload is for sync (default false). + * + * @return {void} + */ +const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: string, is_sync:boolean = false ) => { /** * Using mime_type will restrict the upload types in media modal, * Which we don't want as we only need to restrict for OneMedia uploader frame. @@ -219,6 +252,10 @@ const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: stri */ frame.once( 'uploader:ready', () => { const uploader = frame.uploader.uploader.uploader; + + // Get existing multipart_params first + const existingParams = uploader.settings.multipart_params || {}; + uploader.setOption( 'filters', { mime_types: [ @@ -229,6 +266,20 @@ const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: stri // Trick to re-init field uploader.setOption( 'multi_selection', false ); + + // Set is_onemedia_sync param + uploader.setOption( 'multipart_params', { + ...existingParams, + is_onemedia_sync: is_sync, + } ); + } ); + + // Observe the library to link with uploader queue. + frame.on( 'ready', function() { + const library = frame.state().get( 'library' ); + if ( library && window.wp.Uploader && window.wp.Uploader.queue ) { + library.observe( window.wp.Uploader.queue ); + } } ); }; diff --git a/inc/Modules/MediaSharing/Attachment.php b/inc/Modules/MediaSharing/Attachment.php index 4426359..df98519 100644 --- a/inc/Modules/MediaSharing/Attachment.php +++ b/inc/Modules/MediaSharing/Attachment.php @@ -63,6 +63,17 @@ public function register_hooks(): void { */ public function register_attachment_post_meta(): void { $post_meta = [ + self::IS_SYNC_POSTMETA_KEY => [ + 'show_in_rest' => true, + 'single' => true, + 'type' => 'boolean', + 'default' => false, + 'revisions_enabled' => false, + 'description' => __( 'Indicates if the attachment is synced to brand site or not.', 'onemedia' ), + 'auth_callback' => static function (): bool { + return current_user_can( 'edit_posts' ); + }, + ], self::SYNC_STATUS_POSTMETA_KEY => [ 'show_in_rest' => [ 'schema' => [ diff --git a/inc/Modules/MediaSharing/MediaActions.php b/inc/Modules/MediaSharing/MediaActions.php index cbe136b..12208e7 100644 --- a/inc/Modules/MediaSharing/MediaActions.php +++ b/inc/Modules/MediaSharing/MediaActions.php @@ -874,7 +874,7 @@ public function add_sync_meta( $response, $attachment ) { } // Add sync status to the response. - $response['is_sync_attachment'] = Attachment::is_sync_attachment( $attachment->ID ); + $response['is_onemedia_sync'] = Attachment::is_sync_attachment( $attachment->ID ); return $response; } diff --git a/inc/Modules/MediaSharing/MediaProtection.php b/inc/Modules/MediaSharing/MediaProtection.php index d6adcb4..11c8cb4 100644 --- a/inc/Modules/MediaSharing/MediaProtection.php +++ b/inc/Modules/MediaSharing/MediaProtection.php @@ -38,19 +38,35 @@ public function register_hooks(): void { * @return void */ public function add_term_to_attachment( int $attachment_id ): void { - $is_onemedia_attachment = metadata_exists( 'post', $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY ); - if ( ! $attachment_id || ! taxonomy_exists( Media::TAXONOMY ) || ! $is_onemedia_attachment ) { + if ( ! wp_doing_ajax() ) { + return; + } + $action = isset( $_REQUEST['action'] ) ? sanitize_text_field( $_REQUEST['action'] ) : ''; + if ( 'upload-attachment' !== $action ) { + return; + } + // check if is_onemedia_sync is set and true. + $is_onemedia_sync = isset( $_POST['is_onemedia_sync'] ) && + filter_var( $_POST['is_onemedia_sync'], FILTER_VALIDATE_BOOLEAN ); + + // Verify nonce for security. + if ( ! isset( $_POST['_wpnonce'] ) ) { return; } - // Assign the 'onemedia' term to the attachment. - $success = wp_set_object_terms( $attachment_id, Media::TAXONOMY_TERM, Media::TAXONOMY, true ); + if ( isset( $_POST['_wpnonce'] ) ) { + $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ); + if ( ! wp_verify_nonce( $nonce, 'media-form' ) ) { + return; + } + } + update_post_meta( $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY, $is_onemedia_sync ); - if ( ! is_wp_error( $success ) ) { + if ( true !== $is_onemedia_sync ) { return; } - wp_send_json_error( [ 'message' => __( 'Failed to assign taxonomy term to attachment.', 'onemedia' ) ], 500 ); + wp_set_object_terms( $attachment_id, Media::TAXONOMY_TERM, Media::TAXONOMY, true ); } /** diff --git a/inc/Modules/MediaSharing/UserInterface.php b/inc/Modules/MediaSharing/UserInterface.php index e2724a0..02b9402 100644 --- a/inc/Modules/MediaSharing/UserInterface.php +++ b/inc/Modules/MediaSharing/UserInterface.php @@ -49,20 +49,9 @@ public function display_media_column_content( string $column_name, int $attachme return; } - $terms = Attachment::get_post_terms( $attachment_id, [ 'fields' => 'names' ] ); - $classes = 'onemedia-media-term-label'; - - // Build the labels and css classes. - if ( empty( $terms ) ) { - $label = __( 'Not assigned', 'onemedia' ); - $classes .= ' empty'; - } else { - $labels = []; - foreach ( $terms as $term ) { - $labels[] = Media::TAXONOMY_TERM === $term ? Media::TERM_NAME : esc_html( $term ); - } - $label = implode( ', ', $labels ); - } + $is_sync = Attachment::is_sync_attachment( $attachment_id ); + $label = $is_sync ? __( 'OneMedia', 'onemedia' ) : __( 'Not Assigned', 'onemedia' ); + $classes = $is_sync ? 'onemedia-media-term-label' : 'onemedia-media-term-label empty'; printf( /* translators: %1$s is the class attribute, %2$s is the label text. */ diff --git a/inc/Modules/Rest/Media_Sharing_Controller.php b/inc/Modules/Rest/Media_Sharing_Controller.php index c4d26e9..9c79809 100644 --- a/inc/Modules/Rest/Media_Sharing_Controller.php +++ b/inc/Modules/Rest/Media_Sharing_Controller.php @@ -585,6 +585,9 @@ public function get_media_files( \WP_REST_Request $request ): \WP_Error|\WP_REST $args['s'] = sanitize_text_field( $search_term ); } + /** + * @todo => This taxonomy approach is complete overkill we can do it using meta so need to remove this in future. + */ // If image_type is provided, filter by onemedia_media_type taxonomy. if ( ! empty( $image_type ) ) { $args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query From 54888b4a68aeef5f85b9cecfe8c311ab2473ef7d Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Wed, 24 Dec 2025 17:59:39 +0530 Subject: [PATCH 09/21] FEAT: Add `jpg, jpe` extension. --- inc/Utils.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/inc/Utils.php b/inc/Utils.php index 1635364..093b53d 100644 --- a/inc/Utils.php +++ b/inc/Utils.php @@ -5,7 +5,7 @@ * @package OneMedia */ -declare( strict_types = 1 ); +declare( strict_types=1 ); namespace OneMedia; @@ -59,6 +59,9 @@ public static function get_supported_mime_types(): array { $supported_types = array_values( get_allowed_mime_types() ); $allowed_types = array_intersect( $allowed_types, $supported_types ); + // WP uses jpeg for all jpeg types, so we need to add jpg and jpe as well explicitly. + $allowed_types = array_merge( $allowed_types, [ 'image/jpg', 'image/jpe' ] ); + return $allowed_types; } From abb6386530371770a93b0006d96c308555bfc5b0 Mon Sep 17 00:00:00 2001 From: Utsav Patel Date: Wed, 24 Dec 2025 18:08:22 +0530 Subject: [PATCH 10/21] updated: js doc comment --- assets/src/js/utils.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/assets/src/js/utils.ts b/assets/src/js/utils.ts index 1cc848a..b62024b 100644 --- a/assets/src/js/utils.ts +++ b/assets/src/js/utils.ts @@ -274,7 +274,11 @@ const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: stri } ); } ); - // Observe the library to link with uploader queue. + /** + * Observe the library to link with uploader queue. + * + * @see https://core.trac.wordpress.org/ticket/34465 + */ frame.on( 'ready', function() { const library = frame.state().get( 'library' ); if ( library && window.wp.Uploader && window.wp.Uploader.queue ) { From 67e1ca068174544b513daf1b75641cfdcb5982b3 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Wed, 24 Dec 2025 19:53:07 +0530 Subject: [PATCH 11/21] FIX: PR feedbacks --- assets/src/js/utils.ts | 30 ++++++++++---------- inc/Modules/MediaLibrary/Admin.php | 2 +- inc/Modules/MediaSharing/MediaProtection.php | 26 ++++++----------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/assets/src/js/utils.ts b/assets/src/js/utils.ts index b62024b..4c7f723 100644 --- a/assets/src/js/utils.ts +++ b/assets/src/js/utils.ts @@ -4,6 +4,21 @@ import type { NoticeType } from '../admin/settings/page'; +declare global { + interface Window { + wp: { + Uploader: { + queue: unknown; + }; + media: { + attachment( id: number ): { + get( key: string ): unknown; + } | undefined; + }; + }; + } +} + type WPMediaUploader = { settings: { multipart_params: Record; @@ -29,21 +44,6 @@ type WPMediaFrame = { }; }; -declare global { - interface Window { - wp: { - Uploader: { - queue: unknown; - }; - media: { - attachment( id: number ): { - get( key: string ): unknown; - } | undefined; - }; - }; - } -} - /** * Helper function to validate if a string is a well-formed URL. * diff --git a/inc/Modules/MediaLibrary/Admin.php b/inc/Modules/MediaLibrary/Admin.php index 1867282..bb27129 100644 --- a/inc/Modules/MediaLibrary/Admin.php +++ b/inc/Modules/MediaLibrary/Admin.php @@ -121,7 +121,7 @@ public function filter_ajax_query_attachments_args( array $query ): array { } // check for is_onemedia_sync meta filter. - if ( isset( $request_query['is_onemedia_sync'] ) ) { + if ( ! empty( $request_query['is_onemedia_sync'] ) ) { $is_onemedia_sync = filter_var( $request_query['is_onemedia_sync'], FILTER_VALIDATE_BOOLEAN ); if ( true === $is_onemedia_sync ) { diff --git a/inc/Modules/MediaSharing/MediaProtection.php b/inc/Modules/MediaSharing/MediaProtection.php index 11c8cb4..08036a3 100644 --- a/inc/Modules/MediaSharing/MediaProtection.php +++ b/inc/Modules/MediaSharing/MediaProtection.php @@ -41,25 +41,16 @@ public function add_term_to_attachment( int $attachment_id ): void { if ( ! wp_doing_ajax() ) { return; } - $action = isset( $_REQUEST['action'] ) ? sanitize_text_field( $_REQUEST['action'] ) : ''; - if ( 'upload-attachment' !== $action ) { + if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['_wpnonce'] ), 'media-form' ) ) { return; } - // check if is_onemedia_sync is set and true. - $is_onemedia_sync = isset( $_POST['is_onemedia_sync'] ) && - filter_var( $_POST['is_onemedia_sync'], FILTER_VALIDATE_BOOLEAN ); - - // Verify nonce for security. - if ( ! isset( $_POST['_wpnonce'] ) ) { + if ( ! isset( $_REQUEST['action'] ) || 'upload-attachment' !== sanitize_text_field( $_REQUEST['action'] ) ) { return; } - if ( isset( $_POST['_wpnonce'] ) ) { - $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ); - if ( ! wp_verify_nonce( $nonce, 'media-form' ) ) { - return; - } - } + // Check if is_onemedia_sync is set and true. + $is_onemedia_sync = ! empty( $_POST['is_onemedia_sync'] ); + update_post_meta( $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY, $is_onemedia_sync ); if ( true !== $is_onemedia_sync ) { @@ -89,6 +80,7 @@ public function maybe_block_media_delete( int $attachment_id ): int|\WP_Error { wp_safe_redirect( $redirect_url ); exit; } + return $attachment_id; } @@ -118,10 +110,10 @@ public function show_deletion_notice(): void { /** * Prevent editing or deleting of synced media attachments on brand sites. * - * @param array $caps Current user's capabilities. - * @param string $cap Capability being checked. + * @param array $caps Current user's capabilities. + * @param string $cap Capability being checked. * @param int $user_id User ID. - * @param array $args Arguments for the capability check. + * @param array $args Arguments for the capability check. * * @return array|string[] */ From afadf3e2034c268cd9df3b5796e2ba027b2ea3ee Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Wed, 24 Dec 2025 20:38:31 +0530 Subject: [PATCH 12/21] FEAT: Make use of Mime type map from `get_allowed_mime_types` --- .../components/browser-uploader.js | 20 +++++++------ assets/src/admin/media-sharing/index.js | 8 ++--- assets/src/js/utils.ts | 19 ++++++++++++ inc/Modules/Core/Assets.php | 30 +++++++++---------- inc/Utils.php | 22 +++++++------- 5 files changed, 61 insertions(+), 38 deletions(-) diff --git a/assets/src/admin/media-sharing/components/browser-uploader.js b/assets/src/admin/media-sharing/components/browser-uploader.js index d00d7c8..d667b6f 100644 --- a/assets/src/admin/media-sharing/components/browser-uploader.js +++ b/assets/src/admin/media-sharing/components/browser-uploader.js @@ -9,12 +9,12 @@ import { useState, useRef } from '@wordpress/element'; * Internal dependencies */ import { uploadMedia, updateExistingAttachment, checkIfAllSitesConnected, isSyncAttachment as isSyncAttachmentApi } from '../../../components/api'; -import { getFrameProperty, restrictMediaFrameUploadTypes, showSnackbarNotice } from '../../../js/utils'; +import { getExtensions, getFrameProperty, getMimeTypes, restrictMediaFrameUploadTypes, showSnackbarNotice } from '../../../js/utils'; // const UPLOAD_NONCE = window.OneMediaMediaFrame?.uploadNonce || ''; -const ALLOWED_MIME_TYPES = typeof window.OneMediaMediaFrame?.allowedMimeTypes !== 'undefined' - ? Object.values( window.OneMediaMediaFrame?.allowedMimeTypes ) +const ALLOWED_MIME_TYPES_MAP = typeof window.OneMediaMediaFrame?.allowedMimeTypesMap !== 'undefined' + ? window.OneMediaMediaFrame?.allowedMimeTypesMap : []; const BrowserUploaderButton = ( { @@ -108,12 +108,12 @@ const BrowserUploaderButton = ( { }, multiple: false, library: { - type: ALLOWED_MIME_TYPES, + type: getMimeTypes( ALLOWED_MIME_TYPES_MAP ), is_onemedia_sync: false, }, } ); - restrictMediaFrameUploadTypes( frame, ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ).replaceAll( '+xml', '' ) ); + restrictMediaFrameUploadTypes( frame, getExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ) ); frame.on( 'open', () => { const frameEl = frame.el; @@ -194,12 +194,12 @@ const BrowserUploaderButton = ( { }, multiple: false, library: { - type: ALLOWED_MIME_TYPES, + type: getMimeTypes( ALLOWED_MIME_TYPES_MAP ), is_onemedia_sync: false, }, } ); - restrictMediaFrameUploadTypes( frame, ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ).replaceAll( '+xml', '' ) ); + restrictMediaFrameUploadTypes( frame, getExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ) ); frame.on( 'open', () => { const frameEl = frame.el; @@ -258,8 +258,10 @@ const BrowserUploaderButton = ( { return; } + const mimeTypes = getMimeTypes( ALLOWED_MIME_TYPES_MAP ); + // Validate file type. - if ( ! ALLOWED_MIME_TYPES.length > 0 || ! ALLOWED_MIME_TYPES.includes( file.type ) ) { + if ( ! mimeTypes.length > 0 || ! mimeTypes.includes( file.type ) ) { setNotice( { type: 'error', message: __( 'Please select a valid image file.', 'onemedia' ), @@ -352,7 +354,7 @@ const BrowserUploaderButton = ( { diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index c8beda2..0f28cb4 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -32,15 +32,15 @@ import BrowserUploaderButton from './components/browser-uploader'; import ShareMediaModal from './components/ShareMediaModal'; import VersionModal from './components/VersionModal'; import { fetchSyncedSites as fetchSyncedSitesApi, fetchMediaItems as fetchMediaItemsApi, fetchBrandSites as fetchBrandSitesApi, shareMedia as shareMediaApi, uploadMedia } from '../../components/api'; -import { getNoticeClass, trimTitle, debounce, getFrameProperty, restrictMediaFrameUploadTypes } from '../../js/utils'; +import { getNoticeClass, trimTitle, debounce, getFrameProperty, restrictMediaFrameUploadTypes, getExtensions } from '../../js/utils'; import fallbackImage from '../../images/fallback-image.svg'; const MEDIA_PER_PAGE = 12; const ONEMEDIA_PLUGIN_TAXONOMY_TERM = 'onemedia'; const UPLOAD_NONCE = window.OneMediaMediaSharing?.uploadNonce || ''; const ONEMEDIA_MEDIA_SHARING = window.OneMediaMediaSharing || {}; -const ALLOWED_MIME_TYPES = typeof window.OneMediaMediaFrame?.allowedMimeTypes !== 'undefined' - ? Object.values( window.OneMediaMediaFrame?.allowedMimeTypes ) +const ALLOWED_MIME_TYPES_MAP = typeof window.OneMediaMediaFrame?.allowedMimeTypesMap !== 'undefined' + ? window.OneMediaMediaFrame?.allowedMimeTypesMap : []; const MediaSharingApp = ( { @@ -217,7 +217,7 @@ const MediaSharingApp = ( { }, } ); - restrictMediaFrameUploadTypes( editFrame, ALLOWED_MIME_TYPES.join( ',' ).replaceAll( 'image/', '' ).replaceAll( '+xml', '' ), true ); + restrictMediaFrameUploadTypes( editFrame, getExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ), true ); editFrame.on( 'open', function() { // Reset the selection state. diff --git a/assets/src/js/utils.ts b/assets/src/js/utils.ts index 4c7f723..1dd7a4d 100644 --- a/assets/src/js/utils.ts +++ b/assets/src/js/utils.ts @@ -287,6 +287,23 @@ const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: stri } ); }; +/** + * Get MIME types from a MIME map. + * @param {Object} mimeMap + */ +function getMimeTypes( mimeMap : Object ) : string[] { + return [ ...new Set( Object.values( mimeMap ) ) ]; +} + +/** + * Get extensions from a MIME map. + * @param {Object} mimeMap + */ +function getExtensions( mimeMap : Object ) : string[] { + return Object.keys( mimeMap ) + .flatMap( ( key ) => key.split( '|' ) ); +} + export { isURL, isValidUrl, @@ -298,4 +315,6 @@ export { getFrameProperty, showSnackbarNotice, restrictMediaFrameUploadTypes, + getMimeTypes, + getExtensions, }; diff --git a/inc/Modules/Core/Assets.php b/inc/Modules/Core/Assets.php index 43ba043..fd81fa6 100644 --- a/inc/Modules/Core/Assets.php +++ b/inc/Modules/Core/Assets.php @@ -68,21 +68,21 @@ final class Assets implements Registrable { public static function get_localized_data(): array { if ( empty( self::$localized_data ) ) { self::$localized_data = [ - 'restUrl' => esc_url( home_url( '/wp-json' ) ), - 'restNonce' => wp_create_nonce( 'wp_rest' ), - 'apiKey' => Settings::get_api_key(), - 'settingsLink' => esc_url( admin_url( 'admin.php?page=onemedia-settings' ) ), - 'siteType' => Settings::get_site_type(), - 'siteName' => get_bloginfo( 'name' ), - 'ajaxUrl' => admin_url( 'admin-ajax.php' ), - 'uploadNonce' => wp_create_nonce( 'onemedia_upload_media' ), - 'allowedMimeTypes' => Utils::get_supported_mime_types(), - 'mediaSyncNonce' => wp_create_nonce( 'onemedia_check_sync_status' ), - 'allLabel' => __( 'All media', 'onemedia' ), - 'syncLabel' => __( 'Synced', 'onemedia' ), - 'notSyncLabel' => __( 'Not Synced', 'onemedia' ), - 'filterLabel' => __( 'Sync Status', 'onemedia' ), - 'syncStatus' => Attachment::SYNC_STATUS_POSTMETA_KEY, + 'restUrl' => esc_url( home_url( '/wp-json' ) ), + 'restNonce' => wp_create_nonce( 'wp_rest' ), + 'apiKey' => Settings::get_api_key(), + 'settingsLink' => esc_url( admin_url( 'admin.php?page=onemedia-settings' ) ), + 'siteType' => Settings::get_site_type(), + 'siteName' => get_bloginfo( 'name' ), + 'ajaxUrl' => admin_url( 'admin-ajax.php' ), + 'uploadNonce' => wp_create_nonce( 'onemedia_upload_media' ), + 'allowedMimeTypesMap' => Utils::get_supported_mime_types(), + 'mediaSyncNonce' => wp_create_nonce( 'onemedia_check_sync_status' ), + 'allLabel' => __( 'All media', 'onemedia' ), + 'syncLabel' => __( 'Synced', 'onemedia' ), + 'notSyncLabel' => __( 'Not Synced', 'onemedia' ), + 'filterLabel' => __( 'Sync Status', 'onemedia' ), + 'syncStatus' => Attachment::SYNC_STATUS_POSTMETA_KEY, ]; } diff --git a/inc/Utils.php b/inc/Utils.php index 093b53d..49c73a8 100644 --- a/inc/Utils.php +++ b/inc/Utils.php @@ -53,16 +53,18 @@ public static function decode_filename( string $filename ): string { * @return array Array of supported mime types by the server. */ public static function get_supported_mime_types(): array { - $allowed_types = self::ALLOWED_MIME_TYPES; - - // Remove any types that are not supported by the server. - $supported_types = array_values( get_allowed_mime_types() ); - $allowed_types = array_intersect( $allowed_types, $supported_types ); - - // WP uses jpeg for all jpeg types, so we need to add jpg and jpe as well explicitly. - $allowed_types = array_merge( $allowed_types, [ 'image/jpg', 'image/jpe' ] ); - - return $allowed_types; + $allowed_mimes = array_flip( self::ALLOWED_MIME_TYPES ); + $wp_mimes = get_allowed_mime_types(); + + /** + * Filter WordPress mime list by allowed mime values. + */ + return array_filter( + $wp_mimes, + static function ( string $mime ) use ( $allowed_mimes ): bool { + return isset( $allowed_mimes[ $mime ] ); + } + ); } /** From 3fb504eaa0b598dbaa574e6a3ec6338d86287455 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Wed, 24 Dec 2025 20:53:51 +0530 Subject: [PATCH 13/21] FIX: Term assignment --- inc/Modules/MediaSharing/MediaProtection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/Modules/MediaSharing/MediaProtection.php b/inc/Modules/MediaSharing/MediaProtection.php index 08036a3..d1ac5f5 100644 --- a/inc/Modules/MediaSharing/MediaProtection.php +++ b/inc/Modules/MediaSharing/MediaProtection.php @@ -49,7 +49,7 @@ public function add_term_to_attachment( int $attachment_id ): void { } // Check if is_onemedia_sync is set and true. - $is_onemedia_sync = ! empty( $_POST['is_onemedia_sync'] ); + $is_onemedia_sync = isset( $_POST['is_onemedia_sync'] ) && filter_var( wp_unslash( $_POST['is_onemedia_sync'] ), FILTER_VALIDATE_BOOLEAN ); update_post_meta( $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY, $is_onemedia_sync ); From e2453a151de663d50d92df33b449f11a453a6248 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Wed, 24 Dec 2025 21:46:25 +0530 Subject: [PATCH 14/21] FIX: Term assignment --- .../media-sharing/components/browser-uploader.js | 14 +++++++------- assets/src/admin/media-sharing/index.js | 4 ++-- assets/src/js/utils.ts | 8 ++++---- inc/Modules/MediaSharing/MediaProtection.php | 2 ++ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/assets/src/admin/media-sharing/components/browser-uploader.js b/assets/src/admin/media-sharing/components/browser-uploader.js index d667b6f..65dee65 100644 --- a/assets/src/admin/media-sharing/components/browser-uploader.js +++ b/assets/src/admin/media-sharing/components/browser-uploader.js @@ -9,7 +9,7 @@ import { useState, useRef } from '@wordpress/element'; * Internal dependencies */ import { uploadMedia, updateExistingAttachment, checkIfAllSitesConnected, isSyncAttachment as isSyncAttachmentApi } from '../../../components/api'; -import { getExtensions, getFrameProperty, getMimeTypes, restrictMediaFrameUploadTypes, showSnackbarNotice } from '../../../js/utils'; +import { getAllowedMimeTypeExtensions, getFrameProperty, getAllowedMimeTypes, restrictMediaFrameUploadTypes, showSnackbarNotice } from '../../../js/utils'; // const UPLOAD_NONCE = window.OneMediaMediaFrame?.uploadNonce || ''; @@ -108,12 +108,12 @@ const BrowserUploaderButton = ( { }, multiple: false, library: { - type: getMimeTypes( ALLOWED_MIME_TYPES_MAP ), + type: getAllowedMimeTypes( ALLOWED_MIME_TYPES_MAP ), is_onemedia_sync: false, }, } ); - restrictMediaFrameUploadTypes( frame, getExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ) ); + restrictMediaFrameUploadTypes( frame, getAllowedMimeTypeExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ) ); frame.on( 'open', () => { const frameEl = frame.el; @@ -194,12 +194,12 @@ const BrowserUploaderButton = ( { }, multiple: false, library: { - type: getMimeTypes( ALLOWED_MIME_TYPES_MAP ), + type: getAllowedMimeTypes( ALLOWED_MIME_TYPES_MAP ), is_onemedia_sync: false, }, } ); - restrictMediaFrameUploadTypes( frame, getExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ) ); + restrictMediaFrameUploadTypes( frame, getAllowedMimeTypeExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ) ); frame.on( 'open', () => { const frameEl = frame.el; @@ -258,7 +258,7 @@ const BrowserUploaderButton = ( { return; } - const mimeTypes = getMimeTypes( ALLOWED_MIME_TYPES_MAP ); + const mimeTypes = getAllowedMimeTypes( ALLOWED_MIME_TYPES_MAP ); // Validate file type. if ( ! mimeTypes.length > 0 || ! mimeTypes.includes( file.type ) ) { @@ -354,7 +354,7 @@ const BrowserUploaderButton = ( { diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index 0f28cb4..59145d5 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -32,7 +32,7 @@ import BrowserUploaderButton from './components/browser-uploader'; import ShareMediaModal from './components/ShareMediaModal'; import VersionModal from './components/VersionModal'; import { fetchSyncedSites as fetchSyncedSitesApi, fetchMediaItems as fetchMediaItemsApi, fetchBrandSites as fetchBrandSitesApi, shareMedia as shareMediaApi, uploadMedia } from '../../components/api'; -import { getNoticeClass, trimTitle, debounce, getFrameProperty, restrictMediaFrameUploadTypes, getExtensions } from '../../js/utils'; +import { getNoticeClass, trimTitle, debounce, getFrameProperty, restrictMediaFrameUploadTypes, getAllowedMimeTypeExtensions } from '../../js/utils'; import fallbackImage from '../../images/fallback-image.svg'; const MEDIA_PER_PAGE = 12; @@ -217,7 +217,7 @@ const MediaSharingApp = ( { }, } ); - restrictMediaFrameUploadTypes( editFrame, getExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ), true ); + restrictMediaFrameUploadTypes( editFrame, getAllowedMimeTypeExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ), true ); editFrame.on( 'open', function() { // Reset the selection state. diff --git a/assets/src/js/utils.ts b/assets/src/js/utils.ts index 1dd7a4d..06f9670 100644 --- a/assets/src/js/utils.ts +++ b/assets/src/js/utils.ts @@ -291,7 +291,7 @@ const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: stri * Get MIME types from a MIME map. * @param {Object} mimeMap */ -function getMimeTypes( mimeMap : Object ) : string[] { +function getAllowedMimeTypes( mimeMap : Object ) : string[]|undefined { return [ ...new Set( Object.values( mimeMap ) ) ]; } @@ -299,7 +299,7 @@ function getMimeTypes( mimeMap : Object ) : string[] { * Get extensions from a MIME map. * @param {Object} mimeMap */ -function getExtensions( mimeMap : Object ) : string[] { +function getAllowedMimeTypeExtensions( mimeMap : Object ) : string[] { return Object.keys( mimeMap ) .flatMap( ( key ) => key.split( '|' ) ); } @@ -315,6 +315,6 @@ export { getFrameProperty, showSnackbarNotice, restrictMediaFrameUploadTypes, - getMimeTypes, - getExtensions, + getAllowedMimeTypes, + getAllowedMimeTypeExtensions, }; diff --git a/inc/Modules/MediaSharing/MediaProtection.php b/inc/Modules/MediaSharing/MediaProtection.php index d1ac5f5..89e9b39 100644 --- a/inc/Modules/MediaSharing/MediaProtection.php +++ b/inc/Modules/MediaSharing/MediaProtection.php @@ -41,9 +41,11 @@ public function add_term_to_attachment( int $attachment_id ): void { if ( ! wp_doing_ajax() ) { return; } + if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['_wpnonce'] ), 'media-form' ) ) { return; } + if ( ! isset( $_REQUEST['action'] ) || 'upload-attachment' !== sanitize_text_field( $_REQUEST['action'] ) ) { return; } From 524f51aea2e72e6e60455a4e7cf42beef6ada31d Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Thu, 25 Dec 2025 11:26:14 +0530 Subject: [PATCH 15/21] FIX: Update allowed mime type array --- inc/Utils.php | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/inc/Utils.php b/inc/Utils.php index 49c73a8..081e837 100644 --- a/inc/Utils.php +++ b/inc/Utils.php @@ -27,13 +27,13 @@ final class Utils { * @var array */ private const ALLOWED_MIME_TYPES = [ - 'image/jpg', - 'image/jpeg', - 'image/png', - 'image/gif', - 'image/webp', - 'image/bmp', - 'image/svg+xml', + 'jpg|jpeg|jpe' => 'image/jpeg', + 'png' => 'image/png', + 'gif' => 'image/gif', + 'bmp' => 'image/bmp', + 'webp' => 'image/webp', + 'svg' => 'image/svg+xml', + 'svgz' => 'image/svg+xml', ]; /** @@ -53,17 +53,14 @@ public static function decode_filename( string $filename ): string { * @return array Array of supported mime types by the server. */ public static function get_supported_mime_types(): array { - $allowed_mimes = array_flip( self::ALLOWED_MIME_TYPES ); - $wp_mimes = get_allowed_mime_types(); + $wp_mimes = get_allowed_mime_types(); /** * Filter WordPress mime list by allowed mime values. */ - return array_filter( + return array_intersect_key( $wp_mimes, - static function ( string $mime ) use ( $allowed_mimes ): bool { - return isset( $allowed_mimes[ $mime ] ); - } + self::ALLOWED_MIME_TYPES ); } From 0e3b0f759ef0dbb3d16ccc6d57e58534613a6c51 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Thu, 25 Dec 2025 13:12:13 +0530 Subject: [PATCH 16/21] FIX: Db issues --- inc/Modules/MediaSharing/MediaProtection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/Modules/MediaSharing/MediaProtection.php b/inc/Modules/MediaSharing/MediaProtection.php index 89e9b39..e3ab2e4 100644 --- a/inc/Modules/MediaSharing/MediaProtection.php +++ b/inc/Modules/MediaSharing/MediaProtection.php @@ -53,7 +53,7 @@ public function add_term_to_attachment( int $attachment_id ): void { // Check if is_onemedia_sync is set and true. $is_onemedia_sync = isset( $_POST['is_onemedia_sync'] ) && filter_var( wp_unslash( $_POST['is_onemedia_sync'] ), FILTER_VALIDATE_BOOLEAN ); - update_post_meta( $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY, $is_onemedia_sync ); + update_post_meta( $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY, $is_onemedia_sync ? 1 : 0 ); if ( true !== $is_onemedia_sync ) { return; From 643703f6ea5f068eccc1f191d3bf5c357600bf57 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Thu, 25 Dec 2025 13:42:21 +0530 Subject: [PATCH 17/21] FIX: Allow non-sync media delete on brand site. --- inc/Modules/MediaSharing/MediaProtection.php | 25 -------------------- 1 file changed, 25 deletions(-) diff --git a/inc/Modules/MediaSharing/MediaProtection.php b/inc/Modules/MediaSharing/MediaProtection.php index e3ab2e4..b010391 100644 --- a/inc/Modules/MediaSharing/MediaProtection.php +++ b/inc/Modules/MediaSharing/MediaProtection.php @@ -20,7 +20,6 @@ class MediaProtection implements Registrable { * {@inheritDoc} */ public function register_hooks(): void { - add_filter( 'delete_attachment', [ $this, 'maybe_block_media_delete' ], 10, 1 ); add_action( 'admin_notices', [ $this, 'show_deletion_notice' ] ); add_action( 'add_attachment', [ $this, 'add_term_to_attachment' ] ); @@ -62,30 +61,6 @@ public function add_term_to_attachment( int $attachment_id ): void { wp_set_object_terms( $attachment_id, Media::TAXONOMY_TERM, Media::TAXONOMY, true ); } - /** - * Block deletion of media attachments assigned to the 'onemedia' term. - * - * This method prevents the deletion of media attachments that are assigned to the 'onemedia' term, - * ensuring that important media cannot be removed unintentionally. - * - * @param int $attachment_id The ID of the attachment being deleted. - * - * @return int|\WP_Error The attachment ID if deletion is allowed, or a WP_Error if blocked. - */ - public function maybe_block_media_delete( int $attachment_id ): int|\WP_Error { - $terms = Attachment::get_post_terms( $attachment_id, [ 'fields' => 'slugs' ] ); - if ( ! empty( $terms ) && isset( array_flip( $terms )[ Media::TAXONOMY_TERM ] ) ) { - // Set a transient to show a notice on the next admin page load. - set_transient( 'onemedia_delete_notice', true, 30 ); - // Redirect back to prevent deletion. - $redirect_url = admin_url( 'upload.php' ); - wp_safe_redirect( $redirect_url ); - exit; - } - - return $attachment_id; - } - /** * Show a notice when trying to delete media that is assigned to the 'onemedia' term. * From e5aa406f3852317347a0cdb243d8e0fa4e575b8b Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Thu, 25 Dec 2025 16:06:36 +0530 Subject: [PATCH 18/21] FIX: Show onboarding on settings page. --- inc/Modules/Settings/Admin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inc/Modules/Settings/Admin.php b/inc/Modules/Settings/Admin.php index 0cd1652..a113e69 100644 --- a/inc/Modules/Settings/Admin.php +++ b/inc/Modules/Settings/Admin.php @@ -131,7 +131,7 @@ public function enqueue_scripts( string $hook ): void { */ public function inject_site_selection_modal(): void { $current_screen = get_current_screen(); - if ( ! $current_screen || 'plugins' !== $current_screen->base ) { + if ( ! $current_screen || ( 'plugins' !== $current_screen->base && ! str_contains( $current_screen->id, self::MENU_SLUG ) ) ) { return; } @@ -234,7 +234,7 @@ private function enqueue_onboarding_scripts(): void { * @param \WP_Screen $current_screen Current screen object. */ private function add_body_class_for_modal( string $classes, \WP_Screen $current_screen ): string { - if ( 'plugins' !== $current_screen->base ) { + if ( 'plugins' !== $current_screen->base && ! str_contains( $current_screen->id, self::MENU_SLUG ) ) { return $classes; } @@ -252,7 +252,7 @@ private function add_body_class_for_modal( string $classes, \WP_Screen $current_ /** * Add body class for missing sites. * - * @param string $classes Existing body classes. + * @param string $classes Existing body classes. */ private function add_body_class_for_missing_sites( string $classes ): string { // Bail if the shared sites are already set. From 87926104d870d80f68ac48d10f9210e59906c6f6 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Thu, 25 Dec 2025 16:29:21 +0530 Subject: [PATCH 19/21] CHORE: Update comment --- inc/Modules/MediaSharing/MediaProtection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/Modules/MediaSharing/MediaProtection.php b/inc/Modules/MediaSharing/MediaProtection.php index b010391..9c4ef1f 100644 --- a/inc/Modules/MediaSharing/MediaProtection.php +++ b/inc/Modules/MediaSharing/MediaProtection.php @@ -49,7 +49,7 @@ public function add_term_to_attachment( int $attachment_id ): void { return; } - // Check if is_onemedia_sync is set and true. + // Handle boolean strings (e.g. 'false'). $is_onemedia_sync = isset( $_POST['is_onemedia_sync'] ) && filter_var( wp_unslash( $_POST['is_onemedia_sync'] ), FILTER_VALIDATE_BOOLEAN ); update_post_meta( $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY, $is_onemedia_sync ? 1 : 0 ); From 7be7fe1fb76878ee683df22ee5fa3c50c02e29ba Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Thu, 25 Dec 2025 16:39:30 +0530 Subject: [PATCH 20/21] FEAT: Move show onboarding condition to dedicated method --- inc/Modules/Settings/Admin.php | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/inc/Modules/Settings/Admin.php b/inc/Modules/Settings/Admin.php index a113e69..50391d7 100644 --- a/inc/Modules/Settings/Admin.php +++ b/inc/Modules/Settings/Admin.php @@ -114,10 +114,8 @@ public function enqueue_scripts( string $hook ): void { return; } - if ( ( 'plugins.php' === $hook || str_contains( $hook, 'plugins' ) || str_contains( $hook, 'onemedia' ) ) ) { - // Enqueue the onboarding modal. - $this->enqueue_onboarding_scripts(); - } + // Enqueue the onboarding modal. + $this->enqueue_onboarding_scripts(); if ( strpos( $hook, 'onemedia-settings' ) !== false ) { $this->enqueue_settings_scripts(); @@ -130,8 +128,7 @@ public function enqueue_scripts( string $hook ): void { * Inject site selection modal into the admin footer. */ public function inject_site_selection_modal(): void { - $current_screen = get_current_screen(); - if ( ! $current_screen || ( 'plugins' !== $current_screen->base && ! str_contains( $current_screen->id, self::MENU_SLUG ) ) ) { + if ( ! $this->should_display_site_selection_modal() ) { return; } @@ -208,8 +205,7 @@ public function enqueue_settings_scripts(): void { * Enqueue scripts and styles for the onboarding modal. */ private function enqueue_onboarding_scripts(): void { - // Bail if the site type is already set. - if ( ! empty( Settings::get_site_type() ) ) { + if ( ! $this->should_display_site_selection_modal() ) { return; } @@ -234,7 +230,7 @@ private function enqueue_onboarding_scripts(): void { * @param \WP_Screen $current_screen Current screen object. */ private function add_body_class_for_modal( string $classes, \WP_Screen $current_screen ): string { - if ( 'plugins' !== $current_screen->base && ! str_contains( $current_screen->id, self::MENU_SLUG ) ) { + if ( ! $this->should_display_site_selection_modal() ) { return $classes; } @@ -265,4 +261,17 @@ private function add_body_class_for_missing_sites( string $classes ): string { return $classes; } + + /** + * Whether to display the site selection modal. + */ + private function should_display_site_selection_modal(): bool { + $current_screen = get_current_screen(); + if ( ! $current_screen || ( 'plugins' !== $current_screen->base && ! str_contains( $current_screen->id, self::MENU_SLUG ) ) ) { + return false; + } + + // Bail if the site type is already set. + return empty( Settings::get_site_type() ); + } } From 4bfb09b639c19eb20a8adc1e6f5323c1204d65d6 Mon Sep 17 00:00:00 2001 From: Vipul Patil Date: Thu, 25 Dec 2025 16:54:36 +0530 Subject: [PATCH 21/21] FIX: Show full loader --- assets/src/css/main.scss | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/assets/src/css/main.scss b/assets/src/css/main.scss index b7782f1..88a99b8 100644 --- a/assets/src/css/main.scss +++ b/assets/src/css/main.scss @@ -258,15 +258,7 @@ } .media-toolbar:not(:has(.media-button-select)) { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - - .media-toolbar-primary, - .media-toolbar-secondary { - float: none; - } + height: fit-content; .media-toolbar-secondary .attachment-filters { width: 100% !important;