public class Application extends android.app.Application {

    private static AppComponent sAppComponent;

    @Inject
    protected Setting mSetting;

    public static AppComponent getAppComponent() {
        return sAppComponent;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        sAppComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
        sAppComponent.inject(this);

        if (BuildConfig.DEBUG || mSetting.isCatchCrashEnable()) {
            CustomActivityOnCrash.install(this);
        }

        RxJavaPlugins.setErrorHandler(Throwable::printStackTrace);
    }

} public interface MainContact {

    interface View extends BaseView<Presenter> {
        void setTitle(String title);
        void scrollToPosition(int position);
        void replaceData(List<Media> mediaList);
        void startViewer(int position, Media media);
        void showLoading(boolean isLoading);
    }

    interface Presenter extends BasePresenter {

        boolean isRoot();

        void reFresh();

        void addServer(String uri, String user, String pass);

        void clickItem(int position, Media mediaFile, int firstPosition);

        void loadChild(int position, Media media);

        boolean loadParent(int firstVisibleItemPosition);

        void clear();

        int getPosition();
    }
} public interface MediaDataSource {

    void register(Media media);

    void addRoot(String uri, String username, String password);

    List<Media> roots();

    Media getCurrent();

    void setCurrent(Media media);

    Media getMedia(String uri);

    int getRotate(String uri);

    void setRotate(String uri, int rotate);

    Observable<List<Media>> loadDir(Media media, boolean isRefresh);

    Observable<List<Media>> loadMediaList(Media media);

    void clearCache();

    void setMediaPosition(int position);

    int getMediaPosition();

    void setFilePosition(int position);

    int getFilePosition();
} public interface Media<T extends Media> {

    String[] scheme();

    String getName();

    String getHost();

    long getLastModified();

    long length();

    String getPath();

    String getParent();

    void setParent(T parent);

    T parent();

    void clear();

    boolean hasImage();

    List<T> children();

    int childrenSize();

    String getUri();

    InputStream getInputStream() throws IOException;

    boolean isFile();

    T[] listMedia();

    boolean isImage();

    boolean isDirectory();

    T fromUri(String uri);

    T auth(String domain, String directory, String username, String password);

    int getPosition();

    void setPosition(int position);

    class MediaException extends RuntimeException {

        public MediaException(String detailMessage) {
            super(detailMessage);
        }
    }

    class NumericComparator implements Comparator<Media> {

        public static NumericComparator factory() {
            return SingletonHelper.INSTANCE;
        }

        private boolean isDigit(char ch) {
            return ch >= 48 && ch <= 57;
        }

        /**
         * Length of string is passed in for improved efficiency (only need to calculate it once)
         **/
        private String getChunk(String s, int length, int marker) {
            StringBuilder chunk = new StringBuilder();
            char c = s.charAt(marker);
            chunk.append(c);
            marker++;
            if (isDigit(c)) {
                while (marker < length) {
                    c = s.charAt(marker);
                    if (!isDigit(c)) {
                        break;
                    }
                    chunk.append(c);
                    marker++;
                }
            } else {
                while (marker < length) {
                    c = s.charAt(marker);
                    if (isDigit(c)) {
                        break;
                    }
                    chunk.append(c);
                    marker++;
                }
            }
            return chunk.toString();
        }

        @Override
        public int compare(Media m1, Media m2) {
            String s1 = m1.getName();
            String s2 = m2.getName();

            return compare(s1, s2);
        }

        public int compare(String s1, String s2) {

            int thisMarker = 0;
            int thatMarker = 0;
            int s1Length = s1.length();
            int s2Length = s2.length();

            while (thisMarker < s1Length && thatMarker < s2Length) {
                String thisChunk = getChunk(s1, s1Length, thisMarker);
                thisMarker += thisChunk.length();

                String thatChunk = getChunk(s2, s2Length, thatMarker);
                thatMarker += thatChunk.length();

                // If both chunks contain numeric characters, sort them numerically
                int result = 0;
                if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) {
                    // Simple chunk comparison by length.
                    int thisChunkLength = thisChunk.length();
                    result = thisChunkLength - thatChunk.length();
                    // If equal, the first different number counts
                    if (result == 0) {
                        for (int i = 0; i < thisChunkLength; i++) {
                            result = thisChunk.charAt(i) - thatChunk.charAt(i);
                            if (result != 0) {
                                return result;
                            }
                        }
                    }
                } else {
                    result = thisChunk.compareTo(thatChunk);
                }

                if (result != 0) {
                    return result;
                }
            }

            return s1Length - s2Length;
        }

        private final static class SingletonHelper {
            private final static NumericComparator INSTANCE = new NumericComparator();
        }
    }

} public interface Database {

    Observable<List<Server>> getServers();

    List<Server> getServersSync();

    void addServer(Server server);

    void removeServer(Server server);

    void updateServer(Server server);

} public class AutoIndexMedia extends AutoIndexFile
        implements Media<AutoIndexMedia>, Comparable<AutoIndexMedia> {

    private final static String[] SCHEME = new String[] { "http", "https" };

    private AutoIndexMedia parent;
    private List<AutoIndexMedia> children = new ArrayList<>();
    private int position;
    private boolean hasImage = false;

    public AutoIndexMedia() throws MalformedURLException {
        super();
    }

    public AutoIndexMedia(String url) throws MalformedURLException {
        super(url);
    }

    public AutoIndexMedia(AutoIndexFile media) throws MalformedURLException {
        super(media.getPath());
        setParent(media.getParent());
        setIsDirectory(media.isDirectory());
    }

    @Override
    public String[] scheme() {
        return SCHEME;
    }

    @Override
    public long length() {
        return 0;
    }

    @Override
    public AutoIndexMedia parent() {
        return parent;
    }

    @Override
    public void setParent(AutoIndexMedia parent) {
        this.parent = parent;
    }

    @Override
    public void clear() {
        children.clear();
        hasImage = false;
        position = 0;
    }

    @Override
    public boolean hasImage() {
        return hasImage;
    }

    @Override
    public synchronized List<AutoIndexMedia> children() {

        if (children.size() == 0) {
            try {
                List<AutoIndexFile> files = super.listFiles();
                if (files != null) {
                    for (AutoIndexFile file : files) {
                        AutoIndexMedia media = new AutoIndexMedia(file);
                        media.setParent(this);
                        children.add(media);

                        if (!hasImage) {
                            if (media.isImage()) {
                                hasImage = true;
                            }
                        }
                    }
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            Collections.sort(children);
        }
        return Collections.unmodifiableList(children);
    }

    @Override
    public int childrenSize() {
        return children.size();
    }

    @Override
    public String getUri() {
        return super.getPath();
    }

    @Override
    public boolean isFile() {
        return false;
    }

    @Override
    public AutoIndexMedia[] listMedia() {
        ArrayList<AutoIndexMedia> list = new ArrayList<>();
        try {
            List<AutoIndexFile> files = super.listFiles();
            for (AutoIndexFile file : files) {
                list.add(new AutoIndexMedia(file));
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        Collections.sort(list);
        return list.toArray(new AutoIndexMedia[list.size()]);
    }

    @Override
    public boolean isImage() {
        String name = getName().toLowerCase();
        return name.endsWith(".png") ||
                name.endsWith(".jpg") ||
                name.endsWith(".jpeg") ||
                name.endsWith(".bmp") ||
                name.endsWith(".gif");
    }

    @Override
    public AutoIndexMedia fromUri(String uri) {
        try {
            return new AutoIndexMedia(uri);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public AutoIndexMedia auth(String uri, String directory, String username, String password) {
        if (HttpAuth.getAuth(uri) == null) {
            HttpAuth.addAuth(uri, username, password);
        }
        return this;
    }

    @Override
    public int getPosition() {
        return position;
    }

    @Override
    public void setPosition(int position) {
        this.position = position;
    }

    @Override
    public boolean equals(Object object) {
        boolean equal = false;

        if (object != null && object instanceof Media) {
            equal = this.getPath().equals(((Media) object).getPath());
        }

        return equal;
    }

    @Override
    public int compareTo(@NonNull AutoIndexMedia another) {
        return NumericComparator.factory().compare(this, another);
    }
} public class LocalMedia extends File implements Media<LocalMedia>, Comparable<File> {

    private final static String[] SCHEME = new String[] { "file" };

    private LocalMedia parent;
    private List<LocalMedia> children = new ArrayList<>();
    private int position = 0;
    private boolean hasImage = false;

    public LocalMedia() {
        super("/");
    }

    public LocalMedia(String path) {
        super(path);
    }

    public LocalMedia(File media) {
        super(media.getPath());
    }

    @Override
    public String getParent() {
        return "file://" + super.getParent();
    }

    @Override
    public void setParent(LocalMedia parent) {
        this.parent = parent;
    }

    @Override
    public void clear() {
        children.clear();
        hasImage = false;
        position = 0;
    }

    @Override
    public boolean hasImage() {
        return hasImage;
    }

    @Override
    public LocalMedia parent() {
        return parent;
    }

    @Override
    public synchronized List<LocalMedia> children() {
        if (children.size() == 0) {
            File[] files = super.listFiles();
            for (File file : files) {
                LocalMedia media = new LocalMedia(file);
                media.setParent(this);
                children.add(media);

                if (!hasImage) {
                    if (media.isImage()) {
                        hasImage = true;
                    }
                }
            }
            Collections.sort(children);
        }
        return Collections.unmodifiableList(children);
    }

    @Override
    public int childrenSize() {
        return children.size();
    }

    @Override
    public LocalMedia[] listMedia() {
        ArrayList<LocalMedia> list = new ArrayList<>();
        File[] files = super.listFiles();
        for (File file : files) {
            list.add(new LocalMedia(file));
        }
        Collections.sort(list);
        return list.toArray(new LocalMedia[list.size()]);
    }

    @Override
    public String[] scheme() {
        return SCHEME;
    }

    @Override
    public String getHost() {
        return null;
    }

    @Override
    public long getLastModified() {
        return 0;
    }

    @Override
    public String getUri() {
        return "file://" + super.getPath();
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new FileInputStream(this);
    }

    @Override
    public boolean isImage() {
        String name = getName().toLowerCase();
        return name.endsWith(".png") ||
                name.endsWith(".jpg") ||
                name.endsWith(".jpeg") ||
                name.endsWith(".bmp") ||
                name.endsWith(".gif");
    }

    @Override
    public LocalMedia fromUri(String uri) {
        return new LocalMedia(uri.replace("file://", ""));
    }

    @Override
    public LocalMedia auth(String domain, String directory, String username, String password) {
        return this;
    }

    @Override
    public int getPosition() {
        return position;
    }

    @Override
    public void setPosition(int position) {
        this.position = position;
    }

    @Override
    public boolean equals(Object object) {
        boolean equal = false;

        if (object != null && object instanceof Media) {
            equal = this.getPath().equals(((Media) object).getPath());
        }

        return equal;
    }

    @Override
    public int compareTo(@NonNull File another) {
        return NumericComparator.factory().compare(this.getName(), another.getName());
    }
} public class SambaMedia extends SmbFile implements Media<SambaMedia>, Comparable<SambaMedia> {

    private final static String[] SCHEME = new String[]{"smb"};
    private final static Map<String, NtlmPasswordAuthentication> smbAuthList = new HashMap<>();

    private SambaMedia parent;
    private List<SambaMedia> children = new ArrayList<>();
    private int position;
    private boolean hasImage = false;

    public SambaMedia() throws MalformedURLException {
        this("smb://");
    }

    public SambaMedia(String uri) throws MalformedURLException {
        super(uri, getAuth(uri));
    }

    public SambaMedia(SmbFile media) throws MalformedURLException, UnknownHostException {
        super(media.getPath(), getAuth(media.getPath()));
    }

    private static NtlmPasswordAuthentication getAuth(String uri) {
        for (String key : smbAuthList.keySet()) {
            if (uri.contains(key)) {
                return smbAuthList.get(key);
            }
        }
        return null;
    }

    @Override
    public boolean isFile() {
        try {
            return super.isFile();
        } catch (SmbException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public SambaMedia[] listMedia() {
        ArrayList<SambaMedia> list = new ArrayList<>();
        try {
            SmbFile[] files = super.listFiles();
            for (SmbFile file : files) {
                if (!file.getName().contains(":")) {
                    list.add(new SambaMedia(file));
                }
            }
        } catch (SmbException | MalformedURLException | UnknownHostException e) {
            e.printStackTrace();
        }
        Collections.sort(list);
        return list.toArray(new SambaMedia[list.size()]);
    }

    public long length() {
        return super.getContentLength();
    }

    @Override
    public SambaMedia parent() {
        return parent;
    }

    @Override
    public void setParent(SambaMedia parent) {
        this.parent = parent;
    }

    @Override
    public void clear() {
        children.clear();
        hasImage = false;
        position = 0;
    }

    @Override
    public boolean hasImage() {
        return hasImage;
    }

    @Override
    public synchronized List<SambaMedia> children() {

        if (children.size() == 0) {
            try {
                SmbFile[] files = super.listFiles();
                for (SmbFile file : files) {
                    if (!file.getName().contains(":")) {
                        SambaMedia media = new SambaMedia(file);
                        media.setParent(this);
                        children.add(media);

                        if (!hasImage) {
                            if (media.isImage()) {
                                hasImage = true;
                            }
                        }
                    }
                }
            } catch (SmbException | MalformedURLException | UnknownHostException e) {
                e.printStackTrace();
            }
            Collections.sort(children);
        }
        return Collections.unmodifiableList(children);
    }

    @Override
    public int childrenSize() {
        return children.size();
    }

    @Override
    public String[] scheme() {
        return SCHEME;
    }

    @Override
    public String getHost() {
        return super.getServer();
    }

    @Override
    public String getUri() {
        return super.getPath();
    }

    @Override
    public boolean isDirectory() {
        try {
            return super.isDirectory();
        } catch (SmbException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public SambaMedia fromUri(String uri) {
        try {
            return new SambaMedia(uri);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public SambaMedia auth(String uri, String directory, String username, String password) {
        smbAuthList.put(uri + "/" + directory,
                new NtlmPasswordAuthentication(uri.replace("smb://", ""), username, password));
        return this;
    }

    @Override
    public int getPosition() {
        return position;
    }

    @Override
    public void setPosition(int position) {
        this.position = position;
    }

    @Override
    public boolean isImage() {
        String name = getName().toLowerCase();
        return name.endsWith(".png") ||
                name.endsWith(".jpg") ||
                name.endsWith(".jpeg") ||
                name.endsWith(".bmp") ||
                name.endsWith(".gif");
    }

    @Override
    public boolean equals(Object object) {
        boolean equal = false;

        if (object != null && object instanceof Media) {
            equal = this.getPath().equals(((Media) object).getPath());
        }

        return equal;
    }

    @Override
    public int compareTo(@NonNull SambaMedia another) {
        return NumericComparator.factory().compare(this, another);
    }
} public class WebDavMedia extends WebDavFile implements Media<WebDavMedia>, Comparable<WebDavMedia> {

    private final static String[] SCHEME = new String[] { "dav", "davs" };

    private WebDavMedia parent;
    private List<WebDavMedia> children = new ArrayList<>();
    private int position;
    private boolean hasImage = false;

    public WebDavMedia() throws MalformedURLException {
        super("dav://");
    }

    public WebDavMedia(String url) throws MalformedURLException {
        super(url);
    }

    public WebDavMedia(WebDavFile media) throws MalformedURLException {
        super(media.getPath());
        setParent(media.getParent());
        setIsDirectory(media.isDirectory());
    }

    @Override
    public WebDavMedia[] listFiles() throws MalformedURLException {
        return (WebDavMedia[]) super.listFiles();
    }

    @Override
    public String[] scheme() {
        return SCHEME;
    }

    @Override
    public long length() {
        return 0;
    }

    @Override
    public WebDavMedia parent() {
        return parent;
    }

    @Override
    public void setParent(WebDavMedia parent) {
        this.parent = parent;
    }

    @Override
    public void clear() {
        children.clear();
        hasImage = false;
        position = 0;
    }

    @Override
    public boolean hasImage() {
        return hasImage;
    }

    @Override
    public synchronized List<WebDavMedia> children() {

        if (children.size() == 0) {
            try {
                WebDavFile[] files = super.listFiles();
                if (files != null) {
                    for (WebDavFile file : files) {
                        WebDavMedia media = new WebDavMedia(file);
                        media.setParent(this);
                        children.add(media);

                        if (!hasImage) {
                            if (media.isImage()) {
                                hasImage = true;
                            }
                        }
                    }
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            Collections.sort(children);
        }
        return Collections.unmodifiableList(children);
    }

    @Override
    public int childrenSize() {
        return children.size();
    }

    @Override
    public String getUri() {
        return super.getPath();
    }

    @Override
    public boolean isFile() {
        return false;
    }

    @Override
    public WebDavMedia[] listMedia() {
        ArrayList<WebDavMedia> list = new ArrayList<>();
        try {
            WebDavFile[] files = super.listFiles();
            for (WebDavFile file : files) {
                list.add(new WebDavMedia(file));
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        Collections.sort(list);
        return list.toArray(new WebDavMedia[list.size()]);
    }

    @Override
    public boolean isImage() {
        String name = getName().toLowerCase();
        return name.endsWith(".png") ||
                name.endsWith(".jpg") ||
                name.endsWith(".jpeg") ||
                name.endsWith(".bmp") ||
                name.endsWith(".gif");
    }

    @Override
    public WebDavMedia fromUri(String uri) {
        try {
            return new WebDavMedia(uri);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public WebDavMedia auth(String uri, String directory, String username, String password) {
        if (HttpAuth.getAuth(uri) == null) {
            HttpAuth.addAuth(uri, username, password);
        }
        return this;
    }

    @Override
    public int getPosition() {
        return position;
    }

    @Override
    public void setPosition(int position) {
        this.position = position;
    }

    @Override
    public boolean equals(Object object) {
        boolean equal = false;

        if (object != null && object instanceof Media) {
            equal = this.getPath().equals(((Media) object).getPath());
        }

        return equal;
    }

    @Override
    public int compareTo(@NonNull WebDavMedia another) {
        return NumericComparator.factory().compare(this, another);
    }
} public interface Setting {

    boolean isCatchCrashEnable();

    Set<String> getServers();

    void addServer(String server);

    String getLocalPath();

}
import com.google.gson.Gson;
import org.xdty.gallery.application.Application;
import org.xdty.gallery.contract.MainContact;
import org.xdty.gallery.data.MediaDataSource;
import org.xdty.gallery.model.Media;
import org.xdty.gallery.model.database.Database;
import org.xdty.gallery.model.db.Server;
import org.xdty.gallery.model.media.AutoIndexMedia;
import org.xdty.gallery.model.media.LocalMedia;
import org.xdty.gallery.model.media.SambaMedia;
import org.xdty.gallery.model.media.WebDavMedia;
import org.xdty.gallery.setting.Setting;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import io.reactivex.disposables.CompositeDisposable;
package org.xdty.gallery.presenter;






public class MainPresenter implements MainContact.Presenter {

    @Inject
    Setting mSetting;

    @Inject
    Gson mGson;

    @Inject
    MediaDataSource mMediaDataSource;

    @Inject
    Database mDatabase;