| @@ -5,8 +5,9 @@ | ||
| 5 | 5 | if ( ! defined( 'ABSPATH' ) ) { |
| 6 | 6 | exit; // Exit if accessed directly |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | +use WPDeveloper\BetterDocs\Core\AIActions; | |
| 9 | 10 | use WPDeveloper\BetterDocs\Utils\Helper; |
| 10 | 11 | use WPDeveloper\BetterDocs\Editors\BlockEditor\FontLoader; |
| 11 | 12 | use WPDeveloper\BetterDocs\Editors\BlockEditor\StyleHandler; |
| 12 | 13 | use WPDeveloper\BetterDocs\Editors\BlockEditor\TemplatesController; |
| @@ -112,9 +113,11 @@ | ||
| 112 | 113 | 'is_woocommerce_active' => class_exists( 'WooCommerce' ), |
| 113 | 114 | 'resturl' => get_rest_url(), |
| 114 | 115 | 'editorType' => $editor, |
| 115 | 116 | 'betterdocs_glossaries' => Helper::get_glossaries(), |
| 116 | - 'docsIcon' => isset( betterdocs()->settings->get( 'docs_list_icon' )['url'] ) ? betterdocs()->settings->get( 'docs_list_icon' )['url'] : '' | |
| 117 | + 'docsIcon' => isset( betterdocs()->settings->get( 'docs_list_icon' )['url'] ) ? betterdocs()->settings->get( 'docs_list_icon' )['url'] : '', | |
| 118 | + 'settings' => $this->block_setting_defaults(), | |
| 119 | + 'aiActions' => $this->ai_actions_catalog() | |
| 117 | 120 | ], betterdocs()->settings->chatbot_active_localize()) |
| 118 | 121 | ); |
| 119 | 122 | |
| 120 | 123 | if ( $hook == 'post-new.php' || $hook == 'post.php' || $hook == 'site-editor.php' ) { |
| @@ -120,8 +123,104 @@ | ||
| 120 | 123 | if ( $hook == 'post-new.php' || $hook == 'post.php' || $hook == 'site-editor.php' ) { |
| 121 | 124 | $this->assets->enqueue( 'fontpicker-default-theme', 'vendor/css/fonticonpicker.base-theme.react.css' ); |
| 122 | 125 | $this->assets->enqueue( 'fontpicker-material-theme', 'vendor/css/fonticonpicker.material-theme.react.css' ); |
| 123 | 126 | } |
| 127 | + } | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * Settings-panel values a block uses as the default for its own controls. | |
| 131 | + * | |
| 132 | + * A block control that has never been touched should show — and render — what | |
| 133 | + * the Settings panel says, so switching a feature on there is enough and the | |
| 134 | + * per-block control is only for overriding one instance. The editor cannot read | |
| 135 | + * `betterdocs_settings` (the REST route behind it needs `edit_docs_settings`, | |
| 136 | + * which an author does not have), so the values are handed over at enqueue time. | |
| 137 | + * | |
| 138 | + * Nested deliberately: wp_localize_script casts every *top-level* scalar to a | |
| 139 | + * string, so a top-level `false` would arrive in JS as `""` and a `true` as | |
| 140 | + * `"1"`. Inside a sub-array the values are JSON-encoded and keep their types, | |
| 141 | + * which is what a boolean block attribute needs. | |
| 142 | + * | |
| 143 | + * Keys mirror the Settings keys exactly, so the JS side needs no translation | |
| 144 | + * table and a mismatch is obvious on sight. | |
| 145 | + * | |
| 146 | + * @return array | |
| 147 | + */ | |
| 148 | + protected function block_setting_defaults() { | |
| 149 | + $settings = betterdocs()->settings; | |
| 150 | + | |
| 151 | + $booleans = [ | |
| 152 | + 'enable_estimated_reading_time', | |
| 153 | + 'enable_ai_actions', | |
| 154 | + 'enable_listen', | |
| 155 | + 'listen_show_speed', | |
| 156 | + 'ai_actions_copy_page', | |
| 157 | + 'ai_actions_view_markdown', | |
| 158 | + 'ai_actions_chatgpt', | |
| 159 | + 'ai_actions_claude', | |
| 160 | + 'ai_actions_gemini', | |
| 161 | + 'ai_actions_perplexity', | |
| 162 | + 'ai_actions_grok' | |
| 163 | + ]; | |
| 164 | + | |
| 165 | + $strings = [ | |
| 166 | + 'estimated_reading_time_title', | |
| 167 | + 'estimated_reading_time_text', | |
| 168 | + 'singular_estimated_reading_time_text', | |
| 169 | + 'ai_actions_button_label', | |
| 170 | + 'ai_actions_prompt_template', | |
| 171 | + 'listen_button_label' | |
| 172 | + ]; | |
| 173 | + | |
| 174 | + // Kept apart from the strings above so it arrives as a number: the JS side | |
| 175 | + // divides by it, and "180" would work by coercion while an empty string | |
| 176 | + // would quietly become 0. | |
| 177 | + $numbers = [ | |
| 178 | + 'listen_words_per_minute' | |
| 179 | + ]; | |
| 180 | + | |
| 181 | + $defaults = []; | |
| 182 | + | |
| 183 | + foreach ( $booleans as $key ) { | |
| 184 | + $defaults[ $key ] = (bool) $settings->get( $key ); | |
| 185 | + } | |
| 186 | + | |
| 187 | + foreach ( $strings as $key ) { | |
| 188 | + $defaults[ $key ] = (string) $settings->get( $key ); | |
| 189 | + } | |
| 190 | + | |
| 191 | + foreach ( $numbers as $key ) { | |
| 192 | + $defaults[ $key ] = (int) $settings->get( $key ); | |
| 193 | + } | |
| 194 | + | |
| 195 | + return $defaults; | |
| 196 | + } | |
| 197 | + | |
| 198 | + /** | |
| 199 | + * Everything the editor needs to draw the AI Actions dropdown. | |
| 200 | + * | |
| 201 | + * The reading-time block's preview shows the real menu — same order, labels, | |
| 202 | + * descriptions and icons as the frontend — so an author can see what the action | |
| 203 | + * toggles do without saving and previewing. There is no post to resolve against | |
| 204 | + * in the editor, so no hrefs are sent: the preview is deliberately inert. | |
| 205 | + * | |
| 206 | + * `caret` rides along because the disclosure arrow is not a registry entry but | |
| 207 | + * still has to match the button the frontend renders. | |
| 208 | + * | |
| 209 | + * @return array | |
| 210 | + */ | |
| 211 | + protected function ai_actions_catalog() { | |
| 212 | + if ( ! isset( betterdocs()->ai_actions ) ) { | |
| 213 | + return [ | |
| 214 | + 'items' => [], | |
| 215 | + 'caret' => '' | |
| 216 | + ]; | |
| 217 | + } | |
| 218 | + | |
| 219 | + return [ | |
| 220 | + 'items' => betterdocs()->ai_actions->catalog(), | |
| 221 | + 'caret' => AIActions::icon( 'caret' ) | |
| 222 | + ]; | |
| 124 | 223 | } |
| 125 | 224 | |
| 126 | 225 | /** |
| 127 | 226 | * Add a block category |