Icon Request

This library allows icon pack dashboards to easily send icon requests either traditionally via email, or through the Arctic Manager system.

Gradle Dependency

Add this to your module's build.gradle file (make sure the version matches the jCenter badge above):

dependencies {
  ...
  implementation 'com.afollestad:icon-request:4.1.0'
}

Creating a Request

To create a new Request object, you use the simple constructor. The only required
parameter is a Context.

val request = ArcticRequest(this)

Options

There are more optional parameters that you can pass:

val request = ArcticRequest(
  context = this,
  savedInstanceState = savedInstanceState,
  config = config,
  uriTransformer = uriTransformer,
  onLoading = { },
  onLoadError = {
     // `it` is a Throwable
  },
  onLoaded = {
    // `it` is a List<AppModel>
  },
  onSelectionChange = {
    // `it` is a AppModel
  },
  onSending = { },
  onSendError = {
    // `it` is a Throwable
  },
  onSent = {
    // `it` is an Int (how many apps were sent)
  }
)

Saved Instance State

Above, savedInstanceState is a Bundle received from onCreate(...) in your Activity
or Fragment which is used to restore your appfilter and app list state when recreating
your UI (e.g. after screen rotation). But you also need to make use of saveInstanceState
in order for that to work.

override fun onSaveInstanceState(outState: Bundle) {
  request.saveInstance(outState)
  super.onSaveInstanceState(outState)
}

UriTransformer

The uriTransformer allows you to modify the Uri pointing to a generated ZIP file before it
gets passed through an Intent to an email client. On newer versions of Android, apps can
only share files through FileProvider Uris. Here's an example of how you can convert a Uri of a
local file into a FileProvider Uri which external apps can use, this is backwards compatible as well.

{ file ->
  FileProvider.getUriForFile(
      this,
      BuildConfig.APPLICATION_ID + ".fileProvider",
      File(file.path)
  )
}

In order to use FileProvider, you'll need a file in /res/xml called filepaths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths>
  <cache-path name="cache" path="/"/>
  <external-path name="external_cache" path="/"/>
</paths>

Which is registered in your AndroidManifest.xml:

<application ...>
  <provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.fileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
      android:name="android.support.FILE_PROVIDER_PATHS"
      android:resource="@xml/filepaths"/>
  </provider>
</application>

ArcticConfig

The config takes an ArcticConfig instance which has various optional parameters:

val config = ArcticConfig(
    cacheFolder = File(externalCacheDir, "com.afollestad.arctic"),
    appFilterName = "appfilter.xml",
    emailRecipient = "[email protected]",
    emailSubject = "Icon Request",
    emailHeader = "These apps aren't themed on my device!",
    emailFooter = "Hello world",
    includeDeviceInfo = true,
    errorOnInvalidDrawables = true,
    apiHost = "arcticmanager.com",
    apiKey = "ojtopiu23rp9u34p0iu43-9i4"
)

You can pass an apiHost and apiKey to integrate with Arctic Request Manager.


Loading Unthemed Apps

With a configured ArcticRequest instance, you can load unthemed apps:

// Rely on only the onLoad and onLoadError callbacks passed into ArcticRequest(...).
// If onLoadError isn't set, an error will result in a thrown RuntimeException.
request.performLoad()

// You will still receive onLoad and onLoadError notifications, but the result is also passed
// into the parameterized lambda.
request.performLoad { list, throwable ->  }

Your onLoaded callback will receive a List of unthemed apps. If an error occurs,
the onLoadError callback is invoked.

After onLoaded, the loaded apps List will be populated:

val apps = request.loadedApps

Selecting Apps

Once you've loaded apps, you can select/deselect apps that are sent in a request:

request.toggleSelection(app);

request.select(app);
request.deselect(app);

request.selectAll();
request.deselectAll();

You can retrieve a List of selected apps:

// List<AppModel>
val apps = request.selectedApps

Keep in mind this method is doing a computation with every get performed on it, returning a new
filtered list based off the list of all loaded apps.


Sending a Request

Once you've selected apps, you can send a request:

// Rely on only the onSent and onSendError callbacks passed into ArcticRequest(...).
// If onSendError isn't set, an error will result in a thrown RuntimeException.
request.performSend()

// You will still receive onSent and onSendError notifications, but the result is also passed
// into the parameterized lambda.
request.performSend { count, throwable ->  }

Your onSent callback will be invoked if all is well; your onSendError callback
is invoked if an error occurs.

You can retrieve a List of requested apps:

// List<AppModel>
val apps = request.requestedApps

Keep in mind this method is doing a computation with every get performed on it, returning a new
filtered list based off the list of all loaded apps.


Cleanup

When appropriate, you should call dispose() on your request object. This will let
go of any pending actions that could result in memory leaks, or accessing your UI views
after your app is in the background.

override fun onPause() {
  request.dispose()
  super.onPause()
}

GitHub