oddsdk / ts-odd

An SDK for building apps with decentralized identity and storage.
https://odd.dev/
Apache License 2.0
179 stars 24 forks source link

Add event emitter interface to recoverFileSystem #474

Open avivash opened 1 year ago

avivash commented 1 year ago

Summary

Problem

Users often don't know what is happening behind the scenes in webnative when they are recovering their file systems. Emitting events during this flow will give app developers more options to display feedback to users.

Impact

Solution

Apply Steven's newly added event emitter functionality to the recoverFileSystem function

Detail

Is your feature request related to a problem? Please describe. App users often don't know what's happening behind the scenes in webnative when they request to have their file system recovered. This will give app devs the option to display feedback to them, which is particularly useful if the process takes longer than expected

Describe the solution you'd like Add an event map to the recoverFileSystem method output the currentStep and totalSteps, along with a one-liner to describe what is happening in the currentStep

Let's discuss implementation details below!

avivash commented 1 year ago

One potential implementation approach could be something like this 👇🏼 . I didn't include the actual eventEmitter.emit() calls in here, but we can add those to the recoverFileSystem method as needed. I'm thinking webnative can define and export the RECOVERY_STEPS(and maybe even a default eventMap), but maybe we also give users the option to create their own eventMaps so they can add whichever properties they want to them. Also, the RECOVERY_STEPS I've defined here are just some rough ideas, but I imagine we'll tweak them:

export enum RECOVERY_STEPS {
  RegisteringNewUser,
  ProvisioningUcan,
  LookingUpOldRootCid,
  UpdatingDataRoot,
  StoringReadKey,
}
import { RECOVERY_STEPS } from 'webnative/fs'

export const eventMap = {
  [RECOVERY_STEPS.RegisteringNewUser]: {
    msg: 'Registering new user',
    stepNumber: 1,
    callback: () => addNotification(eventMap[RECOVERY_STEPS.RegisteringNewUser].msg) // Optional callback function
  },
  [RECOVERY_STEPS.ProvisioningUcan]: {
    msg: 'Provisioning UCAN with file system access permissions',
    stepNumber: 2,
  },
  [RECOVERY_STEPS.LookingUpOldRootCid]: {
    msg: 'Looking up old root CID',
    stepNumber: 3,
  },
  [RECOVERY_STEPS.UpdatingDataRoot]: {
    msg: 'Tying data root to newly registered user',
    stepNumber: 4,
  },
  [RECOVERY_STEPS.StoringReadKey]: {
    msg: 'Storing read key',
    stepNumber: 5,
  },
}

session.fs.on('recovery:progress', progress => {
  const { steps: { stepId }, totalSteps } = progress
  const { callback, msg, stepNumber }  = eventMap[stepId] // Where stepId is one of the `RECOVERY_STEPS`

  // Expose the `msg`, `stepNumber` and `totalSteps` so the app dev can surface them in the UI
  renderMessage(msg, stepNumber, totalSteps)

  // If the app dev has added a callbackFunction to their eventMap, they can call it in here too
  if (callback) { // I know we won't be able to destructure `callback` if it's not defined, but i just left it in here for the example
    callback()
  }
})
bgins commented 1 year ago

This is looking great! 💯

Bringing an idea that it still under discussion. We could return the event emitter from program.filesystem.recover instead of returning a boolean from that function. The idea is it would strongly tie the event emitter to recovery when it happens.