react-native-ios-context-menu/docs/TODO.md
2022-06-13 10:57:49 +08:00

22 KiB
Raw Blame History

TODO

  • Implement: ContextMenu — Add support for UIDefferedElement.

  • Refactor: Use structs instead of classes for holding configuration for making the menu items.`

  • Cleanup: Remove print logs.


  • Docs: Update documentation sections

    • Remove numbered subsections.

    • Move links to files out of the section title.

    • Temporarily strip out links to section (i.e. replace with PLACEHOLDER_LINK).

    • Add versions table.

    • Remove collapsable sections.


  • Implement: Add support for targeted previews on text (i.e. similar to safari).
  • Implement: Subscribe to ContextMenuView events via event emitter from context.

  • Read apple documentation to find any new changes added.

  • Refactor: Make classes public and accessible outside the library.


  • Refactor: Extract types/components from RNIWrapperView to separate files.

  • Docs: Add documentation for "Context Menu Preview Auxiliary View".

  • Refactor: Move event-related types to their respective files where they're first used.

  • Refactor: Update Access Modifiers for Classes/Structs — Make classes/structs public so they can be imported by other code.

  • Docs: Update version history.

  • Refactor: Use react-native-ios-utilities.


  • Test: Try to re-produce the bug where the context menu no longer works after a certain period of time

    • React Native Version: 0.63.4

    • Hide app, wait 1 minute, reopen app, then test context menu

      • Test on production mode + simulator: OK
      • Test on production mode + Debug Off + simulator: OK
      • Test on Production + No Xcode + Simulator: OK
    • Hide app, open contacts, wait 1 minute, reopen app, then test context menu

      • Test on production mode + simulator: OK
        • Test on production mode + Debug Off + simulator: OK
        • Test on Production + No Xcode + Simulator: OK

  • Bugfix: Running on device + production crashes immediately when context menu is invoked.
    • Might be a problem with Xcode beta — Running on iOS 16 simulator works fine on both production mode and debug mode.
    • Xcode beta + running on device (iPhone XR + iOS 15.1) causes crashes when the context menu is being created (i.e. UIContextMenuConfiguration).
    • Xcode 13 + running on device (iPhone XR + iOS 15.1) works fine.
    • Maybe the constructor for UIContextMenuConfiguration was changed?
      • Still crashes when nil is provided as an argument to all the parameters in the constructor.
      • Using the constructor that takes no arguments doesn't trigger a crash.



For Next Major Version

  • Cleanup: Breaking Change — Remove legacy support for icon config shorthand/shortcut that was added temporarily when migrating between an older version of this library.


Completed

Version: next


Version: 1.7.6

  • (Commit: 0c7a91d) Test: Example — Add test for react navigation tabs
  • (Commit: 5092dab) Bugfix: Fix + re-enable cleanup logic
  • (Commit: 110dfe4) Refactor: Fix iOS 16 deprecations

Version: 1.7.5

  • (Commit: cde5061) Bugfix: Context menu auxiliary preview not sizing properly in yoga layout
    • Layout-Related Bug: The auxiliary preview is sized properly via autolayout (confirmed via setting the background color of the view), but react-native uses the "old size" of the view, i.e. before it was resized via autolayout (e.g. the children of the view will act as if the view's size hasn't changed yet) — In other words, react-native is not aware of the new size of the view.

    • Attempts to fix:

      • A. Updating the size via uiManager.setSize works, but causes a temporary layout bug where the aux. preview gets pinned towards the top left part of the screen.
        • Likely due to the aux. view using it's parent view as the basis for it's layout — i.e. the parent view (RNIWrapperView) has a style of absolute positioning so it doesn't interfere with layout.
        • The layout position bug disappears when the context menu preview's position changes (e.g. via dragging the preview) — this likely due to autolayout triggering a layout update to its subviews when you start moving the preview around.
        • Unfortunately, manually triggering layoutSubviews method on the context menu preview (i.e. morphingPlatterView) does not fix the layout position bug.
        • Triggering layoutSubviews on the aux. preview also does not fix the layout position bug.
        • Toggling RNIWrapperView.autoSetSizeOnLayout does nothing.
        • Triggering UIManger.setNeedsLayout does nothing.
        • Triggering uiManager.setSize   at a later time (e.g. after the fade in transition) does nothing.
      • B. Updating the aux. view's size via it's shadow view's width and height does nothing (i.e. changing the yoga value for the its width and height does nothing, even after calling UIManger.setNeedsLayout).
        • Removing the shadow view for both the aux. view and it's wrapper does nothing and causes layout problems.
      • C. As a last resort, a possible temp. solution is to just manually change the size of the aux. view via the style prop in the JS side. This can be done via an event that gets triggered from the native side, whenever we want to change the size of the view.
      • D. It turns out, the reason for the aux. preview layout bug is due to the new size being too big — i.e. the new size for the aux. preview is bigger than it's current size, causing it to "overflow" and glitch.

Version: 1.7.2

  • Bugfix: Android error (importing/use of iOS-related native components on non-iOS platforms).
    • (Commit: ba00412) Revert platform-specific extensions for ContextMenuView, and ContextMenuButton.
    • (Commit: 5fe92e8) Use platform specific exports for native components (i.e. RNIContextMenuView, RNIContextMenuButton).

  • (Commit: 756514b) Implement: Impl. ContextMenuButton.dismissMenu.

Version: 1.7.1

  • Bugfix: Android error (importing/use of iOS-related native components on non-iOS platforms).
    • (Commit: e57aabe) Refactor ContextMenuView to use platform-specific extensions.
    • (Commit: 0acea05) Refactor ContextMenuButton to use platform-specific extensions.

Version: 1.7.0

  • (Commit: 6b606da) Implement: Impl. ContextMenuView.isContextMenuEnabled prop.

Version: 1.6.2

  • (Commit: ce8dbac) Refactor: Add compiler directives to support building using Xcode 12.

Version: 1.6.1

  • (Commit: ca30678) Clenaup: Remove RNIMenuIcon.ImageLoader
    • Fix build error due to RCTImageCache.

  • Fix example not building when using "Release" configuration.
    • (Commit: ca30678) Cleanup: Remove RNIMenuIcon.ImageLoader.
    • (Commit: 78a7e51) Refactor: Example - Rename index.js to index.ts
    • (Commit: 8258328) Implement: Create .nvmrc — Use specific node version.
    • (Commit: 9f6f895) Implement: Update build-ios.yml to use .nvmrc for node version.

Version: 1.6.0

  • (Commit: 2c55fdb) Implement: Implement ContextMenuViewContext
  • (Commit: 05f6c73) Implement: Implement useMenuContext hook.
  • Refactor: Update example to use typescript.
    • Commits: 7ec95a5, 51a50f6, 2e3c05a, 104d36d, b84a0db, 73ff6f1, be6d40e, 3bc8e2a, 491874d, 9596954, 080d44f, 497f032, de1f93c, e745dda, 7b0c4f1, e714a1f, 6483c79, 447dd2b, ecd96fc, 78a9c10, 96877c2, bb3fff9, aea43db, 0c5436a, ee446c3, bdee609, e3846d7, 827f0bb.

  • (Commit: 7045e61) Bugfix: Fix types — Make menuConfig prop optional.
  • (Commit: 2310b7e) Bugfix: Fix types — Fix wrong type for MenuConfig.menuAttributes.
  • (Commit: 52c0459) Bugfix: Fix library exports — Export types from MenuEvents.
  • (Commit: 9f4e332) Refactor: Remove ContextMenuButton.wrapNativeComponent Prop.
  • (Commit: 9caf7d7) Implement: Implement ContextMenuButtonContext.
  • (Commit: 4d063f9) Implement: Implement useMenuButtonContext hook.

Version: 1.5.0

  • Bugfix: Fix memory leak
    • (Commit: 6ddabae) Partially fix memory leak by performing cleanup during reload + when the view is unmounted.
    • (Commit: 19533b2) Use RNIWrapperView for the menu preview.
    • (Commit: c45c576) Fix menu preview memory leak,

  • (Commit: 4c75563) Bugfix: Fix menu action subtitles no longer working on iOS 15.

    • Example #13 — Setting discoverabilityTitle no longer does anything.
    • In iOS 13, this used to show a subtitle blurb below the menu item title. In iOS 15, it no longer displays the subtitle.
    • In iOS 15, there's a new property added called UIMenuElement.subtitle.

  • Refactor: Update to use RNIImageItem for the menu icons.
    • Update logic for handling images.
      • Copy over RNIImageItem impl. from react-native-ios-navigator.
      • Rename IconConfig type to IconConfigDeprecated.
      • Make the icon property accept both IconConfigDeprecated and ImageItemConfig.
      • Then in native, map IconConfigDeprecated to ImageItemConfig.
      • Then use RNIImageItem to create the icon images for the context menu.
      • Import RNIImageItem and update RCTMenuIcon to use it.
    • (Commit: 836f0a3) Copy over RNIImageItem impl. from react-native-ios-navigator.
    • (Commit: 97fa40c) Refactor to use RNIImageItem for menu item icon.
    • (Commit: e02d96e) Copy over ImageItemConfig types from react-native-ios-navigator.
    • (Commit: e176438) Update types for menu config to accept ImageItemConfig.

Version: 1.4.0

  • (Commit: a0b008c) Migrate project to use the new template generated by create-react-native-library and react-native-builder-bob.
    • Example app no longer builds, but the library still works when installed on a newly created react-native app. The example project may be incompatible with Xcode 13.1.
    • After migrating the project to the new template, the example app now builds + run on iOS 15.

  • (Commit: d1c8277) Sync: Update UIColor+Helpers.swift to use the newer code in react-native-ios-context-menu.
  • (Commit: 59d4faf) Refactor: Migrate Extension+Init-related types to use failable initializers instead of static functions.
  • (Commit: 7bb8148) Cleanup: Update MARK comments in native code.
  • (Commit: 873b61a) Cleanup: Cleanup swift types (e.g. NSString -> String).
  • (Commit: ebfa1cc) Cleanup: Remove RCTSwiftLog + usage.
  • (Commit: 3702dfc) Refactor: Replace RCT prefix with RNI.
  • (Commit: 2102840) Refactor: Extract RNIContextMenuView native component to its own separate file.
  • (Commit: 3fb4faa) Refactor: Extract RNIContextMenuButton native component to its own separate file.
  • (Commit: 023f8e7) Implement: Types — Add type declaration for MenuConfig and related types.
  • (Commit: 6768b32) Implement: Types — Add type declaration for MenuPreviewConfig and related types.
  • (Commit: 01089f0) Implement: Types — Add type declaration for IconConfig and related types.
  • (Commit: 0d71080) Refactor: Extract constants (e.g. isContextMenuButtonSupported, isContextMenuViewSupported) to their own separate file.

  • Implement: Types — Add type declaration for ContextMenuView
    • (Commit: 8c72054) Implement: Types — Migrate ContextMenuView component to use typescript and partially added type declarations.
    • (Commit: 348d2f9) Implement: Types — Add type declaration for ContextMenuView events.

  • (Commit: e0bc64f) Implement: Types — Add type declaration for ContextMenuButton
  • (Commit: 25bf0b2) Implement: Types — Partially add type declaration for ActionSheetFallback
  • (Commit: 47a97bc) Implement: Types — Add type declaration for Helpers


Archived/Abandoned

  • Docs: In the MenuAction Object section, add example object with comments.
  • Docs: In the MenuConfig Object section, add example object with comments.
  • Docs: Create collapsable "Table of Contents"
  • Docs: Add README.md in example directory

  • ContextMenuButton: Add SystemImage component for creating a UIImage that uses SF Icons (Research first if the built-in image component already supports this).
  • ContextMenuButton: Add example for wrapNativeComponent prop, i.e. example for using a different "button" component.

  • ContextMenuView: Custom Preview - Add support for setting an image as the custom preview. Use the built-in Image react native component to handle setting the image source + sizing. Receive the image as a child from RCTContextMenuView and cast it to RCTImage if necessary. The image will then be wrapped inside a view controller and is set as the UIMenu's preview target. The view should be resized to fit the screen.

  • Test: ContextMenuView and ContextMenuButton on different react native versions
    • Test on 0.60
    • Test on 0.61
    • Test on 0.62
    • Test on 0.63.3
    • Test on 0.63.4
  • Test: react-native-context-menu uses autolinking for installation. Check if this library will work on older react-native versions prior to 0.60 i.e test ContextMenuView and ContextMenuButton on react native versions older than 0.60
    • Test on 0.59
    • Test on 0.58

  • Submit a PR to the RN repo — Update RN template to fix Undefined Symbol
  • Update PreviewConfig.previewSize to support passing in a size object, e.g. {width: 100, height: 100}
  • Docs: Fix grammar/spelling errors
  • Docs: Test/Fix jump links
  • Attach RN touch handler to context menu
  • Impl. support for icon weight

  • Implement: ActionSheetModule to display an "Action Sheet" menu via UIAlertController.

    • Reference: Article in the apple developer about "Alerts and Action Sheets"

    • Reference: ActionSheetIOS JS code. The native module is called RCTActionSheetManager (link to JS native module, and link to native code)

    • Reference: @react-native-menu/menu library has a very good looking ActionSheet fallback with icons and disabled menu actions.


  • ContextMenu : Add support for UIDefferedElement

    • In MenuConfig.menuItems property or in the menuConfig prop, if an object has a property called defferedKey, then it means we want to create a UIDefferedElement element.

    • Impl. onRequestDefferedElement function. This function is called whenever a UIDefferedElement item needs to be loaded.

      • This function will receive a defferedKey. This function must return a promise, i.e. either a MenuConfig or MenuAction object.
      • If the returned promise is a MenuAction object, it will use defferedKey for the actionKey property.
      • In this function, based on the defferedKey it must return a corresponding MenuConfig/MenuAction object. If null is returned, then it means it failed.
      • This function is invoked from the native side. Native UI component NativeCommands don't natively support promises, so a workaround must be used based on request callbacks (like the one i used on react-native-ios-modal). But NativeModule functions has support for proimises built in.
        • We can use findNodeHandle(this.nativeCompRef) to get a node handle. Then we can use self.bridge.uiManager.view(forReactTag: node) to get a ref to the component. Then we cast it to the correct type: component as? RCTContextMenuView and then call the completion function for the corresponding UIDefferedElement, something like: contextMenuView.resolveDefferedMenuElement(for: defferedKey, item: menuElementDict)
      • We need to create a class to create a UIDeferredMenuElement. It will extend RNIMenuElement and can be init from a dictionary. Probably name it something like: RCTMenuDefferedItem. It will have one property: defferedKey
        • RNIMenuItem.createMenu function must be updated to also handle creating a RCTMenuDefferedItem item.
      • On the native side when we create a UIDeferredMenuElement we do this: UIDeferredMenuElement { completion in self.completionDict[defferedKey] = completion }, and then invoke a RN event: self.onRequestDefferedElement([defferedKey: defferedKey]).
        • onRequestDefferedElement event prop will be invoked. We wait for the promise to return some value and then call a NativeModule function.
        • The NativeModule function will probably look like this: ContextMenuViewModule.resolveDefferedMenuElement({nodeHandle, defferedKey, menuItem});
        • Completion handlers will be stored in a dictionary. I'm not sure if I can use NSMapTable. I can use a plain NSDictionary but if I accidentally forget to cleanup (i.e. remove the completion handler from the dict) then that completion handler will be retained, causing a memory leak.
          • Completion handlers, i.e. closures, are reference types. If I assign it to NSMapTable with valueOptions: .weakMemory, will it be automatically be released when it's no longer used? Will it be retained while it's in use or will it be released the moment i add it to NSMapTable because nothing is using it? Technically, it is in use because it's in UIDeferredMenuElement argument (so the ref count should increase?)


Completed Archive

  • Docs: First remove all the links that point to the examples directory or links to different section. Highlight them in yellow then replace the highlighted text in the documentation with the new/updated section/examples links.
    • Move ContextMenuView examples + tests in examples/src to examples/src/ContextMenuView then update documentation links
    • In the "Examples" section add section for ContextMenuView and ContextMenuButton, then update the documentation "jump to" heading links
    • Update and rename Images/Gifs
      • Move gifs for ContextMenuView in /assets to assets/ContextMenuView/
      • Rename ContextMenuView gifs i.e. prefix them with "ContextMenuView" e.g. SimpleExample-1-2-3-4.gif becomes ContextMenuView-SimpleExample-1-2-3-4.gif, etc.
      • In the /assets/example-screenshots folder, prefix images with "ContextMenuView", e.g. SimpleExample01.png becomes ContextMenuView-SimpleExample01.png, etc.
  • Docs: Add images to steps: Undefined Symbol
  • Docs: Make sections collapsabe
  • Docs: Fix table layout
  • In the "Documentation" section, add ContextMenuButton props.
  • Finish onPressMenuItem nativeEvent Object section.
  • Add section for useActionSheetFallback prop.

  • ContextMenuView: Export ActionSheetFallback function and add it to the docs.

  • ContextMenuView: Rename RCTContextMenuManager to RCTContextMenuViewManager and update corresponding js native component

  • ContextMenuView: Impl. iOS 14 specific feature: UpdateVisibleMenu

  • ContextMenuView: Impl. iOS 14 specific feature: dismissMenu

    • Try implementing this via NativeModule
  • ContextMenuView: Custom Preview - Add support for custom previews, i.e by passing a child component to RCTContextMenuView, and wrapping that child inside a view controller and passing it as the preview target in UIMenu config. The first child of the RCTContextMenuView will be reserved for the custom menu preview. If no child is passed, i.e no custom preview is configured, then the preview target is not set for the UIMenu. The preview view should only be mounted when the menu is visible, and thus, it should support setting the preferred size of the preview target. Test if the preview target can be changed when it's already visible.


  • ContextMenuButton: Finish initial impl. with 1 working simple example
  • ContextMenuButton: Add documentation for ContextMenuButton

  • General: Implement targeted previews
  • General: Implement tinted/colored menu icons + config for line weight etc.
  • Refactor: Change "ImageType" to "IconType", and "imageValue" to "imageType"
  • General: Move menu icon related properties to "icon": { icon: { iconType: '', iconValue: '', tint: ''} }
  • ContextMenu — Add discoverabilityTitle to UIAction

  • Implement ImageType.ASSET to support: "create an image from an image asset or image file located in your apps main bundle"
    • The imageValue string from MenuAction/MenuConfig will be used to init a UIImage, like: UIImage(named: imageValue)

  • Implement ImageType.REQUIRE to support using images via require(path/to/image)

    • One way to implement is to use Image.resolveAssetSource(source); from the RN docs. So we have something like: { imageType: 'REQUIRE', imageValue: require('path/to/image.png') }.

      • Reference: Medium Article. Explains how Image.resolveAssetSource works.
    • Attempted to impl. this but ran into problems: when in debug mode, assets are provided via a local URL via the metro bundler.