Full Code of nohana/Laevatein for AI

master 983fad53933f cached
259 files
306.5 KB
86.9k tokens
579 symbols
1 requests
Download .txt
Showing preview only (373K chars total). Download the full file or copy to clipboard to get everything.
Repository: nohana/Laevatein
Branch: master
Commit: 983fad53933f
Files: 259
Total size: 306.5 KB

Directory structure:
gitextract_gancgo1e/

├── .gitignore
├── .travis.yml
├── README.md
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── laevatein/
│   ├── .gitignore
│   ├── build.gradle
│   ├── gradle.properties
│   ├── proguard-rules.txt
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── laevatein/
│       │               └── MimeTypeTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── laevatein/
│       │   │           ├── Laevatein.java
│       │   │           ├── MimeType.java
│       │   │           ├── SelectionSpecBuilder.java
│       │   │           ├── internal/
│       │   │           │   ├── entity/
│       │   │           │   │   ├── Album.java
│       │   │           │   │   ├── CaptureResources.java
│       │   │           │   │   ├── CounterViewResources.java
│       │   │           │   │   ├── DialogResources.java
│       │   │           │   │   ├── ErrorViewResources.java
│       │   │           │   │   ├── ErrorViewSpec.java
│       │   │           │   │   ├── Item.java
│       │   │           │   │   ├── ItemViewResources.java
│       │   │           │   │   ├── PreviewViewResources.java
│       │   │           │   │   ├── SelectionSpec.java
│       │   │           │   │   ├── UncapableCause.java
│       │   │           │   │   └── ViewResourceSpec.java
│       │   │           │   ├── loader/
│       │   │           │   │   ├── AlbumLoader.java
│       │   │           │   │   └── AlbumPhotoLoader.java
│       │   │           │   ├── misc/
│       │   │           │   │   ├── ui/
│       │   │           │   │   │   ├── ConfirmationDialogFragment.java
│       │   │           │   │   │   ├── FragmentUtils.java
│       │   │           │   │   │   └── helper/
│       │   │           │   │   │       └── options/
│       │   │           │   │   │           ├── OptionsMenu.java
│       │   │           │   │   │           └── OptionsMenuHandler.java
│       │   │           │   │   └── widget/
│       │   │           │   │       └── SquareGridViewItemRelativeLayout.java
│       │   │           │   ├── model/
│       │   │           │   │   ├── AlbumPhotoCollection.java
│       │   │           │   │   ├── DevicePhotoAlbumCollection.java
│       │   │           │   │   ├── PreviewStateHolder.java
│       │   │           │   │   └── SelectedUriCollection.java
│       │   │           │   ├── package-info.java
│       │   │           │   ├── ui/
│       │   │           │   │   ├── AlbumListFragment.java
│       │   │           │   │   ├── PhotoGridFragment.java
│       │   │           │   │   ├── PreviewFragment.java
│       │   │           │   │   ├── SelectedCountFragment.java
│       │   │           │   │   ├── SelectedPhotoGridFragment.java
│       │   │           │   │   ├── adapter/
│       │   │           │   │   │   ├── AlbumPhotoAdapter.java
│       │   │           │   │   │   ├── DevicePhotoAlbumAdapter.java
│       │   │           │   │   │   ├── PreviewPagerAdapter.java
│       │   │           │   │   │   ├── RecyclerViewCursorAdapter.java
│       │   │           │   │   │   └── SelectedPhotoAdapter.java
│       │   │           │   │   ├── helper/
│       │   │           │   │   │   ├── AlbumListViewHelper.java
│       │   │           │   │   │   ├── PhotoGridViewHelper.java
│       │   │           │   │   │   ├── PhotoSelectionActivityDrawerToggle.java
│       │   │           │   │   │   ├── PhotoSelectionViewHelper.java
│       │   │           │   │   │   ├── PreviewHelper.java
│       │   │           │   │   │   ├── SelectedCountViewHelper.java
│       │   │           │   │   │   ├── SelectedGridViewHelper.java
│       │   │           │   │   │   └── options/
│       │   │           │   │   │       ├── FinishSelectMenuHandler.java
│       │   │           │   │   │       ├── PhotoSelectionOptionsMenu.java
│       │   │           │   │   │       ├── PhotoSelectionOptionsMenuHandler.java
│       │   │           │   │   │       └── UnknownMenuHandler.java
│       │   │           │   │   └── widget/
│       │   │           │   │       └── PhotoDecoration.java
│       │   │           │   ├── utils/
│       │   │           │   │   ├── ErrorViewUtils.java
│       │   │           │   │   ├── ExifInterfaceUtils.java
│       │   │           │   │   ├── MediaStoreUtils.java
│       │   │           │   │   └── PhotoMetadataUtils.java
│       │   │           │   └── view/
│       │   │           │       └── PreviewViewPager.java
│       │   │           └── ui/
│       │   │               ├── ImagePreviewActivity.java
│       │   │               └── PhotoSelectionActivity.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   ├── l_bg_drawer_item.xml
│       │       │   ├── l_ic_capture.xml
│       │       │   ├── l_ic_capture_normal.xml
│       │       │   ├── l_ic_capture_pressed.xml
│       │       │   ├── l_ic_folder.xml
│       │       │   ├── l_ic_folder_close.xml
│       │       │   ├── l_ic_folder_open.xml
│       │       │   └── l_list_selector_drawer_menu.xml
│       │       ├── drawable-v21/
│       │       │   └── l_bg_drawer_item.xml
│       │       ├── layout/
│       │       │   ├── l_action_layout_checkbox.xml
│       │       │   ├── l_activity_preview.xml
│       │       │   ├── l_activity_select_photo.xml
│       │       │   ├── l_fragment_default_preview.xml
│       │       │   ├── l_fragment_grid_photo.xml
│       │       │   ├── l_fragment_list_album.xml
│       │       │   ├── l_fragment_selected_count.xml
│       │       │   ├── l_grid_item_default_photo.xml
│       │       │   ├── l_list_item_default_album.xml
│       │       │   └── l_view_counter.xml
│       │       ├── menu/
│       │       │   ├── l_activity_image_preview.xml
│       │       │   └── l_activity_options_select_photo.xml
│       │       ├── values/
│       │       │   ├── attrs.xml
│       │       │   ├── colors.xml
│       │       │   ├── dimens.xml
│       │       │   ├── strings.xml
│       │       │   └── styles.xml
│       │       ├── values-ja/
│       │       │   └── strings.xml
│       │       └── values-v21/
│       │           └── styles.xml
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── laevatein/
│           │           ├── LaevateinTest.java
│           │           ├── MimeTypeTest.java
│           │           ├── SelectionSpecBuilderTest.java
│           │           └── internal/
│           │               └── entity/
│           │                   └── AlbumTest.java
│           └── resources/
│               └── com/
│                   └── laevatein/
│                       └── robolectric.properties
├── repository/
│   └── com/
│       └── laevatein/
│           └── Laevatein/
│               ├── 0.10.0/
│               │   ├── Laevatein-0.10.0.aar
│               │   ├── Laevatein-0.10.0.aar.md5
│               │   ├── Laevatein-0.10.0.aar.sha1
│               │   ├── Laevatein-0.10.0.pom
│               │   ├── Laevatein-0.10.0.pom.md5
│               │   └── Laevatein-0.10.0.pom.sha1
│               ├── 0.10.1/
│               │   ├── Laevatein-0.10.1.aar
│               │   ├── Laevatein-0.10.1.aar.md5
│               │   ├── Laevatein-0.10.1.aar.sha1
│               │   ├── Laevatein-0.10.1.pom
│               │   ├── Laevatein-0.10.1.pom.md5
│               │   └── Laevatein-0.10.1.pom.sha1
│               ├── 0.10.2/
│               │   ├── Laevatein-0.10.2.aar
│               │   ├── Laevatein-0.10.2.aar.md5
│               │   ├── Laevatein-0.10.2.aar.sha1
│               │   ├── Laevatein-0.10.2.pom
│               │   ├── Laevatein-0.10.2.pom.md5
│               │   └── Laevatein-0.10.2.pom.sha1
│               ├── 0.10.3/
│               │   ├── Laevatein-0.10.3.aar
│               │   ├── Laevatein-0.10.3.aar.md5
│               │   ├── Laevatein-0.10.3.aar.sha1
│               │   ├── Laevatein-0.10.3.pom
│               │   ├── Laevatein-0.10.3.pom.md5
│               │   └── Laevatein-0.10.3.pom.sha1
│               ├── 0.10.4/
│               │   ├── Laevatein-0.10.4.aar
│               │   ├── Laevatein-0.10.4.aar.md5
│               │   ├── Laevatein-0.10.4.aar.sha1
│               │   ├── Laevatein-0.10.4.pom
│               │   ├── Laevatein-0.10.4.pom.md5
│               │   └── Laevatein-0.10.4.pom.sha1
│               ├── 0.10.5/
│               │   ├── Laevatein-0.10.5.aar
│               │   ├── Laevatein-0.10.5.aar.md5
│               │   ├── Laevatein-0.10.5.aar.sha1
│               │   ├── Laevatein-0.10.5.pom
│               │   ├── Laevatein-0.10.5.pom.md5
│               │   └── Laevatein-0.10.5.pom.sha1
│               ├── 0.9.0/
│               │   ├── Laevatein-0.9.0.aar
│               │   ├── Laevatein-0.9.0.aar.md5
│               │   ├── Laevatein-0.9.0.aar.sha1
│               │   ├── Laevatein-0.9.0.pom
│               │   ├── Laevatein-0.9.0.pom.md5
│               │   └── Laevatein-0.9.0.pom.sha1
│               ├── 0.9.1/
│               │   ├── Laevatein-0.9.1.aar
│               │   ├── Laevatein-0.9.1.aar.md5
│               │   ├── Laevatein-0.9.1.aar.sha1
│               │   ├── Laevatein-0.9.1.pom
│               │   ├── Laevatein-0.9.1.pom.md5
│               │   └── Laevatein-0.9.1.pom.sha1
│               ├── 0.9.10/
│               │   ├── Laevatein-0.9.10.aar
│               │   ├── Laevatein-0.9.10.aar.md5
│               │   ├── Laevatein-0.9.10.aar.sha1
│               │   ├── Laevatein-0.9.10.pom
│               │   ├── Laevatein-0.9.10.pom.md5
│               │   └── Laevatein-0.9.10.pom.sha1
│               ├── 0.9.11/
│               │   ├── Laevatein-0.9.11.aar
│               │   ├── Laevatein-0.9.11.aar.md5
│               │   ├── Laevatein-0.9.11.aar.sha1
│               │   ├── Laevatein-0.9.11.pom
│               │   ├── Laevatein-0.9.11.pom.md5
│               │   └── Laevatein-0.9.11.pom.sha1
│               ├── 0.9.12/
│               │   ├── Laevatein-0.9.12.aar
│               │   ├── Laevatein-0.9.12.aar.md5
│               │   ├── Laevatein-0.9.12.aar.sha1
│               │   ├── Laevatein-0.9.12.pom
│               │   ├── Laevatein-0.9.12.pom.md5
│               │   └── Laevatein-0.9.12.pom.sha1
│               ├── 0.9.13/
│               │   ├── Laevatein-0.9.13.aar
│               │   ├── Laevatein-0.9.13.aar.md5
│               │   ├── Laevatein-0.9.13.aar.sha1
│               │   ├── Laevatein-0.9.13.pom
│               │   ├── Laevatein-0.9.13.pom.md5
│               │   └── Laevatein-0.9.13.pom.sha1
│               ├── 0.9.14/
│               │   ├── Laevatein-0.9.14.aar
│               │   ├── Laevatein-0.9.14.aar.md5
│               │   ├── Laevatein-0.9.14.aar.sha1
│               │   ├── Laevatein-0.9.14.pom
│               │   ├── Laevatein-0.9.14.pom.md5
│               │   └── Laevatein-0.9.14.pom.sha1
│               ├── 0.9.15/
│               │   ├── Laevatein-0.9.15.aar
│               │   ├── Laevatein-0.9.15.aar.md5
│               │   ├── Laevatein-0.9.15.aar.sha1
│               │   ├── Laevatein-0.9.15.pom
│               │   ├── Laevatein-0.9.15.pom.md5
│               │   └── Laevatein-0.9.15.pom.sha1
│               ├── 0.9.16/
│               │   ├── Laevatein-0.9.16.aar
│               │   ├── Laevatein-0.9.16.aar.md5
│               │   ├── Laevatein-0.9.16.aar.sha1
│               │   ├── Laevatein-0.9.16.pom
│               │   ├── Laevatein-0.9.16.pom.md5
│               │   └── Laevatein-0.9.16.pom.sha1
│               ├── 0.9.2/
│               │   ├── Laevatein-0.9.2.aar
│               │   ├── Laevatein-0.9.2.aar.md5
│               │   ├── Laevatein-0.9.2.aar.sha1
│               │   ├── Laevatein-0.9.2.pom
│               │   ├── Laevatein-0.9.2.pom.md5
│               │   └── Laevatein-0.9.2.pom.sha1
│               ├── 0.9.3/
│               │   ├── Laevatein-0.9.3.aar
│               │   ├── Laevatein-0.9.3.aar.md5
│               │   ├── Laevatein-0.9.3.aar.sha1
│               │   ├── Laevatein-0.9.3.pom
│               │   ├── Laevatein-0.9.3.pom.md5
│               │   └── Laevatein-0.9.3.pom.sha1
│               ├── 0.9.4/
│               │   ├── Laevatein-0.9.4.aar
│               │   ├── Laevatein-0.9.4.aar.md5
│               │   ├── Laevatein-0.9.4.aar.sha1
│               │   ├── Laevatein-0.9.4.pom
│               │   ├── Laevatein-0.9.4.pom.md5
│               │   └── Laevatein-0.9.4.pom.sha1
│               ├── 0.9.5/
│               │   ├── Laevatein-0.9.5.aar
│               │   ├── Laevatein-0.9.5.aar.md5
│               │   ├── Laevatein-0.9.5.aar.sha1
│               │   ├── Laevatein-0.9.5.pom
│               │   ├── Laevatein-0.9.5.pom.md5
│               │   └── Laevatein-0.9.5.pom.sha1
│               ├── 0.9.6/
│               │   ├── Laevatein-0.9.6.aar
│               │   ├── Laevatein-0.9.6.aar.md5
│               │   ├── Laevatein-0.9.6.aar.sha1
│               │   ├── Laevatein-0.9.6.pom
│               │   ├── Laevatein-0.9.6.pom.md5
│               │   └── Laevatein-0.9.6.pom.sha1
│               ├── 0.9.7/
│               │   ├── Laevatein-0.9.7.aar
│               │   ├── Laevatein-0.9.7.aar.md5
│               │   ├── Laevatein-0.9.7.aar.sha1
│               │   ├── Laevatein-0.9.7.pom
│               │   ├── Laevatein-0.9.7.pom.md5
│               │   └── Laevatein-0.9.7.pom.sha1
│               ├── 0.9.8/
│               │   ├── Laevatein-0.9.8.aar
│               │   ├── Laevatein-0.9.8.aar.md5
│               │   ├── Laevatein-0.9.8.aar.sha1
│               │   ├── Laevatein-0.9.8.pom
│               │   ├── Laevatein-0.9.8.pom.md5
│               │   └── Laevatein-0.9.8.pom.sha1
│               ├── 0.9.9/
│               │   ├── Laevatein-0.9.9.aar
│               │   ├── Laevatein-0.9.9.aar.md5
│               │   ├── Laevatein-0.9.9.aar.sha1
│               │   ├── Laevatein-0.9.9.pom
│               │   ├── Laevatein-0.9.9.pom.md5
│               │   └── Laevatein-0.9.9.pom.sha1
│               ├── maven-metadata.xml
│               ├── maven-metadata.xml.md5
│               └── maven-metadata.xml.sha1
├── sample/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.txt
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── laevatein/
│           │           └── sample/
│           │               └── LSampleActivity.java
│           └── res/
│               ├── drawable/
│               │   └── selector_background.xml
│               ├── layout/
│               │   └── activity_sample.xml
│               ├── values/
│               │   ├── colors.xml
│               │   ├── dimens.xml
│               │   ├── strings.xml
│               │   └── styles.xml
│               ├── values-w820dp/
│               │   └── dimens.xml
│               └── xml/
│                   └── file_paths.xml
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# build app files
*.apk
*.ap_

# ignore crashlytics config
com_crashlytics_export_strings.xml

# Dalvik files
*.dex

# Java class files
*.class

# Generated files
bin/
gen/
build/
lint.xml
proguard/

# Local configs
local.properties

# roboelectric
tmp/

# Eclipse workspace
.metadata/
.checkstyle

# intelli J
.idea
*.iml
*.ipr
*.iws

# mac
.Trashes
.DS_Store

# Win
Thumbs.db

# Vim
*.swp

#emacs
*.*~

# Keystore
keystore.properties

# Gradle
.gradle


================================================
FILE: .travis.yml
================================================
language: android
jdk: oraclejdk8
env:
 global:
    - ANDROID_SDK=android-29
    - ANDROID_BUILD_TOOLS_VERSION=28.0.3
    - ANDROID_ABI=armeabi-v7a
    - ANDROID_EMULATOR_SDK=android-22
    - ADB_INSTALL_TIMEOUT=10
android:
  components:
    - tools
    - $ANDROID_SDK
    - $ANDROID_EMULATOR_SDK
    - build-tools-$ANDROID_BUILD_TOOLS_VERSION
    - google-google_play_services
    - extra-google-m2repository 
    - extra-android-m2repository
    - addon-google_apis-google-22
    - sys-img-${ANDROID_ABI}-${ANDROID_EMULATOR_SDK}
licenses:
    - 'android-sdk-preview-license-.+'
    - 'android-sdk-license-.+'
    - 'google-gdk-license-.+'
before_cache:
  - rm -f  $HOME/.gradle/caches/modules-2/modules-2.lock
  - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
  directories:
    - $HOME/.gradle/caches/
    - $HOME/.gradle/wrapper/
    - $HOME/.android/build-cache
before_script:
  - echo no | android create avd --force -n test -t $ANDROID_EMULATOR_SDK --abi $ANDROID_ABI
  - emulator -avd test -no-skin -no-audio -no-window &
  - android-wait-for-emulator
  - adb shell input keyevent 82 &
script:
  - ./gradlew clean build connectedAndroidTest -PdisablePreDex

notifications:
  email: false


================================================
FILE: README.md
================================================
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ 

**WARNING: This library is no longer maintained.**

⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ 

Thank you for using and contributing! 🙇

---

# Laevatein

Photo image selection activity set library.

## Screen Shot

![Selection Activity](https://raw.githubusercontent.com/nohana/Laevatein/master/documents/ss-1.png)
![Album List on DrawerMenu](https://raw.githubusercontent.com/nohana/Laevatein/master/documents/ss-2.png)
![Selected List](https://raw.githubusercontent.com/nohana/Laevatein/master/documents/ss-3.png)

## Usage

Call photo image selection activity by the following code snipet.

```java
public class SomeActivity extends Activity {
  public static final int REQUEST_CODE_CHOOSE = 1;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_some);
  }

  @Override
  protected void onActivityResult(int requestCode, int resultcode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
    case REQUEST_CODE_CHOOSE:
      if (resultCode == RESULT_OK) {
        // Get result and proceed your work from here...
        List<Uri> selected = Laevatein.obtainResult(data);
      }
      break;
    default:
      break;
    }
  }

  public void onClickButton(View view) {
    // call chooser on click button like this
    Laevatein.from(this).choose(MimeType.of(MimeType.JPEG)).forResult(REQUEST_CODE_CHOOSE);
  }
}
```

And you'll get the selection result on `Activity#onActivityResult(int, int, Intent)`.

## Features

Laevatein provides some APIs to customize selector behaviour for your spec.

### Selectable count limitation

Set selectable count with `count(int, int)`.
Default is `0 <= count <= 1`.

```java
Laevatein.from(this)
        .choose(MimeType.of(MimeType.JPEG))
        .count(0, 10)  // minimum = 0, max = 10, so 0 <= count <= 10;
        .forResult(REQUEST_CODE_CHOOSE);
```

### Selectable photo quality limitation

Set selectable photo quality by pixel count with `quality(int, int)`.
Default is `0 <= pixels <= Integer.MAX_VALUE`.

```java
Laevatein.from(this)
        .choose(MimeType.of(MimeType.JPEG))
        .quality(30000, Integer.MAX_VALUE)  // minimum = 30000px, max = Integer.MAX_VALUEpx, so 30000px <= count <= Integer.MAX_VALUEpx;
        .forResult(REQUEST_CODE_CHOOSE);
```

### Selectable photo size limitation

Set selectable photo size by pixel with `size(int, int)`.
Default is `0 <= pixels <= Integer.MAX_VALUE`.

```java
Laevatein.from(this)
        .choose(MimeType.of(MimeType.JPEG))
        .size(300, 400)  // minimum width = 300px, minimum height = 400px;
        .forResult(REQUEST_CODE_CHOOSE);
```

### Selectable photo size limitation

Set selectable photo size by pixel with `size(int, int, int, int)`.
Default is `0 <= pixels <= Integer.MAX_VALUE`.

```java
Laevatein.from(this)
        .choose(MimeType.of(MimeType.JPEG))
        .size(300, 400, Integer.MAX_VALUE, Integer.MAX_VALUE)  // minimum width = 300px, minimum height = 400px, max width = Integer.MAX_VALUEpx, max height = Integer.MAX_VALUEpx;
        .forResult(REQUEST_CODE_CHOOSE);
```

### Use custom cell layout

Set your layout and ids for the image cell with `bindEachImageWith(int, int, int)`.

```java
Laevatein.from(this)
        .choose(MimeType.of(MimeType.JPEG))
        .bindEachImageWith(R.layout.my_cell, R.id.my_cell_image_view, R.id.my_cell_check_box)
        .forResult(REQUEST_CODE_CHOOSE);
```

### Resume selection with previously selected photos

Set defaultly selected URIs with `resume(List<Uri>)`.

```java
List<Uri> mSelectedList;

Laevatein.from(this)
        .choose(MimeType.of(MimeType.JPEG))
        .resume(mSelectedList)
        .forResult(REQUEST_CODE_CHOOSE);
```

### Call camera from the selection activity

Set flag to enable camera capture from the selection activity with `capture(boolean)`.

```java
Laevatein.from(this)
        .choose(MimeType.of(MimeType.JPEG))
        .capture(true)
        .forResult(REQUEST_CODE_CHOOSE);
```

### Customize theme

Change Laevatein's theme with `theme(int)`.

```java
Laevatein.from(this)
        .theme(R.style.OriginalTheme)
        .choose(MimeType.of(MimeType.JPEG))
        .forResult(REQUEST_CODE_CHOOSE);
```

Theme must implement these parameter at least.

```xml
<style name="OriginalTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="l_drawerStyle">@style/L_DrawerMenu</item>
    <item name="l_drawerItemStyle">@style/L_DrawerMenuItem</item>
    <item name="l_gridStyle">@style/L_Grid</item>
    <item name="l_counterStyle">@style/L_Counter</item>
</style>
```

## Sample App

Sample application is available [here](https://deploygate.com/distributions/b43dc74fc4025bbb8587f179f5b8464418cca559).
[<img src="https://dply.me/orf0t9/button/large" alt="Try it on your device via DeployGate">](https://dply.me/orf0t9#install)

## Download

Via Gradle

for Android Studio ~2.x

```groovy
repositories {
    mavenCentral()
}
android {
    dependencies {
        compile 'jp.co.nohana:Laevatein:2.3.2@aar'
    }
}
```

for Android Studio 3.x~

```groovy
repositories {
    mavenCentral()
}
android {
    dependencies {
        implementation 'jp.co.nohana:Laevatein:2.3.2'
    }
}
```

## Acknowledgement

This library depends on the following libraries.

1. [Picasso](https://github.com/square/picasso) by Square Inc.
2. [ImageViewZoom](https://github.com/sephiroth74/ImageViewZoom) by Alessandro Crugnola
3. [Amalgam](https://github.com/nohana/Amalgam) by nohana, Inc.
4. [CompoundContainers](https://github.com/KeithYokoma/CompoundContainers) by KeithYokoma
5. [AndroidDeviceCompatibility](https://github.com/mixi-inc/Android-Device-Compatibility) by mixi, Inc.
6. [PermissionsDispatcher](https://github.com/hotchemi/PermissionsDispatcher) by Shintaro Katafuchi, Marcel Schnelle, Yoshinori Isogai

## License

This library is licensed under Apache License v2.

```
Copyright (C) 2014 nohana, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
```


[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/nohana/laevatein/trend.png)](https://bitdeli.com/free "Bitdeli Badge")



================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Thu Nov 30 10:11:36 JST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip


================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Settings specified in this file will override any Gradle settings
# configured through the IDE.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
VERSION_NAME=3.1.0
VERSION_CODE=26
GROUP=jp.co.nohana
POM_DESCRIPTION=Photo image selection activity set library. Currently under development.
POM_URL=https://github.com/nohana/Laevatein
POM_SCM_URL=https://github.com/nohana/Laevatein
POM_SCM_CONNECTION=scm:git@github.com:nohana/Laevatein.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:nohana/Laevatein.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=nohana
POM_DEVELOPER_NAME=nohana,Inc.
ANDROID_BUILD_TARGET_SDK_VERSION=29
ANDROID_BUILD_TOOLS_VERSION=29.0.3
ANDROID_BUILD_SDK_VERSION=29
android.useAndroidX=true
android.enableJetifier=true


================================================
FILE: gradlew
================================================
#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
    echo "$*"
}

die ( ) {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: laevatein/.gitignore
================================================
/build


================================================
FILE: laevatein/build.gradle
================================================
apply plugin: 'com.android.library'

android {
    compileSdkVersion 29

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 29

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    lintOptions {
        abortOnError false
    }
    testOptions.unitTests.includeAndroidResources true

    useLibrary 'android.test.mock'
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.annotation:annotation:1.1.0'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'androidx.exifinterface:exifinterface:1.1.0'
    implementation("com.github.bumptech.glide:glide:4.11.0") {
        exclude group: 'com.android.support', module: 'support-fragment'
    }
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
    implementation 'it.sephiroth.android.library.imagezoom:library:1.0.4'
    implementation 'jp.co.nohana:Amalgam:0.4.0@aar'

    // Robolectric
    testImplementation 'junit:junit:4.13'
    testImplementation 'androidx.test:core:1.2.0'
    testImplementation 'androidx.test:runner:1.2.0'
    testImplementation 'androidx.test:rules:1.2.0'
    testImplementation 'androidx.test.ext:junit:1.1.1'

    testImplementation 'junit:junit:4.13'
    testImplementation 'org.robolectric:robolectric:4.3'
    testImplementation 'org.mockito:mockito-all:1.10.19'

    androidTestImplementation 'androidx.test:runner:1.2.0'
}

apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'

afterEvaluate {
    androidJavadocs.failOnError false
    androidJavadocs.classpath += project.android.libraryVariants.toList().first().javaCompile.classpath
}

apply plugin: 'idea'

idea {
    module {
        testOutputDir = file('build/test-classes/debug')
    }
}


================================================
FILE: laevatein/gradle.properties
================================================
POM_NAME=Laevatein
POM_ARTIFACT_ID=Laevatein
POM_PACKAGING=aar

================================================
FILE: laevatein/proguard-rules.txt
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Library/android-sdk-macosx/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

-dontwarn com.squareup.okhttp.**

================================================
FILE: laevatein/src/androidTest/java/com/laevatein/MimeTypeTest.java
================================================
package com.laevatein;

import android.net.Uri;
import android.test.mock.MockContentResolver;

import org.junit.Test;
import org.junit.runner.RunWith;

import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

@RunWith(AndroidJUnit4ClassRunner.class)
public class MimeTypeTest {
    @Test
    public void typeCheck() throws Exception {
        MockContentResolver resolver = new MockContentResolver();

        {
            assertTrue(MimeType.JPEG.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.jpg")));
            assertTrue(MimeType.JPEG.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.jpeg")));
            assertFalse(MimeType.JPEG.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.png")));
            assertFalse(MimeType.JPEG.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.gif")));
            assertFalse(MimeType.JPEG.checkType(resolver, null));
        }

        {
            assertFalse(MimeType.PNG.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.jpg")));
            assertFalse(MimeType.PNG.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.jpeg")));
            assertTrue(MimeType.PNG.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.png")));
            assertFalse(MimeType.PNG.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.gif")));
            assertFalse(MimeType.PNG.checkType(resolver, null));
        }

        {
            assertFalse(MimeType.GIF.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.jpg")));
            assertFalse(MimeType.GIF.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.jpeg")));
            assertFalse(MimeType.GIF.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.png")));
            assertTrue(MimeType.GIF.checkType(resolver, Uri.parse("file://hogehoge/fugafuga/image.gif")));
            assertFalse(MimeType.GIF.checkType(resolver, null));
        }
    }
}


================================================
FILE: laevatein/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.laevatein">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


    <application android:allowBackup="true">
        <activity android:name=".ui.PhotoSelectionActivity" />
        <activity android:name=".ui.ImagePreviewActivity" />
    </application>
</manifest>

================================================
FILE: laevatein/src/main/java/com/laevatein/Laevatein.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.laevatein.ui.PhotoSelectionActivity;

import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Set;

/**
 * Photo selection activity set provider.
 * Use {@link #from(android.app.Activity)} to start selection activity with the specification you'd like.
 * And the result will be delivered to {@link Activity#onActivityResult(int, int, android.content.Intent)},
 * and use {@link #obtainResult(android.content.Intent)} for the convenience of receiving the selection result.
 *
 * @author KeithYokoma
 * @version 1.0.0
 * @since 2014/03/19
 */
@SuppressWarnings("unused") // public APIs
public final class Laevatein {
    public static final String TAG = Laevatein.class.getSimpleName();
    private final WeakReference<Activity> mContext;
    private final WeakReference<Fragment> mFragment;

    protected Laevatein(Activity context) {
        mContext = new WeakReference<>(context);
        mFragment = null;
    }

    protected Laevatein(Activity activity, Fragment fragment) {
        mContext = new WeakReference<>(activity);
        mFragment = new WeakReference<>(fragment);
    }

    /**
     * Starts selection from the specified {@link android.app.Activity}.
     *
     * @param activity to start.
     * @return the requester context wrapper.
     */
    public static Laevatein from(Activity activity) {
        return new Laevatein(activity);
    }

    public static Laevatein from(Fragment fragment) {
        return new Laevatein(fragment.getActivity(), fragment);
    }

    /**
     * Obtains the selection result passed to your {@link Activity#onActivityResult(int, int, android.content.Intent)}.
     *
     * @param data the data.
     * @return the selected {@link android.net.Uri}s.
     */
    public static List<Uri> obtainResult(Intent data) {
        return data.getParcelableArrayListExtra(PhotoSelectionActivity.EXTRA_RESULT_SELECTION);
    }

    /**
     * Specifies the MIME Type to select.
     *
     * @param mimeType the mime type of the photo you would like to choose.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder choose(Set<MimeType> mimeType) {
        return new SelectionSpecBuilder(this, mimeType);
    }

    /**
     * @return the actual requester context.
     */
    /* package */
    @Nullable
    Activity getActivity() {
        return mContext.get();
    }

    /**
     * @return the fragment that is responsible for result handling.
     */
    /* package */
    @Nullable
    Fragment getFragment() {
        return mFragment != null ? mFragment.get() : null;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/MimeType.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein;

import com.laevatein.internal.utils.PhotoMetadataUtils;

import android.content.ContentResolver;
import android.net.Uri;
import android.webkit.MimeTypeMap;

import java.util.EnumSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

/**
 * MIME Type enumeration to restrict selectable photo on the selection activity.
 * @author KeithYokoma
 * @since 2014/03/19
 * @version 1.0.0
 */
@SuppressWarnings("unused") // public APIs
public enum MimeType {
    JPEG("image/jpeg", new HashSet<String>() {{ add("jpg"); add("jpeg"); }}),
    PNG("image/png", new HashSet<String>() {{ add("png"); }}),
    GIF("image/gif", new HashSet<String>() {{ add("gif"); }});

    private final String mMimeTypeName;
    private final Set<String> mExtensions;

    MimeType(String mimeTypeName, Set<String> extensions) {
        mMimeTypeName = mimeTypeName;
        mExtensions = extensions;
    }

    public static Set<MimeType> allOf() {
        return EnumSet.allOf(MimeType.class);
    }

    public static Set<MimeType> of(MimeType type) {
        return EnumSet.of(type);
    }

    public static Set<MimeType> of(MimeType type, MimeType... rest) {
        return EnumSet.of(type, rest);
    }

    @Override
    public String toString() {
        return mMimeTypeName;
    }

    public boolean checkType(ContentResolver resolver, Uri uri) {
        MimeTypeMap map = MimeTypeMap.getSingleton();
        if (uri == null) {
            return false;
        }
        String type = map.getExtensionFromMimeType(resolver.getType(uri));
        for (String extension : mExtensions) {
            if (extension.equals(type)) {
                return true;
            }
            String path = PhotoMetadataUtils.getPath(resolver, uri);
            if (path != null && path.toLowerCase(Locale.US).endsWith(extension)) {
                return true;
            }
        }
        return false;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/SelectionSpecBuilder.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.StringRes;
import androidx.annotation.StyleRes;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.fragment.app.Fragment;
import android.view.View;

import com.laevatein.internal.entity.CaptureResources;
import com.laevatein.internal.entity.CounterViewResources;
import com.laevatein.internal.entity.DialogResources;
import com.laevatein.internal.entity.ErrorViewResources;
import com.laevatein.internal.entity.ErrorViewSpec;
import com.laevatein.internal.entity.ItemViewResources;
import com.laevatein.internal.entity.PreviewViewResources;
import com.laevatein.internal.entity.SelectionSpec;
import com.laevatein.internal.entity.ViewResourceSpec;
import com.laevatein.ui.ImagePreviewActivity;
import com.laevatein.ui.PhotoSelectionActivity;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Fluent API for building photo select specification.
 *
 * @author KeithYokoma
 * @version 1.0.0
 * @since 2014/03/19
 */
@SuppressWarnings("unused") // public APIs
public final class SelectionSpecBuilder {
    public static final String TAG = SelectionSpecBuilder.class.getSimpleName();
    private final Laevatein mLaevatein;
    private final Set<MimeType> mMimeType;
    private final SelectionSpec mSelectionSpec;
    @StyleRes
    private int mActivityTheme;
    private ItemViewResources mItemViewResources;
    private CounterViewResources mCounterViewResources;
    private PreviewViewResources mPreviewViewResources;
    private ErrorViewResources mCountUnderErrorSpec;
    private ErrorViewResources mCountOverErrorSpec;
    private ErrorViewResources mUnderQualityErrorSpec;
    private ErrorViewResources mOverQualityErrorSpec;
    private ErrorViewResources mUnderSizeErrorSpec;
    private ErrorViewResources mOverSizeErrorSpec;
    private ErrorViewResources mTypeErrorSpec;
    private DialogResources mConfirmDialogSpec;
    private boolean mOpenDrawer = true;
    private String mFileProviderAuthorities;
    private boolean mEnableSelectedView;
    private int mActivityOrientation;
    private List<Uri> mResumeList;
    private Class<? extends PhotoSelectionActivity> mPhotoSelectionActivityClass;
    private Class<? extends ImagePreviewActivity> mPreviewActivityClass = ImagePreviewActivity.class;

    /**
     * Constructs a new specification builder on the context.
     * @param laevatein a requester context wrapper.
     * @param mimeType MimeType set to select.
     */
    /* package */ SelectionSpecBuilder(Laevatein laevatein, Set<MimeType> mimeType) {
        mLaevatein = laevatein;
        mMimeType = mimeType;
        mSelectionSpec = new SelectionSpec();
        mResumeList = new ArrayList<>();
        mActivityOrientation = -1;
    }

    /**
     * Sets the theme of activities.
     *
     * @param theme theme of activity
     * @return the specification builder context.
     */
    public SelectionSpecBuilder theme(@StyleRes int theme) {
        mActivityTheme = theme;
        return this;
    }

    /**
     * Sets the binding cell of the grid view with the specified layout resource for photo list.
     * @param layoutId a layout resource id.
     * @param imageViewId an id for the image view.
     * @param checkBoxId an id for the check box.
     * @param spanCount an span count for GridLayout.
     */
    public SelectionSpecBuilder bindEachImageWith(int layoutId, int imageViewId, int checkBoxId, int spanCount) {
        mItemViewResources = new ItemViewResources(layoutId, imageViewId, checkBoxId, spanCount);
        return this;
    }

    /**
     * Sets counter view style of photo selection.
     *
     * @param viewPosition the position where counter view layouted
     * @param textId counter text id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder counterView(@CounterViewResources.VIEW_POSITION int viewPosition, @StringRes int textId) {
        mCounterViewResources = new CounterViewResources(viewPosition, textId);
        return this;
    }

    /**
     * Sets the binding page of the ViewPager with the specified layout resource for photo list.
     *
     * @param layoutId    a layout resource id.
     * @param imageViewId an id for the image view.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder bindPreviewImageWith(int layoutId, int imageViewId) {
        mPreviewViewResources = new PreviewViewResources(layoutId, imageViewId);
        return this;
    }

    /**
     * Sets the limitation of a selectable count within the specified range.
     * @param min minimum value to select.
     * @param max maximum value to select.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder count(int min, int max) {
        mSelectionSpec.setMinSelectable(min);
        mSelectionSpec.setMaxSelectable(max);
        return this;
    }

    /**
     * Sets the error view specification for the error of count over.
     * @param type error view type.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder countUnder(ErrorViewResources.ViewType type, int errorMessageId) {
        return countUnder(type, -1, errorMessageId);
    }

    /**
     * Sets the error view specification for the error of count over.
     * @param type error view type.
     * @param errorTitleId an error title resource id. If type is not {@see ErrorViewResources.ViewType.DIALOG}, this parameter is ignored.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder countUnder(ErrorViewResources.ViewType type, int errorTitleId, int errorMessageId) {
        mCountUnderErrorSpec = type.createSpec(errorTitleId, errorMessageId);
        return this;
    }

    /**
     * Sets the error view specification for the error of count over.
     * @param type error view type.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder countOver(ErrorViewResources.ViewType type, int errorMessageId) {
        return countOver(type, -1, errorMessageId);
    }

    /**
     * Sets the error view specification for the error of count over.
     * @param type error view type.
     * @param errorTitleId an error title resource id. If type is not {@see ErrorViewResources.ViewType.DIALOG}, this parameter is ignored.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder countOver(ErrorViewResources.ViewType type, int errorTitleId, int errorMessageId) {
        mCountOverErrorSpec = type.createSpec(errorTitleId, errorMessageId);
        return this;
    }

    /**
     * Sets the flag to determine whether the list of which image has been selected should be shown or not.
     * The flag is set as false by default.
     * @param enableSelectedView the flag of visibility.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder enableSelectedView(boolean enableSelectedView) {
        mEnableSelectedView = enableSelectedView;
        return this;
    }

    /**
     * Sets the error view specification for the error of quality un-satisfaction.
     * @param type error view type.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder underQuality(ErrorViewResources.ViewType type, int errorMessageId) {
        return underQuality(type, -1, errorMessageId);
    }

    /**
     * Sets the error view specification for the error of quality un-satisfaction.
     * @param type error view type.
     * @param errorTitleId an error title resource id. If type is not {@see ErrorViewResources.ViewType.DIALOG}, this parameter is ignored.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder underQuality(ErrorViewResources.ViewType type, int errorTitleId, int errorMessageId) {
        mUnderQualityErrorSpec = type.createSpec(errorTitleId, errorMessageId);
        return this;
    }

    /**
     * Sets the error view specification for the error of quality un-satisfaction..
     * @param type error view type.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder overQuality(ErrorViewResources.ViewType type, int errorMessageId) {
        return overQuality(type, -1, errorMessageId);
    }

    /**
     * Sets the error view specification for the error of quality un-satisfaction..
     * @param type error view type.
     * @param errorTitleId an error title resource id. If type is not {@see ErrorViewResources.ViewType.DIALOG}, this parameter is ignored.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder overQuality(ErrorViewResources.ViewType type, int errorTitleId, int errorMessageId) {
        mOverQualityErrorSpec = type.createSpec(errorTitleId, errorMessageId);
        return this;
    }

    /**
     * Sets the error view specification for the error of size un-satisfaction.
     * @param type error view type.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder underSize(ErrorViewResources.ViewType type, int errorMessageId) {
        return underSize(type, -1, errorMessageId);
    }

    /**
     * Sets the error view specification for the error of size un-satisfaction.
     * @param type error view type.
     * @param errorTitleId an error title resource id. If type is not {@see ErrorViewResources.ViewType.DIALOG}, this parameter is ignored.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder underSize(ErrorViewResources.ViewType type, int errorTitleId, int errorMessageId) {
        mUnderSizeErrorSpec = type.createSpec(errorTitleId, errorMessageId);
        return this;
    }

    /**
     * Sets the error view specification for the error of size un-satisfaction..
     * @param type error view type.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder overSize(ErrorViewResources.ViewType type, int errorMessageId) {
        return overSize(type, -1, errorMessageId);
    }

    /**
     * Sets the error view specification for the error of size un-satisfaction..
     * @param type error view type.
     * @param errorTitleId an error title resource id. If type is not {@see ErrorViewResources.ViewType.DIALOG}, this parameter is ignored.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder overSize(ErrorViewResources.ViewType type, int errorTitleId, int errorMessageId) {
        mOverSizeErrorSpec = type.createSpec(errorTitleId, errorMessageId);
        return this;
    }

    /**
     * Sets the error view specification for the error of type validation.
     * @param type error view type.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder invalidType(ErrorViewResources.ViewType type, int errorMessageId) {
        return invalidType(type, -1, errorMessageId);
    }

    /**
     * Sets the error view specification for the error of type validation.
     * @param type error view type.
     * @param errorTitleId an error title resource id. If type is not {@see ErrorViewResources.ViewType.DIALOG}, this parameter is ignored.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder invalidType(ErrorViewResources.ViewType type, int errorTitleId, int errorMessageId) {
        mTypeErrorSpec = type.createSpec(errorTitleId, errorMessageId);
        return this;
    }

    /**
     * Sets the error view specification for the press back without finish.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder confirmDialog(int errorMessageId) {
        return confirmDialog(-1, errorMessageId);
    }

    /**
     * Sets the error view specification for the press back without finish.
     * @param errorTitleId an error title resource id. If type is not {@see ErrorViewResources.ViewType.DIALOG}, this parameter is ignored.
     * @param errorMessageId an error message resource id.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder confirmDialog(int errorTitleId, int errorMessageId) {
        mConfirmDialogSpec = new DialogResources(errorTitleId, errorMessageId);
        return this;
    }

    /**
     * Sets the limitation of a selectable image quality by pixel count within the specified range.
     * @param minPixel minimum value to select.
     * @param maxPixel maximum value to select.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder quality(int minPixel, int maxPixel) {
        mSelectionSpec.setMinPixels(minPixel);
        mSelectionSpec.setMaxPixels(maxPixel);
        return this;
    }

    /**
     * Sets the limitation of a selectable image size by pixel count minimum.
     *
     * @param minWidth  minimum width value to select.
     * @param minHeight minimum width value to select.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder size(int minWidth, int minHeight) {
        size(minWidth, minHeight, Integer.MAX_VALUE, Integer.MAX_VALUE);
        return this;
    }

    /**
     * Sets the limitation of a selectable image size by pixel count minimum and maximum.
     *
     * @param minWidth  minimum width value to select.
     * @param minHeight minimum width value to select.
     * @param maxWidth  maximum height value to select.
     * @param maxHeight maximum height value to select.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder size(int minWidth, int minHeight, int maxWidth, int maxHeight) {
        mSelectionSpec.setMinSize(minWidth, minHeight);
        mSelectionSpec.setMaxSize(maxWidth, maxHeight);
        return this;
    }

    /**
     * Sets the default selected album.
     *
     * @param albumId default selected album.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder albumId(String albumId) {
        mSelectionSpec.setDefaultAlbumId(albumId);
        return this;
    }

    /**
     * Sets the Activity instead of PhotoSelectionActivity
     * @param photoSelectionActivityClass an Activity called on photo selecting
     * @return the specification builder context.
     */
    public SelectionSpecBuilder photoSelectionActivityClass(Class<? extends PhotoSelectionActivity> photoSelectionActivityClass) {
        mPhotoSelectionActivityClass = photoSelectionActivityClass;
        return this;
    }

    /**
     * Sets the Activity instead of ImagePreviewActivity
     *
     * @param previewActivityClass an Activity called on photo preview
     * @return the specification builder context.
     */
    public SelectionSpecBuilder previewActivityClass(Class<? extends ImagePreviewActivity> previewActivityClass) {
        mPreviewActivityClass = previewActivityClass;
        return this;
    }

    /**
     * Sets the default selection to resume photo picking activity.
     * @param uriList to set selected as default.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder resume(List<Uri> uriList) {
        if (uriList == null) { // nothing to do.
            return this;
        }
        mResumeList.addAll(uriList);
        return this;
    }

    /**
     * Determines whether opening NavigationDrawer on launch or not.
     * This flag is true by default.
     *
     * @param open whether to open drawer or not.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder openDrawer(boolean open) {
        mOpenDrawer = open;
        return this;
    }

    /**
     * Determines whether the photo capturing is enabled or not on the camera photo grid view.
     * This flag is false by default.
     *
     * @param fileProviderAuthorities your FileProvider authorities name.
     * @return the specification builder context.
     */
    public SelectionSpecBuilder enableCapture(String fileProviderAuthorities) {
        mFileProviderAuthorities = fileProviderAuthorities;
        return this;
    }

    /**
     * Determines whether the photo capturing is enabled or not on the camera photo grid view.
     * This flag is false by default.
     *
     * @return the specification builder context.
     */
    public SelectionSpecBuilder disableCapture() {
        mFileProviderAuthorities = null;
        return this;
    }

    public SelectionSpecBuilder restrictOrientation(int activityOrientation) {
        mActivityOrientation = activityOrientation;
        return this;
    }

    /**
     * Start to select photo.
     * @param requestCode identity of the requester activity.
     */
    public void forResult(int requestCode) {
        forResultWithTransition(requestCode, null);
    }

    /**
     * Start to select photo.
     *
     * @param requestCode identity of the requester activity.
     * @param view        transition source view
     */
    public void forResultWithTransition(int requestCode, View view) {
        Activity activity = mLaevatein.getActivity();
        if (activity == null) {
            return; // cannot continue;
        }

        mSelectionSpec.setMimeTypeSet(mMimeType);
        if (mActivityTheme == 0) {
            mActivityTheme = R.style.L_DefaultTheme;
        }

        ViewResourceSpec viewSpec = new ViewResourceSpec.Builder()
                .setTheme(mActivityTheme)
                .setPreviewClass(mPreviewActivityClass)
                .setItemViewResources(mItemViewResources)
                .setCounterViewResources(mCounterViewResources)
                .setPreviewViewResources(mPreviewViewResources)
                .setOpenDrawer(mOpenDrawer)
                .setCaptureResources(new CaptureResources(mFileProviderAuthorities))
                .setEnableSelectedView(mEnableSelectedView)
                .setActivityOrientation(mActivityOrientation)
                .create();
        ErrorViewSpec errorSpec = new ErrorViewSpec.Builder()
                .setCountUnderSpec(mCountUnderErrorSpec)
                .setCountOverSpec(mCountOverErrorSpec)
                .setOverQualitySpec(mOverQualityErrorSpec)
                .setUnderQualitySpec(mUnderQualityErrorSpec)
                .setOverSizeSpec(mOverSizeErrorSpec)
                .setUnderSizeSpec(mUnderSizeErrorSpec)
                .setTypeSpec(mTypeErrorSpec)
                .setConfirmSpec(mConfirmDialogSpec)
                .create();

        if (mPhotoSelectionActivityClass == null) {
            mPhotoSelectionActivityClass = PhotoSelectionActivity.class;
        }

        Intent intent = new Intent(activity, mPhotoSelectionActivityClass);
        intent.putExtra(PhotoSelectionActivity.EXTRA_VIEW_SPEC, viewSpec);
        intent.putExtra(PhotoSelectionActivity.EXTRA_ERROR_SPEC, errorSpec);
        intent.putExtra(PhotoSelectionActivity.EXTRA_SELECTION_SPEC, mSelectionSpec);
        intent.putParcelableArrayListExtra(PhotoSelectionActivity.EXTRA_RESUME_LIST, (ArrayList<? extends android.os.Parcelable>) mResumeList);

        Fragment fragment = mLaevatein.getFragment();
        if (fragment != null) {
            fragment.startActivityForResult(intent, requestCode);
        } else if (view != null) {
            ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
                    view, activity.getString(R.string.l_content_transition_name));
            ActivityCompat.startActivityForResult(activity, intent, requestCode, options.toBundle());
        } else {
            activity.startActivityForResult(intent, requestCode);
        }
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/Album.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.entity;

import com.laevatein.R;

import android.content.Context;
import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.MediaStore;

import androidx.annotation.Nullable;

/**
 * @author KeithYokoma
 * @since 2014/03/20
 * @version 1.0.0
 * @hide
 */
public class Album implements Parcelable {
    public static final Creator<Album> CREATOR = new Creator<Album>() {
        @Nullable
        @Override
        public Album createFromParcel(Parcel source) {
            return new Album(source);
        }

        @Override
        public Album[] newArray(int size) {
            return new Album[size];
        }
    };
    public static final String ALBUM_ID_ALL = String.valueOf(-1);
    public static final String ALBUM_NAME_ALL = "All";
    public static final String ALBUM_NAME_CAMERA = "Camera";
    public static final String ALBUM_NAME_DOWNLOAD = "Download";
    public static final String ALBUM_NAME_SCREEN_SHOT = "Screenshots";
    private final String mId;
    private final long mCoverId;
    private final String mDisplayName;

    /* package */ Album(String id, long coverId, String albumName) {
        mId = id;
        mCoverId = coverId;
        mDisplayName = albumName;
    }

    /* package */ Album(Parcel source) {
        mId = source.readString();
        mCoverId = source.readLong();
        mDisplayName = source.readString();
    }

    /**
     * Constructs a new {@link com.laevatein.internal.entity.Album} entity from the {@link android.database.Cursor}.
     * This method is not responsible for managing cursor resource, such as close, iterate, and so on.
     * @param cursor to be converted.
     * @return a new {@link com.laevatein.internal.entity.Album}.
     */
    public static Album valueOf(Cursor cursor) {
        return new Album(
                cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID)),
                cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID)),
                cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)));
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mId);
        dest.writeLong(mCoverId);
        dest.writeString(mDisplayName);
    }

    public String getId() {
        return mId;
    }

    public long getCoverId() {
        return mCoverId;
    }

    public String getDisplayName(Context context) {
        if (isAll()) {
            return context.getString(R.string.l_album_name_all);
        }
        if (isCamera()) {
            return context.getString(R.string.l_album_name_camera);
        }
        if (ALBUM_NAME_DOWNLOAD.equals(mDisplayName)) {
            return context.getString(R.string.l_album_name_download);
        }
        if (ALBUM_NAME_SCREEN_SHOT.equals(mDisplayName)) {
            return context.getString(R.string.l_album_name_screen_shot);
        }
        return mDisplayName;
    }

    public boolean isAll() {
        return ALBUM_ID_ALL.equals(mId);
    }

    public boolean isCamera() {
        return ALBUM_NAME_CAMERA.equals(mDisplayName);
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/CaptureResources.java
================================================
package com.laevatein.internal.entity;

import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Nullable;

public class CaptureResources implements Parcelable {

    public static final Creator<CaptureResources> CREATOR = new Creator<CaptureResources>() {
        @Override
        public CaptureResources createFromParcel(Parcel in) {
            return new CaptureResources(in);
        }

        @Override
        public CaptureResources[] newArray(int size) {
            return new CaptureResources[size];
        }
    };

    @Nullable
    private final String mFileProviderAuthorities;

    public CaptureResources(@Nullable String fileProviderAuthorities) {
        mFileProviderAuthorities = fileProviderAuthorities;
    }

    private CaptureResources(Parcel in) {
        mFileProviderAuthorities = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mFileProviderAuthorities);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public boolean enabled() {
        return mFileProviderAuthorities != null;
    }

    @Nullable
    public String getFileProviderAuthorities() {
        return mFileProviderAuthorities;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/CounterViewResources.java
================================================
package com.laevatein.internal.entity;

import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.IntDef;
import androidx.annotation.StringRes;

import com.laevatein.R;

/**
 * @author keishin.yokomaku
 * @since 2014/04/07
 */
public class CounterViewResources implements Parcelable {
    public static final Creator<CounterViewResources> CREATOR = new Creator<CounterViewResources>() {
        @Override
        public CounterViewResources createFromParcel(Parcel source) {
            return new CounterViewResources(source);
        }

        @Override
        public CounterViewResources[] newArray(int size) {
            return new CounterViewResources[size];
        }
    };


    @IntDef({LAYOUT_APP_BAR, LAYOUT_BOTTOM})
    public @interface VIEW_POSITION {
    }

    public static final int LAYOUT_APP_BAR = 1;
    public static final int LAYOUT_BOTTOM = 2;

    private static volatile CounterViewResources sDefault;
    @VIEW_POSITION
    private final int mViewPosition;
    @StringRes
    private final int mTextId;

    /* package */ CounterViewResources(Parcel source) {
        mViewPosition = readViewPosition(source);
        mTextId = source.readInt();
    }

    public CounterViewResources(@VIEW_POSITION int viewPosition, @StringRes int textId) {
        mViewPosition = viewPosition;
        mTextId = textId;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mViewPosition);
        dest.writeInt(mTextId);
    }

    @VIEW_POSITION
    public int getViewType() {
        return mViewPosition;
    }

    @StringRes
    public int getTextRes(){
        return mTextId;
    }

    public static CounterViewResources getDefault() {
        if (sDefault == null) {
            sDefault = new CounterViewResources(LAYOUT_BOTTOM, R.string.l_format_selection_count);
        }
        return sDefault;
    }

    @VIEW_POSITION
    private int readViewPosition(Parcel source) {
        int result = source.readInt();
        switch (result) {
            case LAYOUT_APP_BAR:
                return LAYOUT_APP_BAR;
            case LAYOUT_BOTTOM:
                return LAYOUT_BOTTOM;
            default:
                throw new IllegalArgumentException();
        }
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/DialogResources.java
================================================
package com.laevatein.internal.entity;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * @author hiroyuki.setp
 * @since 2017/01/11
 */
public class DialogResources implements Parcelable {
    public static final Creator<DialogResources> CREATOR = new Creator<DialogResources>() {
        @Override
        public DialogResources createFromParcel(Parcel source) {
            return new DialogResources(source);
        }

        @Override
        public DialogResources[] newArray(int size) {
            return new DialogResources[size];
        }
    };
    private final int mTitleId;
    private final int mMessageId;

    /* package */ DialogResources(Parcel source) {
        mTitleId = source.readInt();
        mMessageId = source.readInt();
    }

    public DialogResources(int messageId) {
        this(-1, messageId);
    }

    public DialogResources(int titleId, int messageId) {
        mTitleId = titleId;
        mMessageId = messageId;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mTitleId);
        dest.writeInt(mMessageId);
    }

    public int getTitleId() {
        return mTitleId;
    }

    public int getMessageId() {
        return mMessageId;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/ErrorViewResources.java
================================================
package com.laevatein.internal.entity;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * @author keishin.yokomaku
 * @since 2014/04/07
 */
public class ErrorViewResources implements Parcelable {
    public static final Creator<ErrorViewResources> CREATOR = new Creator<ErrorViewResources>() {
        @Override
        public ErrorViewResources createFromParcel(Parcel source) {
            return new ErrorViewResources(source);
        }

        @Override
        public ErrorViewResources[] newArray(int size) {
            return new ErrorViewResources[size];
        }
    };
    private final ViewType mViewType;
    private final int mTitleId;
    private final int mMessageId;

    /* package */ ErrorViewResources(Parcel source) {
        mViewType = (ViewType) source.readSerializable();
        mTitleId = source.readInt();
        mMessageId = source.readInt();
    }

    /* package */ ErrorViewResources(ViewType viewType, int messageId) {
        this(viewType, -1, messageId);
    }

    /* package */ ErrorViewResources(ViewType viewType, int titleId, int messageId) {
        mViewType = viewType;
        mTitleId = titleId;
        mMessageId = messageId;
    }

    /* package */ static ErrorViewResources asNoView() {
        return new ErrorViewResources(ViewType.NONE, 0);
    }

    /* package */ static ErrorViewResources asAlertDialog(int titleId, int messageId) {
        return new ErrorViewResources(ViewType.DIALOG, titleId, messageId);
    }

    /* package */  static ErrorViewResources asToast(int messageId) {
        return new ErrorViewResources(ViewType.TOAST, messageId);
    }

    /* package */  static ErrorViewResources asSnackbar(int messageId) {
        return new ErrorViewResources(ViewType.SNACKBAR, messageId);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeSerializable(mViewType);
        dest.writeInt(mTitleId);
        dest.writeInt(mMessageId);
    }

    public ViewType getViewType() {
        return mViewType;
    }

    public int getTitleId() {
        return mTitleId;
    }

    public int getMessageId() {
        return mMessageId;
    }

    public boolean isNoView() {
        return mViewType == ViewType.NONE;
    }

    public enum ViewType {
        TOAST {
            @Override
            public ErrorViewResources createSpec(int titleId, int messageId) {
                return ErrorViewResources.asToast(messageId);
            }
        },
        SNACKBAR {
            @Override
            public ErrorViewResources createSpec(int titleId, int messageId) {
                return ErrorViewResources.asSnackbar(messageId);
            }
        },
        DIALOG {
            @Override
            public ErrorViewResources createSpec(int titleId, int messageId) {
                return ErrorViewResources.asAlertDialog(titleId, messageId);
            }
        },
        NONE {
            @Override
            public ErrorViewResources createSpec(int titleId, int messageId) {
                return ErrorViewResources.asNoView();
            }
        };

        public abstract ErrorViewResources createSpec(int titleId, int messageId);
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/ErrorViewSpec.java
================================================
package com.laevatein.internal.entity;

import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Nullable;

import com.laevatein.R;

/**
 * @author Keithyokoma
 * @since 2014/04/07
 * @version 1.0.0
 * @hide
 */
public class ErrorViewSpec implements Parcelable {
    public static final Creator<ErrorViewSpec> CREATOR = new Creator<ErrorViewSpec>() {
        @Override
        @Nullable
        public ErrorViewSpec createFromParcel(Parcel source) {
            return new ErrorViewSpec(source);
        }

        @Override
        public ErrorViewSpec[] newArray(int size) {
            return new ErrorViewSpec[size];
        }
    };
    private final ErrorViewResources mCountUnderErrorSpec;
    private final ErrorViewResources mCountOverErrorSpec;
    private final ErrorViewResources mUnderQualitySpec;
    private final ErrorViewResources mOverQualitySpec;
    private final ErrorViewResources mUnderSizeSpec;
    private final ErrorViewResources mOverSizeSpec;
    private final ErrorViewResources mTypeErrorSpec;
    private final DialogResources mBackConfirmSpec;

    /* package */ ErrorViewSpec(Parcel source) {
        mCountUnderErrorSpec = source.readParcelable(ErrorViewResources.class.getClassLoader());
        mCountOverErrorSpec = source.readParcelable(ErrorViewResources.class.getClassLoader());
        mUnderQualitySpec = source.readParcelable(ErrorViewResources.class.getClassLoader());
        mOverQualitySpec = source.readParcelable(ErrorViewResources.class.getClassLoader());
        mUnderSizeSpec = source.readParcelable(ErrorViewResources.class.getClassLoader());
        mOverSizeSpec = source.readParcelable(ErrorViewResources.class.getClassLoader());
        mTypeErrorSpec = source.readParcelable(ErrorViewResources.class.getClassLoader());
        mBackConfirmSpec = source.readParcelable(DialogResources.class.getClassLoader());
    }

    /* package */ ErrorViewSpec(ErrorViewResources countUnderSpec, ErrorViewResources countOverSpec,
                                ErrorViewResources underQualitySpec, ErrorViewResources overQualitySpec,
                                ErrorViewResources underSizeSpec, ErrorViewResources overSizeSpec,
                                ErrorViewResources typeErrorSpec, DialogResources backConfirmSpec) {
        mCountUnderErrorSpec = countUnderSpec;
        mCountOverErrorSpec = countOverSpec;
        mUnderQualitySpec = underQualitySpec;
        mOverQualitySpec = overQualitySpec;
        mUnderSizeSpec = underSizeSpec;
        mOverSizeSpec = overSizeSpec;
        mTypeErrorSpec = typeErrorSpec;
        mBackConfirmSpec = backConfirmSpec;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(mCountUnderErrorSpec, flags);
        dest.writeParcelable(mCountOverErrorSpec, flags);
        dest.writeParcelable(mUnderQualitySpec, flags);
        dest.writeParcelable(mOverQualitySpec, flags);
        dest.writeParcelable(mUnderSizeSpec, flags);
        dest.writeParcelable(mOverSizeSpec, flags);
        dest.writeParcelable(mTypeErrorSpec, flags);
        dest.writeParcelable(mBackConfirmSpec, flags);
    }

    public ErrorViewResources getCountUnderErrorSpec() {
        return mCountUnderErrorSpec;
    }

    public ErrorViewResources getCountOverErrorSpec() {
        return mCountOverErrorSpec;
    }

    public ErrorViewResources getUnderQualitySpec() {
        return mUnderQualitySpec;
    }

    public ErrorViewResources getOverQualitySpec() {
        return mOverQualitySpec;
    }

    public ErrorViewResources getUnderSizeSpec() {
        return mUnderSizeSpec;
    }

    public ErrorViewResources getOverSizeSpec() {
        return mOverSizeSpec;
    }

    public ErrorViewResources getTypeErrorSpec() {
        return mTypeErrorSpec;
    }

    public DialogResources getBackConfirmSpec() {
        return mBackConfirmSpec;
    }

    public static class Builder {
        private ErrorViewResources mCountUnderSpec;
        private ErrorViewResources mCountOverSpec;
        private ErrorViewResources mUnderQualitySpec;
        private ErrorViewResources mOverQualitySpec;
        private ErrorViewResources mUnderSizeSpec;
        private ErrorViewResources mOverSizeSpec;
        private ErrorViewResources mTypeSpec;
        private DialogResources mBackSpec;

        public Builder setCountUnderSpec(ErrorViewResources spec) {
            mCountUnderSpec = spec;
            return this;
        }

        public Builder setCountOverSpec(ErrorViewResources spec) {
            mCountOverSpec = spec;
            return this;
        }

        public Builder setUnderQualitySpec(ErrorViewResources spec) {
            mUnderQualitySpec = spec;
            return this;
        }

        public Builder setOverQualitySpec(ErrorViewResources spec) {
            mOverQualitySpec = spec;
            return this;
        }

        public Builder setUnderSizeSpec(ErrorViewResources spec) {
            mUnderSizeSpec = spec;
            return this;
        }

        public Builder setOverSizeSpec(ErrorViewResources spec) {
            mOverSizeSpec = spec;
            return this;
        }

        public Builder setTypeSpec(ErrorViewResources spec) {
            mTypeSpec = spec;
            return this;
        }

        public Builder setConfirmSpec(DialogResources spec) {
            mBackSpec = spec;
            return this;
        }

        public ErrorViewSpec create() {
            if (mCountUnderSpec == null) {
                mCountUnderSpec = ErrorViewResources.ViewType.NONE.createSpec(0, 0);
            }
            if (mCountOverSpec == null) {
                mCountOverSpec = ErrorViewResources.ViewType.NONE.createSpec(0, 0);
            }
            if (mUnderQualitySpec == null) {
                mUnderQualitySpec = ErrorViewResources.ViewType.DIALOG.createSpec(-1, R.string.l_error_quality);
            }
            if (mOverQualitySpec == null) {
                mOverQualitySpec = ErrorViewResources.ViewType.DIALOG.createSpec(-1, R.string.l_error_quality);
            }
            if (mUnderSizeSpec == null) {
                mUnderSizeSpec = ErrorViewResources.ViewType.DIALOG.createSpec(-1, R.string.l_error_size);
            }
            if (mOverSizeSpec == null) {
                mOverSizeSpec = ErrorViewResources.ViewType.DIALOG.createSpec(-1, R.string.l_error_size);
            }
            if (mTypeSpec == null) {
                mTypeSpec = ErrorViewResources.ViewType.DIALOG.createSpec(-1, R.string.l_error_invalid_format);
            }
            if (mBackSpec == null) {
                mBackSpec = new DialogResources(R.string.l_confirm_dialog_title, R.string.l_confirm_dialog_message);
            }
            return new ErrorViewSpec(mCountUnderSpec, mCountOverSpec, mUnderQualitySpec,
                    mOverQualitySpec, mUnderSizeSpec, mOverSizeSpec, mTypeSpec, mBackSpec);
        }
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/Item.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.entity;

import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.MediaStore;

import androidx.annotation.Nullable;

/**
 * @author KeithYokoma
 * @since 2014/03/24
 * @version 1.0.0
 * @hide
 */
public class Item implements Parcelable {
    public static final Creator<Item> CREATOR = new Creator<Item>() {
        @Override
        @Nullable
        public Item createFromParcel(Parcel source) {
            return new Item(source);
        }

        @Override
        public Item[] newArray(int size) {
            return new Item[size];
        }
    };
    public static final long ITEM_ID_CAPTURE = -1;
    public static final String ITEM_DISPLAY_NAME_CAPTURE = "Capture";
    private final long mId;

    /* package */ Item(long id) {
        mId = id;
    }

    /* package */ Item(Parcel source) {
        mId = source.readLong();
    }

    public static Item valueOf(Cursor cursor) {
        return new Item(cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID)));
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(mId);
    }

    public long getId() {
        return mId;
    }

    public Uri buildContentUri() {
        return ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mId);
    }

    public boolean isCapture() {
        return mId == ITEM_ID_CAPTURE;
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/ItemViewResources.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.entity;

import android.os.Parcel;
import android.os.Parcelable;

import com.laevatein.R;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/20
 */
public final class ItemViewResources implements Parcelable {
    private static final int DEFAULT_SPAN_COUNT = 4;
    public static final Creator<ItemViewResources> CREATOR = new Creator<ItemViewResources>() {
        @Override
        public ItemViewResources createFromParcel(Parcel source) {
            return new ItemViewResources(source);
        }

        @Override
        public ItemViewResources[] newArray(int size) {
            return new ItemViewResources[size];
        }
    };
    private static volatile ItemViewResources sDefault;
    private final int mLayoutId;
    private final int mImageViewId;
    private final int mCheckBoxId;
    private final int mSpanCount;

    public ItemViewResources(int layoutId, int imageViewId, int checkBoxId, int spanCount) {
        mLayoutId = layoutId;
        mImageViewId = imageViewId;
        mCheckBoxId = checkBoxId;
        mSpanCount = spanCount;
    }

    /* package */ ItemViewResources(Parcel source) {
        mLayoutId = source.readInt();
        mImageViewId = source.readInt();
        mCheckBoxId = source.readInt();
        mSpanCount = source.readInt();
    }

    public static ItemViewResources getDefault() {
        if (sDefault == null) {
            sDefault = new ItemViewResources(R.layout.l_grid_item_default_photo, R.id.l_default_grid_image, R.id.l_default_check_box, DEFAULT_SPAN_COUNT);
        }
        return sDefault;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mLayoutId);
        dest.writeInt(mImageViewId);
        dest.writeInt(mCheckBoxId);
        dest.writeInt(mSpanCount);
    }

    public int getLayoutId() {
        return mLayoutId;
    }

    public int getImageViewId() {
        return mImageViewId;
    }

    public int getCheckBoxId() {
        return mCheckBoxId;
    }

    public int getSpanCount() {
        return mSpanCount;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/PreviewViewResources.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.entity;

import android.os.Parcel;
import android.os.Parcelable;

import com.laevatein.R;

/**
 * @author HiroyukiSeto
 * @version 2.0.0
 * @hide
 * @since 2016/11/25
 */
public final class PreviewViewResources implements Parcelable {
    public static final Creator<PreviewViewResources> CREATOR = new Creator<PreviewViewResources>() {
        @Override
        public PreviewViewResources createFromParcel(Parcel source) {
            return new PreviewViewResources(source);
        }

        @Override
        public PreviewViewResources[] newArray(int size) {
            return new PreviewViewResources[size];
        }
    };
    private static volatile PreviewViewResources sDefault;
    private final int mLayoutId;
    private final int mImageViewId;

    public PreviewViewResources(int layoutId, int imageViewId) {
        mLayoutId = layoutId;
        mImageViewId = imageViewId;
    }

    /* package */ PreviewViewResources(Parcel source) {
        mLayoutId = source.readInt();
        mImageViewId = source.readInt();
    }

    public static PreviewViewResources getDefault() {
        if (sDefault == null) {
            sDefault = new PreviewViewResources(R.layout.l_fragment_default_preview, R.id.l_default_image_zoom_view);
        }
        return sDefault;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mLayoutId);
        dest.writeInt(mImageViewId);
    }

    public int getLayoutId() {
        return mLayoutId;
    }

    public int getImageViewId() {
        return mImageViewId;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/SelectionSpec.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.entity;

import android.os.Parcel;
import android.os.Parcelable;

import com.laevatein.MimeType;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

/**
 * @author KeithYokoma
 * @since 2014/03/20
 * @version 1.0.0
 * @hide
 */
public final class SelectionSpec implements Parcelable {
    public static final Creator<SelectionSpec> CREATOR = new Creator<SelectionSpec>() {
        @Override
        public SelectionSpec createFromParcel(Parcel source) {
            return new SelectionSpec(source);
        }

        @Override
        public SelectionSpec[] newArray(int size) {
            return new SelectionSpec[size];
        }
    };
    private int mMaxSelectable;
    private int mMinSelectable;
    private long mMinPixels;
    private long mMaxPixels;
    private int mMinWidthPixels;
    private int mMinHeightPixels;
    private int mMaxWidthPixels;
    private int mMaxHeightPixels;
    private Set<MimeType> mMimeTypeSet;
    private String mDefaultAlbumId;

    public SelectionSpec() {
        mMinSelectable = 0;
        mMaxSelectable = 1;
        mMinPixels = 0L;
        mMaxPixels = Long.MAX_VALUE;
        mMinWidthPixels = 0;
        mMinHeightPixels = 0;
        mMaxWidthPixels = Integer.MAX_VALUE;
        mMaxHeightPixels = Integer.MAX_VALUE;
        mDefaultAlbumId = Album.ALBUM_ID_ALL;
    }

    /* package */ SelectionSpec(Parcel source) {
        mMinSelectable = source.readInt();
        mMaxSelectable = source.readInt();
        mMinPixels = source.readLong();
        mMaxPixels = source.readLong();
        mMinWidthPixels = source.readInt();
        mMinHeightPixels = source.readInt();
        mMaxWidthPixels = source.readInt();
        mMaxHeightPixels = source.readInt();
        List<MimeType> list = new ArrayList<>();
        source.readList(list, MimeType.class.getClassLoader());
        mMimeTypeSet = EnumSet.copyOf(list);
        mDefaultAlbumId = source.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mMinSelectable);
        dest.writeInt(mMaxSelectable);
        dest.writeLong(mMinPixels);
        dest.writeLong(mMaxPixels);
        dest.writeInt(mMinWidthPixels);
        dest.writeInt(mMinHeightPixels);
        dest.writeInt(mMaxWidthPixels);
        dest.writeInt(mMaxHeightPixels);
        dest.writeList(new ArrayList<>(mMimeTypeSet));
        dest.writeString(mDefaultAlbumId);
    }

    public void setMaxSelectable(int maxSelectable) {
        mMaxSelectable = maxSelectable;
    }

    public void setMinSelectable(int minSelectable) {
        mMinSelectable = minSelectable;
    }

    public void setMinPixels(long minPixels) {
        mMinPixels = minPixels;
    }

    public void setMaxPixels(long maxPixels) {
        mMaxPixels = maxPixels;
    }

    public void setMinSize(int minWidthPixels, int minHeightPixels) {
        this.mMinWidthPixels = minWidthPixels;
        this.mMinHeightPixels = minHeightPixels;
    }

    public void setMaxSize(int maxWidthPixels, int maxHeightPixels) {
        this.mMaxWidthPixels = maxWidthPixels;
        this.mMaxHeightPixels = maxHeightPixels;
    }

    public void setMimeTypeSet(Set<MimeType> set) {
        mMimeTypeSet = set;
    }

    public void setDefaultAlbumId(String albumId) {
        mDefaultAlbumId = albumId;
    }

    public int getMinSelectable() {
        return mMinSelectable;
    }

    public int getMaxSelectable() {
        return mMaxSelectable;
    }

    public long getMinPixels() {
        return mMinPixels;
    }

    public long getMaxPixels() {
        return mMaxPixels;
    }

    public int getMinWidthPixels() {
        return mMinWidthPixels;
    }

    public int getMinHeightPixels() {
        return mMinHeightPixels;
    }

    public int getMaxWidthPixels() {
        return mMaxWidthPixels;
    }

    public int getMaxHeightPixels() {
        return mMaxHeightPixels;
    }

    public Set<MimeType> getMimeTypeSet() {
        return mMimeTypeSet;
    }

    public String getDefaultAlbumId() {
        return mDefaultAlbumId;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/UncapableCause.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.entity;

/**
 * @author KeithYokoma
 * @since 2014/03/25
 * @version 1.0.0
 * @hide
 */
public enum UncapableCause {
    OVER_COUNT {
        @Override
        public ErrorViewResources getErrorResources(ErrorViewSpec spec) {
            return spec.getCountOverErrorSpec();
        }
    },
    UNDER_QUALITY {
        @Override
        public ErrorViewResources getErrorResources(ErrorViewSpec spec) {
            return spec.getUnderQualitySpec();
        }
    },
    OVER_QUALITY {
        @Override
        public ErrorViewResources getErrorResources(ErrorViewSpec spec) {
            return spec.getOverQualitySpec();
        }
    },
    UNDER_SIZE {
        @Override
        public ErrorViewResources getErrorResources(ErrorViewSpec spec) {
            return spec.getUnderSizeSpec();
        }
    },
    OVER_SIZE {
        @Override
        public ErrorViewResources getErrorResources(ErrorViewSpec spec) {
            return spec.getOverSizeSpec();
        }
    },
    FILE_TYPE {
        @Override
        public ErrorViewResources getErrorResources(ErrorViewSpec spec) {
            return spec.getTypeErrorSpec();
        }
    };

    public abstract ErrorViewResources getErrorResources(ErrorViewSpec spec);
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/entity/ViewResourceSpec.java
================================================
package com.laevatein.internal.entity;

import android.content.pm.ActivityInfo;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;

import com.amalgam.os.ParcelUtils;
import com.laevatein.ui.ImagePreviewActivity;

/**
 * @author keishin.yokomaku
 * @since 2014/04/07
 */
public class ViewResourceSpec implements Parcelable {
    public static final Creator<ViewResourceSpec> CREATOR = new Creator<ViewResourceSpec>() {
        @Override
        @Nullable
        public ViewResourceSpec createFromParcel(Parcel source) {
            return new ViewResourceSpec(source);
        }

        @Override
        public ViewResourceSpec[] newArray(int size) {
            return new ViewResourceSpec[size];
        }
    };
    public static final int DEFAULT_SCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; // no restriction
    @StyleRes
    private int mTheme;
    private final Class<? extends ImagePreviewActivity> mPreviewActivityClass;
    private final ItemViewResources mItemViewResources;
    private final CounterViewResources mCounterViewResources;
    private final PreviewViewResources mPreviewViewResources;
    private final boolean mOpenDrawer;
    private final CaptureResources mCaptureResources;
    private final boolean mEnableSelectedView;
    private final int mActivityOrientation;

    /* package */ ViewResourceSpec(Parcel source) {
        mTheme = source.readInt();
        mPreviewActivityClass = (Class<? extends ImagePreviewActivity>) source.readSerializable();
        mItemViewResources = source.readParcelable(ItemViewResources.class.getClassLoader());
        mCounterViewResources = source.readParcelable(CounterViewResources.class.getClassLoader());
        mPreviewViewResources = source.readParcelable(PreviewViewResources.class.getClassLoader());
        mOpenDrawer = ParcelUtils.readBoolean(source);
        mCaptureResources = source.readParcelable(CaptureResources.class.getClassLoader());
        mEnableSelectedView = ParcelUtils.readBoolean(source);
        mActivityOrientation = source.readInt();
    }

    /* package */ ViewResourceSpec(
            @StyleRes int theme,
            Class<? extends ImagePreviewActivity> previewActivityClass,
            ItemViewResources itemViewResources,
            CounterViewResources counterViewResources,
            PreviewViewResources previewViewResources,
            boolean openDrawer,
            CaptureResources captureResources,
            boolean enableSelectedView,
            int activityOrientation) {
        mTheme = theme;
        mPreviewActivityClass = previewActivityClass;
        mItemViewResources = itemViewResources;
        mCounterViewResources = counterViewResources;
        mPreviewViewResources = previewViewResources;
        mOpenDrawer = openDrawer;
        mCaptureResources = captureResources;
        mEnableSelectedView = enableSelectedView;
        mActivityOrientation = activityOrientation;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mTheme);
        dest.writeSerializable(mPreviewActivityClass);
        dest.writeParcelable(mItemViewResources, flags);
        dest.writeParcelable(mCounterViewResources, flags);
        dest.writeParcelable(mPreviewViewResources, flags);
        ParcelUtils.writeBoolean(dest, mOpenDrawer);
        dest.writeParcelable(mCaptureResources, flags);
        ParcelUtils.writeBoolean(dest, mEnableSelectedView);
        dest.writeInt(mActivityOrientation);
    }

    public static class Builder {
        @StyleRes
        private int mTheme;
        private Class<? extends ImagePreviewActivity> mPreviewActivityClass;
        private ItemViewResources mItemViewResources;
        private CounterViewResources mCounterViewResources;
        private PreviewViewResources mPreviewViewResources;
        private boolean mOpenDrawer;
        private CaptureResources mCaptureResources;
        private boolean mEnableSelectedView;
        private int mActivityOrientation;

        public Builder setTheme(@StyleRes int theme) {
            mTheme = theme;
            return this;
        }

        public Builder setPreviewClass(Class<? extends ImagePreviewActivity> previewActivityClass) {
            mPreviewActivityClass = previewActivityClass;
            return this;
        }

        public Builder setItemViewResources(ItemViewResources itemViewResources) {
            mItemViewResources = itemViewResources;
            return this;
        }

        public Builder setCounterViewResources(CounterViewResources counterViewResources) {
            mCounterViewResources = counterViewResources;
            return this;
        }

        public Builder setPreviewViewResources(PreviewViewResources previewViewResources) {
            mPreviewViewResources = previewViewResources;
            return this;
        }

        public Builder setOpenDrawer(boolean openDrawer) {
            mOpenDrawer = openDrawer;
            return this;
        }

        public Builder setCaptureResources(CaptureResources captureResources) {
            mCaptureResources = captureResources;
            return this;
        }

        public Builder setEnableSelectedView(boolean enableSelectedView) {
            mEnableSelectedView = enableSelectedView;
            return this;
        }

        public Builder setActivityOrientation(int activityOrientation) {
            mActivityOrientation = activityOrientation;
            return this;
        }

        public ViewResourceSpec create() {
            if (mItemViewResources == null) {
                mItemViewResources = ItemViewResources.getDefault();
            }
            if (mCounterViewResources == null) {
                mCounterViewResources = CounterViewResources.getDefault();
            }
            if (mPreviewViewResources == null) {
                mPreviewViewResources = PreviewViewResources.getDefault();
            }
            return new ViewResourceSpec(mTheme, mPreviewActivityClass,
                    mItemViewResources, mCounterViewResources, mPreviewViewResources, mOpenDrawer,
                    mCaptureResources, mEnableSelectedView, mActivityOrientation);
        }
    }

    public int getTheme() {
        return mTheme;
    }

    public Class<? extends ImagePreviewActivity> getPreviewActivityClass() {
        return mPreviewActivityClass;
    }

    public ItemViewResources getItemViewResources() {
        return mItemViewResources;
    }

    public CounterViewResources getCounterViewResources() {
        return mCounterViewResources;
    }

    public PreviewViewResources getPreviewViewResources() {
        return mPreviewViewResources;
    }

    public boolean openDrawer() {
        return mOpenDrawer;
    }

    public CaptureResources getCaptureResource() {
        return mCaptureResources;
    }

    public boolean isEnableSelectedView() {
        return mEnableSelectedView;
    }

    public boolean needActivityOrientationRestriction() {
        return mActivityOrientation != DEFAULT_SCREEN_ORIENTATION;
    }

    public int getActivityOrientation() {
        return mActivityOrientation;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/loader/AlbumLoader.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.loader;

import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.provider.MediaStore;

import androidx.loader.content.CursorLoader;

import com.laevatein.internal.entity.Album;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Wrapper for {@link CursorLoader} to merge custom cursors.
 * @author KeithYokoma
 * @since 2014/03/26
 * @version 1.0.0
 * @hide
 */
public class AlbumLoader extends CursorLoader {
    public static final String TAG = AlbumLoader.class.getSimpleName();
    private static final String[] PROJECTION = { MediaStore.Images.Media.BUCKET_ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media._ID };
    private static final String BUCKET_ORDER_BY = "datetaken DESC";
    private static final String MEDIA_ID_DUMMY = String.valueOf(-1);

    public AlbumLoader(Context context) {
        super(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION, null, null, BUCKET_ORDER_BY);
    }

    @Override
    public Cursor loadInBackground() {
        Cursor albums = super.loadInBackground();

        Map<String, BucketEntry> buckets = new LinkedHashMap<>();
        if (albums != null) {
            try {
                while (albums.moveToNext()) {
                    String bucketId = albums.getString(albums.getColumnIndex(MediaStore.Images.Media.BUCKET_ID));
                    if (!buckets.containsKey(bucketId)) {
                        buckets.put(bucketId, new BucketEntry(
                                albums.getString(albums.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)),
                                albums.getString(albums.getColumnIndex(MediaStore.Images.Media._ID))
                        ));
                    }
                }
            } finally {
                albums.close();
            }
        }

        MatrixCursor allAlbum = new MatrixCursor(PROJECTION);
        allAlbum.addRow(new String[]{Album.ALBUM_ID_ALL, Album.ALBUM_NAME_ALL, MEDIA_ID_DUMMY});
        for (Map.Entry<String, BucketEntry> entry : buckets.entrySet()) {
            BucketEntry bucket = entry.getValue();
            allAlbum.addRow(new String[]{entry.getKey(), bucket.displayName, bucket.mediaId});
        }

        return allAlbum;
    }

    private static class BucketEntry {
        private final String displayName;
        private final String mediaId;

        public BucketEntry(String displayName, String mediaId) {
            this.displayName = displayName;
            this.mediaId = mediaId;
        }
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/loader/AlbumPhotoLoader.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.loader;

import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import android.net.Uri;
import android.provider.MediaStore;
import androidx.loader.content.CursorLoader;

import com.laevatein.internal.entity.Album;
import com.laevatein.internal.entity.Item;
import com.laevatein.internal.utils.MediaStoreUtils;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/27
 */
public class AlbumPhotoLoader extends CursorLoader {
    public static final String TAG = AlbumPhotoLoader.class.getSimpleName();
    private static final String[] PROJECTION = {MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME};
    private static final String ORDER_BY = MediaStore.Images.Media._ID + " DESC";
    private final boolean mEnableCapture;

    public AlbumPhotoLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, boolean capture) {
        super(context, uri, projection, selection, selectionArgs, sortOrder);
        mEnableCapture = capture;
    }

    public static CursorLoader newInstance(Context context, Album album) {
        if (album.isAll()) {
            return new AlbumPhotoLoader(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION, null, null, ORDER_BY, false);
        }
        return newInstance(context, album, false);
    }

    public static CursorLoader newInstance(Context context, Album album, boolean capture) {
        return new AlbumPhotoLoader(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION,
                MediaStore.Images.Media.BUCKET_ID + " = ?", new String[]{album.getId()}, ORDER_BY, capture);
    }

    @Override
    public Cursor loadInBackground() {
        Cursor result = super.loadInBackground();
        if (!mEnableCapture || !MediaStoreUtils.hasCameraFeature(getContext())) {
            return result;
        }
        MatrixCursor dummy = new MatrixCursor(PROJECTION);
        dummy.addRow(new Object[]{Item.ITEM_ID_CAPTURE, Item.ITEM_DISPLAY_NAME_CAPTURE});
        return new MergeCursor(new Cursor[]{dummy, result});
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/misc/ui/ConfirmationDialogFragment.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.misc.ui;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;

import com.amalgam.os.BundleUtils;
import com.laevatein.R;

/**
 * @author KeithYokoma
 * @since 2014/03/25
 * @version 1.0.0
 * @hide
 */
public class ConfirmationDialogFragment extends DialogFragment {
    public static final String TAG = ConfirmationDialogFragment.class.getSimpleName();
    private static final String ARGS_TITLE = BundleUtils.buildKey(ConfirmationDialogFragment.class, "ARGS_TITLE");
    private static final String ARGS_MESSAGE = BundleUtils.buildKey(ConfirmationDialogFragment.class, "ARGS_MESSAGE");
    private ConfirmationSelectionListener mListener;

    public ConfirmationDialogFragment() {}

    public static ConfirmationDialogFragment newInstance(int message) {
        ConfirmationDialogFragment fragment = new ConfirmationDialogFragment();
        Bundle args = new Bundle();
        args.putInt(ARGS_MESSAGE, message);
        fragment.setArguments(args);
        return fragment;
    }

    public static ConfirmationDialogFragment newInstance(int title, int message) {
        ConfirmationDialogFragment fragment = new ConfirmationDialogFragment();
        Bundle args = new Bundle();
        args.putInt(ARGS_TITLE, title);
        args.putInt(ARGS_MESSAGE, message);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        try {
            mListener = (ConfirmationSelectionListener) context;
        } catch (ClassCastException e) {
            throw new IllegalArgumentException("the host activity should implement ConfirmationSelectionListener");
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        int title = getArguments().getInt(ARGS_TITLE, -1);
        if (title == -1) {
            title = R.string.l_confirm_dialog_title;
        }
        int message = getArguments().getInt(ARGS_MESSAGE);
        AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity())
                .setTitle(title)
                .setMessage(message)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mListener.onPositive();
                        dialog.dismiss();
                    }
                })
                .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mListener.onNegative();
                        dialog.dismiss();
                    }
                });
        return dialog.create();
    }

    public interface ConfirmationSelectionListener {
        void onPositive();
        void onNegative();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/misc/ui/FragmentUtils.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.misc.ui;

import android.app.Activity;
import android.content.Intent;
import android.os.Parcelable;
import androidx.fragment.app.Fragment;
import android.view.View;

/**
 * @author KeithYokoma
 * @since 2014/03/20
 * @version 1.0.0
 * @hide
 */
public final class FragmentUtils {
    private FragmentUtils() {}

    public static <T extends Parcelable> T getIntentParcelableExtra(Fragment fragment, String key) {
        Activity activity = fragment.getActivity();
        Intent intent = activity.getIntent();
        return intent.getParcelableExtra(key);
    }

    public static boolean getIntentBooleanExtra(Fragment fragment, String key, boolean fallback) {
        Activity activity = fragment.getActivity();
        Intent intent = activity.getIntent();
        return intent.getBooleanExtra(key, fallback);
    }

    public static View findViewById(Fragment fragment, int id) {
        View view = fragment.getView().findViewById(id);
        if(view == null){
            view = fragment.getView();
        }
        return view;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/misc/ui/helper/options/OptionsMenu.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.misc.ui.helper.options;

import android.app.Activity;

/**
 * @author KeithYokoma
 * @since 2014/03/20
 * @version 1.0.0
 * @hide
 */
public interface OptionsMenu<A extends Activity, H extends OptionsMenuHandler<A, ?>> {
    int getMenuId();
    H getHandler();
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/misc/ui/helper/options/OptionsMenuHandler.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.misc.ui.helper.options;

import android.app.Activity;

/**
 * @author KeithYokoma
 * @since 2014/03/20
 * @version 1.0.0
 * @hide
 */
public interface OptionsMenuHandler<A extends Activity, E> {
    boolean handle(A activity, E extra);
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/misc/widget/SquareGridViewItemRelativeLayout.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.misc.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

/**
 * @author KeithYokoma
 * @since 2014/03/24
 * @version 1.0.0
 * @hide
 */
public class SquareGridViewItemRelativeLayout extends RelativeLayout {
    public SquareGridViewItemRelativeLayout(Context context) {
        this(context, null);
    }

    public SquareGridViewItemRelativeLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SquareGridViewItemRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/model/AlbumPhotoCollection.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.model;

import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;

import com.amalgam.os.BundleUtils;
import com.laevatein.internal.entity.Album;
import com.laevatein.internal.loader.AlbumPhotoLoader;

import java.lang.ref.WeakReference;

/**
 * @author KeithYokoma
 * @since 2014/03/24
 * @version 1.0.0
 * @hide
 */
public class AlbumPhotoCollection implements LoaderManager.LoaderCallbacks<Cursor> {
    private static final int LOADER_ID = 2;
    private static final String ARGS_ALBUM = BundleUtils.buildKey(AlbumPhotoCollection.class, "ARGS_ALBUM");
    private static final String ARGS_ENABLE_CAPTURE = BundleUtils.buildKey(AlbumPhotoCollection.class, "ARGS_ENABLE_CAPTURE");
    private WeakReference<Context> mContext;
    private LoaderManager mLoaderManager;
    private AlbumPhotoCallbacks mCallbacks;

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Context context = mContext.get();
        if (context == null) {
            return null;
        }

        Album album = args.getParcelable(ARGS_ALBUM);
        if (album == null) {
            return null;
        }

        if (album.isCamera()) {
            boolean capture = args.getBoolean(ARGS_ENABLE_CAPTURE, false);
            return AlbumPhotoLoader.newInstance(context, album, capture);
        }
        return AlbumPhotoLoader.newInstance(context, album);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        Context context = mContext.get();
        if (context == null) {
            return;
        }

        mCallbacks.onLoad(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        Context context = mContext.get();
        if (context == null) {
            return;
        }

        mCallbacks.onReset();
    }

    public void onCreate(@NonNull FragmentActivity context, @NonNull AlbumPhotoCallbacks callbacks) {
        mContext = new WeakReference<Context>(context);
        mLoaderManager = context.getSupportLoaderManager();
        mCallbacks = callbacks;
    }

    public void onDestroy() {
        mLoaderManager.destroyLoader(LOADER_ID);
        mCallbacks = null;
    }

    public void load(@Nullable Album target) {
        load(target, false);
    }

    public void load(@Nullable Album target, boolean enableCapture) {
        Bundle args = new Bundle();
        args.putParcelable(ARGS_ALBUM, target);
        args.putBoolean(ARGS_ENABLE_CAPTURE, enableCapture);
        mLoaderManager.initLoader(LOADER_ID, args, this);
    }

    public interface AlbumPhotoCallbacks {
        void onLoad(Cursor cursor);
        void onReset();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/model/DevicePhotoAlbumCollection.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.model;

import com.amalgam.os.BundleUtils;
import com.laevatein.internal.loader.AlbumLoader;

import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;

import java.lang.ref.WeakReference;

/**
 * @author KeithYokoma
 * @since 2014/03/24
 * @version 1.0.0
 * @hide
 */
public class DevicePhotoAlbumCollection implements LoaderManager.LoaderCallbacks<Cursor> {
    private static final int LOADER_ID = 1;
    private static final String STATE_CURRENT_SELECTION = BundleUtils.buildKey(DevicePhotoAlbumCollection.class, "STATE_CURRENT_SELECTION");
    private WeakReference<Context> mContext;
    private LoaderManager mLoaderManager;
    private DevicePhotoAlbumCallbacks mCallbacks;
    private int mCurrentSelection;

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Context context = mContext.get();
        if (context == null) {
            return null;
        }
        return new AlbumLoader(context);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        Context context = mContext.get();
        if (context == null) {
            return;
        }

        mCallbacks.onLoad(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        Context context = mContext.get();
        if (context == null) {
            return;
        }

        mCallbacks.onReset();
    }

    public void onCreate(FragmentActivity activity, DevicePhotoAlbumCallbacks callbacks) {
        mContext = new WeakReference<Context>(activity);
        mLoaderManager = activity.getSupportLoaderManager();
        mCallbacks = callbacks;
    }

    public void onRestoreInstanceState(Bundle savedInstanceState) {
        if (savedInstanceState == null) {
            return;
        }

        mCurrentSelection = savedInstanceState.getInt(STATE_CURRENT_SELECTION);
    }

    public void onSaveInstanceState(Bundle outState) {
        outState.putInt(STATE_CURRENT_SELECTION, mCurrentSelection);
    }

    public void onDestroy() {
        mLoaderManager.destroyLoader(LOADER_ID);
        mCallbacks = null;
    }

    public void loadAlbums() {
        mLoaderManager.initLoader(LOADER_ID, null, this);
    }

    public int getCurrentSelection() {
        return mCurrentSelection;
    }

    public void setStateCurrentSelection(int currentSelection) {
        mCurrentSelection = currentSelection;
    }

    public interface DevicePhotoAlbumCallbacks {
        void onLoad(Cursor cursor);
        void onReset();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/model/PreviewStateHolder.java
================================================
package com.laevatein.internal.model;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;

import com.amalgam.os.BundleUtils;
import com.laevatein.ui.ImagePreviewActivity;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * @author keishin.yokomaku
 * @since 2014/04/03
 */
public class PreviewStateHolder {
    private static final String STATE_CHECKED = BundleUtils.buildKey(PreviewStateHolder.class, "STATE_CHECKED");
    private ArrayList<Uri> mChecked;
    private WeakReference<Activity> mContext;

    public PreviewStateHolder(Activity activity) {
        mContext = new WeakReference<>(activity);
    }

    public void onCreate() {
        Activity activity = mContext.get();
        if (activity == null) {
            return;
        }
        mChecked = activity.getIntent().getParcelableArrayListExtra(ImagePreviewActivity.EXTRA_DEFAULT_CHECKED);
    }

    public void onRestoreInstanceState(Bundle savedInstanceState) {
        if (savedInstanceState == null) {
            return;
        }
        mChecked = savedInstanceState.getParcelableArrayList(STATE_CHECKED);
    }

    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelableArrayList(STATE_CHECKED, mChecked);
    }

    public boolean isChecked(Uri uri) {
        return mChecked.contains(uri);
    }

    public void setChecked(Uri uri, boolean checked) {
        if (checked && !mChecked.contains(uri)) {
            mChecked.add(uri);
        } else if (!checked) {
            mChecked.remove(uri);
        }
    }

    public int getCheckedCount() {
        return mChecked.size();
    }

    public List<Uri> getAllChecked() {
        return new ArrayList<>(mChecked);
    }

}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/model/SelectedUriCollection.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.model;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;

import com.amalgam.os.BundleUtils;
import com.laevatein.internal.entity.SelectionSpec;
import com.laevatein.internal.entity.UncapableCause;
import com.laevatein.internal.utils.PhotoMetadataUtils;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/20
 */
public class SelectedUriCollection {
    private static final String STATE_SELECTION = BundleUtils.buildKey(SelectedUriCollection.class, "STATE_SELECTION");
    private final WeakReference<Context> mContext;
    private Set<Uri> mUris;
    private SelectionSpec mSpec;

    public SelectedUriCollection(Context context) {
        mContext = new WeakReference<>(context);
    }

    public void onCreate(Bundle savedInstanceState) {
        if (savedInstanceState == null) {
            mUris = new LinkedHashSet<>();
        } else {
            List<Uri> saved = savedInstanceState.getParcelableArrayList(STATE_SELECTION);
            mUris = new LinkedHashSet<>(saved);
        }
    }

    public void prepareSelectionSpec(SelectionSpec spec) {
        mSpec = spec;
    }

    public void setDefaultSelection(List<Uri> uris) {
        mUris.addAll(uris);
    }

    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelableArrayList(STATE_SELECTION, new ArrayList<>(mUris));
    }

    public boolean add(Uri uri) {
        return mUris.add(uri);
    }

    public boolean remove(Uri uri) {
        return mUris.remove(uri);
    }

    public void overwrite(ArrayList<Uri> uriLists) {
        mUris.clear();
        mUris.addAll(uriLists);
    }

    public List<Uri> asList() {
        return new ArrayList<>(mUris);
    }

    public boolean isEmpty() {
        return mUris == null || mUris.isEmpty();
    }

    public boolean isSelected(Uri uri) {
        return mUris.contains(uri);
    }

    public UncapableCause isAcceptable(Uri uri) {
        return PhotoMetadataUtils.isAcceptable(mContext.get(), mSpec, uri);
    }

    public boolean isCountInRange() {
        return mSpec.getMinSelectable() <= mUris.size() && !isCountOver();
    }

    public boolean isCountOver() {
        return mUris.size() > mSpec.getMaxSelectable();
    }

    public int count() {
        return mUris.size();
    }

    public int maxCount() {
        return mSpec.getMaxSelectable();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/package-info.java
================================================
/**
 * This package contains various internal-use classes.
 * @author KeithYokoma
 * @since 2014/03/20
 * @version 1.0.0
 * @hide
 */
package com.laevatein.internal;

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/AlbumListFragment.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui;

import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;

import com.amalgam.os.BundleUtils;
import com.laevatein.R;
import com.laevatein.internal.entity.Album;
import com.laevatein.internal.misc.ui.FragmentUtils;
import com.laevatein.internal.model.DevicePhotoAlbumCollection;
import com.laevatein.internal.ui.helper.AlbumListViewHelper;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/20
 */
public class AlbumListFragment extends Fragment implements
        AdapterView.OnItemClickListener,
        DevicePhotoAlbumCollection.DevicePhotoAlbumCallbacks {
    private static final String ARGS_ALBUM_ID = BundleUtils.buildKey(AlbumListFragment.class, "ARGS_ALBUM_ID");

    private final DevicePhotoAlbumCollection mCollection = new DevicePhotoAlbumCollection();
    private OnDirectorySelectListener mListener;
    private String defaultAlbum;

    public static AlbumListFragment newInstance(String defaultAlbumId) {
        AlbumListFragment fragment = new AlbumListFragment();
        Bundle args = new Bundle();
        args.putString(ARGS_ALBUM_ID, defaultAlbumId);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mListener = (OnDirectorySelectListener) context;
        } catch (ClassCastException e) {
            throw new IllegalStateException("the host activity should implement OnDirectorySelectListener.", e);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.l_fragment_list_album, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        AlbumListViewHelper.setUpHeader(this);
        AlbumListViewHelper.setUpListView(this, this);
        defaultAlbum = getArguments().getString(ARGS_ALBUM_ID);
        mCollection.onCreate(getActivity(), this);
        mCollection.onRestoreInstanceState(savedInstanceState);
        ListView list = (ListView) FragmentUtils.findViewById(this, R.id.l_list_album);
        if (list.getHeaderViewsCount() > 0 && mCollection.getCurrentSelection() == 0) {
            mCollection.setStateCurrentSelection(1);
        }
        AlbumListViewHelper.setCheckedState(this, mCollection.getCurrentSelection());
        mCollection.loadAlbums();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        mCollection.onSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onDestroyView() {
        mCollection.onDestroy();
        super.onDestroyView();
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Cursor cursor = (Cursor) parent.getItemAtPosition(position);
        if (cursor == null) {
            //avoid moving selection to header
            AlbumListViewHelper.setCheckedState(this, mCollection.getCurrentSelection());
            return;
        }
        AlbumListViewHelper.callOnSelect(mListener, cursor);
        AlbumListViewHelper.setCheckedState(this, position);
        mCollection.setStateCurrentSelection(position);
    }

    @Override
    public void onLoad(final Cursor cursor) {
        AlbumListViewHelper.setCursor(this, cursor);
        AlbumListViewHelper.callOnDefaultSelect(this, mListener, cursor, defaultAlbum, mCollection);
    }

    @Override
    public void onReset() {
        AlbumListViewHelper.setCursor(this, null);
    }

    public interface OnDirectorySelectListener {
        void onSelect(Album album);
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/PhotoGridFragment.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui;

import android.database.Cursor;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.amalgam.os.BundleUtils;
import com.laevatein.R;
import com.laevatein.internal.entity.Album;
import com.laevatein.internal.entity.ViewResourceSpec;
import com.laevatein.internal.misc.ui.FragmentUtils;
import com.laevatein.internal.model.AlbumPhotoCollection;
import com.laevatein.internal.ui.adapter.AlbumPhotoAdapter;
import com.laevatein.internal.ui.helper.PhotoGridViewHelper;
import com.laevatein.ui.PhotoSelectionActivity;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/20
 */
public class PhotoGridFragment extends Fragment implements
        AlbumPhotoCollection.AlbumPhotoCallbacks, AlbumPhotoAdapter.CheckStateListener {
    public static final String TAG = PhotoGridFragment.class.getSimpleName();
    public static final String ARGS_ALBUM = BundleUtils.buildKey(PhotoGridFragment.class, "ARGS_ALBUM");
    private final AlbumPhotoCollection mPhotoCollection = new AlbumPhotoCollection();

    public static PhotoGridFragment newInstance(Album album) {
        PhotoGridFragment fragment = new PhotoGridFragment();
        Bundle args = new Bundle();
        args.putParcelable(ARGS_ALBUM, album);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.l_fragment_grid_photo, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ViewResourceSpec resources = FragmentUtils.getIntentParcelableExtra(this, PhotoSelectionActivity.EXTRA_VIEW_SPEC);
        Album album = getArguments().getParcelable(ARGS_ALBUM);
        AlbumPhotoAdapter.BindViewListener listener;
        try {
            listener = (AlbumPhotoAdapter.BindViewListener) getActivity();
        } catch (ClassCastException e) {
            throw new IllegalStateException("the host activity should implement BindViewListener.");
        }
        PhotoGridViewHelper.setUpGridView(this, resources, PhotoGridViewHelper.getSelectedPhotoSet(this), listener);
        mPhotoCollection.onCreate(getActivity(), this);
        mPhotoCollection.load(album, resources.getCaptureResource().enabled());
        getActivity().setTitle(album.getDisplayName(getActivity()));
    }

    @Override
    public void onDestroyView() {
        PhotoGridViewHelper.tearDownGridView(this);
        mPhotoCollection.onDestroy();
        super.onDestroyView();
    }

    @Override
    public void onLoad(Cursor cursor) {
        PhotoGridViewHelper.setCursor(this, cursor);
    }

    @Override
    public void onReset() {
        PhotoGridViewHelper.setCursor(this, null);
    }

    @Override
    public void onUpdate() {
        getActivity().invalidateOptionsMenu();
    }

    public void refreshGrid() {
        PhotoGridViewHelper.refreshView(this);
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/PreviewFragment.java
================================================
package com.laevatein.internal.ui;

import android.net.Uri;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.amalgam.os.BundleUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.bumptech.glide.request.RequestOptions;
import com.laevatein.internal.entity.PreviewViewResources;

import it.sephiroth.android.library.imagezoom.ImageViewTouch;
import it.sephiroth.android.library.imagezoom.ImageViewTouchBase;

/**
 * Created by hiroyuki.seto on 15/06/16.
 *
 * @hide
 */
public class PreviewFragment extends Fragment {
    private static final String ARGS_URI = BundleUtils.buildKey(PhotoGridFragment.class, "ARGS_URI");
    private static final String ARGS_RESOURCES = BundleUtils.buildKey(PhotoGridFragment.class, "ARGS_RESOURCES");

    private PreviewViewResources mViewResources;

    public static PreviewFragment newInstance(Uri uri, PreviewViewResources resources) {
        PreviewFragment fragment = new PreviewFragment();
        Bundle bundle = new Bundle();
        bundle.putParcelable(ARGS_URI, uri);
        bundle.putParcelable(ARGS_RESOURCES, resources);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mViewResources = getArguments().getParcelable(ARGS_RESOURCES);
        return inflater.inflate(mViewResources.getLayoutId(), container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        ImageViewTouch image = getView().findViewById(mViewResources.getImageViewId());
        image.setDisplayType(ImageViewTouchBase.DisplayType.FIT_TO_SCREEN);
        Uri uri = getArguments().getParcelable(ARGS_URI);
        Glide.with(getActivity()).load(uri)
                .apply(new RequestOptions().priority(Priority.HIGH).fitCenter().centerInside())
                .into(image);
    }

    public void resetView() {
        ((ImageViewTouch) getView()).resetMatrix();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/SelectedCountFragment.java
================================================
package com.laevatein.internal.ui;

import com.laevatein.R;
import com.laevatein.internal.ui.helper.SelectedCountViewHelper;
import com.laevatein.ui.PhotoSelectionActivity;

import android.content.Context;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author KeithYokoma
 * @since 2014/04/03
 * @version 1.0.0
 * @hide
 */
public class SelectedCountFragment extends Fragment {
    private OnShowSelectedClickListener mListener;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        try {
            mListener = (OnShowSelectedClickListener) context;
        } catch (ClassCastException e) {
            throw new IllegalStateException("the host activity should implement OnShowSelectedClickListener.");
        }

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.l_fragment_selected_count, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        SelectedCountViewHelper.setUpCountView(this);
        SelectedCountViewHelper.updateCountView((PhotoSelectionActivity) getActivity(), this);
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        SelectedCountViewHelper.updateCountView((PhotoSelectionActivity) getActivity(), this); // bit hacky
    }

    public OnShowSelectedClickListener getListener() {
        return mListener;
    }

    public interface OnShowSelectedClickListener {
        void onClickSelectedView();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/SelectedPhotoGridFragment.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui;

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.laevatein.R;
import com.laevatein.internal.entity.ViewResourceSpec;
import com.laevatein.internal.misc.ui.FragmentUtils;
import com.laevatein.internal.ui.adapter.SelectedPhotoAdapter;
import com.laevatein.internal.ui.helper.SelectedGridViewHelper;
import com.laevatein.ui.PhotoSelectionActivity;

/**
 * @author KeithYokoma
 * @since 2014/03/27
 * @version 1.0.0
 * @hide
 */
public class SelectedPhotoGridFragment extends Fragment implements SelectedPhotoAdapter.CheckStateListener {
    public static final String TAG = SelectedPhotoGridFragment.class.getSimpleName();

    public SelectedPhotoGridFragment() {
    }

    public static SelectedPhotoGridFragment newInstance() {
        return new SelectedPhotoGridFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.l_fragment_grid_photo, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ViewResourceSpec resources = FragmentUtils.getIntentParcelableExtra(this, PhotoSelectionActivity.EXTRA_VIEW_SPEC);
        getActivity().setTitle(R.string.l_album_name_selected);
        SelectedGridViewHelper.setUpGridView(this, resources.getItemViewResources(), SelectedGridViewHelper.getSelectedPhotoSet(this));
    }

    @Override
    public void onDestroyView() {

        super.onDestroyView();
    }

    @Override
    public void onUpdate() {
        getActivity().invalidateOptionsMenu();
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/AlbumPhotoAdapter.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.adapter;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.laevatein.R;
import com.laevatein.internal.entity.CaptureResources;
import com.laevatein.internal.entity.Item;
import com.laevatein.internal.entity.ItemViewResources;
import com.laevatein.internal.entity.ViewResourceSpec;
import com.laevatein.internal.model.SelectedUriCollection;
import com.laevatein.internal.ui.helper.PhotoGridViewHelper;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/24
 */
public class AlbumPhotoAdapter extends RecyclerViewCursorAdapter<AlbumPhotoAdapter.ViewHolder> {
    private final Context mContext;
    private final ItemViewResources mResources;
    private final CaptureResources mCaptureResources;
    private final SelectedUriCollection mCollection;
    private CheckStateListener mListener;
    private BindViewListener mBindViewListener;

    public AlbumPhotoAdapter(Context context, ViewResourceSpec resources, SelectedUriCollection collection, BindViewListener bindViewListener) {
        super(null);
        mContext = context;
        mResources = resources.getItemViewResources();
        mCaptureResources = resources.getCaptureResource();
        mCollection = collection;
        mBindViewListener = bindViewListener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(mResources.getLayoutId(), viewGroup, false);
        return new ViewHolder(v, mResources);
    }

    @Override
    protected void onBindViewHolder(ViewHolder holder, Cursor cursor) {
        final Item item = Item.valueOf(cursor);
        holder.thumbnail.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (item.isCapture()) {
                    if (mCaptureResources.getFileProviderAuthorities() == null) {
                        throw new IllegalStateException();
                    }
                    PhotoGridViewHelper.callCamera(mContext, mCaptureResources.getFileProviderAuthorities());
                } else {
                    PhotoGridViewHelper.callPreview(mContext, item, mCollection.asList());
                }
            }
        });
        holder.checkBox.setVisibility(item.isCapture() ? View.GONE : View.VISIBLE);
        holder.checkBox.setChecked(mCollection.isSelected(item.buildContentUri()));
        holder.checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PhotoGridViewHelper.syncCheckState(mContext, mCollection, item, (CheckBox) v);
                PhotoGridViewHelper.callCheckStateListener(mListener);
            }
        });
        if (item.isCapture()) {
            holder.thumbnail.setImageResource(R.drawable.l_ic_capture);
        } else {
            Glide.with(mContext).load(item.buildContentUri())
                    .apply(new RequestOptions().fitCenter().centerCrop())
                    .into(holder.thumbnail);
        }
        mBindViewListener.onBindView(mContext, holder.itemView, item.buildContentUri());
    }

    public void registerCheckStateListener(CheckStateListener listener) {
        mListener = listener;
    }

    public void unregisterCheckStateListener() {
        mListener = null;
    }

    public interface CheckStateListener {
        void onUpdate();
    }

    public interface BindViewListener {
        /**
         * Called when view is bound to data.
         *
         * @param context context of photo selection activity
         * @param view    view of grid
         * @param uri     uri of image in grid
         */
        void onBindView(Context context, View view, Uri uri);
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        private final ImageView thumbnail;
        private final CheckBox checkBox;

        ViewHolder(View v, ItemViewResources resources) {
            super(v);
            thumbnail = v.findViewById(resources.getImageViewId());
            checkBox = v.findViewById(resources.getCheckBoxId());
        }
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/DevicePhotoAlbumAdapter.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.adapter;

import android.content.Context;
import android.database.Cursor;
import androidx.cursoradapter.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.amalgam.content.ContextUtils;
import com.laevatein.R;
import com.laevatein.internal.entity.Album;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/24
 */
public class DevicePhotoAlbumAdapter extends CursorAdapter {

    public DevicePhotoAlbumAdapter(Context context, Cursor c) {
        super(context, c, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        LayoutInflater inflater = ContextUtils.getLayoutInflater(context);
        return inflater.inflate(R.layout.l_list_item_default_album, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        Album album = Album.valueOf(cursor);
        TextView textView = view.findViewById(R.id.l_default_directory_label);
        textView.setText(album.getDisplayName(context));
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/PreviewPagerAdapter.java
================================================
package com.laevatein.internal.ui.adapter;

import android.net.Uri;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import android.view.ViewGroup;

import com.laevatein.internal.entity.PreviewViewResources;
import com.laevatein.internal.ui.PreviewFragment;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by hiroyuki.seto on 15/06/16.
 *
 * @hide
 */
public class PreviewPagerAdapter extends FragmentPagerAdapter {

    private ArrayList<Uri> mUris = new ArrayList<>();

    private PreviewViewResources mPreviewViewResources;
    private OnPrimaryItemSetListener mListener;

    public PreviewPagerAdapter(FragmentManager manager, PreviewViewResources previewViewResources,
                               OnPrimaryItemSetListener listener) {
        super(manager);
        mPreviewViewResources = previewViewResources;
        mListener = listener;
    }

    @Override
    public Fragment getItem(int position) {
        return PreviewFragment.newInstance(mUris.get(position), mPreviewViewResources);
    }

    @Override
    public int getCount() {
        return mUris.size();
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        mListener.onPrimaryItemSet(position);
    }

    public Uri getUri(int position) {
        return mUris.get(position);
    }

    public void addAll(List<Uri> uris) {
        mUris.addAll(uris);
    }

    public interface OnPrimaryItemSetListener {
        void onPrimaryItemSet(int position);
    }

}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/RecyclerViewCursorAdapter.java
================================================
/*
 * This file is based on the code of `RecyclerViewCursorAdapter.java` in `Matisse`.
 *
 * https://github.com/zhihu/Matisse/blob/master/matisse/src/main/java/com/zhihu/matisse/internal/ui/adapter/RecyclerViewCursorAdapter.java
 */
package com.laevatein.internal.ui.adapter;

import android.database.Cursor;
import android.provider.MediaStore;
import androidx.recyclerview.widget.RecyclerView;

public abstract class RecyclerViewCursorAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
    private Cursor mCursor;
    private int mRowIDColumn;

    protected abstract void onBindViewHolder(VH holder, Cursor cursor);

    RecyclerViewCursorAdapter(Cursor c) {
        setHasStableIds(true);
        swapCursor(c);
    }

    @Override
    public void onBindViewHolder(VH holder, int position) {
        if (!isDataValid(mCursor)) {
            throw new IllegalStateException("Cannot bind view holder when cursor is in invalid state.");
        }
        if (!mCursor.moveToPosition(position)) {
            throw new IllegalStateException("Could not move cursor to position " + position
                    + " when trying to bind view holder");
        }

        onBindViewHolder(holder, mCursor);
    }

    @Override
    public int getItemCount() {
        if (isDataValid(mCursor)) {
            return mCursor.getCount();
        } else {
            return 0;
        }
    }

    @Override
    public long getItemId(int position) {
        if (!isDataValid(mCursor)) {
            throw new IllegalStateException("Cannot lookup item id when cursor is in invalid state.");
        }
        if (!mCursor.moveToPosition(position)) {
            throw new IllegalStateException("Could not move cursor to position " + position
                    + " when trying to get an item id");
        }

        return mCursor.getLong(mRowIDColumn);
    }

    public void swapCursor(Cursor newCursor) {
        if (newCursor == mCursor) {
            return;
        }

        if (newCursor != null) {
            mCursor = newCursor;
            mRowIDColumn = mCursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID);
            notifyDataSetChanged();
        } else {
            notifyItemRangeRemoved(0, getItemCount());
            mCursor = null;
            mRowIDColumn = -1;
        }
    }

    public Cursor getCursor() {
        return mCursor;
    }

    private boolean isDataValid(Cursor cursor) {
        return cursor != null && !cursor.isClosed();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/SelectedPhotoAdapter.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.adapter;

import android.content.Context;
import android.net.Uri;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.laevatein.internal.entity.ItemViewResources;
import com.laevatein.internal.model.SelectedUriCollection;
import com.laevatein.internal.ui.helper.SelectedGridViewHelper;

import java.util.List;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/27
 */
public class SelectedPhotoAdapter extends RecyclerView.Adapter<SelectedPhotoAdapter.ViewHolder> {
    public static final String TAG = SelectedPhotoAdapter.class.getSimpleName();
    private final Context mContext;
    private final ItemViewResources mResources;
    private final SelectedUriCollection mCollection;
    private CheckStateListener mListener;
    private List<Uri> mUris;

    public SelectedPhotoAdapter(Context context, ItemViewResources resources, SelectedUriCollection collection) {
        mContext = context;
        mResources = resources;
        mCollection = collection;
        mUris = collection.asList();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(mResources.getLayoutId(), viewGroup, false);
        return new ViewHolder(v, mResources);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        final Uri uri = mUris.get(position);
        holder.checkBox.setChecked(mCollection.isSelected(uri));
        holder.checkBox.setText(null);
        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                SelectedGridViewHelper.syncCollection(mCollection, uri, isChecked);
                SelectedGridViewHelper.callCheckStateListener(mListener);
            }
        });
        Glide.with(mContext).load(uri)
                .apply(new RequestOptions().fitCenter().centerCrop())
                .into(holder.thumbnail);
    }

    @Override
    public int getItemCount() {
        return mUris.size();
    }

    public void registerCheckStateListener(CheckStateListener listener) {
        mListener = listener;
    }

    public void unregisterCheckStateListener() {
        mListener = null;
    }

    public interface CheckStateListener {
        void onUpdate();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        private final ImageView thumbnail;
        private final CheckBox checkBox;

        ViewHolder(View v, ItemViewResources resources) {
            super(v);
            thumbnail = v.findViewById(resources.getImageViewId());
            checkBox = v.findViewById(resources.getCheckBoxId());
        }
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/AlbumListViewHelper.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper;

import android.database.Cursor;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.cursoradapter.widget.CursorAdapter;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.HeaderViewListAdapter;
import android.widget.ListView;

import com.amalgam.os.HandlerUtils;
import com.laevatein.R;
import com.laevatein.internal.entity.Album;
import com.laevatein.internal.misc.ui.FragmentUtils;
import com.laevatein.internal.model.DevicePhotoAlbumCollection;
import com.laevatein.internal.ui.AlbumListFragment;
import com.laevatein.internal.ui.adapter.DevicePhotoAlbumAdapter;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/20
 */
public final class AlbumListViewHelper {
    private AlbumListViewHelper() {
        throw new AssertionError("oops! the utility class is about to be instantiated...");
    }

    public static void setUpHeader(Fragment fragment) {
        TypedValue value = new TypedValue();
        fragment.getContext().getTheme().resolveAttribute(R.attr.l_drawerHeaderLayout, value, true);
        if (value.resourceId == 0) {
            return;
        }
        ListView listView = (ListView) FragmentUtils.findViewById(fragment, R.id.l_list_album);
        LayoutInflater inflater = LayoutInflater.from(fragment.getContext());
        View header = inflater.inflate(value.resourceId, listView, false);
        listView.addHeaderView(header);
    }

    public static void setUpListView(Fragment fragment, AdapterView.OnItemClickListener listener) {
        ListView listView = (ListView) FragmentUtils.findViewById(fragment, R.id.l_list_album);
        listView.setOnItemClickListener(listener);
        listView.setAdapter(new DevicePhotoAlbumAdapter(fragment.getActivity(), null));
    }

    public static void setCursor(Fragment fragment, Cursor cursor) {
        ListView listView = (ListView) FragmentUtils.findViewById(fragment, R.id.l_list_album);
        CursorAdapter adapter;
        if (listView.getHeaderViewsCount() > 0) {
            adapter = (CursorAdapter) ((HeaderViewListAdapter) listView.getAdapter()).getWrappedAdapter();
        } else {
            adapter = (CursorAdapter) listView.getAdapter();
        }
        adapter.swapCursor(cursor);
    }

    public static void callOnSelect(AlbumListFragment.OnDirectorySelectListener listener, Cursor cursor) {
        Album album = Album.valueOf(cursor);
        listener.onSelect(album);
    }

    public static void callOnDefaultSelect(final Fragment fragment, final AlbumListFragment.OnDirectorySelectListener listener, final Cursor cursor,
                                           final String albumId, final DevicePhotoAlbumCollection collection) {
        HandlerUtils.getMainHandler().post(new Runnable() {
            @Override
            public void run() {
                FragmentActivity fragmentActivity = fragment.getActivity();
                if (fragmentActivity == null) {
                    return;
                }

                FragmentManager manager = fragmentActivity.getSupportFragmentManager();
                Fragment f = manager.findFragmentById(R.id.l_container_grid_fragment);
                if (f != null) {
                    return;
                }

                cursor.moveToFirst();
                do {
                    Album item = Album.valueOf(cursor);
                    if (item.getId().equals(albumId)) {
                        ListView listView = (ListView) FragmentUtils.findViewById(fragment, R.id.l_list_album);
                        int position = cursor.getPosition() + listView.getHeaderViewsCount();
                        collection.setStateCurrentSelection(position);
                        setCheckedState(fragment, position);
                        listener.onSelect(item);
                        return;
                    }
                } while (cursor.moveToNext());

                cursor.moveToFirst();
                callOnSelect(listener, cursor);
                ListView listView = (ListView) FragmentUtils.findViewById(fragment, R.id.l_list_album);
                setCheckedState(fragment, listView.getHeaderViewsCount());
            }
        });
    }

    public static void setCheckedState(Fragment fragment, int position) {
        ListView listView = (ListView) FragmentUtils.findViewById(fragment, R.id.l_list_album);
        listView.setItemChecked(position, true);
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoGridViewHelper.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;

import com.laevatein.R;
import com.laevatein.internal.entity.Album;
import com.laevatein.internal.entity.ErrorViewResources;
import com.laevatein.internal.entity.ErrorViewSpec;
import com.laevatein.internal.entity.Item;
import com.laevatein.internal.entity.UncapableCause;
import com.laevatein.internal.entity.ViewResourceSpec;
import com.laevatein.internal.model.SelectedUriCollection;
import com.laevatein.internal.ui.PhotoGridFragment;
import com.laevatein.internal.ui.adapter.AlbumPhotoAdapter;
import com.laevatein.internal.ui.adapter.RecyclerViewCursorAdapter;
import com.laevatein.internal.ui.widget.PhotoDecoration;
import com.laevatein.internal.utils.ErrorViewUtils;
import com.laevatein.internal.utils.MediaStoreUtils;
import com.laevatein.ui.ImagePreviewActivity;
import com.laevatein.ui.PhotoSelectionActivity;

import java.util.ArrayList;
import java.util.List;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/24
 */
public final class PhotoGridViewHelper {
    private PhotoGridViewHelper() {
        throw new AssertionError("oops! the utility class is about to be instantiated...");
    }

    public static SelectedUriCollection getSelectedPhotoSet(Fragment fragment) {
        return ((PhotoSelectionActivity) fragment.getActivity()).getCollection();
    }

    public static void setUpGridView(Fragment fragment, ViewResourceSpec resources, SelectedUriCollection collection, AlbumPhotoAdapter.BindViewListener listener) {
        RecyclerView recyclerView = fragment.getView().findViewById(R.id.l_recyclerview);
        int spanCount = resources.getItemViewResources().getSpanCount();
        recyclerView.setLayoutManager(new GridLayoutManager(fragment.getContext(), resources.getItemViewResources().getSpanCount()));
        recyclerView.setHasFixedSize(true);
        recyclerView.setDrawingCacheEnabled(true);
        recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_LOW);

        AlbumPhotoAdapter adapter = new AlbumPhotoAdapter(fragment.getActivity(), resources, collection, listener);
        adapter.registerCheckStateListener((AlbumPhotoAdapter.CheckStateListener) fragment);

        int spacing = fragment.getResources().getDimensionPixelSize(R.dimen.grid_spacing);
        recyclerView.addItemDecoration(new PhotoDecoration(spanCount, spacing, false));
        recyclerView.setAdapter(adapter);

        TextView emptyMessage = fragment.getView().findViewById(R.id.l_label_empty);
        if (adapter.getItemCount() == 0) {
            emptyMessage.setVisibility(View.VISIBLE);
            emptyMessage.setText(R.string.l_empty_photo);
        } else {
            emptyMessage.setVisibility(View.GONE);
        }
    }

    public static void tearDownGridView(Fragment fragment) {
        RecyclerView recyclerView = fragment.getView().findViewById(R.id.l_recyclerview);
        AlbumPhotoAdapter adapter = (AlbumPhotoAdapter) recyclerView.getAdapter();
        adapter.unregisterCheckStateListener();
    }

    public static void setCursor(Fragment fragment, Cursor cursor) {
        RecyclerView recyclerView = fragment.getView().findViewById(R.id.l_recyclerview);
        RecyclerViewCursorAdapter adapter = (RecyclerViewCursorAdapter) recyclerView.getAdapter();
        adapter.swapCursor(cursor);

        TextView emptyMessage = fragment.getView().findViewById(R.id.l_label_empty);
        if (adapter.getItemCount() == 0) {
            emptyMessage.setVisibility(View.VISIBLE);
            emptyMessage.setText(R.string.l_empty_photo);
        } else {
            emptyMessage.setVisibility(View.GONE);
        }
    }

    public static void refreshView(Fragment fragment) {
        RecyclerView recyclerView = fragment.getView().findViewById(R.id.l_recyclerview);
        RecyclerViewCursorAdapter adapter = (RecyclerViewCursorAdapter) recyclerView.getAdapter();
        adapter.notifyDataSetChanged();
    }

    public static void callPreview(Context context, Item item, List<Uri> checked) {
        PhotoSelectionActivity activity = (PhotoSelectionActivity) context;
        ViewResourceSpec resources = activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_VIEW_SPEC);
        Intent intent = new Intent(context, resources.getPreviewActivityClass());
        Fragment fragment = activity.getSupportFragmentManager().findFragmentById(R.id.l_container_grid_fragment);
        Album album = fragment.getArguments().getParcelable(PhotoGridFragment.ARGS_ALBUM);
        intent.putExtra(ImagePreviewActivity.EXTRA_ALBUM, album);
        intent.putExtra(ImagePreviewActivity.EXTRA_ITEM, item);
        intent.putExtra(ImagePreviewActivity.EXTRA_ERROR_SPEC, activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_ERROR_SPEC));
        intent.putExtra(ImagePreviewActivity.EXTRA_SELECTION_SPEC, activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_SELECTION_SPEC));
        intent.putExtra(ImagePreviewActivity.EXTRA_VIEW_SPEC, activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_VIEW_SPEC));
        intent.putParcelableArrayListExtra(ImagePreviewActivity.EXTRA_DEFAULT_CHECKED, (ArrayList<Uri>) checked);
        activity.startActivityForResult(intent, PhotoSelectionActivity.REQUEST_CODE_PREVIEW);
    }

    public static void callCamera(Context context, String fileProviderAuthorities) {
        PhotoSelectionActivity activity = (PhotoSelectionActivity) context;
        MediaStoreUtils utils = activity.getMediaStoreUtils();
        String preparedUri = utils.invokeCameraCapture(activity, fileProviderAuthorities, PhotoSelectionActivity.REQUEST_CODE_CAPTURE);
        activity.prepareCapture(preparedUri);
    }

    public static void syncCheckState(Context context, SelectedUriCollection collection, Item item, CheckBox checkBox) {
        Uri uri = item.buildContentUri();
        if (collection.isSelected(uri)) {
            removeSelection(collection, uri, checkBox);
        } else {
            addSelection(context, collection, uri, checkBox);
        }
    }

    public static void removeSelection(SelectedUriCollection collection, Uri uri, CheckBox checkBox) {
        collection.remove(uri);
        checkBox.setChecked(false);
    }

    public static void addSelection(Context context, SelectedUriCollection collection, Uri uri, CheckBox checkBox) {
        UncapableCause cause = collection.isAcceptable(uri);
        FragmentActivity activity = (FragmentActivity) context;
        ErrorViewSpec spec = activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_ERROR_SPEC);

        if (cause == null) {
            ErrorViewResources countSpec = spec.getCountOverErrorSpec();
            collection.add(uri);
            if (collection.isCountOver() && !countSpec.isNoView()) {
                ErrorViewUtils.showErrorView(activity, countSpec);
                collection.remove(uri);
                checkBox.setChecked(false);
                return;
            }
            checkBox.setChecked(true);
        } else {
            checkBox.setChecked(false);
            ErrorViewUtils.showErrorView(activity, cause.getErrorResources(spec));
        }
    }

    public static void callCheckStateListener(AlbumPhotoAdapter.CheckStateListener listener) {
        if (listener == null) {
            return;
        }
        listener.onUpdate();
    }
}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoSelectionActivityDrawerToggle.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper;

import android.app.Activity;
import androidx.fragment.app.FragmentActivity;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.widget.Toolbar;
import android.view.View;

import com.laevatein.R;

/**
 * @author KeithYokoma
 * @since 2014/03/24
 * @version 1.0.0
 * @hide
 */
public class PhotoSelectionActivityDrawerToggle extends ActionBarDrawerToggle {
    private FragmentActivity mActivity;
    /**
     * Construct a new ActionBarDrawerToggle.
     *
     * <p>The given {@link android.app.Activity} will be linked to the specified {@link DrawerLayout}.
     * The provided drawer indicator drawable will animate slightly off-screen as the drawer
     * is opened, indicating that in the open state the drawer will move off-screen when pressed
     * and in the closed state the drawer will move on-screen when pressed.</p>
     *
     * <p>String resources must be provided to describe the open/close drawer actions for
     * accessibility services.</p>
     *
     * @param activity                  The Activity hosting the drawer
     * @param drawerLayout              The DrawerLayout to link to the given Activity's ActionBar
     */
    public PhotoSelectionActivityDrawerToggle(Activity activity, DrawerLayout drawerLayout) {
        super(activity, drawerLayout, R.string.l_content_desc_open_drawer, R.string.l_content_desc_close_drawer);
        mActivity = (FragmentActivity) activity;
        drawerLayout.setDrawerShadow(R.drawable.l_drawer_shadow, GravityCompat.START);
    }

    public PhotoSelectionActivityDrawerToggle(Activity activity, DrawerLayout drawerLayout,Toolbar toolbar) {
        super(activity, drawerLayout, toolbar, R.string.l_content_desc_open_drawer, R.string.l_content_desc_close_drawer);
        mActivity = (FragmentActivity) activity;
        drawerLayout.setDrawerShadow(R.drawable.l_drawer_shadow, GravityCompat.START);
    }

    public void setUpActionBar(ActionBar actionBar) {
        if (actionBar == null) {
            return; // FIXME for now just check null or not to avoid NPE, consider compatibility layer to deal with tool bar later on.
        }
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
    }

    @Override
    public void onDrawerClosed(View drawerView) {
        super.onDrawerClosed(drawerView);
        mActivity.invalidateOptionsMenu();
    }

    @Override
    public void onDrawerOpened(View drawerView) {
        super.onDrawerOpened(drawerView);
        mActivity.invalidateOptionsMenu();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoSelectionViewHelper.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper;

import com.google.android.material.appbar.AppBarLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.laevatein.R;
import com.laevatein.internal.entity.Album;
import com.laevatein.internal.entity.CounterViewResources;
import com.laevatein.internal.entity.ErrorViewResources;
import com.laevatein.internal.entity.ErrorViewSpec;
import com.laevatein.internal.entity.ViewResourceSpec;
import com.laevatein.internal.model.SelectedUriCollection;
import com.laevatein.internal.ui.AlbumListFragment;
import com.laevatein.internal.ui.PhotoGridFragment;
import com.laevatein.internal.ui.SelectedPhotoGridFragment;
import com.laevatein.ui.PhotoSelectionActivity;

/**
 * @author KeithYokoma
 * @since 2014/03/25
 * @version 1.0.0
 * @hide
 */
public final class PhotoSelectionViewHelper {
    private PhotoSelectionViewHelper() {
        throw new AssertionError("oops! the utility class is about to be instantiated...");
    }

    public static void setUpActivity(PhotoSelectionActivity activity) {
        ViewResourceSpec spec = activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_VIEW_SPEC);
        if (spec != null && spec.needActivityOrientationRestriction()) {
            activity.setRequestedOrientation(spec.getActivityOrientation());
        }
    }

    public static void setUpCounter(PhotoSelectionActivity activity) {
        ViewResourceSpec spec = activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_VIEW_SPEC);
        if (spec.getCounterViewResources().getViewType() == CounterViewResources.LAYOUT_APP_BAR) {
            AppBarLayout appBar = activity.findViewById(R.id.l_app_bar);
            LayoutInflater.from(activity).inflate(R.layout.l_view_counter, appBar);
        } else {
            RelativeLayout content = activity.findViewById(R.id.l_content);
            View counter = LayoutInflater.from(activity).inflate(R.layout.l_view_counter, content, false);
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            content.addView(counter, params);
            View view = activity.findViewById(R.id.l_container_grid_fragment);
            RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) view.getLayoutParams();
            params2.addRule(RelativeLayout.ABOVE, R.id.l_fragment_selected_count);
        }
    }

    public static void refreshOptionsMenuState(PhotoSelectionActivity activity, SelectedUriCollection collection, Menu menu) {
        if (collection == null) {
            return;
        }
        ErrorViewSpec spec = activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_ERROR_SPEC);
        ErrorViewResources res = spec.getCountUnderErrorSpec();
        MenuItem select = menu.findItem(R.id.action_finish_select);
        updateSelectMenuState(select, res, collection, activity.isDrawerOpen());
    }

    public static void updateSelectMenuState(MenuItem item, ErrorViewResources res, SelectedUriCollection collection, boolean drawerOpen) {
        if (item == null) {
            return;
        }
        item.setVisible(!drawerOpen);
        if (res.isNoView()) {
            item.setEnabled(!collection.isEmpty() && collection.isCountInRange());
        } else {
            item.setEnabled(!collection.isEmpty());
        }
    }

    public static void setPhotoGridFragment(FragmentActivity activity, DrawerLayout drawer, Album album) {
        Fragment fragment = PhotoGridFragment.newInstance(album);
        FragmentManager manager = activity.getSupportFragmentManager();
        manager.beginTransaction()
                .replace(R.id.l_container_grid_fragment, fragment, PhotoGridFragment.TAG)
                .commit();
        if (((PhotoSelectionActivity) activity).isDrawerOpen()) {
            drawer.closeDrawers();
        } else {
            ViewResourceSpec spec = activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_VIEW_SPEC);
            if (spec.openDrawer()) {
                drawer.openDrawer(GravityCompat.START);
            }
        }
    }

    public static void setAlbumList(FragmentActivity activity, String albumId) {
        Fragment fragment = AlbumListFragment.newInstance(albumId);
        FragmentManager manager = activity.getSupportFragmentManager();
        manager.beginTransaction()
                .add(R.id.l_container_album_list, fragment, PhotoGridFragment.TAG)
                .commit();
    }

    public static void setSelectedGridFragment(FragmentActivity activity) {
        Fragment fragment = SelectedPhotoGridFragment.newInstance();
        FragmentManager manager = activity.getSupportFragmentManager();
        manager.beginTransaction()
                .replace(R.id.l_container_grid_fragment, fragment, PhotoGridFragment.TAG)
                .commit();
    }

    public static void refreshGridView(FragmentActivity activity) {
        FragmentManager manager = activity.getSupportFragmentManager();
        Fragment fragment = manager.findFragmentByTag(PhotoGridFragment.TAG);
        if (fragment instanceof PhotoGridFragment) {
            ((PhotoGridFragment) fragment).refreshGrid();
        }
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/PreviewHelper.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.CompoundButton;

import com.laevatein.R;
import com.laevatein.internal.entity.ErrorViewResources;
import com.laevatein.internal.entity.ErrorViewSpec;
import com.laevatein.internal.entity.Item;
import com.laevatein.internal.entity.PreviewViewResources;
import com.laevatein.internal.entity.SelectionSpec;
import com.laevatein.internal.entity.UncapableCause;
import com.laevatein.internal.entity.ViewResourceSpec;
import com.laevatein.ui.ImagePreviewActivity;
import com.laevatein.internal.ui.adapter.PreviewPagerAdapter;
import com.laevatein.internal.utils.ErrorViewUtils;
import com.laevatein.internal.utils.PhotoMetadataUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/24
 */
public final class PreviewHelper {
    private PreviewHelper() {
        throw new AssertionError("oops! the utility class is about to be instantiated...");
    }

    public static void setUpActivity(ImagePreviewActivity activity) {
        ViewResourceSpec spec = activity.getIntent().getParcelableExtra(ImagePreviewActivity.EXTRA_VIEW_SPEC);
        if (spec != null && spec.needActivityOrientationRestriction()) {
            activity.setRequestedOrientation(spec.getActivityOrientation());
        }
        PreviewViewResources previewViewResources;
        if (spec != null && spec.getPreviewViewResources() != null) {
            previewViewResources = spec.getPreviewViewResources();
        } else {
            previewViewResources = PreviewViewResources.getDefault();
        }
        PreviewPagerAdapter adapter = new PreviewPagerAdapter(activity.getSupportFragmentManager(),
                previewViewResources, activity);
        ViewPager pager = activity.findViewById(R.id.l_pager);
        pager.setAdapter(adapter);
    }

    public static void setUpActionBar(AppCompatActivity activity) {
        Toolbar toolbar = activity.findViewById(R.id.l_toolbar);
        toolbar.setTitle(activity.getApplicationContext().getString(R.string.l_detail_photo_title));
        activity.setSupportActionBar(toolbar);
        ActionBar actionBar = activity.getSupportActionBar();
        actionBar.setHomeButtonEnabled(true);
        actionBar.setDisplayHomeAsUpEnabled(true);
    }

    public static void setUpActionItem(final ImagePreviewActivity activity, Menu menu) {
        final MenuItem item = menu.findItem(R.id.l_action_selection_state);
        if (item == null) {
            return;
        }
        final Item photo = activity.getIntent().getParcelableExtra(ImagePreviewActivity.EXTRA_ITEM);
        final SelectionSpec spec = activity.getIntent().getParcelableExtra(ImagePreviewActivity.EXTRA_SELECTION_SPEC);
        final ErrorViewSpec errorSpec = activity.getIntent().getParcelableExtra(ImagePreviewActivity.EXTRA_ERROR_SPEC);
        item.setActionView(R.layout.l_action_layout_checkbox);
        final CheckBox checkBox = item.getActionView().findViewById(R.id.l_default_check_box);
        checkBox.setChecked(activity.getStateHolder().isChecked(photo.buildContentUri()));
        checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                ViewPager pager = activity.findViewById(R.id.l_pager);
                Uri currentUri = ((PreviewPagerAdapter) pager.getAdapter()).getUri(pager.getCurrentItem());
                if (!isChecked) {
                    activity.getStateHolder().setChecked(currentUri, false);
                    return;
                }
                UncapableCause cause = PhotoMetadataUtils
                        .isAcceptable(activity, spec, currentUri);
                int currentCount = activity.getStateHolder().getCheckedCount();
                if (!activity.getStateHolder().isChecked(currentUri) && currentCount + 1 > spec.getMaxSelectable()) {
                    cause = UncapableCause.OVER_COUNT;
                }
                if (cause == null) {
                    activity.getStateHolder().setChecked(currentUri, true);
                    return;
                }

                ErrorViewResources error = cause.getErrorResources(errorSpec);
                ErrorViewUtils.showErrorView(activity, error);
                checkBox.setChecked(false);
                activity.getStateHolder().setChecked(currentUri, false);
            }
        });
    }

    public static void sendBackResult(ImagePreviewActivity activity) {
        Intent intent = new Intent();
        List<Uri> checked = activity.getStateHolder().getAllChecked();
        intent.putParcelableArrayListExtra(ImagePreviewActivity.EXTRA_RESULT_CHECKED, (ArrayList<Uri>) checked);
        activity.setResult(Activity.RESULT_OK, intent);
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/SelectedCountViewHelper.java
================================================
package com.laevatein.internal.ui.helper;

import android.view.View;
import android.widget.TextView;

import com.laevatein.R;
import com.laevatein.internal.entity.ViewResourceSpec;
import com.laevatein.internal.misc.ui.FragmentUtils;
import com.laevatein.internal.ui.SelectedCountFragment;
import com.laevatein.ui.PhotoSelectionActivity;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/04/04
 */
public final class SelectedCountViewHelper {
    private SelectedCountViewHelper() {
        throw new AssertionError("oops! the utility class is about to be instantiated...");
    }

    public static void setUpCountView(final SelectedCountFragment fragment) {
        TextView counter = (TextView) FragmentUtils.findViewById(fragment, R.id.l_container_count_view);
        ViewResourceSpec spec = FragmentUtils.getIntentParcelableExtra(fragment, PhotoSelectionActivity.EXTRA_VIEW_SPEC);
        counter.setEnabled(spec.isEnableSelectedView());
        counter.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                fragment.getListener().onClickSelectedView();
            }
        });
    }

    public static void updateCountView(PhotoSelectionActivity activity, SelectedCountFragment fragment) {
        if (activity == null || fragment == null || activity.getCollection() == null || fragment.getView() == null) {
            return;
        }
        ViewResourceSpec spec = FragmentUtils.getIntentParcelableExtra(fragment, PhotoSelectionActivity.EXTRA_VIEW_SPEC);
        TextView label = (TextView) FragmentUtils.findViewById(fragment, R.id.l_container_count_view);
        int max = activity.getCollection().maxCount();
        int current = activity.getCollection().count();
        label.setText(activity.getString(spec.getCounterViewResources().getTextRes(), current, max));
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/SelectedGridViewHelper.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper;

import android.net.Uri;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

import com.laevatein.R;
import com.laevatein.internal.entity.ItemViewResources;
import com.laevatein.internal.model.SelectedUriCollection;
import com.laevatein.internal.ui.adapter.SelectedPhotoAdapter;
import com.laevatein.internal.ui.widget.PhotoDecoration;
import com.laevatein.ui.PhotoSelectionActivity;

/**
 * @author keishin.yokomaku
 * @version 1.0.0
 * @hide
 * @since 2014/03/27
 */
public final class SelectedGridViewHelper {
    private SelectedGridViewHelper() {
        throw new AssertionError("oops! the utility class is about to be instantiated...");
    }

    public static SelectedUriCollection getSelectedPhotoSet(Fragment fragment) {
        return ((PhotoSelectionActivity) fragment.getActivity()).getCollection();
    }

    public static void setUpGridView(Fragment fragment, ItemViewResources resources, SelectedUriCollection collection) {
        RecyclerView recyclerView = fragment.getView().findViewById(R.id.l_recyclerview);
        int spanCount = resources.getSpanCount();
        recyclerView.setLayoutManager(new GridLayoutManager(fragment.getContext(), resources.getSpanCount()));
        recyclerView.setHasFixedSize(true);
        recyclerView.setDrawingCacheEnabled(true);
        recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_LOW);

        SelectedPhotoAdapter adapter = new SelectedPhotoAdapter(fragment.getActivity(), resources, collection);
        adapter.registerCheckStateListener((SelectedPhotoAdapter.CheckStateListener) fragment);

        int spacing = fragment.getResources().getDimensionPixelSize(R.dimen.grid_spacing);
        recyclerView.addItemDecoration(new PhotoDecoration(spanCount, spacing, false));
        recyclerView.setAdapter(adapter);

        TextView emptyMessage = fragment.getView().findViewById(R.id.l_label_empty);
        if (collection.asList().size() == 0) {
            emptyMessage.setVisibility(View.VISIBLE);
            emptyMessage.setText(R.string.l_empty_selection);
        } else {
            emptyMessage.setVisibility(View.GONE);
        }
    }

    public static void tearDownGridView(Fragment fragment) {
        RecyclerView recyclerView = fragment.getView().findViewById(R.id.l_recyclerview);
        SelectedPhotoAdapter adapter = (SelectedPhotoAdapter) recyclerView.getAdapter();
        adapter.unregisterCheckStateListener();
    }

    public static void syncCollection(SelectedUriCollection collection, Uri uri, boolean checked) {
        if (checked) {
            collection.add(uri);
        } else {
            collection.remove(uri);
        }
    }

    public static void callCheckStateListener(SelectedPhotoAdapter.CheckStateListener listener) {
        if (listener == null) {
            return;
        }
        listener.onUpdate();
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/options/FinishSelectMenuHandler.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper.options;

import android.app.Activity;
import android.content.Intent;
import android.os.Parcelable;

import com.laevatein.internal.entity.ErrorViewResources;
import com.laevatein.internal.entity.ErrorViewSpec;
import com.laevatein.internal.model.SelectedUriCollection;
import com.laevatein.internal.utils.ErrorViewUtils;
import com.laevatein.ui.PhotoSelectionActivity;

import java.util.ArrayList;

/**
 * @author KeithYokoma
 * @since 2014/03/25
 */
public class FinishSelectMenuHandler implements PhotoSelectionOptionsMenuHandler {
    @Override
    public boolean handle(PhotoSelectionActivity activity, Void extra) {
        SelectedUriCollection collection = activity.getCollection();
        if (collection.isCountInRange()) {
            Intent intent = new Intent();
            intent.putParcelableArrayListExtra(PhotoSelectionActivity.EXTRA_RESULT_SELECTION,
                    (ArrayList<? extends Parcelable>) collection.asList());
            activity.setResult(Activity.RESULT_OK, intent);
            activity.finish();
        } else {
            ErrorViewSpec spec = activity.getIntent().getParcelableExtra(PhotoSelectionActivity.EXTRA_ERROR_SPEC);
            ErrorViewResources res = spec.getCountUnderErrorSpec();
            ErrorViewUtils.showErrorView(activity, res);
        }
        return true;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/options/PhotoSelectionOptionsMenu.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper.options;

import android.view.MenuItem;

import com.laevatein.R;
import com.laevatein.internal.misc.ui.helper.options.OptionsMenu;
import com.laevatein.ui.PhotoSelectionActivity;

/**
 * @author KeithYokoma
 * @version 1.0.0
 * @hide
 * @since 2014/03/20
 */
public enum PhotoSelectionOptionsMenu implements OptionsMenu<PhotoSelectionActivity, PhotoSelectionOptionsMenuHandler> {
    SELECT(R.id.action_finish_select, new FinishSelectMenuHandler()),
    UNKNOWN(-1, new UnknownMenuHandler()); // null object pattern

    private final int mMenuId;
    private final PhotoSelectionOptionsMenuHandler mHandler;

    PhotoSelectionOptionsMenu(int menuId, PhotoSelectionOptionsMenuHandler handler) {
        mMenuId = menuId;
        mHandler = handler;
    }

    public static PhotoSelectionOptionsMenu valueOf(MenuItem item) {
        for (PhotoSelectionOptionsMenu menu : values()) {
            if (menu.getMenuId() == item.getItemId()) {
                return menu;
            }
        }
        return UNKNOWN;
    }

    @Override
    public int getMenuId() {
        return mMenuId;
    }

    @Override
    public PhotoSelectionOptionsMenuHandler getHandler() {
        return mHandler;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/options/PhotoSelectionOptionsMenuHandler.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper.options;

import com.laevatein.internal.misc.ui.helper.options.OptionsMenuHandler;
import com.laevatein.ui.PhotoSelectionActivity;

/**
 * @author KeithYokoma
 * @since 2014/03/20
 * @version 1.0.0
 * @hide
 */
public interface PhotoSelectionOptionsMenuHandler extends OptionsMenuHandler<PhotoSelectionActivity, Void> {}

================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/options/UnknownMenuHandler.java
================================================
/*
 * Copyright (C) 2014 nohana, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.laevatein.internal.ui.helper.options;

import com.laevatein.ui.PhotoSelectionActivity;

/**
 * @author KeithYokoma
 * @since 2014/03/25
 */
public class UnknownMenuHandler implements PhotoSelectionOptionsMenuHandler {
    @Override
    public boolean handle(PhotoSelectionActivity activity, Void extra) {
        return false;
    }
}


================================================
FILE: laevatein/src/main/java/com/laevatein/internal/ui/widget/PhotoDecoration.java
================================================
package com.laevatein.internal.ui.widget;

import android.graphics.Rect;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;

public class PhotoDecoration extends RecyclerView.ItemDecoration {

    private int mSpanCount;
    private int mSpacing;
    private boolean mIncludeEdge;

    public PhotoDecoration(int spanCount, int spacing, boolean includeEdge) {
        this.mSpanCount = spanCount;
        this.mSpacing = spacing;
        this.mIncludeEdge = includeEdge;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view);
        int column = position % mSpanCount;

        if (mIncludeEdge) {
            outRect.left = mSpacing - column * mSpacing / mSpanCount;
            outRect.right = (column + 1) * mSpacing / mSpanCount;
            if (position < mSpanCount) {
                outRect.top = mSpacing;
            }
            outRect.bottom = mSpacing;
        } else {
            outRect.left = column * mSpacing / mSpanCount;
            outRect.right = mSpacing - (column + 1) * mSpacing / mSpanCount;
            if (posi
Download .txt
gitextract_gancgo1e/

├── .gitignore
├── .travis.yml
├── README.md
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── laevatein/
│   ├── .gitignore
│   ├── build.gradle
│   ├── gradle.properties
│   ├── proguard-rules.txt
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── laevatein/
│       │               └── MimeTypeTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── laevatein/
│       │   │           ├── Laevatein.java
│       │   │           ├── MimeType.java
│       │   │           ├── SelectionSpecBuilder.java
│       │   │           ├── internal/
│       │   │           │   ├── entity/
│       │   │           │   │   ├── Album.java
│       │   │           │   │   ├── CaptureResources.java
│       │   │           │   │   ├── CounterViewResources.java
│       │   │           │   │   ├── DialogResources.java
│       │   │           │   │   ├── ErrorViewResources.java
│       │   │           │   │   ├── ErrorViewSpec.java
│       │   │           │   │   ├── Item.java
│       │   │           │   │   ├── ItemViewResources.java
│       │   │           │   │   ├── PreviewViewResources.java
│       │   │           │   │   ├── SelectionSpec.java
│       │   │           │   │   ├── UncapableCause.java
│       │   │           │   │   └── ViewResourceSpec.java
│       │   │           │   ├── loader/
│       │   │           │   │   ├── AlbumLoader.java
│       │   │           │   │   └── AlbumPhotoLoader.java
│       │   │           │   ├── misc/
│       │   │           │   │   ├── ui/
│       │   │           │   │   │   ├── ConfirmationDialogFragment.java
│       │   │           │   │   │   ├── FragmentUtils.java
│       │   │           │   │   │   └── helper/
│       │   │           │   │   │       └── options/
│       │   │           │   │   │           ├── OptionsMenu.java
│       │   │           │   │   │           └── OptionsMenuHandler.java
│       │   │           │   │   └── widget/
│       │   │           │   │       └── SquareGridViewItemRelativeLayout.java
│       │   │           │   ├── model/
│       │   │           │   │   ├── AlbumPhotoCollection.java
│       │   │           │   │   ├── DevicePhotoAlbumCollection.java
│       │   │           │   │   ├── PreviewStateHolder.java
│       │   │           │   │   └── SelectedUriCollection.java
│       │   │           │   ├── package-info.java
│       │   │           │   ├── ui/
│       │   │           │   │   ├── AlbumListFragment.java
│       │   │           │   │   ├── PhotoGridFragment.java
│       │   │           │   │   ├── PreviewFragment.java
│       │   │           │   │   ├── SelectedCountFragment.java
│       │   │           │   │   ├── SelectedPhotoGridFragment.java
│       │   │           │   │   ├── adapter/
│       │   │           │   │   │   ├── AlbumPhotoAdapter.java
│       │   │           │   │   │   ├── DevicePhotoAlbumAdapter.java
│       │   │           │   │   │   ├── PreviewPagerAdapter.java
│       │   │           │   │   │   ├── RecyclerViewCursorAdapter.java
│       │   │           │   │   │   └── SelectedPhotoAdapter.java
│       │   │           │   │   ├── helper/
│       │   │           │   │   │   ├── AlbumListViewHelper.java
│       │   │           │   │   │   ├── PhotoGridViewHelper.java
│       │   │           │   │   │   ├── PhotoSelectionActivityDrawerToggle.java
│       │   │           │   │   │   ├── PhotoSelectionViewHelper.java
│       │   │           │   │   │   ├── PreviewHelper.java
│       │   │           │   │   │   ├── SelectedCountViewHelper.java
│       │   │           │   │   │   ├── SelectedGridViewHelper.java
│       │   │           │   │   │   └── options/
│       │   │           │   │   │       ├── FinishSelectMenuHandler.java
│       │   │           │   │   │       ├── PhotoSelectionOptionsMenu.java
│       │   │           │   │   │       ├── PhotoSelectionOptionsMenuHandler.java
│       │   │           │   │   │       └── UnknownMenuHandler.java
│       │   │           │   │   └── widget/
│       │   │           │   │       └── PhotoDecoration.java
│       │   │           │   ├── utils/
│       │   │           │   │   ├── ErrorViewUtils.java
│       │   │           │   │   ├── ExifInterfaceUtils.java
│       │   │           │   │   ├── MediaStoreUtils.java
│       │   │           │   │   └── PhotoMetadataUtils.java
│       │   │           │   └── view/
│       │   │           │       └── PreviewViewPager.java
│       │   │           └── ui/
│       │   │               ├── ImagePreviewActivity.java
│       │   │               └── PhotoSelectionActivity.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   ├── l_bg_drawer_item.xml
│       │       │   ├── l_ic_capture.xml
│       │       │   ├── l_ic_capture_normal.xml
│       │       │   ├── l_ic_capture_pressed.xml
│       │       │   ├── l_ic_folder.xml
│       │       │   ├── l_ic_folder_close.xml
│       │       │   ├── l_ic_folder_open.xml
│       │       │   └── l_list_selector_drawer_menu.xml
│       │       ├── drawable-v21/
│       │       │   └── l_bg_drawer_item.xml
│       │       ├── layout/
│       │       │   ├── l_action_layout_checkbox.xml
│       │       │   ├── l_activity_preview.xml
│       │       │   ├── l_activity_select_photo.xml
│       │       │   ├── l_fragment_default_preview.xml
│       │       │   ├── l_fragment_grid_photo.xml
│       │       │   ├── l_fragment_list_album.xml
│       │       │   ├── l_fragment_selected_count.xml
│       │       │   ├── l_grid_item_default_photo.xml
│       │       │   ├── l_list_item_default_album.xml
│       │       │   └── l_view_counter.xml
│       │       ├── menu/
│       │       │   ├── l_activity_image_preview.xml
│       │       │   └── l_activity_options_select_photo.xml
│       │       ├── values/
│       │       │   ├── attrs.xml
│       │       │   ├── colors.xml
│       │       │   ├── dimens.xml
│       │       │   ├── strings.xml
│       │       │   └── styles.xml
│       │       ├── values-ja/
│       │       │   └── strings.xml
│       │       └── values-v21/
│       │           └── styles.xml
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── laevatein/
│           │           ├── LaevateinTest.java
│           │           ├── MimeTypeTest.java
│           │           ├── SelectionSpecBuilderTest.java
│           │           └── internal/
│           │               └── entity/
│           │                   └── AlbumTest.java
│           └── resources/
│               └── com/
│                   └── laevatein/
│                       └── robolectric.properties
├── repository/
│   └── com/
│       └── laevatein/
│           └── Laevatein/
│               ├── 0.10.0/
│               │   ├── Laevatein-0.10.0.aar
│               │   ├── Laevatein-0.10.0.aar.md5
│               │   ├── Laevatein-0.10.0.aar.sha1
│               │   ├── Laevatein-0.10.0.pom
│               │   ├── Laevatein-0.10.0.pom.md5
│               │   └── Laevatein-0.10.0.pom.sha1
│               ├── 0.10.1/
│               │   ├── Laevatein-0.10.1.aar
│               │   ├── Laevatein-0.10.1.aar.md5
│               │   ├── Laevatein-0.10.1.aar.sha1
│               │   ├── Laevatein-0.10.1.pom
│               │   ├── Laevatein-0.10.1.pom.md5
│               │   └── Laevatein-0.10.1.pom.sha1
│               ├── 0.10.2/
│               │   ├── Laevatein-0.10.2.aar
│               │   ├── Laevatein-0.10.2.aar.md5
│               │   ├── Laevatein-0.10.2.aar.sha1
│               │   ├── Laevatein-0.10.2.pom
│               │   ├── Laevatein-0.10.2.pom.md5
│               │   └── Laevatein-0.10.2.pom.sha1
│               ├── 0.10.3/
│               │   ├── Laevatein-0.10.3.aar
│               │   ├── Laevatein-0.10.3.aar.md5
│               │   ├── Laevatein-0.10.3.aar.sha1
│               │   ├── Laevatein-0.10.3.pom
│               │   ├── Laevatein-0.10.3.pom.md5
│               │   └── Laevatein-0.10.3.pom.sha1
│               ├── 0.10.4/
│               │   ├── Laevatein-0.10.4.aar
│               │   ├── Laevatein-0.10.4.aar.md5
│               │   ├── Laevatein-0.10.4.aar.sha1
│               │   ├── Laevatein-0.10.4.pom
│               │   ├── Laevatein-0.10.4.pom.md5
│               │   └── Laevatein-0.10.4.pom.sha1
│               ├── 0.10.5/
│               │   ├── Laevatein-0.10.5.aar
│               │   ├── Laevatein-0.10.5.aar.md5
│               │   ├── Laevatein-0.10.5.aar.sha1
│               │   ├── Laevatein-0.10.5.pom
│               │   ├── Laevatein-0.10.5.pom.md5
│               │   └── Laevatein-0.10.5.pom.sha1
│               ├── 0.9.0/
│               │   ├── Laevatein-0.9.0.aar
│               │   ├── Laevatein-0.9.0.aar.md5
│               │   ├── Laevatein-0.9.0.aar.sha1
│               │   ├── Laevatein-0.9.0.pom
│               │   ├── Laevatein-0.9.0.pom.md5
│               │   └── Laevatein-0.9.0.pom.sha1
│               ├── 0.9.1/
│               │   ├── Laevatein-0.9.1.aar
│               │   ├── Laevatein-0.9.1.aar.md5
│               │   ├── Laevatein-0.9.1.aar.sha1
│               │   ├── Laevatein-0.9.1.pom
│               │   ├── Laevatein-0.9.1.pom.md5
│               │   └── Laevatein-0.9.1.pom.sha1
│               ├── 0.9.10/
│               │   ├── Laevatein-0.9.10.aar
│               │   ├── Laevatein-0.9.10.aar.md5
│               │   ├── Laevatein-0.9.10.aar.sha1
│               │   ├── Laevatein-0.9.10.pom
│               │   ├── Laevatein-0.9.10.pom.md5
│               │   └── Laevatein-0.9.10.pom.sha1
│               ├── 0.9.11/
│               │   ├── Laevatein-0.9.11.aar
│               │   ├── Laevatein-0.9.11.aar.md5
│               │   ├── Laevatein-0.9.11.aar.sha1
│               │   ├── Laevatein-0.9.11.pom
│               │   ├── Laevatein-0.9.11.pom.md5
│               │   └── Laevatein-0.9.11.pom.sha1
│               ├── 0.9.12/
│               │   ├── Laevatein-0.9.12.aar
│               │   ├── Laevatein-0.9.12.aar.md5
│               │   ├── Laevatein-0.9.12.aar.sha1
│               │   ├── Laevatein-0.9.12.pom
│               │   ├── Laevatein-0.9.12.pom.md5
│               │   └── Laevatein-0.9.12.pom.sha1
│               ├── 0.9.13/
│               │   ├── Laevatein-0.9.13.aar
│               │   ├── Laevatein-0.9.13.aar.md5
│               │   ├── Laevatein-0.9.13.aar.sha1
│               │   ├── Laevatein-0.9.13.pom
│               │   ├── Laevatein-0.9.13.pom.md5
│               │   └── Laevatein-0.9.13.pom.sha1
│               ├── 0.9.14/
│               │   ├── Laevatein-0.9.14.aar
│               │   ├── Laevatein-0.9.14.aar.md5
│               │   ├── Laevatein-0.9.14.aar.sha1
│               │   ├── Laevatein-0.9.14.pom
│               │   ├── Laevatein-0.9.14.pom.md5
│               │   └── Laevatein-0.9.14.pom.sha1
│               ├── 0.9.15/
│               │   ├── Laevatein-0.9.15.aar
│               │   ├── Laevatein-0.9.15.aar.md5
│               │   ├── Laevatein-0.9.15.aar.sha1
│               │   ├── Laevatein-0.9.15.pom
│               │   ├── Laevatein-0.9.15.pom.md5
│               │   └── Laevatein-0.9.15.pom.sha1
│               ├── 0.9.16/
│               │   ├── Laevatein-0.9.16.aar
│               │   ├── Laevatein-0.9.16.aar.md5
│               │   ├── Laevatein-0.9.16.aar.sha1
│               │   ├── Laevatein-0.9.16.pom
│               │   ├── Laevatein-0.9.16.pom.md5
│               │   └── Laevatein-0.9.16.pom.sha1
│               ├── 0.9.2/
│               │   ├── Laevatein-0.9.2.aar
│               │   ├── Laevatein-0.9.2.aar.md5
│               │   ├── Laevatein-0.9.2.aar.sha1
│               │   ├── Laevatein-0.9.2.pom
│               │   ├── Laevatein-0.9.2.pom.md5
│               │   └── Laevatein-0.9.2.pom.sha1
│               ├── 0.9.3/
│               │   ├── Laevatein-0.9.3.aar
│               │   ├── Laevatein-0.9.3.aar.md5
│               │   ├── Laevatein-0.9.3.aar.sha1
│               │   ├── Laevatein-0.9.3.pom
│               │   ├── Laevatein-0.9.3.pom.md5
│               │   └── Laevatein-0.9.3.pom.sha1
│               ├── 0.9.4/
│               │   ├── Laevatein-0.9.4.aar
│               │   ├── Laevatein-0.9.4.aar.md5
│               │   ├── Laevatein-0.9.4.aar.sha1
│               │   ├── Laevatein-0.9.4.pom
│               │   ├── Laevatein-0.9.4.pom.md5
│               │   └── Laevatein-0.9.4.pom.sha1
│               ├── 0.9.5/
│               │   ├── Laevatein-0.9.5.aar
│               │   ├── Laevatein-0.9.5.aar.md5
│               │   ├── Laevatein-0.9.5.aar.sha1
│               │   ├── Laevatein-0.9.5.pom
│               │   ├── Laevatein-0.9.5.pom.md5
│               │   └── Laevatein-0.9.5.pom.sha1
│               ├── 0.9.6/
│               │   ├── Laevatein-0.9.6.aar
│               │   ├── Laevatein-0.9.6.aar.md5
│               │   ├── Laevatein-0.9.6.aar.sha1
│               │   ├── Laevatein-0.9.6.pom
│               │   ├── Laevatein-0.9.6.pom.md5
│               │   └── Laevatein-0.9.6.pom.sha1
│               ├── 0.9.7/
│               │   ├── Laevatein-0.9.7.aar
│               │   ├── Laevatein-0.9.7.aar.md5
│               │   ├── Laevatein-0.9.7.aar.sha1
│               │   ├── Laevatein-0.9.7.pom
│               │   ├── Laevatein-0.9.7.pom.md5
│               │   └── Laevatein-0.9.7.pom.sha1
│               ├── 0.9.8/
│               │   ├── Laevatein-0.9.8.aar
│               │   ├── Laevatein-0.9.8.aar.md5
│               │   ├── Laevatein-0.9.8.aar.sha1
│               │   ├── Laevatein-0.9.8.pom
│               │   ├── Laevatein-0.9.8.pom.md5
│               │   └── Laevatein-0.9.8.pom.sha1
│               ├── 0.9.9/
│               │   ├── Laevatein-0.9.9.aar
│               │   ├── Laevatein-0.9.9.aar.md5
│               │   ├── Laevatein-0.9.9.aar.sha1
│               │   ├── Laevatein-0.9.9.pom
│               │   ├── Laevatein-0.9.9.pom.md5
│               │   └── Laevatein-0.9.9.pom.sha1
│               ├── maven-metadata.xml
│               ├── maven-metadata.xml.md5
│               └── maven-metadata.xml.sha1
├── sample/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.txt
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── laevatein/
│           │           └── sample/
│           │               └── LSampleActivity.java
│           └── res/
│               ├── drawable/
│               │   └── selector_background.xml
│               ├── layout/
│               │   └── activity_sample.xml
│               ├── values/
│               │   ├── colors.xml
│               │   ├── dimens.xml
│               │   ├── strings.xml
│               │   └── styles.xml
│               ├── values-w820dp/
│               │   └── dimens.xml
│               └── xml/
│                   └── file_paths.xml
└── settings.gradle
Download .txt
SYMBOL INDEX (579 symbols across 61 files)

FILE: laevatein/src/androidTest/java/com/laevatein/MimeTypeTest.java
  class MimeTypeTest (line 14) | @RunWith(AndroidJUnit4ClassRunner.class)
    method typeCheck (line 16) | @Test

FILE: laevatein/src/main/java/com/laevatein/Laevatein.java
  class Laevatein (line 40) | @SuppressWarnings("unused") // public APIs
    method Laevatein (line 46) | protected Laevatein(Activity context) {
    method Laevatein (line 51) | protected Laevatein(Activity activity, Fragment fragment) {
    method from (line 62) | public static Laevatein from(Activity activity) {
    method from (line 66) | public static Laevatein from(Fragment fragment) {
    method obtainResult (line 76) | public static List<Uri> obtainResult(Intent data) {
    method choose (line 86) | public SelectionSpecBuilder choose(Set<MimeType> mimeType) {
    method getActivity (line 94) | @Nullable
    method getFragment (line 103) | @Nullable

FILE: laevatein/src/main/java/com/laevatein/MimeType.java
  type MimeType (line 35) | @SuppressWarnings("unused") // public APIs
    method MimeType (line 44) | MimeType(String mimeTypeName, Set<String> extensions) {
    method allOf (line 49) | public static Set<MimeType> allOf() {
    method of (line 53) | public static Set<MimeType> of(MimeType type) {
    method of (line 57) | public static Set<MimeType> of(MimeType type, MimeType... rest) {
    method toString (line 61) | @Override
    method checkType (line 66) | public boolean checkType(ContentResolver resolver, Uri uri) {

FILE: laevatein/src/main/java/com/laevatein/SelectionSpecBuilder.java
  class SelectionSpecBuilder (line 51) | @SuppressWarnings("unused") // public APIs
    method SelectionSpecBuilder (line 83) | SelectionSpecBuilder(Laevatein laevatein, Set<MimeType> mimeType) {
    method theme (line 97) | public SelectionSpecBuilder theme(@StyleRes int theme) {
    method bindEachImageWith (line 109) | public SelectionSpecBuilder bindEachImageWith(int layoutId, int imageV...
    method counterView (line 121) | public SelectionSpecBuilder counterView(@CounterViewResources.VIEW_POS...
    method bindPreviewImageWith (line 133) | public SelectionSpecBuilder bindPreviewImageWith(int layoutId, int ima...
    method count (line 144) | public SelectionSpecBuilder count(int min, int max) {
    method countUnder (line 156) | public SelectionSpecBuilder countUnder(ErrorViewResources.ViewType typ...
    method countUnder (line 167) | public SelectionSpecBuilder countUnder(ErrorViewResources.ViewType typ...
    method countOver (line 178) | public SelectionSpecBuilder countOver(ErrorViewResources.ViewType type...
    method countOver (line 189) | public SelectionSpecBuilder countOver(ErrorViewResources.ViewType type...
    method enableSelectedView (line 200) | public SelectionSpecBuilder enableSelectedView(boolean enableSelectedV...
    method underQuality (line 211) | public SelectionSpecBuilder underQuality(ErrorViewResources.ViewType t...
    method underQuality (line 222) | public SelectionSpecBuilder underQuality(ErrorViewResources.ViewType t...
    method overQuality (line 233) | public SelectionSpecBuilder overQuality(ErrorViewResources.ViewType ty...
    method overQuality (line 244) | public SelectionSpecBuilder overQuality(ErrorViewResources.ViewType ty...
    method underSize (line 255) | public SelectionSpecBuilder underSize(ErrorViewResources.ViewType type...
    method underSize (line 266) | public SelectionSpecBuilder underSize(ErrorViewResources.ViewType type...
    method overSize (line 277) | public SelectionSpecBuilder overSize(ErrorViewResources.ViewType type,...
    method overSize (line 288) | public SelectionSpecBuilder overSize(ErrorViewResources.ViewType type,...
    method invalidType (line 299) | public SelectionSpecBuilder invalidType(ErrorViewResources.ViewType ty...
    method invalidType (line 310) | public SelectionSpecBuilder invalidType(ErrorViewResources.ViewType ty...
    method confirmDialog (line 320) | public SelectionSpecBuilder confirmDialog(int errorMessageId) {
    method confirmDialog (line 330) | public SelectionSpecBuilder confirmDialog(int errorTitleId, int errorM...
    method quality (line 341) | public SelectionSpecBuilder quality(int minPixel, int maxPixel) {
    method size (line 354) | public SelectionSpecBuilder size(int minWidth, int minHeight) {
    method size (line 368) | public SelectionSpecBuilder size(int minWidth, int minHeight, int maxW...
    method albumId (line 380) | public SelectionSpecBuilder albumId(String albumId) {
    method photoSelectionActivityClass (line 390) | public SelectionSpecBuilder photoSelectionActivityClass(Class<? extend...
    method previewActivityClass (line 401) | public SelectionSpecBuilder previewActivityClass(Class<? extends Image...
    method resume (line 411) | public SelectionSpecBuilder resume(List<Uri> uriList) {
    method openDrawer (line 426) | public SelectionSpecBuilder openDrawer(boolean open) {
    method enableCapture (line 438) | public SelectionSpecBuilder enableCapture(String fileProviderAuthoriti...
    method disableCapture (line 449) | public SelectionSpecBuilder disableCapture() {
    method restrictOrientation (line 454) | public SelectionSpecBuilder restrictOrientation(int activityOrientatio...
    method forResult (line 463) | public void forResult(int requestCode) {
    method forResultWithTransition (line 473) | public void forResultWithTransition(int requestCode, View view) {

FILE: laevatein/src/main/java/com/laevatein/internal/entity/Album.java
  class Album (line 34) | public class Album implements Parcelable {
    method createFromParcel (line 36) | @Nullable
    method newArray (line 42) | @Override
    method Album (line 56) | Album(String id, long coverId, String albumName) {
    method Album (line 62) | Album(Parcel source) {
    method valueOf (line 74) | public static Album valueOf(Cursor cursor) {
    method describeContents (line 81) | @Override
    method writeToParcel (line 86) | @Override
    method getId (line 93) | public String getId() {
    method getCoverId (line 97) | public long getCoverId() {
    method getDisplayName (line 101) | public String getDisplayName(Context context) {
    method isAll (line 117) | public boolean isAll() {
    method isCamera (line 121) | public boolean isCamera() {

FILE: laevatein/src/main/java/com/laevatein/internal/entity/CaptureResources.java
  class CaptureResources (line 7) | public class CaptureResources implements Parcelable {
    method createFromParcel (line 10) | @Override
    method newArray (line 15) | @Override
    method CaptureResources (line 24) | public CaptureResources(@Nullable String fileProviderAuthorities) {
    method CaptureResources (line 28) | private CaptureResources(Parcel in) {
    method writeToParcel (line 32) | @Override
    method describeContents (line 37) | @Override
    method enabled (line 42) | public boolean enabled() {
    method getFileProviderAuthorities (line 46) | @Nullable

FILE: laevatein/src/main/java/com/laevatein/internal/entity/CounterViewResources.java
  class CounterViewResources (line 14) | public class CounterViewResources implements Parcelable {
    method createFromParcel (line 16) | @Override
    method newArray (line 21) | @Override
    method CounterViewResources (line 41) | CounterViewResources(Parcel source) {
    method CounterViewResources (line 46) | public CounterViewResources(@VIEW_POSITION int viewPosition, @StringRe...
    method describeContents (line 51) | @Override
    method writeToParcel (line 56) | @Override
    method getViewType (line 62) | @VIEW_POSITION
    method getTextRes (line 67) | @StringRes
    method getDefault (line 72) | public static CounterViewResources getDefault() {
    method readViewPosition (line 79) | @VIEW_POSITION

FILE: laevatein/src/main/java/com/laevatein/internal/entity/DialogResources.java
  class DialogResources (line 10) | public class DialogResources implements Parcelable {
    method createFromParcel (line 12) | @Override
    method newArray (line 17) | @Override
    method DialogResources (line 25) | DialogResources(Parcel source) {
    method DialogResources (line 30) | public DialogResources(int messageId) {
    method DialogResources (line 34) | public DialogResources(int titleId, int messageId) {
    method describeContents (line 39) | @Override
    method writeToParcel (line 44) | @Override
    method getTitleId (line 50) | public int getTitleId() {
    method getMessageId (line 54) | public int getMessageId() {

FILE: laevatein/src/main/java/com/laevatein/internal/entity/ErrorViewResources.java
  class ErrorViewResources (line 10) | public class ErrorViewResources implements Parcelable {
    method createFromParcel (line 12) | @Override
    method newArray (line 17) | @Override
    method ErrorViewResources (line 26) | ErrorViewResources(Parcel source) {
    method ErrorViewResources (line 32) | ErrorViewResources(ViewType viewType, int messageId) {
    method ErrorViewResources (line 36) | ErrorViewResources(ViewType viewType, int titleId, int messageId) {
    method asNoView (line 42) | static ErrorViewResources asNoView() {
    method asAlertDialog (line 46) | static ErrorViewResources asAlertDialog(int titleId, int messageId) {
    method asToast (line 50) | static ErrorViewResources asToast(int messageId) {
    method asSnackbar (line 54) | static ErrorViewResources asSnackbar(int messageId) {
    method describeContents (line 58) | @Override
    method writeToParcel (line 63) | @Override
    method getViewType (line 70) | public ViewType getViewType() {
    method getTitleId (line 74) | public int getTitleId() {
    method getMessageId (line 78) | public int getMessageId() {
    method isNoView (line 82) | public boolean isNoView() {
    type ViewType (line 86) | public enum ViewType {
      method createSpec (line 88) | @Override
      method createSpec (line 94) | @Override
      method createSpec (line 100) | @Override
      method createSpec (line 106) | @Override
      method createSpec (line 112) | public abstract ErrorViewResources createSpec(int titleId, int messa...

FILE: laevatein/src/main/java/com/laevatein/internal/entity/ErrorViewSpec.java
  class ErrorViewSpec (line 15) | public class ErrorViewSpec implements Parcelable {
    method createFromParcel (line 17) | @Override
    method newArray (line 23) | @Override
    method ErrorViewSpec (line 37) | ErrorViewSpec(Parcel source) {
    method ErrorViewSpec (line 48) | ErrorViewSpec(ErrorViewResources countUnderSpec, ErrorViewResources co...
    method describeContents (line 62) | @Override
    method writeToParcel (line 67) | @Override
    method getCountUnderErrorSpec (line 79) | public ErrorViewResources getCountUnderErrorSpec() {
    method getCountOverErrorSpec (line 83) | public ErrorViewResources getCountOverErrorSpec() {
    method getUnderQualitySpec (line 87) | public ErrorViewResources getUnderQualitySpec() {
    method getOverQualitySpec (line 91) | public ErrorViewResources getOverQualitySpec() {
    method getUnderSizeSpec (line 95) | public ErrorViewResources getUnderSizeSpec() {
    method getOverSizeSpec (line 99) | public ErrorViewResources getOverSizeSpec() {
    method getTypeErrorSpec (line 103) | public ErrorViewResources getTypeErrorSpec() {
    method getBackConfirmSpec (line 107) | public DialogResources getBackConfirmSpec() {
    class Builder (line 111) | public static class Builder {
      method setCountUnderSpec (line 121) | public Builder setCountUnderSpec(ErrorViewResources spec) {
      method setCountOverSpec (line 126) | public Builder setCountOverSpec(ErrorViewResources spec) {
      method setUnderQualitySpec (line 131) | public Builder setUnderQualitySpec(ErrorViewResources spec) {
      method setOverQualitySpec (line 136) | public Builder setOverQualitySpec(ErrorViewResources spec) {
      method setUnderSizeSpec (line 141) | public Builder setUnderSizeSpec(ErrorViewResources spec) {
      method setOverSizeSpec (line 146) | public Builder setOverSizeSpec(ErrorViewResources spec) {
      method setTypeSpec (line 151) | public Builder setTypeSpec(ErrorViewResources spec) {
      method setConfirmSpec (line 156) | public Builder setConfirmSpec(DialogResources spec) {
      method create (line 161) | public ErrorViewSpec create() {

FILE: laevatein/src/main/java/com/laevatein/internal/entity/Item.java
  class Item (line 33) | public class Item implements Parcelable {
    method createFromParcel (line 35) | @Override
    method newArray (line 41) | @Override
    method Item (line 50) | Item(long id) {
    method Item (line 54) | Item(Parcel source) {
    method valueOf (line 58) | public static Item valueOf(Cursor cursor) {
    method describeContents (line 62) | @Override
    method writeToParcel (line 67) | @Override
    method getId (line 72) | public long getId() {
    method buildContentUri (line 76) | public Uri buildContentUri() {
    method isCapture (line 80) | public boolean isCapture() {

FILE: laevatein/src/main/java/com/laevatein/internal/entity/ItemViewResources.java
  class ItemViewResources (line 29) | public final class ItemViewResources implements Parcelable {
    method createFromParcel (line 32) | @Override
    method newArray (line 37) | @Override
    method ItemViewResources (line 48) | public ItemViewResources(int layoutId, int imageViewId, int checkBoxId...
    method ItemViewResources (line 55) | ItemViewResources(Parcel source) {
    method getDefault (line 62) | public static ItemViewResources getDefault() {
    method describeContents (line 69) | @Override
    method writeToParcel (line 74) | @Override
    method getLayoutId (line 82) | public int getLayoutId() {
    method getImageViewId (line 86) | public int getImageViewId() {
    method getCheckBoxId (line 90) | public int getCheckBoxId() {
    method getSpanCount (line 94) | public int getSpanCount() {

FILE: laevatein/src/main/java/com/laevatein/internal/entity/PreviewViewResources.java
  class PreviewViewResources (line 29) | public final class PreviewViewResources implements Parcelable {
    method createFromParcel (line 31) | @Override
    method newArray (line 36) | @Override
    method PreviewViewResources (line 45) | public PreviewViewResources(int layoutId, int imageViewId) {
    method PreviewViewResources (line 50) | PreviewViewResources(Parcel source) {
    method getDefault (line 55) | public static PreviewViewResources getDefault() {
    method describeContents (line 62) | @Override
    method writeToParcel (line 67) | @Override
    method getLayoutId (line 73) | public int getLayoutId() {
    method getImageViewId (line 77) | public int getImageViewId() {

FILE: laevatein/src/main/java/com/laevatein/internal/entity/SelectionSpec.java
  class SelectionSpec (line 34) | public final class SelectionSpec implements Parcelable {
    method createFromParcel (line 36) | @Override
    method newArray (line 41) | @Override
    method SelectionSpec (line 57) | public SelectionSpec() {
    method SelectionSpec (line 69) | SelectionSpec(Parcel source) {
    method describeContents (line 84) | @Override
    method writeToParcel (line 89) | @Override
    method setMaxSelectable (line 103) | public void setMaxSelectable(int maxSelectable) {
    method setMinSelectable (line 107) | public void setMinSelectable(int minSelectable) {
    method setMinPixels (line 111) | public void setMinPixels(long minPixels) {
    method setMaxPixels (line 115) | public void setMaxPixels(long maxPixels) {
    method setMinSize (line 119) | public void setMinSize(int minWidthPixels, int minHeightPixels) {
    method setMaxSize (line 124) | public void setMaxSize(int maxWidthPixels, int maxHeightPixels) {
    method setMimeTypeSet (line 129) | public void setMimeTypeSet(Set<MimeType> set) {
    method setDefaultAlbumId (line 133) | public void setDefaultAlbumId(String albumId) {
    method getMinSelectable (line 137) | public int getMinSelectable() {
    method getMaxSelectable (line 141) | public int getMaxSelectable() {
    method getMinPixels (line 145) | public long getMinPixels() {
    method getMaxPixels (line 149) | public long getMaxPixels() {
    method getMinWidthPixels (line 153) | public int getMinWidthPixels() {
    method getMinHeightPixels (line 157) | public int getMinHeightPixels() {
    method getMaxWidthPixels (line 161) | public int getMaxWidthPixels() {
    method getMaxHeightPixels (line 165) | public int getMaxHeightPixels() {
    method getMimeTypeSet (line 169) | public Set<MimeType> getMimeTypeSet() {
    method getDefaultAlbumId (line 173) | public String getDefaultAlbumId() {

FILE: laevatein/src/main/java/com/laevatein/internal/entity/UncapableCause.java
  type UncapableCause (line 24) | public enum UncapableCause {
    method getErrorResources (line 26) | @Override
    method getErrorResources (line 32) | @Override
    method getErrorResources (line 38) | @Override
    method getErrorResources (line 44) | @Override
    method getErrorResources (line 50) | @Override
    method getErrorResources (line 56) | @Override
    method getErrorResources (line 62) | public abstract ErrorViewResources getErrorResources(ErrorViewSpec spec);

FILE: laevatein/src/main/java/com/laevatein/internal/entity/ViewResourceSpec.java
  class ViewResourceSpec (line 16) | public class ViewResourceSpec implements Parcelable {
    method createFromParcel (line 18) | @Override
    method newArray (line 24) | @Override
    method ViewResourceSpec (line 41) | ViewResourceSpec(Parcel source) {
    method ViewResourceSpec (line 53) | ViewResourceSpec(
    method describeContents (line 74) | @Override
    method writeToParcel (line 79) | @Override
    class Builder (line 92) | public static class Builder {
      method setTheme (line 104) | public Builder setTheme(@StyleRes int theme) {
      method setPreviewClass (line 109) | public Builder setPreviewClass(Class<? extends ImagePreviewActivity>...
      method setItemViewResources (line 114) | public Builder setItemViewResources(ItemViewResources itemViewResour...
      method setCounterViewResources (line 119) | public Builder setCounterViewResources(CounterViewResources counterV...
      method setPreviewViewResources (line 124) | public Builder setPreviewViewResources(PreviewViewResources previewV...
      method setOpenDrawer (line 129) | public Builder setOpenDrawer(boolean openDrawer) {
      method setCaptureResources (line 134) | public Builder setCaptureResources(CaptureResources captureResources) {
      method setEnableSelectedView (line 139) | public Builder setEnableSelectedView(boolean enableSelectedView) {
      method setActivityOrientation (line 144) | public Builder setActivityOrientation(int activityOrientation) {
      method create (line 149) | public ViewResourceSpec create() {
    method getTheme (line 165) | public int getTheme() {
    method getPreviewActivityClass (line 169) | public Class<? extends ImagePreviewActivity> getPreviewActivityClass() {
    method getItemViewResources (line 173) | public ItemViewResources getItemViewResources() {
    method getCounterViewResources (line 177) | public CounterViewResources getCounterViewResources() {
    method getPreviewViewResources (line 181) | public PreviewViewResources getPreviewViewResources() {
    method openDrawer (line 185) | public boolean openDrawer() {
    method getCaptureResource (line 189) | public CaptureResources getCaptureResource() {
    method isEnableSelectedView (line 193) | public boolean isEnableSelectedView() {
    method needActivityOrientationRestriction (line 197) | public boolean needActivityOrientationRestriction() {
    method getActivityOrientation (line 201) | public int getActivityOrientation() {

FILE: laevatein/src/main/java/com/laevatein/internal/loader/AlbumLoader.java
  class AlbumLoader (line 37) | public class AlbumLoader extends CursorLoader {
    method AlbumLoader (line 43) | public AlbumLoader(Context context) {
    method loadInBackground (line 47) | @Override
    class BucketEntry (line 78) | private static class BucketEntry {
      method BucketEntry (line 82) | public BucketEntry(String displayName, String mediaId) {

FILE: laevatein/src/main/java/com/laevatein/internal/loader/AlbumPhotoLoader.java
  class AlbumPhotoLoader (line 36) | public class AlbumPhotoLoader extends CursorLoader {
    method AlbumPhotoLoader (line 42) | public AlbumPhotoLoader(Context context, Uri uri, String[] projection,...
    method newInstance (line 47) | public static CursorLoader newInstance(Context context, Album album) {
    method newInstance (line 54) | public static CursorLoader newInstance(Context context, Album album, b...
    method loadInBackground (line 59) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/misc/ui/ConfirmationDialogFragment.java
  class ConfirmationDialogFragment (line 35) | public class ConfirmationDialogFragment extends DialogFragment {
    method ConfirmationDialogFragment (line 41) | public ConfirmationDialogFragment() {}
    method newInstance (line 43) | public static ConfirmationDialogFragment newInstance(int message) {
    method newInstance (line 51) | public static ConfirmationDialogFragment newInstance(int title, int me...
    method onAttach (line 60) | @Override
    method onCreateDialog (line 71) | @NonNull
    type ConfirmationSelectionListener (line 99) | public interface ConfirmationSelectionListener {
      method onPositive (line 100) | void onPositive();
      method onNegative (line 101) | void onNegative();

FILE: laevatein/src/main/java/com/laevatein/internal/misc/ui/FragmentUtils.java
  class FragmentUtils (line 30) | public final class FragmentUtils {
    method FragmentUtils (line 31) | private FragmentUtils() {}
    method getIntentParcelableExtra (line 33) | public static <T extends Parcelable> T getIntentParcelableExtra(Fragme...
    method getIntentBooleanExtra (line 39) | public static boolean getIntentBooleanExtra(Fragment fragment, String ...
    method findViewById (line 45) | public static View findViewById(Fragment fragment, int id) {

FILE: laevatein/src/main/java/com/laevatein/internal/misc/ui/helper/options/OptionsMenu.java
  type OptionsMenu (line 26) | public interface OptionsMenu<A extends Activity, H extends OptionsMenuHa...
    method getMenuId (line 27) | int getMenuId();
    method getHandler (line 28) | H getHandler();

FILE: laevatein/src/main/java/com/laevatein/internal/misc/ui/helper/options/OptionsMenuHandler.java
  type OptionsMenuHandler (line 26) | public interface OptionsMenuHandler<A extends Activity, E> {
    method handle (line 27) | boolean handle(A activity, E extra);

FILE: laevatein/src/main/java/com/laevatein/internal/misc/widget/SquareGridViewItemRelativeLayout.java
  class SquareGridViewItemRelativeLayout (line 28) | public class SquareGridViewItemRelativeLayout extends RelativeLayout {
    method SquareGridViewItemRelativeLayout (line 29) | public SquareGridViewItemRelativeLayout(Context context) {
    method SquareGridViewItemRelativeLayout (line 33) | public SquareGridViewItemRelativeLayout(Context context, AttributeSet ...
    method SquareGridViewItemRelativeLayout (line 37) | public SquareGridViewItemRelativeLayout(Context context, AttributeSet ...
    method onMeasure (line 41) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/model/AlbumPhotoCollection.java
  class AlbumPhotoCollection (line 39) | public class AlbumPhotoCollection implements LoaderManager.LoaderCallbac...
    method onCreateLoader (line 47) | @Override
    method onLoadFinished (line 66) | @Override
    method onLoaderReset (line 76) | @Override
    method onCreate (line 86) | public void onCreate(@NonNull FragmentActivity context, @NonNull Album...
    method onDestroy (line 92) | public void onDestroy() {
    method load (line 97) | public void load(@Nullable Album target) {
    method load (line 101) | public void load(@Nullable Album target, boolean enableCapture) {
    type AlbumPhotoCallbacks (line 108) | public interface AlbumPhotoCallbacks {
      method onLoad (line 109) | void onLoad(Cursor cursor);
      method onReset (line 110) | void onReset();

FILE: laevatein/src/main/java/com/laevatein/internal/model/DevicePhotoAlbumCollection.java
  class DevicePhotoAlbumCollection (line 36) | public class DevicePhotoAlbumCollection implements LoaderManager.LoaderC...
    method onCreateLoader (line 44) | @Override
    method onLoadFinished (line 53) | @Override
    method onLoaderReset (line 63) | @Override
    method onCreate (line 73) | public void onCreate(FragmentActivity activity, DevicePhotoAlbumCallba...
    method onRestoreInstanceState (line 79) | public void onRestoreInstanceState(Bundle savedInstanceState) {
    method onSaveInstanceState (line 87) | public void onSaveInstanceState(Bundle outState) {
    method onDestroy (line 91) | public void onDestroy() {
    method loadAlbums (line 96) | public void loadAlbums() {
    method getCurrentSelection (line 100) | public int getCurrentSelection() {
    method setStateCurrentSelection (line 104) | public void setStateCurrentSelection(int currentSelection) {
    type DevicePhotoAlbumCallbacks (line 108) | public interface DevicePhotoAlbumCallbacks {
      method onLoad (line 109) | void onLoad(Cursor cursor);
      method onReset (line 110) | void onReset();

FILE: laevatein/src/main/java/com/laevatein/internal/model/PreviewStateHolder.java
  class PreviewStateHolder (line 18) | public class PreviewStateHolder {
    method PreviewStateHolder (line 23) | public PreviewStateHolder(Activity activity) {
    method onCreate (line 27) | public void onCreate() {
    method onRestoreInstanceState (line 35) | public void onRestoreInstanceState(Bundle savedInstanceState) {
    method onSaveInstanceState (line 42) | public void onSaveInstanceState(Bundle outState) {
    method isChecked (line 46) | public boolean isChecked(Uri uri) {
    method setChecked (line 50) | public void setChecked(Uri uri, boolean checked) {
    method getCheckedCount (line 58) | public int getCheckedCount() {
    method getAllChecked (line 62) | public List<Uri> getAllChecked() {

FILE: laevatein/src/main/java/com/laevatein/internal/model/SelectedUriCollection.java
  class SelectedUriCollection (line 39) | public class SelectedUriCollection {
    method SelectedUriCollection (line 45) | public SelectedUriCollection(Context context) {
    method onCreate (line 49) | public void onCreate(Bundle savedInstanceState) {
    method prepareSelectionSpec (line 58) | public void prepareSelectionSpec(SelectionSpec spec) {
    method setDefaultSelection (line 62) | public void setDefaultSelection(List<Uri> uris) {
    method onSaveInstanceState (line 66) | public void onSaveInstanceState(Bundle outState) {
    method add (line 70) | public boolean add(Uri uri) {
    method remove (line 74) | public boolean remove(Uri uri) {
    method overwrite (line 78) | public void overwrite(ArrayList<Uri> uriLists) {
    method asList (line 83) | public List<Uri> asList() {
    method isEmpty (line 87) | public boolean isEmpty() {
    method isSelected (line 91) | public boolean isSelected(Uri uri) {
    method isAcceptable (line 95) | public UncapableCause isAcceptable(Uri uri) {
    method isCountInRange (line 99) | public boolean isCountInRange() {
    method isCountOver (line 103) | public boolean isCountOver() {
    method count (line 107) | public int count() {
    method maxCount (line 111) | public int maxCount() {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/AlbumListFragment.java
  class AlbumListFragment (line 41) | public class AlbumListFragment extends Fragment implements
    method newInstance (line 50) | public static AlbumListFragment newInstance(String defaultAlbumId) {
    method onAttach (line 59) | @Override
    method onCreateView (line 69) | @Override
    method onActivityCreated (line 74) | @Override
    method onSaveInstanceState (line 90) | @Override
    method onDestroyView (line 96) | @Override
    method onItemClick (line 102) | @Override
    method onLoad (line 115) | @Override
    method onReset (line 121) | @Override
    type OnDirectorySelectListener (line 126) | public interface OnDirectorySelectListener {
      method onSelect (line 127) | void onSelect(Album album);

FILE: laevatein/src/main/java/com/laevatein/internal/ui/PhotoGridFragment.java
  class PhotoGridFragment (line 41) | public class PhotoGridFragment extends Fragment implements
    method newInstance (line 47) | public static PhotoGridFragment newInstance(Album album) {
    method onCreateView (line 55) | @Override
    method onActivityCreated (line 60) | @Override
    method onDestroyView (line 77) | @Override
    method onLoad (line 84) | @Override
    method onReset (line 89) | @Override
    method onUpdate (line 94) | @Override
    method refreshGrid (line 99) | public void refreshGrid() {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/PreviewFragment.java
  class PreviewFragment (line 24) | public class PreviewFragment extends Fragment {
    method newInstance (line 30) | public static PreviewFragment newInstance(Uri uri, PreviewViewResource...
    method onCreateView (line 39) | @Override
    method onActivityCreated (line 45) | @Override
    method resetView (line 57) | public void resetView() {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/SelectedCountFragment.java
  class SelectedCountFragment (line 21) | public class SelectedCountFragment extends Fragment {
    method onAttach (line 24) | @Override
    method onCreate (line 36) | @Override
    method onCreateView (line 42) | @Override
    method onActivityCreated (line 47) | @Override
    method onPrepareOptionsMenu (line 54) | @Override
    method getListener (line 60) | public OnShowSelectedClickListener getListener() {
    type OnShowSelectedClickListener (line 64) | public interface OnShowSelectedClickListener {
      method onClickSelectedView (line 65) | void onClickSelectedView();

FILE: laevatein/src/main/java/com/laevatein/internal/ui/SelectedPhotoGridFragment.java
  class SelectedPhotoGridFragment (line 37) | public class SelectedPhotoGridFragment extends Fragment implements Selec...
    method SelectedPhotoGridFragment (line 40) | public SelectedPhotoGridFragment() {
    method newInstance (line 43) | public static SelectedPhotoGridFragment newInstance() {
    method onCreateView (line 47) | @Override
    method onActivityCreated (line 52) | @Override
    method onDestroyView (line 60) | @Override
    method onUpdate (line 66) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/AlbumPhotoAdapter.java
  class AlbumPhotoAdapter (line 44) | public class AlbumPhotoAdapter extends RecyclerViewCursorAdapter<AlbumPh...
    method AlbumPhotoAdapter (line 52) | public AlbumPhotoAdapter(Context context, ViewResourceSpec resources, ...
    method onCreateViewHolder (line 61) | @Override
    method onBindViewHolder (line 67) | @Override
    method registerCheckStateListener (line 102) | public void registerCheckStateListener(CheckStateListener listener) {
    method unregisterCheckStateListener (line 106) | public void unregisterCheckStateListener() {
    type CheckStateListener (line 110) | public interface CheckStateListener {
      method onUpdate (line 111) | void onUpdate();
    type BindViewListener (line 114) | public interface BindViewListener {
      method onBindView (line 122) | void onBindView(Context context, View view, Uri uri);
    class ViewHolder (line 125) | static class ViewHolder extends RecyclerView.ViewHolder {
      method ViewHolder (line 129) | ViewHolder(View v, ItemViewResources resources) {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/DevicePhotoAlbumAdapter.java
  class DevicePhotoAlbumAdapter (line 36) | public class DevicePhotoAlbumAdapter extends CursorAdapter {
    method DevicePhotoAlbumAdapter (line 38) | public DevicePhotoAlbumAdapter(Context context, Cursor c) {
    method newView (line 42) | @Override
    method bindView (line 48) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/PreviewPagerAdapter.java
  class PreviewPagerAdapter (line 20) | public class PreviewPagerAdapter extends FragmentPagerAdapter {
    method PreviewPagerAdapter (line 27) | public PreviewPagerAdapter(FragmentManager manager, PreviewViewResourc...
    method getItem (line 34) | @Override
    method getCount (line 39) | @Override
    method setPrimaryItem (line 44) | @Override
    method getUri (line 50) | public Uri getUri(int position) {
    method addAll (line 54) | public void addAll(List<Uri> uris) {
    type OnPrimaryItemSetListener (line 58) | public interface OnPrimaryItemSetListener {
      method onPrimaryItemSet (line 59) | void onPrimaryItemSet(int position);

FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/RecyclerViewCursorAdapter.java
  class RecyclerViewCursorAdapter (line 12) | public abstract class RecyclerViewCursorAdapter<VH extends RecyclerView....
    method onBindViewHolder (line 16) | protected abstract void onBindViewHolder(VH holder, Cursor cursor);
    method RecyclerViewCursorAdapter (line 18) | RecyclerViewCursorAdapter(Cursor c) {
    method onBindViewHolder (line 23) | @Override
    method getItemCount (line 36) | @Override
    method getItemId (line 45) | @Override
    method swapCursor (line 58) | public void swapCursor(Cursor newCursor) {
    method getCursor (line 74) | public Cursor getCursor() {
    method isDataValid (line 78) | private boolean isDataValid(Cursor cursor) {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/adapter/SelectedPhotoAdapter.java
  class SelectedPhotoAdapter (line 42) | public class SelectedPhotoAdapter extends RecyclerView.Adapter<SelectedP...
    method SelectedPhotoAdapter (line 50) | public SelectedPhotoAdapter(Context context, ItemViewResources resourc...
    method onCreateViewHolder (line 57) | @Override
    method onBindViewHolder (line 63) | @Override
    method getItemCount (line 80) | @Override
    method registerCheckStateListener (line 85) | public void registerCheckStateListener(CheckStateListener listener) {
    method unregisterCheckStateListener (line 89) | public void unregisterCheckStateListener() {
    type CheckStateListener (line 93) | public interface CheckStateListener {
      method onUpdate (line 94) | void onUpdate();
    class ViewHolder (line 97) | static class ViewHolder extends RecyclerView.ViewHolder {
      method ViewHolder (line 101) | ViewHolder(View v, ItemViewResources resources) {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/AlbumListViewHelper.java
  class AlbumListViewHelper (line 44) | public final class AlbumListViewHelper {
    method AlbumListViewHelper (line 45) | private AlbumListViewHelper() {
    method setUpHeader (line 49) | public static void setUpHeader(Fragment fragment) {
    method setUpListView (line 61) | public static void setUpListView(Fragment fragment, AdapterView.OnItem...
    method setCursor (line 67) | public static void setCursor(Fragment fragment, Cursor cursor) {
    method callOnSelect (line 78) | public static void callOnSelect(AlbumListFragment.OnDirectorySelectLis...
    method callOnDefaultSelect (line 83) | public static void callOnDefaultSelect(final Fragment fragment, final ...
    method setCheckedState (line 120) | public static void setCheckedState(Fragment fragment, int position) {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoGridViewHelper.java
  class PhotoGridViewHelper (line 56) | public final class PhotoGridViewHelper {
    method PhotoGridViewHelper (line 57) | private PhotoGridViewHelper() {
    method getSelectedPhotoSet (line 61) | public static SelectedUriCollection getSelectedPhotoSet(Fragment fragm...
    method setUpGridView (line 65) | public static void setUpGridView(Fragment fragment, ViewResourceSpec r...
    method tearDownGridView (line 89) | public static void tearDownGridView(Fragment fragment) {
    method setCursor (line 95) | public static void setCursor(Fragment fragment, Cursor cursor) {
    method refreshView (line 109) | public static void refreshView(Fragment fragment) {
    method callPreview (line 115) | public static void callPreview(Context context, Item item, List<Uri> c...
    method callCamera (line 130) | public static void callCamera(Context context, String fileProviderAuth...
    method syncCheckState (line 137) | public static void syncCheckState(Context context, SelectedUriCollecti...
    method removeSelection (line 146) | public static void removeSelection(SelectedUriCollection collection, U...
    method addSelection (line 151) | public static void addSelection(Context context, SelectedUriCollection...
    method callCheckStateListener (line 172) | public static void callCheckStateListener(AlbumPhotoAdapter.CheckState...

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoSelectionActivityDrawerToggle.java
  class PhotoSelectionActivityDrawerToggle (line 35) | public class PhotoSelectionActivityDrawerToggle extends ActionBarDrawerT...
    method PhotoSelectionActivityDrawerToggle (line 51) | public PhotoSelectionActivityDrawerToggle(Activity activity, DrawerLay...
    method PhotoSelectionActivityDrawerToggle (line 57) | public PhotoSelectionActivityDrawerToggle(Activity activity, DrawerLay...
    method setUpActionBar (line 63) | public void setUpActionBar(ActionBar actionBar) {
    method onDrawerClosed (line 71) | @Override
    method onDrawerOpened (line 77) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoSelectionViewHelper.java
  class PhotoSelectionViewHelper (line 49) | public final class PhotoSelectionViewHelper {
    method PhotoSelectionViewHelper (line 50) | private PhotoSelectionViewHelper() {
    method setUpActivity (line 54) | public static void setUpActivity(PhotoSelectionActivity activity) {
    method setUpCounter (line 61) | public static void setUpCounter(PhotoSelectionActivity activity) {
    method refreshOptionsMenuState (line 78) | public static void refreshOptionsMenuState(PhotoSelectionActivity acti...
    method updateSelectMenuState (line 88) | public static void updateSelectMenuState(MenuItem item, ErrorViewResou...
    method setPhotoGridFragment (line 100) | public static void setPhotoGridFragment(FragmentActivity activity, Dra...
    method setAlbumList (line 116) | public static void setAlbumList(FragmentActivity activity, String albu...
    method setSelectedGridFragment (line 124) | public static void setSelectedGridFragment(FragmentActivity activity) {
    method refreshGridView (line 132) | public static void refreshGridView(FragmentActivity activity) {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/PreviewHelper.java
  class PreviewHelper (line 52) | public final class PreviewHelper {
    method PreviewHelper (line 53) | private PreviewHelper() {
    method setUpActivity (line 57) | public static void setUpActivity(ImagePreviewActivity activity) {
    method setUpActionBar (line 74) | public static void setUpActionBar(AppCompatActivity activity) {
    method setUpActionItem (line 83) | public static void setUpActionItem(final ImagePreviewActivity activity...
    method sendBackResult (line 122) | public static void sendBackResult(ImagePreviewActivity activity) {

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/SelectedCountViewHelper.java
  class SelectedCountViewHelper (line 18) | public final class SelectedCountViewHelper {
    method SelectedCountViewHelper (line 19) | private SelectedCountViewHelper() {
    method setUpCountView (line 23) | public static void setUpCountView(final SelectedCountFragment fragment) {
    method updateCountView (line 35) | public static void updateCountView(PhotoSelectionActivity activity, Se...

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/SelectedGridViewHelper.java
  class SelectedGridViewHelper (line 38) | public final class SelectedGridViewHelper {
    method SelectedGridViewHelper (line 39) | private SelectedGridViewHelper() {
    method getSelectedPhotoSet (line 43) | public static SelectedUriCollection getSelectedPhotoSet(Fragment fragm...
    method setUpGridView (line 47) | public static void setUpGridView(Fragment fragment, ItemViewResources ...
    method tearDownGridView (line 71) | public static void tearDownGridView(Fragment fragment) {
    method syncCollection (line 77) | public static void syncCollection(SelectedUriCollection collection, Ur...
    method callCheckStateListener (line 85) | public static void callCheckStateListener(SelectedPhotoAdapter.CheckSt...

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/options/FinishSelectMenuHandler.java
  class FinishSelectMenuHandler (line 34) | public class FinishSelectMenuHandler implements PhotoSelectionOptionsMen...
    method handle (line 35) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/options/PhotoSelectionOptionsMenu.java
  type PhotoSelectionOptionsMenu (line 30) | public enum PhotoSelectionOptionsMenu implements OptionsMenu<PhotoSelect...
    method PhotoSelectionOptionsMenu (line 37) | PhotoSelectionOptionsMenu(int menuId, PhotoSelectionOptionsMenuHandler...
    method valueOf (line 42) | public static PhotoSelectionOptionsMenu valueOf(MenuItem item) {
    method getMenuId (line 51) | @Override
    method getHandler (line 56) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/options/PhotoSelectionOptionsMenuHandler.java
  type PhotoSelectionOptionsMenuHandler (line 27) | public interface PhotoSelectionOptionsMenuHandler extends OptionsMenuHan...

FILE: laevatein/src/main/java/com/laevatein/internal/ui/helper/options/UnknownMenuHandler.java
  class UnknownMenuHandler (line 24) | public class UnknownMenuHandler implements PhotoSelectionOptionsMenuHand...
    method handle (line 25) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/ui/widget/PhotoDecoration.java
  class PhotoDecoration (line 7) | public class PhotoDecoration extends RecyclerView.ItemDecoration {
    method PhotoDecoration (line 13) | public PhotoDecoration(int spanCount, int spacing, boolean includeEdge) {
    method getItemOffsets (line 19) | @Override

FILE: laevatein/src/main/java/com/laevatein/internal/utils/ErrorViewUtils.java
  class ErrorViewUtils (line 18) | public final class ErrorViewUtils {
    method ErrorViewUtils (line 19) | private ErrorViewUtils() {
    method showErrorView (line 23) | public static void showErrorView(FragmentActivity activity, ErrorViewR...
    method showConfirmDialog (line 43) | public static void showConfirmDialog(FragmentActivity activity, Dialog...

FILE: laevatein/src/main/java/com/laevatein/internal/utils/ExifInterfaceUtils.java
  class ExifInterfaceUtils (line 20) | public class ExifInterfaceUtils {
    method ExifInterfaceUtils (line 26) | private ExifInterfaceUtils() {
    method getExifDateTime (line 29) | private static Date getExifDateTime(String filepath) {
    method getExifDateTimeInMillis (line 58) | public static long getExifDateTimeInMillis(String filepath) {

FILE: laevatein/src/main/java/com/laevatein/internal/utils/MediaStoreUtils.java
  class MediaStoreUtils (line 40) | public class MediaStoreUtils {
    method MediaStoreUtils (line 57) | public MediaStoreUtils(Context context, Handler handler) {
    method hasCameraFeature (line 77) | public static final boolean hasCameraFeature(Context context) {
    method invokeCameraCapture (line 89) | public String invokeCameraCapture(Activity activity, String fileProvid...
    method destroy (line 106) | public void destroy() {
    method getCapturedPhotoUri (line 115) | public Uri getCapturedPhotoUri(Intent data, String preparedUri) {
    method cleanUp (line 147) | public void cleanUp(String uri) {
    method getPathFromUri (line 159) | public static String getPathFromUri(ContentResolver resolver, Uri cont...
    method copyFileStream (line 181) | public static long copyFileStream(FileInputStream is, FileOutputStream...
    method findPhotoFromRecentlyTaken (line 201) | private Uri findPhotoFromRecentlyTaken(File file) {
    method storeImage (line 236) | private Uri storeImage(File file) {
    method updateLatestPhotos (line 271) | private void updateLatestPhotos() {
    method generateThumbnails (line 303) | private void generateThumbnails(long imageId) {
    method getOutputFile (line 317) | @TargetApi(Build.VERSION_CODES.FROYO)
    class PhotoContent (line 336) | private static class PhotoContent {

FILE: laevatein/src/main/java/com/laevatein/internal/utils/PhotoMetadataUtils.java
  class PhotoMetadataUtils (line 45) | public final class PhotoMetadataUtils {
    method PhotoMetadataUtils (line 49) | private PhotoMetadataUtils() {
    method getPixelsCount (line 53) | public static int getPixelsCount(ContentResolver resolver, Uri uri) {
    method getBitmapBound (line 58) | private static Point getBitmapBound(ContentResolver resolver, Uri uri) {
    method getPath (line 75) | public static String getPath(ContentResolver resolver, Uri uri) {
    method isAcceptable (line 95) | public static UncapableCause isAcceptable(Context context, SelectionSp...
    method hasOverAtLeastQuality (line 114) | public static boolean hasOverAtLeastQuality(Context context, Selection...
    method hasUnderAtMostQuality (line 123) | public static boolean hasUnderAtMostQuality(Context context, Selection...
    method isLargerThanMinSize (line 132) | public static boolean isLargerThanMinSize(Context context, SelectionSp...
    method isSmallerThanMaxSize (line 140) | public static boolean isSmallerThanMaxSize(Context context, SelectionS...
    method isSelectableType (line 149) | public static boolean isSelectableType(Context context, SelectionSpec ...
    method shouldRotate (line 163) | public static boolean shouldRotate(ContentResolver resolver, Uri uri) {
    class ContentResolverWrapper (line 176) | static final class ContentResolverWrapper {
      method openInputStream (line 177) | @Nullable

FILE: laevatein/src/main/java/com/laevatein/internal/view/PreviewViewPager.java
  class PreviewViewPager (line 15) | public class PreviewViewPager extends ViewPager {
    method PreviewViewPager (line 17) | public PreviewViewPager(Context context, AttributeSet attrs) {
    method canScroll (line 21) | @Override

FILE: laevatein/src/main/java/com/laevatein/ui/ImagePreviewActivity.java
  class ImagePreviewActivity (line 51) | public class ImagePreviewActivity extends AppCompatActivity implements A...
    method onCreate (line 69) | @Override
    method onSaveInstanceState (line 85) | @Override
    method onCreateOptionsMenu (line 91) | @Override
    method onOptionsItemSelected (line 100) | @Override
    method onBackPressed (line 110) | @Override
    method onDestroy (line 116) | @Override
    method getStateHolder (line 122) | public PreviewStateHolder getStateHolder() {
    method onLoad (line 126) | @Override
    method onReset (line 146) | @Override
    method onPrimaryItemSet (line 150) | @Override

FILE: laevatein/src/main/java/com/laevatein/ui/PhotoSelectionActivity.java
  class PhotoSelectionActivity (line 58) | public class PhotoSelectionActivity extends AppCompatActivity implements
    method onCreate (line 77) | @Override
    method onPostCreate (line 100) | @Override
    method onSaveInstanceState (line 106) | @Override
    method onConfigurationChanged (line 113) | @Override
    method onDestroy (line 119) | @Override
    method onActivityResult (line 125) | @Override
    method onCreateOptionsMenu (line 144) | @Override
    method onPrepareOptionsMenu (line 150) | @Override
    method onOptionsItemSelected (line 156) | @Override
    method onBackPressed (line 162) | @Override
    method onSelect (line 173) | @Override
    method onClickSelectedView (line 178) | @Override
    method onBindView (line 183) | @Override
    method getCollection (line 187) | public final SelectedUriCollection getCollection() {
    method getMediaStoreUtils (line 191) | public final MediaStoreUtils getMediaStoreUtils() {
    method prepareCapture (line 195) | public final void prepareCapture(String uri) {
    method isDrawerOpen (line 199) | public final boolean isDrawerOpen() {
    method onPositive (line 203) | @Override
    method onNegative (line 209) | @Override

FILE: laevatein/src/test/java/com/laevatein/LaevateinTest.java
  class LaevateinTest (line 26) | @RunWith(RobolectricTestRunner.class)
    method setUp (line 30) | @Before
    method from_returnsLaevatein (line 35) | @Test
    method obtainResult_returnsSomeUri (line 41) | @Test

FILE: laevatein/src/test/java/com/laevatein/MimeTypeTest.java
  class MimeTypeTest (line 17) | @RunWith(RobolectricTestRunner.class)
    method oneOf (line 19) | @Test
    method someOf (line 46) | @Test
    method allOf (line 81) | @Test
    method stringify (line 90) | @Test

FILE: laevatein/src/test/java/com/laevatein/SelectionSpecBuilderTest.java
  class SelectionSpecBuilderTest (line 24) | @RunWith(RobolectricTestRunner.class)
    method setUp (line 30) | @Before
    method ensureAllExtrasExist (line 56) | private void ensureAllExtrasExist(Intent intent) {
    method count (line 63) | @Test
    method enableCapture (line 72) | @Test
    method disableCapture (line 81) | @Test
    method quality (line 90) | @Test
    method size (line 99) | @Test
    method resume (line 108) | @Test

FILE: laevatein/src/test/java/com/laevatein/internal/entity/AlbumTest.java
  class AlbumTest (line 20) | @RunWith(RobolectricTestRunner.class)
    method camera (line 24) | @Test
    method all (line 38) | @Test
    method download (line 52) | @Test
    method screenshot (line 66) | @Test

FILE: sample/src/main/java/com/laevatein/sample/LSampleActivity.java
  class LSampleActivity (line 31) | @RuntimePermissions
    method onCreate (line 37) | @Override
    method onActivityResult (line 53) | @Override
    method onRequestPermissionsResult (line 62) | @Override
    method startPhotoSelect (line 68) | @NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
    method showDeniedForCamera (line 85) | @OnPermissionDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)
    method showNeverAskForCamera (line 90) | @OnNeverAskAgain(Manifest.permission.WRITE_EXTERNAL_STORAGE)
Condensed preview — 259 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (346K chars).
[
  {
    "path": ".gitignore",
    "chars": 454,
    "preview": "# build app files\n*.apk\n*.ap_\n\n# ignore crashlytics config\ncom_crashlytics_export_strings.xml\n\n# Dalvik files\n*.dex\n\n# J"
  },
  {
    "path": ".travis.yml",
    "chars": 1206,
    "preview": "language: android\njdk: oraclejdk8\nenv:\n global:\n    - ANDROID_SDK=android-29\n    - ANDROID_BUILD_TOOLS_VERSION=28.0.3\n  "
  },
  {
    "path": "README.md",
    "chars": 6651,
    "preview": "⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ \n\n**WARNING: This library is no longer maintained.**\n\n⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ \n\nThank you "
  },
  {
    "path": "build.gradle",
    "chars": 336,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    r"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 232,
    "preview": "#Thu Nov 30 10:11:36 JST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 1558,
    "preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Settings specified in this file will override any G"
  },
  {
    "path": "gradlew",
    "chars": 5080,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2404,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "laevatein/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "laevatein/build.gradle",
    "chars": 2073,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion 29\n\n    defaultConfig {\n        minSdkVersion 14\n  "
  },
  {
    "path": "laevatein/gradle.properties",
    "chars": 62,
    "preview": "POM_NAME=Laevatein\nPOM_ARTIFACT_ID=Laevatein\nPOM_PACKAGING=aar"
  },
  {
    "path": "laevatein/proguard-rules.txt",
    "chars": 699,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /L"
  },
  {
    "path": "laevatein/src/androidTest/java/com/laevatein/MimeTypeTest.java",
    "chars": 2069,
    "preview": "package com.laevatein;\n\nimport android.net.Uri;\nimport android.test.mock.MockContentResolver;\n\nimport org.junit.Test;\nim"
  },
  {
    "path": "laevatein/src/main/AndroidManifest.xml",
    "chars": 461,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.laevatein\">\n\n    <uses-permission "
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/Laevatein.java",
    "chars": 3395,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/MimeType.java",
    "chars": 2547,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/SelectionSpecBuilder.java",
    "chars": 21302,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/Album.java",
    "chars": 3877,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/CaptureResources.java",
    "chars": 1266,
    "preview": "package com.laevatein.internal.entity;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport androidx.annotati"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/CounterViewResources.java",
    "chars": 2348,
    "preview": "package com.laevatein.internal.entity;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport androidx.annotati"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/DialogResources.java",
    "chars": 1327,
    "preview": "package com.laevatein.internal.entity;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\n\n/**\n * @author hiroyuki"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/ErrorViewResources.java",
    "chars": 3273,
    "preview": "package com.laevatein.internal.entity;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\n\n/**\n * @author keishin."
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/ErrorViewSpec.java",
    "chars": 7041,
    "preview": "package com.laevatein.internal.entity;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport androidx.annotati"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/Item.java",
    "chars": 2202,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/ItemViewResources.java",
    "chars": 2795,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/PreviewViewResources.java",
    "chars": 2289,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/SelectionSpec.java",
    "chars": 4834,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/UncapableCause.java",
    "chars": 1872,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/entity/ViewResourceSpec.java",
    "chars": 7321,
    "preview": "package com.laevatein.internal.entity;\n\nimport android.content.pm.ActivityInfo;\nimport android.os.Parcel;\nimport android"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/loader/AlbumLoader.java",
    "chars": 3225,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/loader/AlbumPhotoLoader.java",
    "chars": 2820,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/misc/ui/ConfirmationDialogFragment.java",
    "chars": 3793,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/misc/ui/FragmentUtils.java",
    "chars": 1691,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/misc/ui/helper/options/OptionsMenu.java",
    "chars": 905,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/misc/ui/helper/options/OptionsMenuHandler.java",
    "chars": 879,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/misc/widget/SquareGridViewItemRelativeLayout.java",
    "chars": 1437,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/model/AlbumPhotoCollection.java",
    "chars": 3536,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/model/DevicePhotoAlbumCollection.java",
    "chars": 3322,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/model/PreviewStateHolder.java",
    "chars": 1760,
    "preview": "package com.laevatein.internal.model;\n\nimport android.app.Activity;\nimport android.net.Uri;\nimport android.os.Bundle;\n\ni"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/model/SelectedUriCollection.java",
    "chars": 3164,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/package-info.java",
    "chars": 165,
    "preview": "/**\n * This package contains various internal-use classes.\n * @author KeithYokoma\n * @since 2014/03/20\n * @version 1.0.0"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/AlbumListFragment.java",
    "chars": 4624,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/PhotoGridFragment.java",
    "chars": 3772,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/PreviewFragment.java",
    "chars": 2193,
    "preview": "package com.laevatein.internal.ui;\n\nimport android.net.Uri;\nimport android.os.Bundle;\nimport androidx.fragment.app.Fragm"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/SelectedCountFragment.java",
    "chars": 1970,
    "preview": "package com.laevatein.internal.ui;\n\nimport com.laevatein.R;\nimport com.laevatein.internal.ui.helper.SelectedCountViewHel"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/SelectedPhotoGridFragment.java",
    "chars": 2404,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/adapter/AlbumPhotoAdapter.java",
    "chars": 5133,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/adapter/DevicePhotoAlbumAdapter.java",
    "chars": 1820,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/adapter/PreviewPagerAdapter.java",
    "chars": 1665,
    "preview": "package com.laevatein.internal.ui.adapter;\n\nimport android.net.Uri;\nimport androidx.fragment.app.Fragment;\nimport androi"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/adapter/RecyclerViewCursorAdapter.java",
    "chars": 2511,
    "preview": "/*\n * This file is based on the code of `RecyclerViewCursorAdapter.java` in `Matisse`.\n *\n * https://github.com/zhihu/Ma"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/adapter/SelectedPhotoAdapter.java",
    "chars": 3738,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/AlbumListViewHelper.java",
    "chars": 5241,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoGridViewHelper.java",
    "chars": 8388,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoSelectionActivityDrawerToggle.java",
    "chars": 3336,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/PhotoSelectionViewHelper.java",
    "chars": 6299,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/PreviewHelper.java",
    "chars": 5830,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/SelectedCountViewHelper.java",
    "chars": 1887,
    "preview": "package com.laevatein.internal.ui.helper;\n\nimport android.view.View;\nimport android.widget.TextView;\n\nimport com.laevate"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/SelectedGridViewHelper.java",
    "chars": 3652,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/options/FinishSelectMenuHandler.java",
    "chars": 1984,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/options/PhotoSelectionOptionsMenu.java",
    "chars": 1856,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/options/PhotoSelectionOptionsMenuHandler.java",
    "chars": 972,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/helper/options/UnknownMenuHandler.java",
    "chars": 958,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/ui/widget/PhotoDecoration.java",
    "chars": 1292,
    "preview": "package com.laevatein.internal.ui.widget;\n\nimport android.graphics.Rect;\nimport androidx.recyclerview.widget.RecyclerVie"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/utils/ErrorViewUtils.java",
    "chars": 2360,
    "preview": "package com.laevatein.internal.utils;\n\nimport com.google.android.material.snackbar.Snackbar;\nimport androidx.fragment.ap"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/utils/ExifInterfaceUtils.java",
    "chars": 1958,
    "preview": "package com.laevatein.internal.utils;\n\nimport androidx.exifinterface.media.ExifInterface;\nimport android.text.TextUtils;"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/utils/MediaStoreUtils.java",
    "chars": 12289,
    "preview": "package com.laevatein.internal.utils;\n\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport android."
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/utils/PhotoMetadataUtils.java",
    "chars": 6869,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/internal/view/PreviewViewPager.java",
    "chars": 758,
    "preview": "package com.laevatein.internal.view;\n\nimport android.content.Context;\nimport androidx.viewpager.widget.ViewPager;\nimport"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/ui/ImagePreviewActivity.java",
    "chars": 6355,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/java/com/laevatein/ui/PhotoSelectionActivity.java",
    "chars": 8602,
    "preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "laevatein/src/main/res/drawable/l_bg_drawer_item.xml",
    "chars": 682,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item a"
  },
  {
    "path": "laevatein/src/main/res/drawable/l_ic_capture.xml",
    "chars": 306,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<selector\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <i"
  },
  {
    "path": "laevatein/src/main/res/drawable/l_ic_capture_normal.xml",
    "chars": 495,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <ite"
  },
  {
    "path": "laevatein/src/main/res/drawable/l_ic_capture_pressed.xml",
    "chars": 495,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <ite"
  },
  {
    "path": "laevatein/src/main/res/drawable/l_ic_folder.xml",
    "chars": 268,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item a"
  },
  {
    "path": "laevatein/src/main/res/drawable/l_ic_folder_close.xml",
    "chars": 397,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:width=\"24dp\"\n        android:height=\""
  },
  {
    "path": "laevatein/src/main/res/drawable/l_ic_folder_open.xml",
    "chars": 424,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:width=\"24dp\"\n        android:height=\""
  },
  {
    "path": "laevatein/src/main/res/drawable/l_list_selector_drawer_menu.xml",
    "chars": 1392,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item a"
  },
  {
    "path": "laevatein/src/main/res/drawable-v21/l_bg_drawer_item.xml",
    "chars": 597,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item a"
  },
  {
    "path": "laevatein/src/main/res/layout/l_action_layout_checkbox.xml",
    "chars": 265,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<CheckBox xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:"
  },
  {
    "path": "laevatein/src/main/res/layout/l_activity_preview.xml",
    "chars": 694,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    an"
  },
  {
    "path": "laevatein/src/main/res/layout/l_activity_select_photo.xml",
    "chars": 1596,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.drawerlayout.widget.DrawerLayout xmlns:android=\"http://schemas.android."
  },
  {
    "path": "laevatein/src/main/res/layout/l_fragment_default_preview.xml",
    "chars": 284,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<it.sephiroth.android.library.imagezoom.ImageViewTouch xmlns:android=\"http://sche"
  },
  {
    "path": "laevatein/src/main/res/layout/l_fragment_grid_photo.xml",
    "chars": 696,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    an"
  },
  {
    "path": "laevatein/src/main/res/layout/l_fragment_list_album.xml",
    "chars": 308,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ListView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:"
  },
  {
    "path": "laevatein/src/main/res/layout/l_fragment_selected_count.xml",
    "chars": 269,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<TextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:"
  },
  {
    "path": "laevatein/src/main/res/layout/l_grid_item_default_photo.xml",
    "chars": 766,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<com.laevatein.internal.misc.widget.SquareGridViewItemRelativeLayout\n    xmlns:a"
  },
  {
    "path": "laevatein/src/main/res/layout/l_list_item_default_album.xml",
    "chars": 282,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<CheckedTextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    s"
  },
  {
    "path": "laevatein/src/main/res/layout/l_view_counter.xml",
    "chars": 411,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<fragment xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:to"
  },
  {
    "path": "laevatein/src/main/res/menu/l_activity_image_preview.xml",
    "chars": 300,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:co"
  },
  {
    "path": "laevatein/src/main/res/menu/l_activity_options_select_photo.xml",
    "chars": 326,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:co"
  },
  {
    "path": "laevatein/src/main/res/values/attrs.xml",
    "chars": 445,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <attr name=\"l_toolbarTheme\" format=\"reference\" />\n    <attr name="
  },
  {
    "path": "laevatein/src/main/res/values/colors.xml",
    "chars": 118,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"l_bg_item_selected\">#1b000000</color>\n</resources>"
  },
  {
    "path": "laevatein/src/main/res/values/dimens.xml",
    "chars": 181,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- for drawers -->\n    <dimen name=\"l_drawerMenuWidth\">280dp</d"
  },
  {
    "path": "laevatein/src/main/res/values/strings.xml",
    "chars": 1437,
    "preview": "<resources>\n    <string name=\"l_content_desc_open_drawer\">Open menu</string>\n    <string name=\"l_content_desc_close_draw"
  },
  {
    "path": "laevatein/src/main/res/values/styles.xml",
    "chars": 1943,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"L_DefaultTheme\" parent=\"Theme.AppCompat.Light.NoAct"
  },
  {
    "path": "laevatein/src/main/res/values-ja/strings.xml",
    "chars": 1034,
    "preview": "<resources>\n    <string name=\"l_content_desc_open_drawer\">メニューを開く</string>\n    <string name=\"l_content_desc_close_drawer"
  },
  {
    "path": "laevatein/src/main/res/values-v21/styles.xml",
    "chars": 299,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"L_Counter\" parent=\"L_Base.Counter\">\n        <item n"
  },
  {
    "path": "laevatein/src/test/java/com/laevatein/LaevateinTest.java",
    "chars": 1440,
    "preview": "package com.laevatein;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.net.Uri;\nimport andro"
  },
  {
    "path": "laevatein/src/test/java/com/laevatein/MimeTypeTest.java",
    "chars": 3089,
    "preview": "package com.laevatein;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRu"
  },
  {
    "path": "laevatein/src/test/java/com/laevatein/SelectionSpecBuilderTest.java",
    "chars": 4042,
    "preview": "package com.laevatein;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.net.Uri;\n\nimport com."
  },
  {
    "path": "laevatein/src/test/java/com/laevatein/internal/entity/AlbumTest.java",
    "chars": 3084,
    "preview": "package com.laevatein.internal.entity;\n\nimport android.database.MatrixCursor;\nimport android.provider.MediaStore;\n\nimpor"
  },
  {
    "path": "laevatein/src/test/resources/com/laevatein/robolectric.properties",
    "chars": 42,
    "preview": "sdk=23\nconstants=com.laevatein.BuildConfig"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.0/Laevatein-0.10.0.aar.md5",
    "chars": 32,
    "preview": "4f643bfe2c7071a32d7ae068d810ed59"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.0/Laevatein-0.10.0.aar.sha1",
    "chars": 40,
    "preview": "97376903ff26d05ecd478e82025878bc29a84497"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.0/Laevatein-0.10.0.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.0/Laevatein-0.10.0.pom.md5",
    "chars": 32,
    "preview": "825ca71b37cdc9c0f87ab7523834162b"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.0/Laevatein-0.10.0.pom.sha1",
    "chars": 40,
    "preview": "8d14590b62ad3372970a7a2483320c966f0fc99b"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.1/Laevatein-0.10.1.aar.md5",
    "chars": 32,
    "preview": "fa0e95703cbf65258eaee726c8d1e722"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.1/Laevatein-0.10.1.aar.sha1",
    "chars": 40,
    "preview": "900f14a52904ed3d1c42ee086db60334333ffc22"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.1/Laevatein-0.10.1.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.1/Laevatein-0.10.1.pom.md5",
    "chars": 32,
    "preview": "2ad8acb6b85f1ab1daa75bf7a64e04a8"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.1/Laevatein-0.10.1.pom.sha1",
    "chars": 40,
    "preview": "3bb6b97d4d4a8587ff21b02ccb528d3f86d66b25"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.2/Laevatein-0.10.2.aar.md5",
    "chars": 32,
    "preview": "a504dbb34e1ac26fedc996d8e5ee534b"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.2/Laevatein-0.10.2.aar.sha1",
    "chars": 40,
    "preview": "b6c1070c99ad004fc19ea477caa5794332ecebae"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.2/Laevatein-0.10.2.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.2/Laevatein-0.10.2.pom.md5",
    "chars": 32,
    "preview": "bd3214d3ed7a172e90167ac59d8be2c9"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.2/Laevatein-0.10.2.pom.sha1",
    "chars": 40,
    "preview": "6bb7ce6bf4c8c9b2204a966563c93c3be8ea3033"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.3/Laevatein-0.10.3.aar.md5",
    "chars": 32,
    "preview": "3193eaf71ca35b58a2cefd2afcb7baaf"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.3/Laevatein-0.10.3.aar.sha1",
    "chars": 40,
    "preview": "9522fd2a86aaaa6854a94b6bd770fa4fde805b16"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.3/Laevatein-0.10.3.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.3/Laevatein-0.10.3.pom.md5",
    "chars": 32,
    "preview": "79daa595964fba36734845b2bf435692"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.3/Laevatein-0.10.3.pom.sha1",
    "chars": 40,
    "preview": "957c304d0b60782f533ac1e4add3e7ead1501388"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.4/Laevatein-0.10.4.aar.md5",
    "chars": 32,
    "preview": "33b10d5b4011546d21e4e8461c471f09"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.4/Laevatein-0.10.4.aar.sha1",
    "chars": 40,
    "preview": "c48a129ede7172bda5a1d9e99b88d9aa69869748"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.4/Laevatein-0.10.4.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.4/Laevatein-0.10.4.pom.md5",
    "chars": 32,
    "preview": "5cba2a54bfee064e23d4905f50bb2604"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.4/Laevatein-0.10.4.pom.sha1",
    "chars": 40,
    "preview": "1017e41a27a8f626cd593605e791e4d5d3bbc792"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.5/Laevatein-0.10.5.aar.md5",
    "chars": 32,
    "preview": "085f7a28f8207701d456247ab371f8a1"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.5/Laevatein-0.10.5.aar.sha1",
    "chars": 40,
    "preview": "db89d6e50b2d04617cda8b715b3b41dc4efcf615"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.5/Laevatein-0.10.5.pom",
    "chars": 1978,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.5/Laevatein-0.10.5.pom.md5",
    "chars": 32,
    "preview": "5bd85aeb3f195ccc239b8c6da1a2335c"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.10.5/Laevatein-0.10.5.pom.sha1",
    "chars": 40,
    "preview": "5cb74fbc7b8d3846efed18978b893f206c5f5217"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.0/Laevatein-0.9.0.aar.md5",
    "chars": 32,
    "preview": "538eabb88d9ac6142a1623a52b5669f8"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.0/Laevatein-0.9.0.aar.sha1",
    "chars": 40,
    "preview": "1a191f64578a93da1f71b7780adde2967273b57e"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.0/Laevatein-0.9.0.pom",
    "chars": 1555,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.0/Laevatein-0.9.0.pom.md5",
    "chars": 32,
    "preview": "159f53aa37408e0e5b378203a5a88439"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.0/Laevatein-0.9.0.pom.sha1",
    "chars": 40,
    "preview": "a92b9b4785cda454085be558885433a6f031ffcf"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.1/Laevatein-0.9.1.aar.md5",
    "chars": 32,
    "preview": "b62f7c07ef552a4c8ebc8abc15d1ba51"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.1/Laevatein-0.9.1.aar.sha1",
    "chars": 40,
    "preview": "83927797e3ea2ee46e77478e2940767b7a17606e"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.1/Laevatein-0.9.1.pom",
    "chars": 1740,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.1/Laevatein-0.9.1.pom.md5",
    "chars": 32,
    "preview": "4a8da8a01b92eee9c258d953d19bb820"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.1/Laevatein-0.9.1.pom.sha1",
    "chars": 40,
    "preview": "efd1a13f51038ceb16fe17b8265689e09b083bd1"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.10/Laevatein-0.9.10.aar.md5",
    "chars": 32,
    "preview": "b2e7440b0b791958fc4085d521a79544"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.10/Laevatein-0.9.10.aar.sha1",
    "chars": 40,
    "preview": "0a01102070e107577518cbeeab084c394855772d"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.10/Laevatein-0.9.10.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.10/Laevatein-0.9.10.pom.md5",
    "chars": 32,
    "preview": "a4a3806253a2340e5a72e41aa26c0d1e"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.10/Laevatein-0.9.10.pom.sha1",
    "chars": 40,
    "preview": "bf3991cb0c12ddb94d7c7d89750769cba7084211"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.11/Laevatein-0.9.11.aar.md5",
    "chars": 32,
    "preview": "72f711fe29c9f3ecdcf34b9b81b12a6c"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.11/Laevatein-0.9.11.aar.sha1",
    "chars": 40,
    "preview": "edfcba2479320e9b479a773dfe9ef09dc3bc52da"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.11/Laevatein-0.9.11.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.11/Laevatein-0.9.11.pom.md5",
    "chars": 32,
    "preview": "1c8905d8a0ae8bf8439d3681be2a9207"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.11/Laevatein-0.9.11.pom.sha1",
    "chars": 40,
    "preview": "0dc29c582e4a50413f4fcb3006e9f1aa1d59d2fb"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.12/Laevatein-0.9.12.aar.md5",
    "chars": 32,
    "preview": "3e02bea93f3b529f1ac6864af477cf84"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.12/Laevatein-0.9.12.aar.sha1",
    "chars": 40,
    "preview": "71ef691ba5dbbbbfe3f0c23c7e833f42bdb11675"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.12/Laevatein-0.9.12.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.12/Laevatein-0.9.12.pom.md5",
    "chars": 32,
    "preview": "79b54ebc6fd1c75698343c2bb71357eb"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.12/Laevatein-0.9.12.pom.sha1",
    "chars": 40,
    "preview": "58ec6c0a97c9f8d155fa113010d65fbf8035419b"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.13/Laevatein-0.9.13.aar.md5",
    "chars": 32,
    "preview": "ff0f41dd31730c29a3e6b5f6e147b876"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.13/Laevatein-0.9.13.aar.sha1",
    "chars": 40,
    "preview": "baf7e595d4fc1bd16f87c3230274e8bb691941bb"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.13/Laevatein-0.9.13.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.13/Laevatein-0.9.13.pom.md5",
    "chars": 32,
    "preview": "6c7a73f07e6cb4d11538c60493651bcd"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.13/Laevatein-0.9.13.pom.sha1",
    "chars": 40,
    "preview": "0290b91995d07c3a0a46862f4d8f2674de135d78"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.14/Laevatein-0.9.14.aar.md5",
    "chars": 32,
    "preview": "29029692874470ef1b394c56a4e33a2c"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.14/Laevatein-0.9.14.aar.sha1",
    "chars": 40,
    "preview": "cdc2e1ebb6dcc81a6bb6dafbc6b73432f0c69970"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.14/Laevatein-0.9.14.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.14/Laevatein-0.9.14.pom.md5",
    "chars": 32,
    "preview": "840c34c3a6b960423e81e077980ad007"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.14/Laevatein-0.9.14.pom.sha1",
    "chars": 40,
    "preview": "9a9ccfd0f3b17379e98dfefc2128bd507ffbada4"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.15/Laevatein-0.9.15.aar.md5",
    "chars": 32,
    "preview": "0761abe61356770b23494425a2804254"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.15/Laevatein-0.9.15.aar.sha1",
    "chars": 40,
    "preview": "f8f1b9a4d54332ac3abbcad9a67b72af039af667"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.15/Laevatein-0.9.15.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.15/Laevatein-0.9.15.pom.md5",
    "chars": 32,
    "preview": "c56781ec0e92b76282527946b64be211"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.15/Laevatein-0.9.15.pom.sha1",
    "chars": 40,
    "preview": "8a9a3720d7134ee15e560ea0135a47c0ae952456"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.16/Laevatein-0.9.16.aar.md5",
    "chars": 32,
    "preview": "1dd4a8206305c93d4f9e9913bd871c9d"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.16/Laevatein-0.9.16.aar.sha1",
    "chars": 40,
    "preview": "b462f822d34e4582f4bcec46ce38b5495f2de5a9"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.16/Laevatein-0.9.16.pom",
    "chars": 1945,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.16/Laevatein-0.9.16.pom.md5",
    "chars": 32,
    "preview": "ae762d26171e6f412ec51dc4127fb77a"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.16/Laevatein-0.9.16.pom.sha1",
    "chars": 40,
    "preview": "ffa26337f0c1955da82e26b42acbef7cf72bfc49"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.2/Laevatein-0.9.2.aar.md5",
    "chars": 32,
    "preview": "447b70869a65c5ac7be898fdbba56abb"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.2/Laevatein-0.9.2.aar.sha1",
    "chars": 40,
    "preview": "87082a04c0bf64321fef111087cde5aba77395bb"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.2/Laevatein-0.9.2.pom",
    "chars": 1744,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.2/Laevatein-0.9.2.pom.md5",
    "chars": 32,
    "preview": "a5f355e50c0db5cada41d488c0d6eb42"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.2/Laevatein-0.9.2.pom.sha1",
    "chars": 40,
    "preview": "1df0cf8d0eb9636c52ae345fee0ccd7c86652725"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.3/Laevatein-0.9.3.aar.md5",
    "chars": 32,
    "preview": "65cd2931c5ed653cc10fe96d416ecf0b"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.3/Laevatein-0.9.3.aar.sha1",
    "chars": 40,
    "preview": "8d877fdc66ffcb7d4bc19418302842b79d4a9db9"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.3/Laevatein-0.9.3.pom",
    "chars": 1744,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.3/Laevatein-0.9.3.pom.md5",
    "chars": 32,
    "preview": "dc40e6a91d027e524593b08c4c5ae81d"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.3/Laevatein-0.9.3.pom.sha1",
    "chars": 40,
    "preview": "8f1de44ca20e3489571355eb66f0521f3f501e87"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.4/Laevatein-0.9.4.aar.md5",
    "chars": 32,
    "preview": "856a9126222b9a197cb2ddf31fc50bdf"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.4/Laevatein-0.9.4.aar.sha1",
    "chars": 40,
    "preview": "66a5972ba6261b3f56397ceb5aefe08cc77ccad5"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.4/Laevatein-0.9.4.pom",
    "chars": 1744,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.4/Laevatein-0.9.4.pom.md5",
    "chars": 32,
    "preview": "ef01830482cd3ec14d1236b5d3cc55a5"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.4/Laevatein-0.9.4.pom.sha1",
    "chars": 40,
    "preview": "61b6fda575726d8c36c1c68134447f6538f6671c"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.5/Laevatein-0.9.5.aar.md5",
    "chars": 32,
    "preview": "9e41941bda0831f4c101bdd7c6f08659"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.5/Laevatein-0.9.5.aar.sha1",
    "chars": 40,
    "preview": "9f682e76392ca69e64fd32ae3e89618c361e02f6"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.5/Laevatein-0.9.5.pom",
    "chars": 1944,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apach"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.5/Laevatein-0.9.5.pom.md5",
    "chars": 32,
    "preview": "ad874dfbb5d2d08b61f03c370d13a704"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.5/Laevatein-0.9.5.pom.sha1",
    "chars": 40,
    "preview": "da53069e31988d40888fa0d86dd65eb088cf5e7e"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.6/Laevatein-0.9.6.aar.md5",
    "chars": 32,
    "preview": "d09f4669b90dff71405439c6812cd8b8"
  },
  {
    "path": "repository/com/laevatein/Laevatein/0.9.6/Laevatein-0.9.6.aar.sha1",
    "chars": 40,
    "preview": "c5bf9f1f520f891758057a35380cc23d3bf025d2"
  }
]

// ... and 59 more files (download for full content)

About this extraction

This page contains the full source code of the nohana/Laevatein GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 259 files (306.5 KB), approximately 86.9k tokens, and a symbol index with 579 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!