Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
2.99k stars 2.5k forks source link

[$8000] Feature Request - Profile / Workspace - Allow avatar editing via cropping, rotation and zooming - Reported by: @parasharrajat #6301

Closed isagoico closed 1 year ago

isagoico commented 2 years ago

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


Action Performed:

  1. Navigate to profile settings
  2. Upload a new profile picture

Expected Result:

User should be able to edit the picture before setting the new avatar (Like zooming and cropping)

Actual Result:

User is not given the option to edit the profile picture when uploading a new avatar.

Workaround:

User has to edit the picture before uplaoding.

Platform:

Where is this issue occurring?

Version Number: 1.1.14-0

Reproducible in staging?: Yes Reproducible in production?: Yes

Logs: https://stackoverflow.com/c/expensify/questions/4856

Notes/Photos/Videos: Any additional supporting documentation

Expensify/Expensify Issue URL:

Issue reported by: @parasharrajat Slack conversation: https://expensify.slack.com/archives/C01GTK53T8Q/p1636994572206400

View all open jobs on GitHub

Solution

This is the final UI agreed upon: image

The two new icons you will need (zoom, rotate) are here: Icons.zip

MelvinBot commented 2 years ago

Triggered auto assignment to @mallenexpensify (AutoAssignerTriage), see https://stackoverflow.com/c/expensify/questions/4749 for more details.

MelvinBot commented 2 years ago

Triggered auto assignment to @deetergp (Engineering), see https://stackoverflow.com/c/expensify/questions/4319 for more details.

mallenexpensify commented 2 years ago

Added Engineering label , assigned Deeter, to check to ensure this can be worked on by a contributor

deetergp commented 2 years ago

I can't think of any reason this couldn't be done by a contributor.

MelvinBot commented 2 years ago

Triggered auto assignment to @tgolen (Exported), see https://stackoverflow.com/c/expensify/questions/7972 for more details.

mallenexpensify commented 2 years ago

https://www.upwork.com/jobs/~01c68ed933432e239b Job posted 😎

parasharrajat commented 2 years ago

Looks like this needs Design @Expensify/design

mallenexpensify commented 2 years ago

I think you're right @parasharrajat. Let me assign someone for 👀 and review to see what their initial thoughts, pointers, feedback are. @shawnborton (who was auto-assigned) can you take a look?

MelvinBot commented 2 years ago

Triggered auto assignment to @shawnborton (Design), see these Stack Overflow questions for more details.

tgolen commented 2 years ago

I would like to push the pause button on this for a bit. I think it's an interesting feature request, but I think we should spend a little more time determining if it's a feature that we WANT right now or not. I would like to see whoever proposed it (I think @parasharrajat) craft a problem solution statement for this. I am not sure what problem it solves, so therefore, I am not yet on board with this "solution".

tgolen commented 2 years ago

(let me know if you're familiar with how we do problem/solution statements or not)

parasharrajat commented 2 years ago

I definitely don't know your problem solution technique 😀 but I can try to create a problem statement.

tgolen commented 2 years ago

Haha, sure! So this is the template that we use for our internal issue repo:

# Problem

# Why is this important?

# Solution

Some suggestions to help you out:

anthony-hull commented 2 years ago

Problem:

When a user selects a photo for their profile, it might not be optimal. Some processing happens by us after upload which can be hard to predict by the user, such as masking to a circle. The user might not even have image editing programs to prepare their image to look good after uploading.

A couple of ways the image might not be optimal: framing of the face once masked to a circle might be off so to skew, scale or the face isn't exactly centred image size could be too large

What is this important:

It can be quite frustrating uploading an image over and over after editing and seeing the result in the application. This feedback loop is a bad UX. Even more frustrating when you don't know how to use image editors or have one installed or know you have one installed.

Solution:

Image editor built into the UX, where the mask is overlaid on the image with tools to adjust the underlying image to frame. Image would also be compressed, converted and resized to meet API requirements.

parasharrajat commented 2 years ago

Looks like it slipped off my mind. Thanks @anthony-hull appreciate the help. @tgolen I think the above-posted details are enough to make it a genuine issue. I had the same kind of thoughts. But I can think of one more point.

Problem

Being a chat(social) application, it's very important for two persons to get a connected feeling. Which makes it important to have an avatar. But these days, cellphone cameras capture High-resolution images. An image could contain a lot of objects, e.g. a dog and the person and a nice house behind. We(users) often change our avatars, but we do not edit the images manually while doing so. it could be hectic too (https://github.com/Expensify/App/issues/6301#issuecomment-979084697). Due to the high resolution, the picture could be blurred after upload, the Face of the person may not be clearly visible, Dog's face could cover 60% of the avatar (making it the primary object) which was not the user's intention.

What is this important?

Due to the above-mentioned issue, the app could be rejected by the user.

Solution

Built-in image editor, allowing the user to transform the image via zoom, rotation, simple translation.

This is how I imagine it to be

When the user clicks upload image from the Avatar menu, It first opens the file picker as it does currently. Then a modal is shown to the user where the image is laid out on a canvas and a selection box is covering the canvas. Here User can use a) Zoom slider to resize the image. b) Drag the image around to adjust in the selection box. c) Use rotation control to rotate the image.

tgolen commented 2 years ago

OK, those are great! I would like to take these to our internal channel to see if this is something we would like to pursue now or if it's something we want to hold off on.

tgolen commented 2 years ago

All right, let's move forward and do it! Sounds like the next step would be proposal and some design work? Could you maybe start with a wireframe to get the design process started?

mallenexpensify commented 2 years ago

@parasharrajat @anthony-hull would either of you like to take the lead on this and submit a proposal with some design work? I doubled the job to $500 https://www.upwork.com/jobs/~01c68ed933432e239b. Gonna post in #expensify-open-source now too

parasharrajat commented 2 years ago

@mallenexpensify This needs to be designed internally. This is a big feature and thus it makes it important to feel and look like the rest of the app.

mallenexpensify commented 2 years ago

@Expensify/design Can you review the above and provide feedback on what parts need to be done internally vs what can be worked on by a contributor? If relevant, we could also create separate issues for internal/external work

shawnborton commented 2 years ago

I think the design team needs to create some mocks for the ideal flow and then we can perhaps post internally for alignment, and then get this assigned to a contributor. Looks like I am assigned to this already, so I can work on some mocks and share internally first.

Some inspiration from other products:

image

image

image

parasharrajat commented 2 years ago

So, I think all three controls should be on one screen.

  1. canvas from 3
  2. zoom from 2. looks good.
shawnborton commented 2 years ago

Do you think we should allow the user to crop any area of the image like 1 (Slack) has, or just a simple zoom in/zoom out like the others? I think what we currently have on Expensify is a simple zoom in/out, so I think that would suffice:

image

parasharrajat commented 2 years ago

Yup zoom in/out is fine. So a while circle over the image would indicate thr part that would be set on the profile.

shawnborton commented 2 years ago

Posted to Slack for feedback.

shawnborton commented 2 years ago

Looks like we landed here for the UI: image

Let me know if you need anything else. The two new icons you will need (zoom, rotate) are here: Icons.zip

parasharrajat commented 2 years ago

Looks good @shawnborton . Can someone update the issue description with these images and Assets?

anthony-hull commented 2 years ago

https://expensify.slack.com/archives/C01GTK53T8Q/p1640049268437600 In this discussion the topic of images up to 6MB being created by iOS cameras when taking a photo from the upload photo prompt while updating the profile image. I think this is another good justification of doing image processing client side.

What would be a sensible file size and dimensions to send?

I looked at the image of my profile served up in the app on production and it's 96x128px. Should we send the image to the back end at this size? or is there a place a larger version is used?

tgolen commented 2 years ago

OK, I've updated the issue description with the new UI and the link to the new icons. This is ready for a proposal.

MelvinBot commented 2 years ago

Triggered auto assignment to Contributor-plus team member for initial proposal review - @parasharrajat (Exported)

MelvinBot commented 2 years ago

Triggered auto assignment to @chiragsalian (Exported), see https://stackoverflow.com/c/expensify/questions/7972 for more details.

mallenexpensify commented 2 years ago

Doubled price to $1000 (apologies for the lable/assignee blast, was testing something...)

mallenexpensify commented 2 years ago

Doubled price to $2000 https://www.upwork.com/jobs/~01c68ed933432e239b

mananjadhav commented 2 years ago

@mallenexpensify Ive been thinking of posting a proposal, but I feel the work is worth 3000$.

It might sound higher, but I feel it’ll go through a few iterations and would require effort in building up the screen with all the features.

If the budget happens to increase and nobody sends proposals with the current budget, I’ll send in the proposal.

mallenexpensify commented 2 years ago

@mananjadhav I agree this is a larger job and warrants more pay. Since it's not time-sensitive and it was $1000 yesterday, I think it's best (per our process) to give it another week to see if anyone's interested in fixing for $2k. If not... .you'd be able to submit a proposal then make $4k.

kakajann commented 2 years ago

Can we use external packages like https://github.com/ivpusic/react-native-image-crop-picker ?

MelvinBot commented 2 years ago

Triggered auto assignment to Contributor-plus team member for initial proposal review - @parasharrajat (Exported)

MelvinBot commented 2 years ago

Current assignee @tgolen is eligible for the Exported assigner, not assigning anyone new.

mallenexpensify commented 2 years ago

Doubled price to $4k, removed/added the Exported label to auto-post in #expensify-open-source, post on ExpensifyOSS twitter and to assign a C+. @parasharrajat, can you reply to @kakajann 's comment above? https://github.com/Expensify/App/issues/6301#issuecomment-1014639018

@mananjadhav 👀 ?!? The moment you've been waiting for?

parasharrajat commented 2 years ago

Sure, @mallenexpensify.

Can we use external packages like ivpusic/react-native-image-crop-picker ?

@kakajann , as far as I can tell we are looking at a custom UI screen for the feature.


But to be more clear on this, I will like to clarify the task.

Glossary

Canvas - Image editing box shown in the attached screenshot.

Questions:
  1. Can we use a custom zoom/pinch-zoom lib or we should extend our image zoom solution from AttachmentModal?
  2. Should we have to compress/crop the image on the front end?
  3. What is going to be the default rendering mode(with zoom /first load on canvas) for the image? Should the image cover the whole canvas in the attached mockups? What if image dimensions are smaller than the canvas size?
  4. What is the zoom maximum zoom scale (i think 2)?
  5. What is the dimensions of canvas? AFAIK, we would require fixed values for the web. or max width and max height.

Not sure whom to tag but I will leave these questions here

tgolen commented 2 years ago

Can we use external packages like https://github.com/ivpusic/react-native-image-crop-picker ?

I think we should avoid this if we can. The reason is that many times these libs will come with a lot of features we will never use and they can also be difficult to integrate with all platforms (like web). If we build something ourselves, then we have absolute control over what gets built and how it works.

@parasharrajat I love all your questions, but also I don't know if anyone has specific answers to them. I think what works great in these cases is for the proposal to recommend how to do those things and if there are still unresolved items, a more detailed look at pros/cons of different solutions would help.

@mallenexpensify I'm a bit concerned about the size and scope of the proposals we are going to get for this. GH is fine for smaller proposals but this is going to be architecting an entirely new and large library with many details. I think we should consider using a modified design doc process and at least have the proposals done in a google doc where we can dig into the specifics in more fine-grained detail. What do you think?

anthony-hull commented 2 years ago

I agree from my perspective as a contributor this a feature this too big doesn't fit this process very well. I was put off proposing.

mananjadhav commented 2 years ago

@tgolen Is there some specific format you'd like to share? If you and @parasharrajat can share the level of detail that is expected here? I am in process of writing a proposal, will share as a google doc.

parasharrajat commented 2 years ago

Well. I will suggest documenting every behavior or interaction that is expected in the feature.

tgolen commented 2 years ago

This is the format that we use for our internal projects when we plan out the detailed portion. It might help give you a direction for the proposal that you write:

Offline support

Describe here what will be supported while offline and what would not. How things will look and behave if the user takes some of the actions while offline.

Detailed background

Detailed implementation of the solution

Manual tests

Automated tests

Alternate solutions (detailed)

System requirements

Plan of action / Rollout plan

mallenexpensify commented 2 years ago

Doubled job to $8000 - https://www.upwork.com/jobs/~01c68ed933432e239b We also have a new .md file for "Create a Plan" that would be helpful to review, in conjunction with the above, if you're interested in proposing a solution. https://github.com/Expensify/App/blob/main/HOW_TO_CREATE_A_PLAN.md

mdneyazahmad commented 2 years ago

Initial Proposal

I am proposing my initial approach to implement this feature. I need some more time to propose a detailed documentation. Here's the overview of what I will do.

Steps

  1. Create a separate page ProfileAvatarEdit and link it to react-navigation.
  2. When user selects an image will navigate to this page, user edits and save it.

The ProfileAvatarEdit page will contain InteractiveImageView, Slider and some buttons as per the ui.

InteractiveImageView will be interactive and the user can drag (pinch to scale and rotate on ios and android).

                    <InteractiveImageView
                        uri={this.state.imageSourceUri}
                        scale={this.state.scale}
                        resize={this.state.resize}
                        rotate={this.state.rotate}
                        onScale={this.onScale}
                        onResize={this.onResize}
                        onRotate={this.onRotate}
                    />
                            <Slider
                                minValue={1}
                                maxValue={2}
                                value={this.state.scale}
                                onValueChange={this.onScale}
                            />
diagram

InteractiveImageView will internally use css transform property translate, scale and rotate. When the user click save this property (translate, scale and rotate) values will be converted to imageCropData and will be passed to image-cropper-library. It will crop the image and then it will be saved.

Here, we have separated the ui interaction of image and the image cropping. Image cropping will be done by any library(I can not find any that fulfills our needs). This is related library https://github.com/callstack/react-native-image-editor but it does not have support rotating and also it is not supported in web.

I will propose to fork this library and implement the rotate feature and web support. Something like this.


  cropData = {
    offset: {x: number, y: number},
    size: {width: number, height: number},
    displaySize: {width: number, height: number},
    resizeMode: 'contain' | 'cover' | 'stretch',
    rotate: 's' | 'n' | 'e' | 'w',
  };

https://github.com/dgladkov/react-native-image-rotate is a library to rotate images again not supported in web. It also looks like this project is not maintained.

I am now implementing the crop library in web with the same api as https://github.com/callstack/react-native-image-editor with options to rotate.

Here is the progress so far, The final implementation will have animation for smooth transition.

https://user-images.githubusercontent.com/77761491/152741905-6b256046-aeae-48c7-99c0-920afa3b1745.mp4

parasharrajat commented 2 years ago

Thanks for the proposal @mdneyazahmad. As discussed above, we want to implement the zoom/transform/rotate behavior as a custom component but not based on any third party lib.

Anyways, good luck with the attempt. I am eager to hear the full proposal in the format.

vitalii-tb commented 2 years ago

https://user-images.githubusercontent.com/44551710/152904375-1a9a0da6-94e1-4f57-a165-e7bdc537990e.mp4

Full video: https://www.loom.com/share/98a0c44dad25484db5392207d31d308f

⚠️ After recording I've noticed that rotate button rotates image clockwise instead anti-clockwise. This problem will be fixed in the final version.

Offline support

All action related to Avatar edition (image pick, zoom, rotation, pan, etc) will be allowed, except uploading an image to the server.

Detailed background

At first, I've planned to use some cropping libraries for iOS/Android and implement web separately. But I wasn't satisfied with the quality and maintainability of available libs, so I decided to write everything from scratch.

Detailed implementation of the solution

To implement this feature I've used libs that this project already has: react-native-gesture-handler and react-native-reanimated. We may need to add only one library @react-native-community/image-editor. Unfortunately we have to use it because we can't crop image using only JS. Good news is that that it consists mostly from native code, so it won't have affect on bundle size. But if we can't use it - there is also option to crop image on backend.

The nitty gritty technical details of the solution

Alternate solutions (detailed)

System requirements

What do you need to make this happen?

Questions:

@parasharrajat please let me know if you need anything from my side.

parasharrajat commented 2 years ago

Thanks for the proposal @Tabakharniuk It looks very good. Let's get to the technicals now.

  1. How will implement this in our app? It is important that it works on all platforms that we support.
  2. What will be the flow for a feature?
  3. Where will you hook this in our app? I think there are two places mostly that require avatar uploading.
  4. What are the hidden challenges?
  5. Do you have questions for us?

The work is almost completed. If you are not tight on time - I need around 3-5 days to polish animations, styles etc. If you need this component faster - I could finish it in 2 days.

This can be done if you are hired for the job so hold it for now.

Could you please send me designs of this feature? (Figma, Sketch, Psd, etc)

@shawnborton Could you please help here?