1+ package com .fastcomments ;
2+
3+ import android .os .Bundle ;
4+ import android .view .View ;
5+ import android .widget .Toast ;
6+
7+ import androidx .activity .result .ActivityResultLauncher ;
8+ import androidx .activity .result .contract .ActivityResultContracts ;
9+ import androidx .appcompat .app .AppCompatActivity ;
10+ import androidx .constraintlayout .widget .ConstraintLayout ;
11+ import androidx .constraintlayout .widget .ConstraintSet ;
12+
13+ import com .fastcomments .core .CommentWidgetConfig ;
14+ import com .fastcomments .core .sso .FastCommentsSSO ;
15+ import com .fastcomments .core .sso .SimpleSSOUserData ;
16+ import com .fastcomments .model .FeedPost ;
17+ import com .fastcomments .sdk .CommentsDialog ;
18+ import com .fastcomments .sdk .FastCommentsFeedSDK ;
19+ import com .fastcomments .sdk .FastCommentsFeedView ;
20+ import com .fastcomments .sdk .FeedPostCreateView ;
21+ import com .fastcomments .sdk .OnUserClickListener ;
22+ import com .fastcomments .sdk .UserClickSource ;
23+ import com .fastcomments .sdk .examples .GifPickerFeedToolbarButton ;
24+ import com .google .android .material .floatingactionbutton .FloatingActionButton ;
25+
26+ import java .util .List ;
27+
28+ /**
29+ * Activity demonstrating custom toolbar buttons for feed post creation.
30+ * This example shows how to add global custom toolbar buttons to the feed SDK
31+ * which will appear on all FeedPostCreateView instances.
32+ *
33+ * Features demonstrated:
34+ * - How to add global custom toolbar buttons to FastCommentsFeedSDK
35+ * - How toolbar buttons automatically appear in FeedPostCreateView
36+ * - Example GIF picker button implementation
37+ * - Best practices for custom button integration
38+ */
39+ public class FeedExampleCustomButtonsActivity extends AppCompatActivity {
40+
41+ private FastCommentsFeedView feedView ;
42+ private FastCommentsFeedSDK feedSDK ;
43+ private FeedPostCreateView postCreateView ;
44+ private FloatingActionButton createPostFab ;
45+ private OnUserClickListener userClickListener ;
46+
47+ // Image picker launcher
48+ private final ActivityResultLauncher <String > pickImageLauncher =
49+ registerForActivityResult (new ActivityResultContracts .GetContent (), uri -> {
50+ if (uri != null && postCreateView != null ) {
51+ postCreateView .handleImageResult (uri );
52+ }
53+ });
54+
55+ @ Override
56+ protected void onCreate (Bundle savedInstanceState ) {
57+ super .onCreate (savedInstanceState );
58+ setContentView (R .layout .activity_example_feed );
59+
60+ // Create a configuration for the SDK
61+ CommentWidgetConfig config = new CommentWidgetConfig ();
62+ config .tenantId = "demo" ; // Use your tenant ID here
63+ config .urlId = "https://example.com/toolbar-demo" ; // Different URL to avoid conflicts
64+ config .pageTitle = "Feed Toolbar Demo" ;
65+
66+ // Set up Simple SSO for user authentication
67+ SimpleSSOUserData userData = new SimpleSSOUserData (
68+ "Toolbar Demo User" ,
69+ 70+ "https://staticm.fastcomments.com/1639362726066-DSC_0841.JPG" );
71+
72+ FastCommentsSSO sso = new FastCommentsSSO (userData );
73+ config .sso = sso .prepareToSend ();
74+
75+ // Initialize the Feed SDK
76+ feedSDK = new FastCommentsFeedSDK (config );
77+
78+ // Add global custom toolbar buttons to the SDK
79+ // These buttons will automatically appear in all FeedPostCreateView instances
80+ setupGlobalToolbarButtons ();
81+
82+ // Find the feed view in the layout
83+ feedView = findViewById (R .id .feedView );
84+
85+ // Set the SDK instance for the view
86+ feedView .setSDK (feedSDK );
87+
88+ feedView .setTagSupplier (currentUser -> {
89+ // Return null to get a "global" feed for this demo
90+ return null ;
91+ });
92+
93+ // Create and add the FeedPostCreateView
94+ setupPostCreationView ();
95+
96+ setupUserClickListener ();
97+
98+ // Set interaction listener
99+ feedView .setFeedViewInteractionListener (new FastCommentsFeedView .OnFeedViewInteractionListener () {
100+ @ Override
101+ public void onFeedLoaded (List <FeedPost > posts ) {
102+ // Feed loaded successfully
103+ }
104+
105+ @ Override
106+ public void onFeedError (String errorMessage ) {
107+ // Error loading feed
108+ Toast .makeText (FeedExampleCustomButtonsActivity .this , errorMessage , Toast .LENGTH_SHORT ).show ();
109+ }
110+
111+ @ Override
112+ public void onPostSelected (FeedPost post ) {
113+ // User selected a post
114+ }
115+
116+ @ Override
117+ public void onCommentsRequested (FeedPost post ) {
118+ // Show comments dialog for the post from the SDK
119+ CommentsDialog dialog = new CommentsDialog (FeedExampleCustomButtonsActivity .this , post , feedSDK );
120+
121+ // Set comment added listener to update the post in the feed
122+ dialog .setOnCommentAddedListener (postId -> {
123+ // Post stats already updated in feedSDK, just need to refresh UI
124+ runOnUiThread (() -> {
125+ // Find position of post in adapter and update it
126+ feedView .refreshPost (postId );
127+ });
128+ });
129+
130+ dialog .setOnUserClickListener (userClickListener );
131+
132+ dialog .show ();
133+ }
134+ });
135+
136+ feedView .setOnUserClickListener (userClickListener );
137+
138+ // Load the feed
139+ feedView .load ();
140+ }
141+
142+ /**
143+ * Set up global custom toolbar buttons that will appear in all FeedPostCreateView instances.
144+ * This demonstrates how to configure custom buttons at the SDK level.
145+ */
146+ private void setupGlobalToolbarButtons () {
147+ // Add a GIF picker button that will appear in the feed post creation toolbar
148+ // This button demonstrates how custom toolbar buttons work in the feed context
149+ feedSDK .addGlobalFeedToolbarButton (new GifPickerFeedToolbarButton ());
150+
151+ // You could add additional custom buttons here:
152+ // feedSDK.addGlobalFeedToolbarButton(new CustomEmojiPickerFeedToolbarButton());
153+ // feedSDK.addGlobalFeedToolbarButton(new MentionFeedToolbarButton());
154+ // feedSDK.addGlobalFeedToolbarButton(new CustomFormattingFeedToolbarButton());
155+ }
156+
157+ private void setupUserClickListener () {
158+ userClickListener = (context , userInfo , source ) -> {
159+ String sourceText = source == UserClickSource .NAME ? "name" : "avatar" ;
160+ String contextText = context .isComment () ? "comment" : "feed post" ;
161+ Toast .makeText (FeedExampleCustomButtonsActivity .this ,
162+ "Clicked " + userInfo .getDisplayName () + "'s " + sourceText + " in " + contextText ,
163+ Toast .LENGTH_SHORT ).show ();
164+ };
165+ }
166+
167+ /**
168+ * Set up the post creation view and floating action button.
169+ * The FeedPostCreateView will automatically include all global toolbar buttons
170+ * added to the SDK via addGlobalFeedToolbarButton().
171+ */
172+ private void setupPostCreationView () {
173+ // Get the parent ConstraintLayout
174+ final ConstraintLayout parentLayout = findViewById (R .id .feedParentLayout );
175+
176+ // Create the post creation view
177+ postCreateView = new FeedPostCreateView (this );
178+ postCreateView .setId (View .generateViewId ());
179+
180+ // Setting the SDK will automatically add all global toolbar buttons
181+ postCreateView .setSDK (feedSDK );
182+ postCreateView .setVisibility (View .GONE );
183+
184+ // Create constraints for post creation view (full width at top, floating above content)
185+ ConstraintLayout .LayoutParams postCreateParams = new ConstraintLayout .LayoutParams (
186+ ConstraintLayout .LayoutParams .MATCH_PARENT ,
187+ ConstraintLayout .LayoutParams .WRAP_CONTENT );
188+ postCreateView .setLayoutParams (postCreateParams );
189+ postCreateView .setElevation (16f ); // Elevate above other content
190+
191+ // Add view to parent
192+ parentLayout .addView (postCreateView );
193+
194+ // Update constraints to position the view at the top
195+ ConstraintSet initialConstraintSet = new ConstraintSet ();
196+ initialConstraintSet .clone (parentLayout );
197+ initialConstraintSet .connect (postCreateView .getId (), ConstraintSet .TOP , parentLayout .getId (), ConstraintSet .TOP , 0 );
198+ initialConstraintSet .connect (postCreateView .getId (), ConstraintSet .START , parentLayout .getId (), ConstraintSet .START , 0 );
199+ initialConstraintSet .connect (postCreateView .getId (), ConstraintSet .END , parentLayout .getId (), ConstraintSet .END , 0 );
200+ initialConstraintSet .applyTo (parentLayout );
201+
202+ // Create FAB
203+ createPostFab = new FloatingActionButton (this );
204+ createPostFab .setId (View .generateViewId ());
205+ createPostFab .setImageResource (android .R .drawable .ic_input_add );
206+ createPostFab .setContentDescription (getString (R .string .create_new_post ));
207+
208+ // Create params for FAB
209+ ConstraintLayout .LayoutParams fabParams = new ConstraintLayout .LayoutParams (
210+ ConstraintLayout .LayoutParams .WRAP_CONTENT ,
211+ ConstraintLayout .LayoutParams .WRAP_CONTENT );
212+ createPostFab .setLayoutParams (fabParams );
213+
214+ // Add FAB to parent
215+ parentLayout .addView (createPostFab );
216+
217+ // Update constraints to position the FAB at bottom-end
218+ ConstraintSet fabConstraintSet = new ConstraintSet ();
219+ fabConstraintSet .clone (parentLayout );
220+ fabConstraintSet .connect (createPostFab .getId (), ConstraintSet .BOTTOM , parentLayout .getId (), ConstraintSet .BOTTOM , 32 );
221+ fabConstraintSet .connect (createPostFab .getId (), ConstraintSet .END , parentLayout .getId (), ConstraintSet .END , 32 );
222+ fabConstraintSet .applyTo (parentLayout );
223+
224+ // Set FAB click listener
225+ createPostFab .setOnClickListener (v -> {
226+ // Configure post creation view and prepare it for showing
227+ postCreateView .show ();
228+ createPostFab .setVisibility (View .GONE );
229+
230+ // Apply animation to slide it down
231+ postCreateView .startAnimation (android .view .animation .AnimationUtils .loadAnimation (
232+ FeedExampleCustomButtonsActivity .this , com .fastcomments .sdk .R .anim .slide_down_from_top ));
233+ });
234+
235+ // Set post creation listener
236+ postCreateView .setOnPostCreateListener (new FeedPostCreateView .OnPostCreateListener () {
237+ @ Override
238+ public void onPostCreated (FeedPost post ) {
239+ // Use our new slide up and fade animation
240+ android .view .animation .Animation slideUpFade = android .view .animation .AnimationUtils .loadAnimation (
241+ FeedExampleCustomButtonsActivity .this , com .fastcomments .sdk .R .anim .slide_up_and_fade );
242+
243+ slideUpFade .setAnimationListener (new android .view .animation .Animation .AnimationListener () {
244+ @ Override
245+ public void onAnimationStart (android .view .animation .Animation animation ) {
246+ // No need to change visibility yet
247+ }
248+
249+ @ Override
250+ public void onAnimationEnd (android .view .animation .Animation animation ) {
251+ // Make form completely gone and unclickable
252+ postCreateView .clearAnimation ();
253+ postCreateView .setVisibility (View .GONE );
254+ postCreateView .setClickable (false );
255+ postCreateView .setEnabled (false );
256+
257+ // Show FAB button
258+ createPostFab .setVisibility (View .VISIBLE );
259+
260+ // Refresh the feed to show the new post
261+ feedView .refresh ();
262+ }
263+
264+ @ Override
265+ public void onAnimationRepeat (android .view .animation .Animation animation ) {}
266+ });
267+
268+ postCreateView .startAnimation (slideUpFade );
269+
270+ // Refresh the feed to show the new post
271+ feedView .refresh ();
272+ }
273+
274+ @ Override
275+ public void onPostCreateError (String errorMessage ) {
276+ Toast .makeText (FeedExampleCustomButtonsActivity .this , errorMessage , Toast .LENGTH_SHORT ).show ();
277+ }
278+
279+ @ Override
280+ public void onPostCreateCancelled () {
281+ // Use our new slide up and fade animation
282+ android .view .animation .Animation slideUpFade = android .view .animation .AnimationUtils .loadAnimation (
283+ FeedExampleCustomButtonsActivity .this , com .fastcomments .sdk .R .anim .slide_up_and_fade );
284+
285+ slideUpFade .setAnimationListener (new android .view .animation .Animation .AnimationListener () {
286+ @ Override
287+ public void onAnimationStart (android .view .animation .Animation animation ) {
288+ // No need to change visibility yet
289+ }
290+
291+ @ Override
292+ public void onAnimationEnd (android .view .animation .Animation animation ) {
293+ // Make form completely gone and unclickable
294+ postCreateView .clearAnimation ();
295+ postCreateView .setVisibility (View .GONE );
296+ postCreateView .setClickable (false );
297+ postCreateView .setEnabled (false );
298+
299+ // Show FAB button
300+ createPostFab .setVisibility (View .VISIBLE );
301+ }
302+
303+ @ Override
304+ public void onAnimationRepeat (android .view .animation .Animation animation ) {}
305+ });
306+
307+ postCreateView .startAnimation (slideUpFade );
308+ }
309+
310+ @ Override
311+ public void onImagePickerRequested () {
312+ // Launch image picker
313+ pickImageLauncher .launch ("image/*" );
314+ }
315+ });
316+ }
317+
318+ @ Override
319+ protected void onDestroy () {
320+ super .onDestroy ();
321+ // Clean up the feed view to prevent memory leaks
322+ if (feedView != null ) {
323+ feedView .cleanup ();
324+ }
325+ }
326+ }
0 commit comments