-
Notifications
You must be signed in to change notification settings - Fork 7
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
Backup Optic Tokens to a file to allow importing from another device #590
Conversation
dbced36
to
1fe478f
Compare
1fe478f
to
26349af
Compare
Added working import export feature for both Android and iOS devices
Updated tests snapshots because of the UI changes in the SettingsScreen and added the reset function in the TokenScreen test
Added missing reset function in HomeScreen test
This pull request was automatically deployed using Expo GitHub Actions!
|
@davideroffo on the outstanding design question. If there are secrets when trying to import, we should warn the user that they will be wiped away and replaced. An alert would do. |
@simoneb I already added that alert, you can see it described in one of the bullet points in the PR description:
|
Then we're good 🆗 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM, please see inline comments
Changes due to the PR comments
Added .txt file extension to optic-backup
src/lib/settings.ts
Outdated
const parsedSecrets = JSON.parse(result) as Secret[] | ||
return parsedSecrets | ||
} catch (err) { | ||
console.log(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're not handling the error. if there is an error, the user won't know
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/screens/SettingsScreen.tsx
Outdated
if (Platform.OS === 'android') { | ||
androidExport(fileName, fileContent) | ||
} else { | ||
iosExport(fileName, fileContent) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why don't we move this logic inside the export utils?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/screens/SettingsScreen.tsx
Outdated
try { | ||
const documentMeta = await DocumentPicker.getDocumentAsync() | ||
|
||
if (documentMeta.type === 'success') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why don't we invert this logic so we reduce the nesting and early return in case un error/cancel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/screens/SettingsScreen.tsx
Outdated
} | ||
} | ||
|
||
const showImportConfirmAlert = (onConfirm: () => void) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function doesn't need to live inside the component body
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved in the settings.ts file
src/screens/SettingsScreen.tsx
Outdated
|
||
await reset() | ||
for (const secret of parsedSecrets) { | ||
await add(secret) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't there a quicker way to bulk insert secrets?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a new addAll() method in the Secrets Context for adding all the secrets in one shot
Improving the pull request addressing some of the PR comments
Removed commented code and unuseful check on the document type different from success. Document type can be only success or cancel.
src/screens/SettingsScreen.tsx
Outdated
await reset() | ||
await addAll(parsedSecrets) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to call these two functions? isn't addAll actually replacing the secrets? in which case, maybe a better name is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed reset() and I renamed addAll() to replace()
src/screens/SettingsScreen.tsx
Outdated
const { secrets, reset, addAll } = useSecrets() | ||
|
||
const handleExport = async () => { | ||
if (secrets.length === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's disable the export button if there are no secrets to export
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/lib/settings.ts
Outdated
if (Platform.OS === 'android') { | ||
androidExport(fileName, fileContent) | ||
} else { | ||
iosExport(fileName, fileContent) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these functions return promises, we should return the resulting promise back to the caller
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/lib/settings.ts
Outdated
|
||
const mimeType = 'application/octet-stream' | ||
|
||
const androidExport = async (fileName, fileContent) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function and the one for ios have duplicated error handling. plus, this is somewhat inconsistent with the way we handle errors in the import function. we should identify a single error handling approach and apply it throughout. I would leave the error handling (and showing error messages to the user) to the caller code, meaning the React component.
if you look at the import function, you will also realize there is redundancy because error handling is done both in the function itself AND in the component which calls the function.
I do realize that there are some edge cases (things which are simpler to handle within the function and show a toast when they happen). But apart from those edge cases, let's make sure that exceptions are raised back to the caller and handle them only there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I simplified it a bit by throwing errors with custom messages in the functions. In this way, we are showing the toasts just in the component as you suggested.
I did the same with the edge case in the import function (getSecretsFromFile())
Let me know if now looks good.
Fixed PR comments: error handling only in the components, removed reset and addAll used replace instead, minor other changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure the deploy preview is tested thoroughly before merging. Test especially:
- both ios and android
- import and export work fine
Closes #537
Outstanding Design Questions:
PR update 2022-07-12