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.content.Context;
20 import android.content.Intent;
21 import android.os.Bundle;
22 import android.view.LayoutInflater;
23 import android.view.Menu;
24 import android.view.View;
25 import android.view.ViewGroup;
26 import android.widget.ImageView;
27 import android.widget.TextView;
28 
29 import androidx.annotation.NonNull;
30 import androidx.annotation.Nullable;
31 import androidx.annotation.UiThread;
32 import androidx.appcompat.app.ActionBar;
33 import androidx.appcompat.app.AppCompatActivity;
34 import androidx.recyclerview.widget.RecyclerView;
35 
36 import com.android.pump.R;
37 import com.android.pump.db.Album;
38 import com.android.pump.db.Artist;
39 import com.android.pump.db.Audio;
40 import com.android.pump.db.MediaDb;
41 import com.android.pump.util.Globals;
42 
43 @UiThread
44 public class AlbumDetailsActivity extends AppCompatActivity implements MediaDb.UpdateCallback {
45     private MediaDb mMediaDb;
46     private Album mAlbum;
47 
start(@onNull Context context, @NonNull Album album)48     public static void start(@NonNull Context context, @NonNull Album album) {
49         Intent intent = new Intent(context, AlbumDetailsActivity.class);
50         // TODO(b/123704452) Pass URI instead
51         intent.putExtra("id", album.getId()); // TODO Add constant key
52         context.startActivity(intent);
53     }
54 
55     @Override
onCreate(@ullable Bundle savedInstanceState)56     protected void onCreate(@Nullable Bundle savedInstanceState) {
57         super.onCreate(savedInstanceState);
58         setContentView(R.layout.activity_album_details);
59 
60         setSupportActionBar(findViewById(R.id.activity_album_details_toolbar));
61         ActionBar actionBar = getSupportActionBar();
62         if (actionBar != null) {
63             actionBar.setDisplayShowTitleEnabled(false);
64             actionBar.setDisplayShowHomeEnabled(true);
65             actionBar.setDisplayHomeAsUpEnabled(true);
66         }
67 
68         mMediaDb = Globals.getMediaDb(this);
69         mMediaDb.addAlbumUpdateCallback(this);
70 
71         handleIntent();
72     }
73 
74     @Override
onNewIntent(@ullable Intent intent)75     protected void onNewIntent(@Nullable Intent intent) {
76         super.onNewIntent(intent);
77         setIntent(intent);
78 
79         handleIntent();
80     }
81 
82     @Override
onDestroy()83     protected void onDestroy() {
84         mMediaDb.removeAlbumUpdateCallback(this);
85 
86         super.onDestroy();
87     }
88 
89     @Override
onCreateOptionsMenu(@onNull Menu menu)90     public boolean onCreateOptionsMenu(@NonNull Menu menu) {
91         getMenuInflater().inflate(R.menu.activity_pump, menu); // TODO activity_album_details ?
92         return true;
93     }
94 
95     @Override
onSupportNavigateUp()96     public boolean onSupportNavigateUp() {
97         // TODO It should not be necessary to override this method
98         onBackPressed();
99         return true;
100     }
101 
102     @Override
onItemsInserted(int index, int count)103     public void onItemsInserted(int index, int count) { }
104 
105     @Override
onItemsUpdated(int index, int count)106     public void onItemsUpdated(int index, int count) {
107         for (int i = index; i < index + count; ++i) {
108             Album album = mMediaDb.getAlbums().get(i);
109             if (album.equals(mAlbum)) {
110                 updateViews();
111                 break;
112             }
113         }
114     }
115 
116     @Override
onItemsRemoved(int index, int count)117     public void onItemsRemoved(int index, int count) { }
118 
handleIntent()119     private void handleIntent() {
120         Intent intent = getIntent();
121         Bundle extras = intent != null ? intent.getExtras() : null;
122         if (extras != null) {
123             long id = extras.getLong("id");
124 
125             mAlbum = mMediaDb.getAlbumById(id);
126         } else {
127             mAlbum = null;
128             // TODO This shouldn't happen -- throw exception?
129         }
130 
131         mMediaDb.loadData(mAlbum);
132         updateViews();
133     }
134 
updateViews()135     private void updateViews() {
136         ImageView imageView = findViewById(R.id.activity_album_details_image);
137         TextView nameView = findViewById(R.id.activity_album_details_name);
138         TextView countView = findViewById(R.id.activity_album_details_count);
139 
140         imageView.setImageURI(mAlbum.getAlbumArtUri());
141         nameView.setText(mAlbum.getTitle());
142         // TODO(b/123037263) I18n -- Move to resource
143         countView.setText(mAlbum.getAudios().size() + " songs");
144 
145         ImageView playView = findViewById(R.id.activity_album_details_play);
146         playView.setOnClickListener((view) ->
147                 AudioPlayerActivity.start(view.getContext(), mAlbum));
148 
149         RecyclerView recyclerView = findViewById(R.id.activity_album_details_recycler_view);
150         recyclerView.setHasFixedSize(true);
151         recyclerView.setAdapter(new AlbumAdapter(mMediaDb, mAlbum));
152 
153         // TODO(b/123707260) Enable view caching
154         //recyclerView.setItemViewCacheSize(0);
155         //recyclerView.setRecycledViewPool(Globals.getRecycledViewPool(requireContext()));
156     }
157 
158     private static class AlbumAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
159         private final MediaDb mMediaDb;
160         private final Album mAlbum;
161 
AlbumAdapter(@onNull MediaDb mediaDb, @NonNull Album album)162         private AlbumAdapter(@NonNull MediaDb mediaDb, @NonNull Album album) {
163             setHasStableIds(true);
164             mMediaDb = mediaDb;
165             mAlbum = album;
166         }
167 
168         @Override
onCreateViewHolder( @onNull ViewGroup parent, int viewType)169         public @NonNull RecyclerView.ViewHolder onCreateViewHolder(
170                 @NonNull ViewGroup parent, int viewType) {
171             return new AudioViewHolder(LayoutInflater.from(parent.getContext())
172                     .inflate(viewType, parent, false));
173         }
174 
175         @Override
onBindViewHolder(@onNull RecyclerView.ViewHolder holder, int position)176         public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
177             Audio audio = mAlbum.getAudios().get(position);
178             mMediaDb.loadData(audio); // TODO Where should we call this? In bind()?
179             ((AudioViewHolder) holder).bind(mAlbum, audio);
180         }
181 
182         @Override
getItemCount()183         public int getItemCount() {
184             return mAlbum.getAudios().size();
185         }
186 
187         @Override
getItemId(int position)188         public long getItemId(int position) {
189             return mAlbum.getAudios().get(position).getId();
190         }
191 
192         @Override
getItemViewType(int position)193         public int getItemViewType(int position) {
194             return R.layout.audio;
195         }
196     }
197 
198     private static class AudioViewHolder extends RecyclerView.ViewHolder {
AudioViewHolder(@onNull View itemView)199         private AudioViewHolder(@NonNull View itemView) {
200             super(itemView);
201         }
202 
bind(@onNull Album album, @NonNull Audio audio)203         private void bind(@NonNull Album album, @NonNull Audio audio) {
204             ImageView imageView = itemView.findViewById(R.id.audio_image);
205             TextView titleView = itemView.findViewById(R.id.audio_title);
206             TextView artistView = itemView.findViewById(R.id.audio_artist);
207 
208             imageView.setImageURI(album.getAlbumArtUri());
209             titleView.setText(audio.getTitle());
210             Artist artist = audio.getArtist();
211             artistView.setText(artist == null ? null : artist.getName());
212 
213             itemView.setOnClickListener((view) ->
214                     AudioPlayerActivity.start(view.getContext(), audio));
215         }
216     }
217 }
218