EmojiPicker.pm 1.9 KB

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