npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-native-mo-fs

v0.1.38

Published

react native file system and image tools

Downloads

34

Readme

react-native-mo-fs

Provide file system access and integration

Installation

Install just like your ordinary react-native module.

Usage

Please check the example/ code.

import { Fs } from 'react-native-mo-fs';

// for debugging:
Fs.setVerbose(true);

Basic ideas

  • Fs.readFile / Fs.writeFile all work with react-native's Blobs. These store the data on the native side and only pass a handle to javascript to avoid transferring lots of data using base64 encoding. As long as react-native does not support UInt8Array to NSData*/byte[] bridging this is the fastest solution.

  • You can read out or create blobs using Fs.readBlob and Fs.createBlob using encodings like base64, utf8 or arraybuffers. If using arraybuffers the buffer has to be converted to base64 internally first.

  • Most of the time you do not need the data on the javascript side. You can load a file to a blob and use that blob as payload data for fetch() or the other way around.

  • There is some assorted stuff in the library for hashing, image manipulation and similar stuff. The base idea is to support only operations that do not require additional native libraries to not bloat this library.

System Paths

console.log(Fs.paths);
// cache: Path; // a cache folder
// docs: Path; // the document folder
// bundle?: Path; // ios bundle folder
// document?: Path;
// caches?: Path;
// externalCache?: Path;
// files?: Path;
// packageResource?: Path;
// data?: Path;

Working with files

Reading files

const myBlob = await Fs.readFile(Fs.paths.docs + '/hello.jpg');
const myText = await Fs.readTextFile(Fs.paths.docs + '/hello.txt');

Writing files

await Fs.writeFile(Fs.paths.docs + '/hello.jpg', myBlob);
await Fs.writeTextFile(Fs.paths.docs + '/dump.json', JSON.stringify(data));
await Fs.appendFile(Fs.paths.docs + '/hello.jpg', myBlob);
await Fs.appendTextFile(Fs.paths.docs + '/log.txt', 'my log line\n');

File handling

await Fs.deleteFile(someFilePath);
await Fs.deleteFile(someFolderPath, true); // delete recursive
await Fs.renameFile(oldPath, newPath);
await Fs.listDir(folderPath); // returns array of file names
await Fs.createDir(Fs.paths.docs + '/logs'); // does not create parents
const stat = await Fs.stat(Fs.path.docs + '/somefile.txt');
if (!stat.exists) {
  console.log('not found');
} else if (stat.dir) {
  console.log('is a dir');
} else {
  console.log('is a file with size', stat.size, 'modified', new Date(stat.modified));
}

Working with Blobs

Get URL for Blob

const url = Fs.getBlobURL(myBlob);
return (<Image source={{ uri: url }} />);

Get contents of Blob

const base64_data = await Fs.readBlob(myBlob, 'base64');
const string = await Fs.readBlob(myBlob, 'utf8');
const arrayBuffer = await Fs.readBlob(myBlob, 'arraybuffer');

Create Blob from data

const myBlob = await Fs.createBlob('aGVsbG8gd29ybGQ=', 'base64');
const myBlob = await Fs.createBlob('hello world', 'utf8');
const myBlob = await Fs.createBlob(new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]), 'arraybuffer');

Sharing / picking files

Share / View file

// Share a file (open-in in ios, share intent in android)
await Fs.shareFile(Fs.paths.docs + '/myimage.png');

// View a file (preview in ios, view intent in android)
await Fs.viewFile(Fs.paths.docs + '/myimage.png');

Pick file

// pick any single file
const urls = await Fs.pickFile({ multiple: false })

// pick one or more jpeg or png images
const urls = await Fs.pickFile({ multiple: true, types: ['image/jpeg', 'image/png'] })

// read the response
if (urls.length > 0) {
  const blob = await Fs.readURL(urls[0]);
  // do something
}

Pick/capture image/video

const res = await Fs.pickMedia({ });
const res = await Fs.captureMedia({ });
if (res) {
  const blob = await Fs.readURL(res.url);
  res.release();
}

iTunes file sharing

Add this to your Info.plist:

<key>UIFileSharingEnabled</key>
<true/>

And write stuff to Fs.paths.docs

Handling "Open In"

Add to android manifest:

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  UPDATE THIS
  <data android:scheme="file" />
  <data android:host="*" />
  <data android:pathPattern=".*\\.pdf" />
  <data android:mimeType="application/pdf" />
</intent-filter>

Add to ios Info.plist:

<key>CFBundleDocumentTypes</key>
<array>
  <dict>
    <key>CFBundleTypeName</key>
    <string>PDF</string>
    <key>LSHandlerRank</key>
    <string>Alternate</string>
    <key>LSItemContentTypes</key>
    <array>
        <string>com.adobe.pdf</string>
    </array>
  </dict>
</array>

Subscribe to the Event:

Fs.openFile.subscribe((event) => {
  console.log('requested to open url', event.url);
});

If the app was started initially due to an open event, the event handler is called as soon as the first subscriber is there.

Assorted stuff

Mime Types and EXIF

const mimeType = await Fs.getMimeType('png');
const mimeType = await Fs.getMimeType('blah.png');

// exif is not really done yet but might work for you ;)
const exif = await Fs.getExif(myBlob);

const extension = await Fs.getExtensionForMimeType('image/png'); // returns png

Blob hash

console.log('md5-hex', await Fs.getBlobHash(myBlob, 'md5'));
console.log('sha1-hex', await Fs.getBlobHash(myBlob, 'sha1'));
console.log('sha256-hex', await Fs.getBlobHash(myBlob, 'sha256'));

Images

const myImageBlob = await Fs.readFile(Fs.paths.docs + '/image.jpg');

const size = await Fs.getImageSize(myImageBlob);
console.log('the image size is', size.width, size.height);

const smallBlob = await Fs.resizeImage(myImageBlob, {
  maxWidth: 128,
  maxHeight: 128,
  fill: true, // make result 128x128 and keep aspect. otherwise result image is smaller
  encoding: 'jpeg', // or png, or webp
  quality: 0.3, // 0..1
});

const thumbnail = await Fs.createThumbnail(imageOrVideoBlob, {
  maxWidth: 128,
  maxHeight: 128,
  fill: true,
});

Backups

For android you need to specify the files to be backed up in your manifest:

<application
  android:fullBackupContent="@xml/backup_descriptor"
  android:restoreAnyVersion="true"
/>

Set restoreAnyVersion only if you are able to migrate from an older backup.

The contents of res/xml/backup_descriptor is something like:

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
  <!-- for asyncstorage -->
  <include domain="database" path="RKStorage" />
  <!-- some path relative to data dir -->
  <include domain="root" path="some/path" />
</full-backup-content>

You can test backups using: adb shell bmgr backupnow your.package

Dev builds should be restored after uninstalling and redeploying from android studio.

For iOS pretty much everything is backed up unless excluded.

You can use (experimental):

Fs.ios.Module.setResourceValues('file:///path/to/file', {
  'NSURLIsExcludedFromBackupKey': true,
});

You can use app offloading to test backup / restore in dev.

Notes

  • iOS application:openURL: is swizzled on startup.