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

Onyx File handling - preparation #4908

Merged
merged 38 commits into from
Jan 14, 2022

Conversation

kidroca
Copy link
Contributor

@kidroca kidroca commented Aug 30, 2021

cc @thienlnam

Details

This is a proof of concept work that showcases file handling in Onyx as per the linked issue
Onyx was updated with peer dependency to localforage
Onyx PR: Expensify/react-native-onyx#102

Deleted listenToStorageEvents lib - this is now handled using IndexedDb and localforage in Onyx
Deleted SignOutManager lib - the updated Onyx.clear logic is synchronized across tabs and makes it unnecessary

Fixed Issues

$ #3867

Tests

#### For all platforms

1. Go offline
2. Open a conversation
3. Select and send an attachment
4. Terminated the app
5. Resume connectivity
6. Open the app again
7. Go to the conversation and see the file appearing after it's uploaded
- depending on how big is the file or how fast you do the last step - the file might already be uploaded

Edit: The change needed for this was reverted
It will be added and persisting attachments would work after we resolve: #6556

Regression check for Web

Multiple Tabs
  1. Open multiple tabs
  2. Open the same conversation on multiple tabs
  3. Write a draft message (without sending it)
  4. Observe the message is update across different tabs
Multiple Tabs (Signing out)
  1. Again on multiple tabs
  2. Log out from one tab
  3. You should be logged out on all tabs
  4. You should be able to log back in without problems (from the tab you logged out from or from another tab)

QA Steps

Tested On

  • Web
  • Mobile Web
  • Desktop
  • iOS
  • Android

Screenshots

Web

No regressions on persisting plain messages
New.Expensify.-.Google.Chrome.2021-12-15.01-57-51.mp4
Using multiple tabs/windows
2021-11-03_22-05-01.mp4

Mobile Web

Screen.Recording.2021-12-15.at.2.19.10.mov

Desktop

Screen.Recording.2021-12-15.at.2.12.51.mov

iOS

Screen.Recording.2021-12-15.at.2.15.09.mov

Android

Android.Emulator.-.Pixel_2_API_29_5554.2021-12-15.02-29-11.mp4

@kidroca kidroca force-pushed the kidroca/file-handling-poc branch from 90e0925 to 3ea51ec Compare August 30, 2021 15:46
@kidroca kidroca closed this Aug 30, 2021
@kidroca kidroca deleted the kidroca/file-handling-poc branch August 30, 2021 19:29
@kidroca kidroca restored the kidroca/file-handling-poc branch August 30, 2021 19:29
@kidroca kidroca reopened this Aug 30, 2021
# Conflicts:
#	ios/Podfile.lock
#	package.json
#	src/components/AttachmentPicker/index.native.js
#	src/components/OnyxProvider.js
#	src/libs/listenToStorageEvents/index.js
Copy link
Contributor Author

@kidroca kidroca left a comment

Choose a reason for hiding this comment

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

Mention again that registerStorageEventListener is no longer needed as it's covered internally in Onyx

Comment on lines -38 to -39
registerStorageEventListener: (onStorageEvent) => {
listenToStorageEvents(onStorageEvent);
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Synchronizing storage between tabs is handled internally by Onyx as it depends on the underlying storage implementation.
See: https://github.com/kidroca/react-native-onyx/blob/b6ad24440fe0b07b314373c1a4cfdf7914febc3f/lib/storage/index.js#L10-L15

# Conflicts:
#	android/app/src/main/java/com/expensify/chat/generated/BasePackageList.java
#	ios/Podfile.lock
#	package-lock.json
#	package.json
#	src/setup/index.js
Onyx no longer needs this
Removing `prepareFile` usage
The document picker makes the attachment available until the application
is terminated
To persist Document Attachments and be able to use them on the next app launch
we need to move them to the cache dir
This way we can persist a reference for the attachment in Onyx and support
offline files

The `ImagePicker` library is doing this by default
There seems to be some problem and nothing happens when image is selected
or when an image is shot
This fixes the issue with the image picker not working
Copy link
Contributor Author

@kidroca kidroca left a comment

Choose a reason for hiding this comment

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

Updated the Document/Image picker libraries in an attempt to solve an issue I had
It turned it it wasn't caused by these libraries, but I suppose now it's a good time to update them - QA will use the Attachment picker to test the changes made here anyway

@@ -65,7 +66,7 @@ function getDataForUpload(fileData) {
return {
name: fileData.fileName || fileData.name || 'chat_attachment',
type: fileData.type,
uri: fileData.uri,
uri: fileData.fileCopyUri || fileData.uri,
Copy link
Contributor Author

@kidroca kidroca Nov 2, 2021

Choose a reason for hiding this comment

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

The document picker makes the attachment available until the application is terminated
To persist Document Attachments and be able to use them on the next app launch we need to move them to the cache dir
This way we can persist a reference for the attachment in Onyx and support offline files

The ImagePicker library is already making a copy in cache by default

Comment on lines 120 to 136
* @param {ImagePickerResponse|DocumentPickerResponse} attachment
* @param {Array<ImagePickerResponse|DocumentPickerResponse>} attachments
*/
pickAttachment(attachment) {
if (attachment) {
if (attachment.width === -1 || attachment.height === -1) {
this.showImageCorruptionAlert();
return;
}
const result = getDataForUpload(attachment);
this.completeAttachmentSelection(result);
pickAttachment(attachments = []) {
if (attachments.length === 0) {
return;
}

const fileData = _.first(attachments);

if (fileData.width === -1 || fileData.height === -1) {
this.showImageCorruptionAlert();
return;
}

const result = getDataForUpload(fileData);
this.completeAttachmentSelection(result);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The updated document picker responds with an array. The image picker would also respond with array that's why this was changed to accept an array value

@kidroca kidroca requested a review from tgolen January 6, 2022 14:50
# Conflicts:
#	package-lock.json
#	package.json
@kidroca kidroca force-pushed the kidroca/file-handling-poc branch from a2459be to 555d9ae Compare January 6, 2022 15:07
tgolen
tgolen previously approved these changes Jan 6, 2022
The Pod file already has this version of Flipper and pipelines are failing
due to the mismatch
@kidroca
Copy link
Contributor Author

kidroca commented Jan 6, 2022

Hey @tgolen sorry just pushed an update to fix the pipeline

@kidroca
Copy link
Contributor Author

kidroca commented Jan 12, 2022

I think we forgot to remove the [HOLD] label here
It was added to prevent merging this prematurely but it's in a ready state now
File handling would happen in 2 steps

  1. Current PR transitions us to IndexedDb and the new Onyx implementation with storage providers
  2. Another PR would enable file persistens after Network: Persisted Requests Queue - clear persisted requests after the response #6556 is merged

cc @thienlnam

@kidroca kidroca changed the title [HOLD] Onyx File handling - preparation Onyx File handling - preparation Jan 12, 2022
Copy link
Contributor

@thienlnam thienlnam left a comment

Choose a reason for hiding this comment

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

Sorry for the late review, just a couple questions

Comment on lines -148 to -150
// Notifies all tabs that they should sign out and clear storage.
SHOULD_SIGN_OUT: 'shouldSignOut',

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this just not used? Not seeing it in any changes from this PR

Copy link
Contributor Author

@kidroca kidroca Jan 14, 2022

Choose a reason for hiding this comment

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

This was used here: src/libs/SignoutManager.js
But now the file is deleted - no longer necessary

What the SignoutManager did was to synchronize the logout across multiple tabs
But now with localForage this is no longer needed
We're touching on this here: Expensify/react-native-onyx#102 (comment)

@@ -53,6 +53,7 @@ function getImagePickerOptions(type) {
*/
const documentPickerOptions = {
type: [RNDocumentPicker.types.allFiles],
copyTo: 'cachesDirectory',
Copy link
Contributor

Choose a reason for hiding this comment

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

Does android have a cachesDirectory? I only see it for IOS

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Documentation says:

[iOS and Android only] copyTo:"cachesDirectory" | "documentDirectory"
https://www.npmjs.com/package/react-native-document-picker#ios-and-android-only-copytocachesdirectory--documentdirectory

I take it the option copyTo and the value cachesDirectory is available in both

Copy link
Contributor Author

@kidroca kidroca left a comment

Choose a reason for hiding this comment

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

Thanks @thienlnam, I hope these answer your questions well

Comment on lines -148 to -150
// Notifies all tabs that they should sign out and clear storage.
SHOULD_SIGN_OUT: 'shouldSignOut',

Copy link
Contributor Author

@kidroca kidroca Jan 14, 2022

Choose a reason for hiding this comment

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

This was used here: src/libs/SignoutManager.js
But now the file is deleted - no longer necessary

What the SignoutManager did was to synchronize the logout across multiple tabs
But now with localForage this is no longer needed
We're touching on this here: Expensify/react-native-onyx#102 (comment)

@@ -53,6 +53,7 @@ function getImagePickerOptions(type) {
*/
const documentPickerOptions = {
type: [RNDocumentPicker.types.allFiles],
copyTo: 'cachesDirectory',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Documentation says:

[iOS and Android only] copyTo:"cachesDirectory" | "documentDirectory"
https://www.npmjs.com/package/react-native-document-picker#ios-and-android-only-copytocachesdirectory--documentdirectory

I take it the option copyTo and the value cachesDirectory is available in both

Copy link
Contributor

@thienlnam thienlnam left a comment

Choose a reason for hiding this comment

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

Thanks for those comments, this looks all good on my end 👍 Thanks for those comments, this looks all good on my end 👍

@thienlnam thienlnam merged commit 537101f into Expensify:main Jan 14, 2022
@kidroca
Copy link
Contributor Author

kidroca commented Jan 14, 2022

🤦‍♂️ It seems this closed another PR due to the added description:

Edit: The change needed for this was reverted
It will be added and persisting attachments would work after we resolve: #6556

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by @thienlnam in version: 1.1.29-7 🚀

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

@kidroca kidroca deleted the kidroca/file-handling-poc branch January 14, 2022 20:22
@mountiny
Copy link
Contributor

There is a deploy blocker causing that PDF attachment shows an infinite spinner on Android (only as far as the QA team found).

This PR seems like the only one in the latest deployment, which is related. Would @kidroca be able to look into this and confirm if it is related?

If yes, would we revert this PR or would you be able to identify a fix to CP it soon?

Thank you for your help! 🙇

@kidroca
Copy link
Contributor Author

kidroca commented Jan 17, 2022

I'll investigate

@kidroca
Copy link
Contributor Author

kidroca commented Jan 17, 2022

@mountiny
Correct this PR introduced the regression, but I've found the problem and submitted a small PR: #7277

@kidroca
Copy link
Contributor Author

kidroca commented Jan 17, 2022

BTW the current PR applies a migration: https://github.com/Expensify/App/pull/4908/files#diff-fc59a9d775dba3004d8ed5a4dec154bbd2487455e7c720afed29bc8003a5228f

Reverting the PR won't revert the migration and the result would be users getting logged out when they open the app

IMO we should not revert, but apply #7277

@mountiny
Copy link
Contributor

@kidroca Thank you very much for looking into this. We should indeed be careful with migrations like this. It might not be very common to run a migration, but maybe it might be worth making PRs like this clearly state it.

For example, the PR could have a [Migration] prefix so then every engineer will immediately know it might not be easy to revert the PR. What do you think, @tgolen and @kidroca?

@tgolen
Copy link
Contributor

tgolen commented Jan 18, 2022 via email

@OSBotify
Copy link
Contributor

🚀 Deployed to production by @roryabraham in version: 1.1.30-3 🚀

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.

6 participants