Skip to content

[Due for payment 2025-11-19] [$175] - Android - Second broken image preview is blank #71971

Closed

Description

@jponikarchuk

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Version Number: v9.2.24-1
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from TestRail: https://test-management.browserstack.com/projects/2219752/folder/13176710/test-cases/41236964
Email or phone of affected tester (no customers): sintayewhaylu01@gmail.comi
Issue reported by: Applause Internal Team
Device used: Samsung A16/ Android 15
App Component: Other

Action Performed:

  1. Open Hybrid app
  2. Send the broken image link: ![AltText](https://invalid-url/image.jpg) to any chat.
  3. Preview the broken image.
  4. Send the broken image link again.
  5. Attempt to view the preview..

Expected Result:

When the broken image is sent for the second time and its preview is opened, the preview should display a message such as "Attachment not found",

Actual Result:

After sending the broken image a second time and attempting to preview it, the preview page opens but remains completely blank with no visible content.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

11.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021977972797478496567
  • Upwork Job ID: 1977972797478496567
  • Last Price Increase: 2025-11-26
Issue OwnerCurrent Issue Owner: @VictoriaExpensify

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 7, 2025
  2. melvin-bot commented on Oct 7, 2025

    @melvin-bot

    Triggered auto assignment to @VictoriaExpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

  3. andriivitiv commented on Oct 7, 2025

    @andriivitiv
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    Android - Second broken image preview is blank

    What is the root cause of that problem?

    When duplicate sources exist, foundPage is incorrectly set to an index of the first attachment

    const foundPage = attachmentCarouselPagerContext.pagerItems.findIndex((item) => item.source === uri || item.previewSource === uri);

    As a result, indexOutOfRange becomes true and isLightboxVisible becomes false

    const isLightboxVisible = useMemo(() => {
    if (!hasSiblingCarouselItems || NUMBER_OF_CONCURRENT_LIGHTBOXES === 'UNLIMITED') {
    return true;
    }
    const indexCanvasOffset = Math.floor((NUMBER_OF_CONCURRENT_LIGHTBOXES - 1) / 2) || 0;
    const indexOutOfRange = page > activePage + indexCanvasOffset || page < activePage - indexCanvasOffset;
    return !indexOutOfRange;
    }, [activePage, hasSiblingCarouselItems, page]);

    Because isLightboxVisible is false, the image is not rendered

    {isLightboxVisible && (

    What changes do you think we should make in order to solve the problem?

    Modify the foundPage logic to also verify that the attachment is active by adding item.isActive to the condition. This ensures that only the currently active attachment is matched, preventing incorrect indexing when duplicate sources exist.

    const foundPage = attachmentCarouselPagerContext.pagerItems.findIndex((item) => (item.source === uri || item.previewSource === uri) && item.isActive);
  4. bernhardoj commented on Oct 10, 2025

    @bernhardoj
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    The 2nd broken image is blank in preview.

    What is the root cause of that problem?

    In this case, isLightboxVisible is false.

    {isLightboxVisible && (
    <View style={[StyleUtils.getFullscreenCenteredContentStyles(), StyleUtils.getOpacityStyle(Number(shouldShowLightbox))]}>
    <MultiGestureCanvas

    It's because the page is smaller than the activePage.

    const indexOutOfRange = page > activePage + indexCanvasOffset || page < activePage - indexCanvasOffset;
    return !indexOutOfRange;

    Let's say we have 2 images only, and we open the 2nd image. The activePage will be 1, but the page is 0. The page is found by finding the first attachment with the same source. But since the 1st broken image has the same source, 0 (index) is returned.

    const foundPage = attachmentCarouselPagerContext.pagerItems.findIndex((item) => item.source === uri || item.previewSource === uri);
    return {
    ...attachmentCarouselPagerContext,
    isUsedInCarousel: !!attachmentCarouselPagerContext.pagerRef,
    isSingleCarouselItem: attachmentCarouselPagerContext.pagerItems.length === 1,
    page: foundPage,

    What changes do you think we should make in order to solve the problem?

    We should compare the attachment with its attachmentID instead. The attachmentID is attached from here.

    function getHtmlWithAttachmentID(html: string, reportActionID: string | undefined) {
    if (!reportActionID) {
    return html;
    }
    let attachmentID = 0;
    return html.replace(/<img |<video /g, (m) => m.concat(`${CONST.ATTACHMENT_ID_ATTRIBUTE}="${reportActionID}_${++attachmentID}" `));

    const foundPage = attachmentCarouselPagerContext.pagerItems.findIndex((item) => item.attachmentID === attachmentID);
    

    First, we need to include the attachmentID when mapping the pager items here.

    /** The `pagerItems` object that passed down to the context. Later used to detect current page, whether it's a single image gallery etc. */
    const pagerItems = useMemo(
    () => items.map((item, index) => ({source: item.source, previewSource: item.previewSource, index, isActive: index === activePageIndex})),
    [activePageIndex, items],
    );

    Then, pass down the attachmentID props from CarouselItem > AttachmentView > AttachmentViewImage > ImageView (native) > Lightbox

  5. VictoriaExpensify commented on Oct 14, 2025

    @VictoriaExpensify
    Contributor

    Yeah ok, I think we should fix this. But I don't think this is a very high priority because it doesn't really impact the customers overall experience. I also think it's a somewhat easy fix (although please correct me if I'm wrong about that) so I'm going to reduce the bounty.

  6. changed the title [-]Android - Second broken image preview is blank[/-] [+][$125] - Android - Second broken image preview is blank[/+] on Oct 14, 2025
  7. melvin-bot commented on Oct 14, 2025

    @melvin-bot

    ⚠️ Could not update price automatically because there is no linked Upwork Job ID. The BZ team member will need to update the price manually in Upwork.

  8. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Oct 14, 2025
  9. melvin-bot commented on Oct 14, 2025

    @melvin-bot
  10. added
    Help WantedApply this label when an issue is open to proposals by contributors
    on Oct 14, 2025
  11. 40 remaining items

  12. VictoriaExpensify commented on Nov 23, 2025

    @VictoriaExpensify
    Contributor

    Hey @Pujan92 did something change with the scope of it, or did it end up being more complex than first anticipated?

    @neil-marcellini - what are your thoughts?

  13. Pujan92 commented on Nov 25, 2025

    @Pujan92
    Contributor

    @VictoriaExpensify according to me, we usually reduce the bounty for very straightforward and minimalistic change. But I think that is not the case here and I believe the default price looks fair here. Still looking forward to knowing @neil-marcellini's thoughts.

  14. VictoriaExpensify commented on Nov 26, 2025

    @VictoriaExpensify
    Contributor

    Hey @Pujan92 - typically, that would be brought up when the bounty is adjusted, which was back on 14 October #71971 (comment) - it was reduced before the issue was assigned and before we started accepting proposals.

    At the time of adjusting the bounty, I stated:

    Yeah ok, I think we should fix this. But I don't think this is a very high priority because it doesn't really impact the customer's overall experience. I also think it's a somewhat easy fix (although please correct me if I'm wrong about that) so I'm going to reduce the bounty.

  15. Pujan92 commented on Nov 26, 2025

    @Pujan92
    Contributor

    Oh, ok. No issues then. It might be my side fault. 👍

  16. VictoriaExpensify commented on Nov 26, 2025

    @VictoriaExpensify
    Contributor

    All good! I'm not an engineer and I might not always fully understand the effort required, so do feel free to speak up if you ever think me (or anyone else) has this wrong.

    In this instance, let's meet in the middle and I'll bump up to $175.

  17. changed the title [-][Due for payment 2025-11-19] [$125] - Android - Second broken image preview is blank[/-] [+][Due for payment 2025-11-19] [$175] - Android - Second broken image preview is blank[/+] on Nov 26, 2025
  18. melvin-bot commented on Nov 26, 2025

    @melvin-bot

    Upwork job price has been updated to $175

  19. VictoriaExpensify commented on Nov 26, 2025

    @VictoriaExpensify
    Contributor
  20. VictoriaExpensify commented on Nov 26, 2025

    @VictoriaExpensify
    Contributor

    Payment summary:
    C: @bernhardoj owed $175 via ND
    C+: @Pujan92 owed $175 via ND

  21. bernhardoj commented on Nov 27, 2025

    @bernhardoj
    Contributor

    Requested in ND.

  22. trjExpensify commented on Nov 27, 2025

    @trjExpensify
    Contributor

    approved $175 for @Pujan92.

  23. garrettmknight commented on Dec 1, 2025

    @garrettmknight
    Contributor

    $175 approved for @bernhardoj

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributor

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions