1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.pump.activity;
18 
19 import android.Manifest;
20 import android.content.pm.PackageManager;
21 import android.os.Bundle;
22 import android.view.Menu;
23 import android.view.MenuItem;
24 import android.view.View;
25 
26 import androidx.annotation.IdRes;
27 import androidx.annotation.NonNull;
28 import androidx.annotation.Nullable;
29 import androidx.annotation.UiThread;
30 import androidx.appcompat.app.ActionBar;
31 import androidx.appcompat.app.AppCompatActivity;
32 import androidx.core.content.ContextCompat;
33 import androidx.core.view.GravityCompat;
34 import androidx.drawerlayout.widget.DrawerLayout;
35 import androidx.fragment.app.Fragment;
36 import androidx.fragment.app.FragmentManager;
37 import androidx.fragment.app.FragmentPagerAdapter;
38 import androidx.viewpager.widget.ViewPager;
39 
40 import com.android.pump.R;
41 import com.android.pump.fragment.AlbumFragment;
42 import com.android.pump.fragment.ArtistFragment;
43 import com.android.pump.fragment.AudioFragment;
44 import com.android.pump.fragment.GenreFragment;
45 import com.android.pump.fragment.HomeFragment;
46 import com.android.pump.fragment.MovieFragment;
47 import com.android.pump.fragment.OtherFragment;
48 import com.android.pump.fragment.PermissionFragment;
49 import com.android.pump.fragment.PlaylistFragment;
50 import com.android.pump.fragment.SeriesFragment;
51 import com.android.pump.util.Globals;
52 import com.google.android.material.bottomnavigation.BottomNavigationView;
53 import com.google.android.material.bottomnavigation.BottomNavigationView.OnNavigationItemSelectedListener;
54 import com.google.android.material.tabs.TabLayout;
55 
56 @UiThread
57 public class PumpActivity extends AppCompatActivity implements OnNavigationItemSelectedListener {
58     // TODO The following should be a non-static member
59     private static boolean sIsMissingPermissions = true;
60 
61     private static final Pages[] PAGES_LIST = {
62         new Pages(R.id.menu_home, new Page[] {
63             new Page(HomeFragment::newInstance, "Home")
64         }),
65         new Pages(R.id.menu_video, new Page[] {
66             new Page(MovieFragment::newInstance, "Movies"),
67             new Page(SeriesFragment::newInstance, "TV Shows"),
68             new Page(OtherFragment::newInstance, "Personal"),
69             new Page(HomeFragment::newInstance, "All videos")
70         }),
71         new Pages(R.id.menu_audio, new Page[] {
72             new Page(AudioFragment::newInstance, "All audios"),
73             new Page(PlaylistFragment::newInstance, "Playlists"),
74             new Page(AlbumFragment::newInstance, "Albums"),
75             new Page(GenreFragment::newInstance, "Genres"),
76             new Page(ArtistFragment::newInstance, "Artists")
77         }),
78         new Pages(R.id.menu_favorite, new Page[] {
79             new Page(HomeFragment::newInstance, "Videos"),
80             new Page(HomeFragment::newInstance, "Audios")
81         })
82     };
83 
84     private boolean mInitialized = false;
85 
86     private ActivityPagerAdapter mActivityPagerAdapter;
87 
88     private DrawerLayout mDrawerLayout;
89     private ViewPager mViewPager;
90     private TabLayout mTabLayout;
91     private BottomNavigationView mBottomNavigationView;
92 
93     @Override
onCreate(@ullable Bundle savedInstanceState)94     protected void onCreate(@Nullable Bundle savedInstanceState) {
95         super.onCreate(savedInstanceState);
96         // NOTE: If you are facing StrictMode violation by setContentView please disable instant run
97         setContentView(R.layout.activity_pump);
98 
99         setSupportActionBar(findViewById(R.id.activity_pump_toolbar));
100 
101         mActivityPagerAdapter = new ActivityPagerAdapter(getSupportFragmentManager());
102 
103         mDrawerLayout = findViewById(R.id.activity_pump_drawer_layout);
104         mViewPager = findViewById(R.id.activity_pump_view_pager);
105         mTabLayout = findViewById(R.id.activity_pump_tab_layout);
106         mBottomNavigationView = findViewById(R.id.activity_pump_bottom_navigation_view);
107 
108         mBottomNavigationView.setOnNavigationItemSelectedListener(this);
109         mBottomNavigationView.setSelectedItemId(R.id.menu_home);
110         mViewPager.setAdapter(mActivityPagerAdapter);
111         mTabLayout.setupWithViewPager(mViewPager);
112     }
113 
114     @Override
onResume()115     public void onResume() {
116         super.onResume();
117 
118         initialize();
119     }
120 
121     @Override
onCreateOptionsMenu(@onNull Menu menu)122     public boolean onCreateOptionsMenu(@NonNull Menu menu) {
123         getMenuInflater().inflate(R.menu.activity_pump, menu);
124         return true;
125     }
126 
127     @Override
onOptionsItemSelected(@onNull MenuItem item)128     public boolean onOptionsItemSelected(@NonNull MenuItem item) {
129         if (item.getItemId() == android.R.id.home) {
130             mDrawerLayout.openDrawer(GravityCompat.START);
131             return true;
132         }
133         return super.onOptionsItemSelected(item);
134     }
135 
136     @Override
onNavigationItemSelected(@onNull MenuItem item)137     public boolean onNavigationItemSelected(@NonNull MenuItem item) {
138         for (Pages pages : PAGES_LIST) {
139             if (pages.getId() == item.getItemId()) {
140                 selectPages(item.getTitle(), pages);
141                 return true;
142             }
143         }
144         return false;
145     }
146 
147     // TODO This should not be public
initialize()148     public void initialize() {
149         if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
150                 == PackageManager.PERMISSION_GRANTED) {
151             if (!mInitialized) {
152                 mInitialized = true;
153 
154                 sIsMissingPermissions = false;
155                 mActivityPagerAdapter.notifyDataSetChanged();
156 
157                 Globals.getMediaDb(this).load();
158             }
159         }
160     }
161 
selectPages(@onNull CharSequence title, @NonNull Pages pages)162     private void selectPages(@NonNull CharSequence title, @NonNull Pages pages) {
163         ActionBar actionBar = getSupportActionBar();
164         if (actionBar != null) {
165             actionBar.setTitle(title);
166         }
167 
168         Pages current = mActivityPagerAdapter.getPages();
169         if (current != null) {
170             current.setCurrent(mViewPager.getCurrentItem());
171         }
172 
173         mActivityPagerAdapter.setPages(pages);
174         int count = mActivityPagerAdapter.getCount();
175         mTabLayout.setVisibility(count <= 1 ? View.GONE : View.VISIBLE);
176         mTabLayout.setTabMode(count <= 4 ? TabLayout.MODE_FIXED : TabLayout.MODE_SCROLLABLE);
177         mViewPager.setCurrentItem(pages.getCurrent());
178     }
179 
180     private static class ActivityPagerAdapter extends FragmentPagerAdapter {
181         private Pages mPages;
182 
ActivityPagerAdapter(@onNull FragmentManager fm)183         ActivityPagerAdapter(@NonNull FragmentManager fm) {
184             super(fm);
185         }
186 
setPages(@onNull Pages pages)187         void setPages(@NonNull Pages pages) {
188             mPages = pages;
189             notifyDataSetChanged();
190         }
191 
getPages()192         @Nullable Pages getPages() {
193             return mPages;
194         }
195 
196         @Override
getCount()197         public int getCount() {
198             return mPages.getPages().length;
199         }
200 
201         @Override
getItem(int position)202         public @NonNull Fragment getItem(int position) {
203             return mPages.getPages()[position].createFragment();
204         }
205 
206         @Override
getItemId(int position)207         public long getItemId(int position) {
208             return mPages.getPages()[position].getId();
209         }
210 
211         @Override
getItemPosition(@onNull Object object)212         public int getItemPosition(@NonNull Object object) {
213             return POSITION_NONE;
214         }
215 
216         @Override
getPageTitle(int position)217         public @NonNull CharSequence getPageTitle(int position) {
218             return mPages.getPages()[position].getTitle();
219         }
220     }
221 
222     private static class Page {
223         private static int sId = 0;
224 
225         private final int mId;
226         private final PageCreator mPageCreator;
227         private final String mTitle;
228 
Page(@onNull PageCreator pageCreator, @NonNull String title)229         Page(@NonNull PageCreator pageCreator, @NonNull String title) {
230             mId = sId++;
231             mPageCreator = pageCreator;
232             mTitle = title;
233         }
234 
getId()235         int getId() {
236             if (isMissingPermissions()) {
237                 return ~mId;
238             }
239             return mId;
240         }
241 
createFragment()242         @NonNull Fragment createFragment() {
243             if (isMissingPermissions()) {
244                 return PermissionFragment.newInstance();
245             }
246             return mPageCreator.newInstance();
247         }
248 
getTitle()249         @NonNull String getTitle() {
250             return mTitle;
251         }
252 
isMissingPermissions()253         private boolean isMissingPermissions() {
254             return sIsMissingPermissions;
255         }
256     }
257 
258     private static class Pages {
259         private final int mId;
260         private final Page[] mPages;
261 
262         private int mCurrent;
263 
Pages(@dRes int id, @NonNull Page[] pages)264         Pages(@IdRes int id, @NonNull Page[] pages) {
265             mId = id;
266             mPages = pages;
267         }
268 
getId()269         int getId() {
270             return mId;
271         }
272 
getPages()273         @NonNull Page[] getPages() {
274             return mPages;
275         }
276 
setCurrent(int current)277         void setCurrent(int current) {
278             mCurrent = current;
279         }
280 
getCurrent()281         int getCurrent() {
282             return mCurrent;
283         }
284     }
285 
286     @FunctionalInterface
287     private interface PageCreator {
newInstance()288         @NonNull Fragment newInstance();
289     }
290 }
291