diff --git a/js/admin-media.js b/js/admin-media.js index fe5d831..e611e96 100644 --- a/js/admin-media.js +++ b/js/admin-media.js @@ -20,6 +20,7 @@ var shapeListContainer = document.getElementById('yooneSnowShapeList'); var shapeAddSelect = document.getElementById('yooneSnowAddShapeSelect'); var shapeLabelPreviewHost = document.getElementById('yooneSnowAddShapeLabelPreview'); + var shapeNativeOverlay = document.getElementById('yooneSnowShapeNativeOverlay'); var shapeAddButton = null; var emojiSelect = document.getElementById('yooneSnowEmojiSelect'); var typeSelect = document.getElementById('yooneSnowAddTypeSelect'); @@ -194,7 +195,7 @@ var cancelBtn = document.createElement('button'); cancelBtn.type = 'button'; cancelBtn.className = 'button yoone-snow-cancel-shape'; - cancelBtn.textContent = 'Cancel'; + cancelBtn.textContent = t('cancel', 'Cancel'); cancelBtn.style.marginTop = '6px'; wrapper.appendChild(previewHost); wrapper.appendChild(nameSpan); @@ -245,7 +246,7 @@ // 条件判断 如果 wp.media 不可用则终止 if (typeof wp === 'undefined' || !wp.media) { return; } var frame = wp.media({ - title: 'Select images or SVG', + title: t('select_images_or_svg', 'Select images or SVG'), multiple: true, library: { type: [ 'image', 'image/svg+xml' ] } }); @@ -284,7 +285,7 @@ var removeBtn = document.createElement('button'); removeBtn.type = 'button'; removeBtn.className = 'button yoone-snow-remove-media'; - removeBtn.textContent = 'Remove'; + removeBtn.textContent = t('remove', 'Remove'); removeBtn.style.marginTop = '6px'; wrapper.appendChild(img); wrapper.appendChild(weightInput); @@ -424,7 +425,7 @@ var removeBtn = document.createElement('button'); removeBtn.type = 'button'; removeBtn.className = 'button yoone-snow-remove-emoji'; - removeBtn.textContent = 'Cancel'; + removeBtn.textContent = t('cancel', 'Cancel'); removeBtn.style.marginTop = '6px'; wrapper.appendChild(preview); wrapper.appendChild(weightInput); @@ -557,6 +558,7 @@ } } }); + // 僅使用原生下拉 不再彈出自定義覆蓋列表 } @@ -624,7 +626,7 @@ var removeBtn = document.createElement('button'); removeBtn.type = 'button'; removeBtn.className = 'button yoone-snow-remove-text'; - removeBtn.textContent = 'Cancel'; + removeBtn.textContent = t('cancel', 'Cancel'); removeBtn.style.marginTop = '6px'; wrapper.appendChild(preview); wrapper.appendChild(weightInput); @@ -665,3 +667,54 @@ initAdminMedia(); } })(); + // 初始化內嵌下拉的預覽與點擊交互 + (function(){ + if (!shapeNativeOverlay) { return; } + var nodes = shapeNativeOverlay.querySelectorAll('.yoone-snow-shape-native-item'); + nodes.forEach(function(btn){ + var key = btn.getAttribute('data-shape-key'); + var host = btn.querySelector('.yoone-snow-shape-native-preview'); + if (host && host.childNodes && host.childNodes.length === 0){ + var previewEl = createShapePreviewElement(key); + if (previewEl){ + try { previewEl.style.backgroundColor = 'transparent'; } catch(e){} + try { previewEl.style.border = 'none'; } catch(e){} + try { previewEl.style.borderRadius = '0'; } catch(e){} + host.appendChild(previewEl); + } + } + btn.addEventListener('click', function(){ + // 先更新左側預覽 再添加卡片 並關閉內嵌下拉 + if (shapeLabelPreviewHost){ + while (shapeLabelPreviewHost.firstChild){ shapeLabelPreviewHost.removeChild(shapeLabelPreviewHost.firstChild); } + var previewEl2 = createShapePreviewElement(key); + if (previewEl2){ + try { previewEl2.style.backgroundColor = 'transparent'; } catch(e){} + try { previewEl2.style.border = 'none'; } catch(e){} + try { previewEl2.style.borderRadius = '0'; } catch(e){} + shapeLabelPreviewHost.style.display = 'flex'; + shapeLabelPreviewHost.appendChild(previewEl2); + } + } + addShapeBox(key); + if (shapeNativeOverlay){ shapeNativeOverlay.style.display = 'none'; } + // 重置原生下拉為未選中 清空左側預覽 保持簡潔 + if (shapeAddSelect){ shapeAddSelect.value = ''; } + if (shapeLabelPreviewHost){ + while (shapeLabelPreviewHost.firstChild){ shapeLabelPreviewHost.removeChild(shapeLabelPreviewHost.firstChild); } + shapeLabelPreviewHost.style.display = 'none'; + } + }); + }); + // 外部點擊時關閉內嵌下拉 + document.addEventListener('click', function(e){ + var t = e.target; + var inside = (t === shapeNativeOverlay || shapeNativeOverlay.contains(t) || (shapeAddSelect && (t === shapeAddSelect || shapeAddSelect.contains(t)))); + if (!inside){ shapeNativeOverlay.style.display = 'none'; } + }); + })(); + function t(key, fallback){ + var dict = (typeof window !== 'undefined' && window.YooneSnowAdmin && window.YooneSnowAdmin.i18n) ? window.YooneSnowAdmin.i18n : {}; + var val = dict[key]; + return String(val || fallback || ''); + } diff --git a/yoone-snow.php b/yoone-snow.php index 002e6b0..506777c 100644 --- a/yoone-snow.php +++ b/yoone-snow.php @@ -113,6 +113,9 @@ function yoone_snow_enqueue_assets() { $media_weights_by_url[$url] = $w; } } + // 形状权重默认值 映射为形状键到非负整数权重 + // 权重用于控制每次生成时的相对概率 权重越大被选中越频繁 + // 权重为 0 表示可选但不参与随机生成 $default_weights = array( 'dot' => 1, 'flake' => 4, @@ -127,6 +130,7 @@ function yoone_snow_enqueue_assets() { ); $saved_weights = get_option('yoone_snow_shape_weights', $default_weights); if (!is_array($saved_weights)) { $saved_weights = array(); } + // 合并用户保存的权重与默认值 并规范为非负整数 $shape_weights = array(); foreach ($default_weights as $k => $v) { $val = isset($saved_weights[$k]) ? intval($saved_weights[$k]) : intval($v); @@ -319,6 +323,23 @@ function yoone_snow_admin_enqueue($hook) { 'christmas_tree' => plugins_url('assets/圣诞树.svg', __FILE__), 'reindeer' => plugins_url('assets/圣诞麋鹿.svg', __FILE__), 'christmas_berry' => plugins_url('assets/圣诞果.svg', __FILE__), + ), + 'i18n' => array( + 'cancel' => esc_html__('Cancel', 'yoone-snow'), + 'remove' => esc_html__('Remove', 'yoone-snow'), + 'select_images_or_svg' => esc_html__('Select images or SVG', 'yoone-snow'), + 'type' => esc_html__('Type', 'yoone-snow'), + 'default' => esc_html__('Default', 'yoone-snow'), + 'emoji' => esc_html__('Emoji', 'yoone-snow'), + 'media' => esc_html__('Media', 'yoone-snow'), + 'text' => esc_html__('Text', 'yoone-snow'), + 'select_shape' => esc_html__('Select shape', 'yoone-snow'), + 'select_emoji' => esc_html__('Select emoji', 'yoone-snow'), + 'add_images' => esc_html__('Add Images', 'yoone-snow'), + 'type_text' => esc_html__('Type text', 'yoone-snow'), + 'type_emoji_or_alias' => esc_html__('Type emoji or alias', 'yoone-snow'), + 'add_shapes_all_in_one' => esc_html__('Add shapes by type all in one list', 'yoone-snow'), + 'shapes' => esc_html__('Shapes', 'yoone-snow') ) )); wp_enqueue_script($admin_script_handle); @@ -370,7 +391,7 @@ function yoone_snow_register_settings() { add_settings_field( 'yoone_snow_mixed_items', - 'Shapes', + esc_html__('Shapes', 'yoone-snow'), function() { // 读取默认形状列表 用于初始渲染卡片 $current_list = get_option('yoone_snow_mixed_items', array('dot','flake')); @@ -390,6 +411,19 @@ function yoone_snow_register_settings() { 'reindeer' => 'Reindeer', 'christmas_berry' => 'Christmas Berry', ); + // 形状描述映射 用于在界面提示 使用国际化函数 + $shape_descriptions = array( + 'dot' => __('Basic dot shape simple and lightweight', 'yoone-snow'), + 'flake' => __('Snowflake shape more decorative', 'yoone-snow'), + 'yuanbao' => __('Yuanbao shape festive theme', 'yoone-snow'), + 'coin' => __('Coin shape festive theme', 'yoone-snow'), + 'santa_hat' => __('Santa hat shape seasonal theme', 'yoone-snow'), + 'candy_cane' => __('Candy cane shape seasonal theme', 'yoone-snow'), + 'christmas_sock' => __('Christmas sock shape seasonal theme', 'yoone-snow'), + 'christmas_tree' => __('Christmas tree shape seasonal theme', 'yoone-snow'), + 'reindeer' => __('Reindeer shape seasonal theme', 'yoone-snow'), + 'christmas_berry' => __('Christmas berry shape seasonal theme', 'yoone-snow'), + ); // 读取已选择的媒体与 emoji 列表 用于统一卡片渲染 $current_media = get_option('yoone_snow_media_items', array()); if (!is_array($current_media)) { $current_media = array(); } @@ -411,13 +445,13 @@ function yoone_snow_register_settings() { // 渲染默认形状卡片 foreach ($current_list as $key) { if (!isset($options[$key])) { continue; } - echo '
'; + echo '
'; echo '
'; echo '' . esc_html($options[$key]) . ''; $shapeWeightVal = isset($shape_weights_current[$key]) ? intval($shape_weights_current[$key]) : 1; echo ''; echo ''; - echo ''; + echo ''; echo '
'; } // 渲染 emoji 卡片 @@ -429,7 +463,7 @@ function yoone_snow_register_settings() { $emojiWeightVal = isset($emoji_weights_current[$label]) ? intval($emoji_weights_current[$label]) : 1; echo ''; echo ''; - echo ''; + echo ''; echo '
'; } // 渲染媒体卡片 @@ -443,7 +477,7 @@ function yoone_snow_register_settings() { $mediaWeightVal = isset($media_weights_current[$safe_id]) ? intval($media_weights_current[$safe_id]) : 1; echo ''; echo ''; - echo ''; + echo ''; echo ''; } // 文本卡片 @@ -455,41 +489,44 @@ function yoone_snow_register_settings() { $textWeightVal = isset($text_weights_current[$label]) ? intval($text_weights_current[$label]) : 1; echo ''; echo ''; - echo ''; + echo ''; echo ''; } echo '
'; echo '
'; - echo ''; echo '
'; echo '
'; echo ''; - echo ''; foreach ($options as $key => $label) { echo ''; } echo ''; + echo '
'; echo ''; echo ''; echo ''; - echo '

Add shapes by type all in one list

'; + // 权重说明 提示用户权重影响概率且为非负整数 + echo '

' . esc_html__('Add shapes by type all in one list', 'yoone-snow') . '

'; echo '
'; echo ''; + echo '

' . esc_html__('Weight controls relative probability Weight is a non negative integer Weight 0 disables a shape Probability equals shape weight divided by the sum of all shape weights Example dot 1 flake 4 flake has about four times the chance of dot', 'yoone-snow') . '

'; }, 'yoone_snow', 'yoone_snow_section'