EmojiPicker.pm 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package Trog::Component::EmojiPicker;
  2. use 5.040;
  3. use re '/aasx';
  4. use warnings FATAL => 'all';
  5. use File::Slurper ();
  6. use JSON::MaybeXS;
  7. use Trog::Renderer;
  8. =head1 Trog::Component::EmojiPicker
  9. The emoji picker component.
  10. =head1 Termination Conditions
  11. Dies if the emoji list isn't on disk, as there's no sensible picker to show
  12. without it. It's a frontend dependency, so C<make prereq-frontend> is what
  13. puts it there.
  14. =head1 FUNCTIONS
  15. =head2 render(%args) = STRING
  16. Render the picker as an HTML component. Reached from templates as
  17. C<< <: component('EmojiPicker') :> >>; takes no arguments, and ignores any it
  18. is handed.
  19. The emoji list ships as a flat array, which is no use to a picker with tabs, so
  20. it gets bucketed by category on the first call and memoized thereafter -- the
  21. list can't change without a redeploy.
  22. Returns the rendered body, rather than a PSGI triplet, as components are meant
  23. to be composed into a page by their caller.
  24. =cut
  25. sub render (%) {
  26. state %categorized;
  27. if ( !%categorized ) {
  28. my $file = 'www/scripts/list.min.json';
  29. # One operation rather than a test and then a read, which also catches
  30. # the unreadable case the test missed. Checked with defined() rather
  31. # than truthiness so that an empty file falls through to the JSON
  32. # parser, which will say what is actually wrong with it.
  33. my $raw = eval { File::Slurper::read_binary($file) };
  34. die "Could not read $file ($@) -- run make prereq-frontend first" unless defined $raw;
  35. my $emojis = JSON::MaybeXS::decode_json($raw);
  36. foreach my $emoji ( @{ $emojis->{emojis} } ) {
  37. $categorized{ $emoji->{category} } //= [];
  38. push( @{ $categorized{ $emoji->{category} } }, $emoji->{emoji} );
  39. }
  40. }
  41. return Trog::Renderer->render(
  42. contenttype => 'text/html',
  43. component => 1,
  44. template => 'emojis.tx',
  45. data => {
  46. categories => \%categorized,
  47. },
  48. );
  49. }
  50. 1;