feed-item.js 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { View } from 'app/design/view';
  2. import Html from 'app/ui/atoms/html';
  3. import { useState, useEffect } from 'react'
  4. import Embed from 'app/ui/molecules/content/embed'
  5. import { cloneObject, appSetting } from 'app/lib/util';
  6. import { subscribeTimelineEdit } from 'app/lib/timeline-edits';
  7. import { ActionMenu, CounterMenu } from 'app/components/elements/feed-item-parts'
  8. import { UnitImages } from 'app/lib/feed-items'
  9. import { PollItem } from 'app/components/elements/entity-poll';
  10. import { BlockWrapper } from 'app/components/block-wrapper'
  11. import { fetcher } from 'app/lib/fetcher'
  12. import { objectStateGeneration, storeObjectsFrom } from 'app/lib/object-state'
  13. export default function ElementFeedItem({ data, isModal, blockWrapperProps }) {
  14. const eventId = data?.event?.id
  15. const [content, setContent] = useState(data.event.content)
  16. // Same as UnitFeed card: refetch on timeline "edited" socket
  17. useEffect(() => {
  18. if (eventId == null) return undefined
  19. return subscribeTimelineEdit(eventId, async () => {
  20. const generation = objectStateGeneration()
  21. const result = await fetcher(
  22. '/api.php?r=' +
  23. appSetting('urls', 'feed_item') +
  24. '{"params":{"browse":"id","value":' +
  25. eventId +
  26. '}}'
  27. )
  28. // Counters and reactions of the post for every widget, unless the
  29. // viewer logged out or switched profiles meanwhile.
  30. if (result.data && generation === objectStateGeneration()) storeObjectsFrom(result.data)
  31. if (result.data?.content) setContent(result.data.content)
  32. })
  33. }, [eventId])
  34. const tlContent = content?.text
  35. let content_attach = [];
  36. if (content?.images_attach?.length > 0) {
  37. content_attach = content_attach.concat(content.images_attach);
  38. }
  39. if (content?.videos_attach?.length > 0) {
  40. content_attach = content_attach.concat(content.videos_attach);
  41. }
  42. let menu_actions2 = cloneObject(data.event.menu_actions)
  43. if (isModal) {
  44. menu_actions2.items = menu_actions2.items.filter(
  45. (x) => x.name !== "item-comment"
  46. );
  47. }
  48. return (
  49. <BlockWrapper {...blockWrapperProps}>
  50. {/* Same stack and gap as the feed card (DefaultView in units/feed-views.js). */}
  51. <View className="w-full gap-y-3">
  52. <Html key={tlContent || 'empty'} data={tlContent} customClassName="u-vanilla-html-small" />
  53. {!!content?.embed && <Embed data={content.embed} />}
  54. {content?.polls_attach?.length > 0 && (
  55. <View className='w-full'>
  56. {content.polls_attach.map((item, index) => {
  57. return <View key={"att" + index} className='mt-4'><PollItem data={item} showTitle={true} results_url='/api.php?r=bx_timeline/get_block_poll_results' /></View>
  58. })}
  59. </View>
  60. )
  61. }
  62. {content_attach.length > 0 && <UnitImages images={content_attach} />}
  63. </View>
  64. {
  65. data.event.menu_actions.items.length > 0 && (<View className=" flex-row items-center ">
  66. <View className="flex-auto gap-2 mt-2 ">
  67. {(!!data.event.menu_counters && appSetting('feed', 'counters_menu')) && <CounterMenu data={data.event.menu_counters} />}
  68. <ActionMenu data={menu_actions2} />
  69. </View>
  70. </View>)
  71. }
  72. </BlockWrapper>
  73. )
  74. }