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