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-ankidroid

v0.6.1

Published

A react native wrapper for the AnkiDroid API

Downloads

17

Readme

ko-fi

react-native-ankidroid

React Native wrapper for the AnkiDroid API

Getting started

npm install react-native-ankidroid --save

RN 0.60+

The library will be automatically linked BUT step 4 of the manual installation is still required.

RN < 0.60

Mostly automatic installation

react-native link react-native-ankidroid

  • Step 4 of the manual installation is still required.

Manual installation

Android

  1. Open up android/app/src/main/java/[...]/MainActivity.java
  • Add import com.is343.reactnativeankidroid.AnkiDroidPackage; to the imports at the top of the file
  • Add new AnkiDroidPackage() to the list returned by the getPackages() method
  1. Append the following lines to android/settings.gradle:

    include ':react-native-ankidroid'
    project(':react-native-ankidroid').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-ankidroid/android')
  2. Insert the following lines inside the dependencies block in android/app/build.gradle:

      implementation project(':react-native-ankidroid')
  3. Add the following lines to /android/app/src/main/res/AndroidManifest.xml:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools" // <---- ADD HERE
        package="com.yourpackage.name">
    
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    
        <application
          android:name="com.yourpackage.name.MainApplication"
          android:label="@string/app_name"
          android:icon="@mipmap/ic_launcher"
          android:allowBackup="true"
          android:theme="@style/AppTheme"
          tools:replace="android:allowBackup" // <---- ADD HERE
          >
  • This will prevent the following error by forcing the compiler to use your app's attribute:
    Execution failed for task ':app:processDebugManifest'.
    > Manifest merger failed : Attribute application@allowBackup value=(false) from AndroidManifest.xml:15:7-34 is also present at [com.github.ankidroid:Anki-Android:api-v1.1.0] AndroidManife
    st.xml:14:9-35 value=(true).
    Suggestion: add 'tools:replace="android:allowBackup"' to <application> element at AndroidManifest.xml:7:5-117 to override.

Usage

import AnkiDroid from 'react-native-ankidroid';

await AnkiDroid.isApiAvailable();

Static Methods

AnkiDroid.____________ *(returns a Promise)

  • isApiAvailable()* - checks if the AnkiDroid API is avaiable (AnkiDroid is installed on the device) in order to access the API, AnkiDroid may need to be installed before the react native app
  • checkPermission()*
  • requestPermission(rationale)* -- rationale (optional)
  • getSelectedDeckName()* -- gets the name of the currently selected deck -- returns a response tuple
  • getDeckList()* -- gets a list of the names and IDs of each deck -- returns a response tuple
  • getModelList()* -- gets a list of the names and IDs of each model -- returns a response tuple
  • getFieldList(modelName, modelId)* -- gets a list of all field names for a specific model -- only one of modelName or modelId is required -- returns a response tuple
  • uploadMediaFromUri(fileUri, preferredName, mimeType)* -- gets a list of all field names for a specific model -- fileUri: the location of the media to upload -- preferredName: the name that will be used to access the media in the card -- mimeType: can be either "audio" or "image" -- returns a response tuple -- import media into notes with <img src="myimage.jpg"> and [sound:myaudio.mp3] -- official anki docs can be found here -- Both AnkiDroid and your app require the android.permission.MANAGE_EXTERNAL_STORAGE permission granted if you intend to upload a file from external storage

Creating a class instance

  • new AnkiDroid(setupOptions) - creates an instance of your deck

The Response tuple

  • some methods will return a tuple in the form of [error, responseData] -- when there is no error the first value in the tuple will be null. The data we want to retrieve will always be in the second value

setupOptions object

| Params | Type | Required | Description | | --------------- | :--------------: | ------------------------------------ | ---------------------------------------------------------- | | deckProperties | object | optional if deckId exists | properties required to search by name / create a new deck | | deckId | string | number | optional if deckProperties exists | Id of the existing deck to add notes to | | modelProperties | object | optional if modelId exists | Id of the existing model to add notes to | | modelId | string | number | optional if modelProperties exists | properties required to search by name / create a new model |

deckProperties object

| Params | Type | Default | Description | | --------- | :----: | -------- | -------------------------------------------------------------------------------------------------- | | reference | string | REQUIRED | Deck reference name to store locally in SharedPreferences | | name | string | REQUIRED | Name of the deck to create / add notes to (Will first search for deck by name before creating) |

modelProperties object

| Params | Type | Default | Description | | -------------- | :------: | -------- | ------------------------------------------------------------------------------------------------------------------------- | | name | string | REQUIRED | Name of the model used / created for notes (Will first search for deck by name before creating) | | reference | string | REQUIRED | Model reference name to store locally in SharedPreferences | | modelFields | string[] | REQUIRED | The names of the fields used for the note's model during creation / use (modelFields.length === valueFields.length) | | cardNames | string[] | REQUIRED | Names for the front/back sides of the model (cardNames.length === 2) | | questionFormat | string[] | REQUIRED | Question formatting for each direction of (questionFormat.length === 2) variable names MUST match modelFields names | | answerFormat | string[] | REQUIRED | Answer formatting for each direction of (answerFormat.length === 2) variable names MUST match modelFields names | | tags | string[] | null | Tags to attach to added notes | | css | string | null | css styling information to be shared across all cards. (null for default CSS) |

AnkiDroid Class Instances

  • addNote(valueFields, modelFields)

    | Param | Type | Description | | ----------- | :------: | --------------------------------------------------------------------------------------------------------------- | | valueFields | string[] | The values for the corresponding model fields. (valueFields.length === modelFields.length) | | modelFields | string[] | The model fields that correspond to the model that will be used. (values must exactly match the model used) |

Gotchas

  • Once a model or reference has been created with a certain name, the format must match for all subsequent cards you wish to create using said model
  • If you intend to change the format in any way, you must use new names as a reference

Example

///////////////////////////////////
// SETTING UP THE DECK AND MODEL //
///////////////////////////////////

// Name of deck which will be created in AnkiDroid
const deckName = 'API Sample Name';
// Name of model which will be created in AnkiDroid (can be any string)
const modelName = 'Sample Model Name';
// Used to save a reference to this deck in the SharedPreferences (can be any string)
const dbDeckReference = 'com.your.app.decks';
// Used to save a reference to this model in the SharedPreferences (can be any string)
const dbModelReference = 'com.your.app.models';
// Optional space separated list of tags to add to every note
const tags = ['API_Sample', 'my', 'tags'];
// List of field names that will be used in AnkiDroid model
const modelFields = [
  'Word',
  'Translation',
  'Meaning',
  'Grammar',
  'Idiom',
  'IdiomTranslation',
  'IdiomMeaning',
];
// List of card names that will be used in AnkiDroid (one for each direction of learning)
const cardNames = ['Korean>English', 'English>Korean'];
// CSS to share between all the cards (optional).
const css = `.card {
  font-family: NotoSansKR;
  font-size: 24px;
  text-align: center;
  color: black;
  background-color: white;
  word-wrap: break-word;
}
.big { font-size: 48px; }
.small { font-size: 18px;}`;
// Template for the question of each card
const questionFmt1 = '<div class=big>{{Word}}</div><br>{{Grammar}}';
const questionFmt2 =
  '{{Meaning}}<br><br><div class=small>{{Grammar}}<br><br>({{Idiom}})</div>';
const questionFormat = [questionFmt1, questionFmt2];
// Template for the answer (this example is identical for both sides)
const answerFmt1 = `<div class=big>{{Translation}}</div><br>{{Meaning}}
<br><br>
{{IdiomTranslation}}<br>
<a href=\"#\" onclick=\"document.getElementById('hint').style.display='block';return false;\">Idiom Meaning</a>
<div id="hint" style="display: none">{{IdiomMeaning}}</div>
<br><br>
{{Grammar}}<br><div class=small>{{Tags}}</div>`;
const answerFormat = [answerFmt1, answerFmt1];

//////////////////
// ADDING NOTES //
//////////////////

const deckProperties = {
  name: deckName,
  reference: dbDeckReference,
};
const modelProperties = {
  name: modelName,
  reference: dbModelReference,
  fields: modelFields,
  tags,
  cardNames,
  questionFormat,
  answerFormat,
  css,
};

const valueFields = [
  '사랑',
  'love',
  'The attitude of sincerely caring about someone out of affection.',
  'noun',
  '사랑을 속삭이다',
  'whisper love',
  'For lovers to have a conversation of love.',
];

const settings = {
  modelId: undefined,
  modelProperties: modelProperties,
  deckId: undefined,
  deckProperties: deckProperties,
};

const myAnkiDeck = new AnkiDroid(settings);

myAnkiDeck.addNote(valueFields, modelFields);
// returns a promise that returns the added note ID

const newNote = [
  '여행사',
  'travel agency',
  'A company that offers an array of services for travel, including transportation, accomodaton, tour guide, etc.',
  'noun',
  '',
  '',
  '',
];

myAnkiDeck.addNote(newNote, modelFields);

Demo App

  • A demo app is in the example folder. Just cd into the demo app directory and npm install && npm run android

Card setup / References

Todo

  • [ ] add basic card
  • [ ] AnkiDroid intent API
  • [ ] add multiple notes at once
  • [x] ~~upload media~~
  • [x] ~~add to default deck~~
  • [x] ~~create by model ID / deck ID~~
  • [x] ~~get selected deck~~
  • [x] ~~get model field values~~
  • [x] ~~get model list~~
  • [x] ~~get deck list~~
  • [x] ~~detailed examples~~
  • [x] ~~typescript~~

Contributions

Pull requests welcome!