com.freshdigitable.udonroad.UserInfoPagerFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.freshdigitable.udonroad.UserInfoPagerFragment.java

Source

/*
 * Copyright (c) 2016. Matsuda, Akihit (akihito104)
 *
 * 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.
 */

package com.freshdigitable.udonroad;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.freshdigitable.udonroad.datastore.SortedCache;
import com.freshdigitable.udonroad.module.InjectionUtil;
import com.freshdigitable.udonroad.subscriber.RequestWorkerBase;
import com.freshdigitable.udonroad.subscriber.StatusRequestWorker;
import com.freshdigitable.udonroad.subscriber.UserRequestWorker;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;

import rx.Observable;
import twitter4j.Paging;
import twitter4j.Status;
import twitter4j.User;

/**
 * UserInfoPagerFragment provides ViewPager to show specified user tweets.
 *
 * Created by akihit on 2016/06/06.
 */
public class UserInfoPagerFragment extends Fragment {
    private static final String TAG = UserInfoPagerFragment.class.getSimpleName();
    public static final String ARGS_USER_ID = "userId";

    public static UserInfoPagerFragment create(long userId) {
        final Bundle args = new Bundle();
        args.putLong(ARGS_USER_ID, userId);
        final UserInfoPagerFragment res = new UserInfoPagerFragment();
        res.setArguments(args);
        return res;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        InjectionUtil.getComponent(this).inject(this);
    }

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

    private ViewPager viewPager;

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        final View v = getView();
        if (v == null) {
            return;
        }
        viewPager = (ViewPager) v.findViewById(R.id.user_pager);
    }

    private PagerAdapter pagerAdapter;

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        pagerAdapter = new PagerAdapter(getChildFragmentManager());
        setupTimeline(UserPageInfo.TWEET, userHomeRequestWorker);
        setupUserList(UserPageInfo.FOLLOWER, userFollowersRequestWorker);
        setupUserList(UserPageInfo.FRIEND, userFriendsRequestWorker);
        setupTimeline(UserPageInfo.FAV, userFavRequestWorker);
        viewPager.setAdapter(pagerAdapter);
    }

    private Map<UserPageInfo, StatusRequestWorker<SortedCache<Status>>> timelineSubscriberMap = new HashMap<>();
    private Map<UserPageInfo, UserRequestWorker<SortedCache<User>>> userSubscriberMap = new HashMap<>();

    @Inject
    StatusRequestWorker<SortedCache<Status>> userHomeRequestWorker;
    @Inject
    StatusRequestWorker<SortedCache<Status>> userFavRequestWorker;
    @Inject
    UserRequestWorker<SortedCache<User>> userFollowersRequestWorker;
    @Inject
    UserRequestWorker<SortedCache<User>> userFriendsRequestWorker;

    private void setupTimeline(@NonNull UserPageInfo page,
            @NonNull StatusRequestWorker<SortedCache<Status>> requestWorker) {
        if (!page.isStatus()) {
            throw new IllegalArgumentException("page must be for Status. passed: " + page.name());
        }
        timelineSubscriberMap.put(page, requestWorker);
        putToPagerAdapter(page, requestWorker);
    }

    private void setupUserList(@NonNull UserPageInfo page,
            @NonNull UserRequestWorker<SortedCache<User>> requestWorker) {
        if (!page.isUser()) {
            throw new IllegalArgumentException("page must be for User. passed: " + page.name());
        }
        userSubscriberMap.put(page, requestWorker);
        putToPagerAdapter(page, requestWorker);
    }

    private <T> void putToPagerAdapter(@NonNull UserPageInfo page, RequestWorkerBase<SortedCache<T>> worker) {
        final TimelineFragment<T> fragment = page.setup(worker, this);
        pagerAdapter.putFragment(page, fragment);
    }

    @Override
    public void onStart() {
        super.onStart();
        final FragmentActivity activity = getActivity();
        if (activity instanceof FabHandleable) {
            viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                @Override
                public void onPageSelected(int position) {
                    Log.d(TAG, "onPageSelected: " + position);
                    TimelineFragment fragment = pagerAdapter.getItem(position);
                    if (fragment.isTweetSelected()) {
                        ((FabHandleable) activity).showFab();
                    } else {
                        ((FabHandleable) activity).hideFab();
                    }
                }
            });
        }
        timelineSubscriberMap.get(UserPageInfo.TWEET).registerRootView(viewPager);
    }

    private TimelineFragment getCurrentFragment() {
        final int currentItem = viewPager.getCurrentItem();
        return pagerAdapter.getItem(currentItem);
    }

    @Override
    public void onStop() {
        super.onStop();
        viewPager.clearOnPageChangeListeners();
        timelineSubscriberMap.get(UserPageInfo.TWEET).unregisterRootView(viewPager);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        viewPager.setAdapter(null);
        for (StatusRequestWorker ts : timelineSubscriberMap.values()) {
            ts.close();
        }
        timelineSubscriberMap.clear();
        for (UserRequestWorker us : userSubscriberMap.values()) {
            us.close();
        }
        userSubscriberMap.clear();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        final UserPageInfo reqPage = UserPageInfo.findByRequestCode(requestCode);
        if (reqPage == null) {
            super.onActivityResult(requestCode, resultCode, data);
            return;
        }
        final long userId = getArguments().getLong(ARGS_USER_ID);
        final Paging paging = (Paging) data.getSerializableExtra(TimelineFragment.EXTRA_PAGING);
        if (reqPage.isStatus()) {
            final StatusRequestWorker<SortedCache<Status>> statusRequestWorker = timelineSubscriberMap.get(reqPage);
            if (reqPage == UserPageInfo.TWEET) {
                statusRequestWorker.fetchHomeTimeline(userId, paging);
            } else if (reqPage == UserPageInfo.FAV) {
                statusRequestWorker.fetchFavorites(userId, paging);
            }
        } else if (reqPage.isUser()) {
            final UserRequestWorker<SortedCache<User>> userRequestWorker = userSubscriberMap.get(reqPage);
            final long nextCursor = paging != null ? paging.getMaxId() : -1;
            if (reqPage == UserPageInfo.FOLLOWER) {
                userRequestWorker.fetchFollowers(userId, nextCursor);
            } else if (reqPage == UserPageInfo.FRIEND) {
                userRequestWorker.fetchFriends(userId, nextCursor);
            }
        }
    }

    public ViewPager getViewPager() {
        return viewPager;
    }

    public void clearSelectedTweet() {
        final TimelineFragment currentFragment = getCurrentFragment();
        currentFragment.clearSelectedTweet();
    }

    private static class PagerAdapter extends FragmentPagerAdapter {
        private PagerAdapter(FragmentManager fm) {
            super(fm);
        }

        private Map<UserPageInfo, TimelineFragment> pages = new HashMap<>();

        private void putFragment(UserPageInfo page, TimelineFragment<?> fragment) {
            pages.put(page, fragment);
        }

        @Override
        public TimelineFragment getItem(int position) {
            return pages.get(UserPageInfo.values()[position]);
        }

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

        @Override
        public CharSequence getPageTitle(int position) {
            return UserPageInfo.values()[position].name();
        }
    }

    long getCurrentSelectedStatusId() {
        final UserPageInfo currentPage = getCurrentPage();
        if (!currentPage.isStatus()) {
            return -1;
        }
        return getCurrentFragment().getSelectedTweetId();
    }

    void createFavorite() {
        final UserPageInfo currentPage = getCurrentPage();
        if (!currentPage.isStatus()) {
            return;
        }
        final long statusId = getCurrentFragment().getSelectedTweetId();
        if (statusId < 0) {
            return;
        }
        final StatusRequestWorker<SortedCache<Status>> statusRequestWorker = timelineSubscriberMap.get(currentPage);
        if (statusRequestWorker != null) {
            statusRequestWorker.createFavorite(statusId);
        }
    }

    void retweetStatus() {
        final UserPageInfo currentPage = getCurrentPage();
        if (!currentPage.isStatus()) {
            return;
        }
        final long statusId = getCurrentFragment().getSelectedTweetId();
        if (statusId < 0) {
            return;
        }
        final StatusRequestWorker<SortedCache<Status>> statusRequestWorker = timelineSubscriberMap.get(currentPage);
        if (statusRequestWorker != null) {
            statusRequestWorker.retweetStatus(statusId);
        }
    }

    void createFavAndRetweet() {
        final UserPageInfo currentPage = getCurrentPage();
        if (!currentPage.isStatus()) {
            return;
        }
        final long statusId = getCurrentFragment().getSelectedTweetId();
        if (statusId < 0) {
            return;
        }
        final StatusRequestWorker<SortedCache<Status>> statusRequestWorker = timelineSubscriberMap.get(currentPage);
        if (statusRequestWorker != null) {
            Observable
                    .concatDelayError(Arrays.asList(statusRequestWorker.observeCreateFavorite(statusId),
                            statusRequestWorker.observeRetweetStatus(statusId)))
                    .subscribe(StatusRequestWorker.<Status>nopSubscriber());
        }
    }

    @NonNull
    UserPageInfo getCurrentPage() {
        final int currentItem = viewPager.getCurrentItem();
        return UserPageInfo.values()[currentItem];
    }

    public static final int REQUEST_CODE_USER_HOME = 10;
    public static final int REQUEST_CODE_USER_FAVS = 11;
    public static final int REQUEST_CODE_USER_FOLLOWERS = 12;
    public static final int REQUEST_CODE_USER_FRIENDS = 13;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(value = { REQUEST_CODE_USER_HOME, REQUEST_CODE_USER_FAVS, REQUEST_CODE_USER_FOLLOWERS,
            REQUEST_CODE_USER_FRIENDS })
    @interface RequestCodeEnum {
    }

    enum UserPageInfo {
        TWEET(REQUEST_CODE_USER_HOME, "user_home") {
            @Override
            public String createTitle(User user) {
                return name() + "\n" + user.getStatusesCount();
            }
        },
        FRIEND(REQUEST_CODE_USER_FRIENDS, "user_friends") {
            @Override
            public String createTitle(User user) {
                return name() + "\n" + user.getFriendsCount();
            }
        },
        FOLLOWER(REQUEST_CODE_USER_FOLLOWERS, "user_followers") {
            @Override
            public String createTitle(User user) {
                return name() + "\n" + user.getFollowersCount();
            }
        },
        FAV(REQUEST_CODE_USER_FAVS, "user_favs") {
            @Override
            public String createTitle(User user) {
                return name() + "\n" + user.getFavouritesCount();
            }
        },;

        final @RequestCodeEnum int requestCode;
        final String cacheName;

        UserPageInfo(@RequestCodeEnum int requestCode, String cacheName) {
            this.requestCode = requestCode;
            this.cacheName = cacheName;
        }

        <T> TimelineFragment<T> setup(RequestWorkerBase<SortedCache<T>> worker, UserInfoPagerFragment target) {
            worker.open(cacheName);
            worker.getCache().clear();
            final TimelineFragment<T> fragment = TimelineFragment.getInstance(target, requestCode);
            fragment.setSortedCache(worker.getCache());
            return fragment;
        }

        @Nullable
        static UserPageInfo findByRequestCode(int requestCode) {
            for (UserPageInfo p : values()) {
                if (p.requestCode == requestCode) {
                    return p;
                }
            }
            return null;
        }

        public boolean isStatus() {
            return this == TWEET || this == FAV;
        }

        public boolean isUser() {
            return this == FOLLOWER || this == FRIEND;
        }

        public abstract String createTitle(User user);
    }
}