1 /* 2 * Copyright (C) 2019 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 package com.google.android.car.bugreport; 17 18 import android.os.Build; 19 import android.view.LayoutInflater; 20 import android.view.View; 21 import android.view.ViewGroup; 22 import android.widget.Button; 23 import android.widget.TextView; 24 25 import androidx.recyclerview.widget.RecyclerView; 26 27 import java.util.ArrayList; 28 import java.util.List; 29 30 /** 31 * Shows bugreport title, status, status message and user action buttons. "Upload to Google" button 32 * is enabled when the status is {@link Status#STATUS_PENDING_USER_ACTION}, "Move to USB" button is 33 * enabled only when status is {@link Status#STATUS_PENDING_USER_ACTION} and USB device is plugged 34 * in. 35 */ 36 public class BugInfoAdapter extends RecyclerView.Adapter<BugInfoAdapter.BugInfoViewHolder> { 37 static final int BUTTON_TYPE_UPLOAD = 0; 38 static final int BUTTON_TYPE_MOVE = 1; 39 static final int BUTTON_TYPE_ADD_AUDIO = 2; 40 41 /** Provides a handler for click events*/ 42 interface ItemClickedListener { 43 /** 44 * Handles click events differently depending on provided buttonType and 45 * uses additional information provided in metaBugReport. 46 * 47 * @param buttonType One of {@link #BUTTON_TYPE_UPLOAD}, {@link #BUTTON_TYPE_MOVE} or 48 * {@link #BUTTON_TYPE_ADD_AUDIO}. 49 * @param metaBugReport Selected bugreport. 50 * @param holder ViewHolder of the clicked item. 51 */ onItemClicked(int buttonType, MetaBugReport metaBugReport, BugInfoViewHolder holder)52 void onItemClicked(int buttonType, MetaBugReport metaBugReport, BugInfoViewHolder holder); 53 } 54 55 /** 56 * Reference to each bug report info views. 57 */ 58 static class BugInfoViewHolder extends RecyclerView.ViewHolder { 59 /** Title view */ 60 TextView mTitleView; 61 62 /** Status View */ 63 TextView mStatusView; 64 65 /** Message View */ 66 TextView mMessageView; 67 68 /** Move Button */ 69 Button mMoveButton; 70 71 /** Upload Button */ 72 Button mUploadButton; 73 74 /** Add Audio Button */ 75 Button mAddAudioButton; 76 BugInfoViewHolder(View v)77 BugInfoViewHolder(View v) { 78 super(v); 79 mTitleView = itemView.findViewById(R.id.bug_info_row_title); 80 mStatusView = itemView.findViewById(R.id.bug_info_row_status); 81 mMessageView = itemView.findViewById(R.id.bug_info_row_message); 82 mMoveButton = itemView.findViewById(R.id.bug_info_move_button); 83 mUploadButton = itemView.findViewById(R.id.bug_info_upload_button); 84 mAddAudioButton = itemView.findViewById(R.id.bug_info_add_audio_button); 85 } 86 } 87 88 private List<MetaBugReport> mDataset; 89 private final ItemClickedListener mItemClickedListener; 90 private final Config mConfig; 91 BugInfoAdapter(ItemClickedListener itemClickedListener, Config config)92 BugInfoAdapter(ItemClickedListener itemClickedListener, Config config) { 93 mItemClickedListener = itemClickedListener; 94 mDataset = new ArrayList<>(); 95 mConfig = config; 96 // Allow RecyclerView to efficiently update UI; getItemId() is implemented below. 97 setHasStableIds(true); 98 } 99 100 @Override onCreateViewHolder(ViewGroup parent, int viewType)101 public BugInfoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 102 // create a new view 103 View v = LayoutInflater.from(parent.getContext()) 104 .inflate(R.layout.bug_info_view, parent, false); 105 return new BugInfoViewHolder(v); 106 } 107 108 @Override onBindViewHolder(BugInfoViewHolder holder, int position)109 public void onBindViewHolder(BugInfoViewHolder holder, int position) { 110 MetaBugReport bugreport = mDataset.get(position); 111 holder.mTitleView.setText(bugreport.getTitle()); 112 holder.mStatusView.setText(Status.toString(bugreport.getStatus())); 113 holder.mMessageView.setText(bugreport.getStatusMessage()); 114 if (bugreport.getStatusMessage().isEmpty()) { 115 holder.mMessageView.setVisibility(View.GONE); 116 } else { 117 holder.mMessageView.setVisibility(View.VISIBLE); 118 } 119 boolean enableUserActionButtons = 120 bugreport.getStatus() == Status.STATUS_PENDING_USER_ACTION.getValue() 121 || bugreport.getStatus() == Status.STATUS_MOVE_FAILED.getValue() 122 || bugreport.getStatus() == Status.STATUS_UPLOAD_FAILED.getValue(); 123 if (enableUserActionButtons) { 124 holder.mMoveButton.setEnabled(true); 125 holder.mMoveButton.setVisibility(View.VISIBLE); 126 holder.mMoveButton.setOnClickListener( 127 view -> mItemClickedListener.onItemClicked(BUTTON_TYPE_MOVE, bugreport, 128 holder)); 129 } else { 130 holder.mMoveButton.setEnabled(false); 131 holder.mMoveButton.setVisibility(View.GONE); 132 } 133 // Enable the upload button only for userdebug/eng builds. 134 if (enableUserActionButtons && Build.IS_DEBUGGABLE) { 135 holder.mUploadButton.setText(R.string.bugreport_upload_gcs_button_text); 136 holder.mUploadButton.setEnabled(true); 137 holder.mUploadButton.setVisibility(View.VISIBLE); 138 holder.mUploadButton.setOnClickListener( 139 view -> mItemClickedListener.onItemClicked(BUTTON_TYPE_UPLOAD, bugreport, 140 holder)); 141 } else { 142 holder.mUploadButton.setVisibility(View.GONE); 143 holder.mUploadButton.setEnabled(false); 144 } 145 if (bugreport.getStatus() == Status.STATUS_AUDIO_PENDING.getValue()) { 146 if (mConfig.getAutoUpload()) { 147 holder.mAddAudioButton.setText(R.string.bugreport_add_audio_upload_button_text); 148 } else { 149 holder.mAddAudioButton.setText(R.string.bugreport_add_audio_button_text); 150 } 151 holder.mAddAudioButton.setEnabled(true); 152 holder.mAddAudioButton.setVisibility(View.VISIBLE); 153 holder.mAddAudioButton.setOnClickListener(view -> 154 mItemClickedListener.onItemClicked(BUTTON_TYPE_ADD_AUDIO, bugreport, holder)); 155 } else { 156 holder.mAddAudioButton.setEnabled(false); 157 holder.mAddAudioButton.setVisibility(View.GONE); 158 } 159 } 160 161 /** Sets dataSet; it copies the list, because it modifies it in this adapter. */ setDataset(List<MetaBugReport> bugReports)162 void setDataset(List<MetaBugReport> bugReports) { 163 mDataset = new ArrayList<>(bugReports); 164 notifyDataSetChanged(); 165 } 166 167 /** Update a bug report in the data set. */ updateBugReportInDataSet(MetaBugReport bugReport, int position)168 void updateBugReportInDataSet(MetaBugReport bugReport, int position) { 169 if (position != RecyclerView.NO_POSITION) { 170 mDataset.set(position, bugReport); 171 notifyItemChanged(position); 172 } 173 } 174 175 @Override getItemId(int position)176 public long getItemId(int position) { 177 return mDataset.get(position).getId(); 178 } 179 180 @Override getItemCount()181 public int getItemCount() { 182 return mDataset.size(); 183 } 184 } 185