Skip to content

Commit 45b8256

Browse files
authored
gcoai-stream-loading-text-animation.php: Added a new snippet for customizing the Steam field's loading text.
1 parent c61ee6a commit 45b8256

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<?php
2+
/**
3+
* Gravity Connect // OpenAI // Stream Loading Text Animation
4+
*
5+
* Adds a customizable shimmer animation and rotating spinner icon to the Stream field's
6+
* loading placeholders. Replaces the static "Loading..." text with animated text and/or
7+
* a rotating spinner icon.
8+
*/
9+
class GCOAI_Loading_Animation {
10+
11+
private $args;
12+
13+
public function __construct( $args = array() ) {
14+
$this->args = wp_parse_args( $args, array(
15+
'text' => 'Thinking...',
16+
'base_color' => '#000',
17+
'shimmer_color' => '#fff',
18+
'shimmer_duration' => '2.2s',
19+
'show_shimmer' => true,
20+
'show_spinner' => false,
21+
'spinner_size' => '24',
22+
'form_id' => null,
23+
'field_id' => null,
24+
) );
25+
26+
add_filter( 'gform_gcoai_field_loading_text', array( $this, 'filter_loading_text' ), 10, 3 );
27+
add_action( 'gform_register_init_scripts', array( $this, 'register_init_script' ), 10, 2 );
28+
}
29+
30+
public function register_init_script( $form, $is_ajax ) {
31+
if ( empty( $form['id'] ) ) {
32+
return;
33+
}
34+
35+
// If form_id is specified, only run scripts on those forms
36+
if ( $this->args['form_id'] !== null ) {
37+
$form_ids = is_array( $this->args['form_id'] ) ? $this->args['form_id'] : array( $this->args['form_id'] );
38+
if ( ! in_array( $form['id'], $form_ids ) ) {
39+
return;
40+
}
41+
}
42+
43+
$markup = $this->get_shimmer_markup();
44+
$css = $this->get_styles_css();
45+
46+
?>
47+
<script type="text/javascript">
48+
(function($) {
49+
var shimmerMarkup = <?php echo wp_json_encode( $markup ); ?>;
50+
var shimmerStyles = <?php echo wp_json_encode( $css ); ?>;
51+
52+
function addStylesToPage() {
53+
if ( ! $('style.gw-gcoai-shimmer-style').length ) {
54+
$('<style>')
55+
.addClass('gw-gcoai-shimmer-style')
56+
.text(shimmerStyles)
57+
.appendTo('head');
58+
}
59+
}
60+
61+
function applyShimmerToPlaceholders($container) {
62+
var $searchContext = $container && $container.length ? $container : $(document);
63+
$searchContext.find('.gcoai-output .gcoai-placeholder').html(shimmerMarkup);
64+
}
65+
66+
if ( window.gform && typeof window.gform.addFilter === 'function' ) {
67+
window.gform.addFilter('gcoai_stream_loading_placeholder', function(current, instance) {
68+
return shimmerMarkup;
69+
});
70+
}
71+
72+
$(function() {
73+
addStylesToPage();
74+
applyShimmerToPlaceholders();
75+
});
76+
77+
// Re-apply after Generate/Regenerate clicks
78+
$(document).on('click', '.gcoai-trigger, .gcoai-regenerate', function() {
79+
setTimeout(function() {
80+
applyShimmerToPlaceholders();
81+
}, 50);
82+
});
83+
84+
// Re-apply after AJAX completes
85+
$(document).ajaxComplete(function() {
86+
applyShimmerToPlaceholders();
87+
});
88+
})(jQuery);
89+
</script>
90+
<?php
91+
}
92+
93+
public function get_shimmer_markup() {
94+
$spinner = '';
95+
96+
if ( $this->args['show_spinner'] ) {
97+
$spinner = sprintf(
98+
'<svg class="shimmer-spinner" xmlns="http://www.w3.org/2000/svg" width="%s" height="%s" stroke="%s" viewBox="0 0 24 24">
99+
<g class="spinner-rotate">
100+
<circle cx="12" cy="12" r="9.5" fill="none" stroke-width="1.5"/>
101+
</g>
102+
</svg>',
103+
esc_attr( $this->args['spinner_size'] ),
104+
esc_attr( $this->args['spinner_size'] ),
105+
esc_attr( $this->args['base_color'] )
106+
);
107+
}
108+
109+
$text_class = $this->args['show_shimmer'] ? 'shimmer' : 'shimmer-text';
110+
111+
return sprintf(
112+
'<span class="shimmer-wrapper">%s<span class="%s">%s</span></span>',
113+
$spinner,
114+
$text_class,
115+
esc_html( $this->args['text'] )
116+
);
117+
}
118+
119+
public function filter_loading_text( $placeholder, $field, $form = null ) {
120+
if ( ! class_exists( '\\GC_OpenAI\\Fields\\Stream' ) || ! $field instanceof \GC_OpenAI\Fields\Stream ) {
121+
return $placeholder;
122+
}
123+
124+
// If form_id is specified, only apply to those forms
125+
if ( $this->args['form_id'] !== null ) {
126+
$form_ids = is_array( $this->args['form_id'] ) ? $this->args['form_id'] : array( $this->args['form_id'] );
127+
if ( $form && ! in_array( rgar( $form, 'id' ), $form_ids ) ) {
128+
return $placeholder;
129+
}
130+
}
131+
132+
// If field_id is specified, only apply to those fields
133+
if ( $this->args['field_id'] !== null ) {
134+
$field_ids = is_array( $this->args['field_id'] ) ? $this->args['field_id'] : array( $this->args['field_id'] );
135+
if ( ! in_array( rgar( $field, 'id' ), $field_ids ) ) {
136+
return $placeholder;
137+
}
138+
}
139+
140+
return $this->get_shimmer_markup();
141+
}
142+
143+
private function get_styles_css() {
144+
$base = esc_attr( $this->args['base_color'] );
145+
$shimmer = esc_attr( $this->args['shimmer_color'] );
146+
$dur = esc_attr( $this->args['shimmer_duration'] );
147+
148+
return
149+
".shimmer-wrapper { display: inline-flex; align-items: center; gap: 8px; } " .
150+
".shimmer-spinner { flex-shrink: 0; } " .
151+
".spinner-rotate { transform-origin: center; animation: spinner-rotation 2s linear infinite; } " .
152+
".spinner-rotate circle { stroke-linecap: round; animation: spinner-stroke 1.5s ease-in-out infinite; } " .
153+
"@keyframes spinner-rotation { 100% { transform: rotate(360deg); } } " .
154+
"@keyframes spinner-stroke { 0% { stroke-dasharray: 0 150; stroke-dashoffset: 0; } 47.5% { stroke-dasharray: 42 150; stroke-dashoffset: -16; } 95%, 100% { stroke-dasharray: 42 150; stroke-dashoffset: -59; } } " .
155+
".shimmer-text { display: inline-block; color: {$base}; line-height: 1.2; } " .
156+
".shimmer { display: inline-block; color: {$base}; line-height: 1.2; background: {$base} linear-gradient(to left, {$base}, {$shimmer} 50%, {$base}); background-position: -4rem top; background-repeat: no-repeat; background-size: 4rem 100%; -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; animation: shimmer {$dur} infinite; } " .
157+
"@keyframes shimmer { 0% { background-position: -4rem top; } 70%, 100% { background-position: 12.5rem top; } }";
158+
}
159+
}
160+
161+
# Configuration
162+
163+
new GCOAI_Loading_Animation( array(
164+
'text' => 'Thinking...',
165+
'base_color' => '#292929',
166+
'shimmer_color' => '#fff',
167+
'shimmer_duration' => '2.2s',
168+
'show_shimmer' => true,
169+
'show_spinner' => true,
170+
'spinner_size' => '16',
171+
// 'form_id' => 123, // Uncomment and set to target specific form(s): 123 or array( 18, 22, 35 )
172+
// 'field_id' => 4, // Uncomment and set to target specific field(s): 5 or array( 5, 7, 12 )
173+
) );

0 commit comments

Comments
 (0)