Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add markAsCash button with wired up action for dismissing the rter violation #41835

Merged
merged 12 commits into from
May 23, 2024

Conversation

BrtqKr
Copy link
Contributor

@BrtqKr BrtqKr commented May 8, 2024

Details

Fixed Issues

$ #39541

PROPOSAL:

Tests

  1. Go to the open report - a workspace for example
  2. Submit an expense and retrieve its transactionId
  3. Go to the report screen and in the console, update the onyx entries containing the mocked card that will be used for the transaction, the given transaction and the corresponding violation.
Onyx.merge('cardList', {
        1: {
            bank: 'Expensify Card',
            lastFourPAN: 3458,
        },
    });

Onyx.merge(`transactions_<transaction_id>`, {cardID: 1, merchant: 'violation test'});

Onyx.merge(`transactionViolations_<transaction_id>`, [{type: 'test', name: CONST.VIOLATIONS.RTER, data: {pendingPattern: true}}]);
  1. The mark as cash button should appear
  2. After pressing it the button and the violation message should disappear and there should be a response in the thread confirming that there was a conversion to cash
  • Verify that no errors appear in the JS console

Offline tests

As the standard ones.

QA Steps

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
    • MacOS: Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. myBool && <MyComponent />.
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I verified the translation was requested/reviewed in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Screen.Recording.2024-05-10.at.11.51.40.mov
Screen.Recording.2024-05-10.at.13.49.11.mov
MacOS: Desktop
Screen.Recording.2024-05-10.at.12.04.43.mov

@yuwenmemon yuwenmemon self-requested a review May 9, 2024 19:21
Copy link
Contributor

@kosmydel kosmydel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor questions

@@ -188,6 +188,7 @@ function ReportActionsList({
const hasFooterRendered = useRef(false);
const lastVisibleActionCreatedRef = useRef(report.lastVisibleActionCreated);
const lastReadTimeRef = useRef(report.lastReadTime);
// Single MoneyRequest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is showing as a change, because ola removed it in her PR and this branch was based on it

src/components/MoneyRequestHeaderStatusBar.tsx Outdated Show resolved Hide resolved
width={variables.iconSizeExtraSmall}
fill={theme.textSupporting}
/>
<Text style={[styles.textLabel, styles.colorMuted, styles.ml1, styles.amountSplitPadding]}>{translate('iou.receiptScanInProgress')}</Text>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB: We can consider creating a new style for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check if any other use cases appear in the first place and apply it separately, but yeah that's probably a good idea

Comment on lines 129 to 140
const getPendingType = () => {
if (TransactionUtils.isExpensifyCardTransaction(transaction) && TransactionUtils.isPending(transaction)) {
return {pendingType: 'PENDING', pendingTitle: translate('iou.pending'), pendingDescription: translate('iou.transactionPendingText')};
}
if (isScanning) {
return {pendingType: 'SCANNING', pendingTitle: ReceiptScan, pendingDescription: translate('iou.receiptScanInProgressDescription')};
}
if (TransactionUtils.hasPendingRTERViolation(TransactionUtils.getTransactionViolations(transaction?.transactionID ?? '', transactionViolations))) {
return {pendingType: 'RTER', pendingTitle: Expensicons.Hourglass, pendingDescription: translate('iou.pendingMatchWithCreditCardDescription')};
}
return {};
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To consider: adding useCallback.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • it's based on the transaction, which is one of the key elements that change in this components props, so probably there wouldn't be any major benefits coming from this change
  • probably useMemo would be more suitable, but as I stated, there aren't any major benefits and since there aren't any issues either we should avoid it as stated in the docs

onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
value: {
[optimisticReportAction.reportActionID]: null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to make sure: which offline pattern do we follow here? Is it B (Optimistic WITH Feedback Pattern)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's from the other branch that has already been merged, but @yuwenmemon probably has more context regarding this action

@yuwenmemon
Copy link
Contributor

@BrtqKr Merge main to simplify the diff a bit!

@yuwenmemon
Copy link
Contributor

@BrtqKr Quick bump on this! I believe all pre-requisite PRs have been merged

@BrtqKr BrtqKr marked this pull request as ready for review May 16, 2024 10:39
@BrtqKr BrtqKr requested a review from a team as a code owner May 16, 2024 10:39
@melvin-bot melvin-bot bot requested review from c3024, dubielzyk-expensify and grgia and removed request for a team May 16, 2024 10:39
Copy link

melvin-bot bot commented May 16, 2024

@dubielzyk-expensify @c3024 @grgia One of you needs to copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

Copy link
Contributor

@dubielzyk-expensify dubielzyk-expensify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me from a visual perspective. cc @Expensify/design for visibility

@shawnborton
Copy link
Contributor

In this screenshot here:
CleanShot 2024-05-16 at 21 14 32@2x

Shouldn't the green button be in the top right and not full width? We only move the button down when the viewport turns into mobile view.

@dubielzyk-expensify
Copy link
Contributor

Oh wow. What a miss on my end. Yep most definitely. Should look like this:

image

@dubielzyk-expensify dubielzyk-expensify self-requested a review May 17, 2024 01:18
@shawnborton
Copy link
Contributor

Yup, exactly!

@BrtqKr
Copy link
Contributor Author

BrtqKr commented May 17, 2024

ok, it should be fine now

Screenshot 2024-05-17 at 10 12 45

@shawnborton
Copy link
Contributor

I could have sworn on mobile, we show the green button above the status - does that sound correct?

@dannymcclain
Copy link
Contributor

@shawnborton in the design doc, the button is below the status, like it is here. 🤷‍♂️

@c3024
Copy link
Contributor

c3024 commented May 20, 2024

Should this report action be here in the report with all transactions?

Screenshot 2024-05-20 at 3 55 15 PM

If it should be there are two issues.

  1. For the first transaction, this report action message marked this receipt as cash. does not appear.
markedAsCashMessageMissing.mp4
  1. The report action is added at the end of the report with transactions when Mark as Cash is clicked for a transaction. This message can be related to a request that might not be the latest request. So, we cannot know which request does this message relate to.
Screenshot 2024-05-20 at 3 55 15 PM

Another question unrelated to the above, should an RBR be shown for this violation on report preview, LHN and in the transaction report (not sure which field that would be.)?

@dannymcclain
Copy link
Contributor

Should this report action be here in the report with all transactions?

Hmm that seems weird to me. I would expect it to be in the transaction thread, not the report thread. (Like if you change the category of an expense, that system message shows up in the expense thread.) I would also expect it to have the avatar/name of the person who marked it as cash. @JmillsExpensify @shawnborton does that sound right to you?

Another question unrelated to the above, should an RBR be shown for this violation on report preview, LHN and in the transaction report (not sure which field that would be.)?

I think @JmillsExpensify would know better, but I feel like the preview should be showing an RBR/error message instead of "Unknown Merchant"... Unless of course someone set the merchant to Unknown Merchant deliberately. 😅

@shawnborton
Copy link
Contributor

Hmm that seems weird to me. I would expect it to be in the transaction thread, not the report thread. (Like if you change the category of an expense, that system message shows up in the expense thread.) I would also expect it to have the avatar/name of the person who marked it as cash. @JmillsExpensify @shawnborton does that sound right to you?

I agree it should be in the transaction thread. As for the avatar, I think it follows the same logic as when the same user sends multiple messages consecutively where we skip the avatar if you send a bunch of messages in a row.

@dannymcclain
Copy link
Contributor

I agree it should be in the transaction thread. As for the avatar, I think it follows the same logic as when the same user sends multiple messages consecutively where we skip the avatar if you send a bunch of messages in a row.

Ah that makes sense. So since this is (wrongly) showing up in the report thread, it's piggy-backing off of the request message. Once we get it in the expense thread like it's supposed to be, that issue should go away. 🤞

@yuwenmemon
Copy link
Contributor

Hmmm yeah @BrtqKr That seems to be stemming from some sort of optimistic action we're adding to the parent report because once you sign in and out, those messages disappear:

Kapture.2024-05-20.at.11.53.15.mp4

Screenshot 2024-05-20 at 11 56 56 AM

@BrtqKr
Copy link
Contributor Author

BrtqKr commented May 21, 2024

@yuwenmemon isn't it because we're using a random id for the messaging optimistic update? Maybe Onyx isn't able to relate the success id and the random one generated in the action and we should be removing it in the successData

            // Dismiss action with a temporary id
            {
                onyxMethod: Onyx.METHOD.MERGE,
                key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
                value: {
                    [optimisticReportAction.reportActionID]: null,
                },
            },
Screen.Recording.2024-05-21.at.12.15.50.mov

text={translate('iou.markAsCash')}
style={[styles.p0]}
onPress={() => {
TransactionActions.markAsCash(transaction?.transactionID ?? '', transaction?.reportID ?? '');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BrtqKr I think this is the source of your issue. We should be using the transactionThreadID here, not the report ID of the transaction.

One can see this here:
Screenshot 2024-05-21 at 11 48 06 AM
Screenshot 2024-05-21 at 11 48 13 AM

@yuwenmemon
Copy link
Contributor

@BrtqKr I don't think it's that, no. I commented on the PR on the line that I believe to be the culprit. Essentially we're passing the transaction's reportID to TransactionActions.markAsCash when we should be passing the Transaction Thread ReportID instead.

@BrtqKr BrtqKr requested a review from yuwenmemon May 21, 2024 23:13
@JmillsExpensify
Copy link

Quickly confirming that yes, this should appear in the transaction thread.

yuwenmemon
yuwenmemon previously approved these changes May 22, 2024
Copy link
Contributor

@yuwenmemon yuwenmemon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@yuwenmemon
Copy link
Contributor

@c3024 Can you prioritize your review of this PR ASAP?

text={translate('iou.markAsCash')}
style={[styles.p0]}
onPress={() => {
TransactionActions.markAsCash(transaction?.transactionID ?? '', transactionThreadReportID ?? '');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TransactionActions.markAsCash(transaction?.transactionID ?? '', transactionThreadReportID ?? '');
TransactionActions.markAsCash(transaction?.transactionID ?? '', report?.reportID ?? '');

text={translate('iou.markAsCash')}
style={[styles.w100, styles.pr0]}
onPress={() => {
TransactionActions.markAsCash(transaction?.transactionID ?? '', transaction?.reportID ?? '');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TransactionActions.markAsCash(transaction?.transactionID ?? '', transaction?.reportID ?? '');
TransactionActions.markAsCash(transaction?.transactionID ?? '', report?.reportID ?? '');

I think it is better to extract this to a local function because it is used twice and in the last commit only one instance was updated.

@@ -147,7 +156,11 @@ function MoneyRequestHeader({
return {title: getStatusIcon(Expensicons.ReceiptScan), description: translate('iou.receiptScanInProgressDescription'), shouldShowBorderBottom: true};
}
if (TransactionUtils.hasPendingRTERViolation(TransactionUtils.getTransactionViolations(transaction?.transactionID ?? '', transactionViolations))) {
return {title: getStatusIcon(Expensicons.Hourglass), description: translate('iou.pendingMatchWithCreditCardDescription'), shouldShowBorderBottom: true};
return {
Copy link
Contributor

@c3024 c3024 May 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be moved above the isScanning message. That is how it is in oneTransactionReports. When there is an RTER violation that message should be shown instead of the 'being scanned' message.

@BrtqKr BrtqKr requested a review from c3024 May 22, 2024 13:17
@c3024
Copy link
Contributor

c3024 commented May 22, 2024

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
    • MacOS: Desktop
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. myBool && <MyComponent />.
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: Native

Screenshot 2024-05-22 at 7 41 31 PM

Android: mWeb Chrome

Screenshot 2024-05-22 at 7 46 05 PM

iOS: Native Screenshot 2024-05-22 at 6 38 54 PM
iOS: mWeb Safari

Screenshot 2024-05-22 at 6 48 31 PM

MacOS: Chrome / Safari
markAsCashChrome.mp4
MacOS: Desktop
markAsCashDesktop.mp4

@c3024
Copy link
Contributor

c3024 commented May 22, 2024

NAB: MoneyReportHeader props do not include transaction or transactionViolations so it does not appear to rerender immediately on Onyx.merge transaction and transactionViolations. But in actual use cases, I think backend sends more info than just transaction and transactionViolations so it should rerender immediately.

Also, MoneyReportHeader here is used only for oneTransactionReports, I think it is fine to not subscribe to these changes and avoid rerenders.

Copy link
Contributor

@c3024 c3024 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@yuwenmemon yuwenmemon merged commit 4bd72e4 into Expensify:main May 23, 2024
16 checks passed
@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by https://github.com/yuwenmemon in version: 1.4.76-0 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

@OSBotify
Copy link
Contributor

🚀 Deployed to production by https://github.com/Beamanator in version: 1.4.76-7 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants