1 /* 2 * Copyright (C) 2016 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.tv.dvr.ui; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.graphics.drawable.Drawable; 22 import android.os.Bundle; 23 24 import androidx.leanback.widget.GuidanceStylist; 25 import androidx.leanback.widget.GuidedAction; 26 27 import com.android.tv.R; 28 import com.android.tv.TvSingletons; 29 import com.android.tv.data.ProgramImpl; 30 import com.android.tv.data.api.Program; 31 import com.android.tv.dvr.DvrScheduleManager; 32 import com.android.tv.dvr.data.ScheduledRecording; 33 import com.android.tv.dvr.data.SeriesRecording; 34 import com.android.tv.dvr.ui.list.DvrSchedulesActivity; 35 import com.android.tv.dvr.ui.list.DvrSeriesSchedulesFragment; 36 37 import java.util.List; 38 39 public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment { 40 /** 41 * The key for program list which will be passed to {@link DvrSeriesSchedulesFragment}. Type: 42 * List<{@link ProgramImpl}> 43 */ 44 public static final String SERIES_SCHEDULED_KEY_PROGRAMS = "series_scheduled_key_programs"; 45 46 private static final long SERIES_RECORDING_ID_NOT_SET = -1; 47 48 private static final int ACTION_VIEW_SCHEDULES = 1; 49 50 private SeriesRecording mSeriesRecording; 51 private boolean mShowViewScheduleOption; 52 private List<Program> mPrograms; 53 private String mSeriesRecordingTitle; 54 55 private int mSchedulesAddedCount = 0; 56 private boolean mHasConflict = false; 57 private int mInThisSeriesConflictCount = 0; 58 private int mOutThisSeriesConflictCount = 0; 59 60 @Override onAttach(Context context)61 public void onAttach(Context context) { 62 super.onAttach(context); 63 long seriesRecordingId = 64 getArguments() 65 .getLong( 66 DvrSeriesScheduledDialogActivity.SERIES_RECORDING_ID, 67 SERIES_RECORDING_ID_NOT_SET); 68 if (seriesRecordingId == SERIES_RECORDING_ID_NOT_SET) { 69 getActivity().finish(); 70 return; 71 } 72 mShowViewScheduleOption = 73 getArguments() 74 .getBoolean(DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION); 75 mSeriesRecording = 76 TvSingletons.getSingletons(context) 77 .getDvrDataManager() 78 .getSeriesRecording(seriesRecordingId); 79 if (mSeriesRecording == null) { 80 getActivity().finish(); 81 return; 82 } 83 mSeriesRecordingTitle = mSeriesRecording.getTitle(); 84 mPrograms = (List<Program>) BigArguments.getArgument(SERIES_SCHEDULED_KEY_PROGRAMS); 85 BigArguments.reset(); 86 mSchedulesAddedCount = 87 TvSingletons.getSingletons(getContext()) 88 .getDvrManager() 89 .getAvailableScheduledRecording(mSeriesRecording.getId()) 90 .size(); 91 DvrScheduleManager dvrScheduleManager = 92 TvSingletons.getSingletons(context).getDvrScheduleManager(); 93 List<ScheduledRecording> conflictingRecordings = 94 dvrScheduleManager.getConflictingSchedules(mSeriesRecording); 95 mHasConflict = !conflictingRecordings.isEmpty(); 96 for (ScheduledRecording recording : conflictingRecordings) { 97 if (recording.getSeriesRecordingId() == mSeriesRecording.getId()) { 98 ++mInThisSeriesConflictCount; 99 } else if (recording.getPriority() < mSeriesRecording.getPriority()) { 100 ++mOutThisSeriesConflictCount; 101 } 102 } 103 } 104 105 @Override onCreateGuidance(Bundle savedInstanceState)106 public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) { 107 String title = getString(R.string.dvr_series_recording_dialog_title); 108 Drawable icon; 109 if (!mHasConflict) { 110 icon = getResources().getDrawable(R.drawable.quantum_ic_check_circle_white_48, null); 111 } else { 112 icon = getResources().getDrawable(R.drawable.quantum_ic_error_white_48, null); 113 } 114 return new GuidanceStylist.Guidance(title, getDescription(), null, icon); 115 } 116 117 @Override onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState)118 public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { 119 Context context = getContext(); 120 actions.add( 121 new GuidedAction.Builder(context).clickAction(GuidedAction.ACTION_ID_OK).build()); 122 if (mShowViewScheduleOption) { 123 actions.add( 124 new GuidedAction.Builder(context) 125 .id(ACTION_VIEW_SCHEDULES) 126 .title(R.string.dvr_action_view_schedules) 127 .build()); 128 } 129 } 130 131 @Override onTrackedGuidedActionClicked(GuidedAction action)132 public void onTrackedGuidedActionClicked(GuidedAction action) { 133 if (action.getId() == ACTION_VIEW_SCHEDULES) { 134 Intent intent = new Intent(getActivity(), DvrSchedulesActivity.class); 135 intent.putExtra( 136 DvrSchedulesActivity.KEY_SCHEDULES_TYPE, 137 DvrSchedulesActivity.TYPE_SERIES_SCHEDULE); 138 intent.putExtra( 139 DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING, 140 mSeriesRecording); 141 BigArguments.reset(); 142 BigArguments.setArgument( 143 DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_PROGRAMS, mPrograms); 144 startActivity(intent); 145 } 146 getActivity().finish(); 147 } 148 149 @Override getTrackerPrefix()150 public String getTrackerPrefix() { 151 return "DvrMissingStorageErrorFragment"; 152 } 153 154 @Override getTrackerLabelForGuidedAction(GuidedAction action)155 public String getTrackerLabelForGuidedAction(GuidedAction action) { 156 long actionId = action.getId(); 157 if (actionId == ACTION_VIEW_SCHEDULES) { 158 return "view-schedules"; 159 } else { 160 return super.getTrackerLabelForGuidedAction(action); 161 } 162 } 163 getDescription()164 private String getDescription() { 165 if (!mHasConflict) { 166 return getResources() 167 .getQuantityString( 168 R.plurals.dvr_series_scheduled_no_conflict, 169 mSchedulesAddedCount, 170 mSchedulesAddedCount, 171 mSeriesRecordingTitle); 172 } else { 173 // mInThisSeriesConflictCount equals 0 and mOutThisSeriesConflictCount equals 0 means 174 // mHasConflict is false. So we don't need to check that case. 175 if (mInThisSeriesConflictCount != 0 && mOutThisSeriesConflictCount != 0) { 176 return getResources() 177 .getQuantityString( 178 R.plurals.dvr_series_scheduled_this_and_other_series_conflict, 179 mSchedulesAddedCount, 180 mSchedulesAddedCount, 181 mSeriesRecordingTitle, 182 mInThisSeriesConflictCount + mOutThisSeriesConflictCount); 183 } else if (mInThisSeriesConflictCount != 0) { 184 return getResources() 185 .getQuantityString( 186 R.plurals.dvr_series_recording_scheduled_only_this_series_conflict, 187 mSchedulesAddedCount, 188 mSchedulesAddedCount, 189 mSeriesRecordingTitle, 190 mInThisSeriesConflictCount); 191 } else { 192 if (mOutThisSeriesConflictCount == 1) { 193 return getResources() 194 .getQuantityString( 195 R.plurals.dvr_series_scheduled_only_other_series_one_conflict, 196 mSchedulesAddedCount, 197 mSchedulesAddedCount, 198 mSeriesRecordingTitle); 199 } else { 200 return getResources() 201 .getQuantityString( 202 R.plurals.dvr_series_scheduled_only_other_series_many_conflicts, 203 mSchedulesAddedCount, 204 mSchedulesAddedCount, 205 mSeriesRecordingTitle, 206 mOutThisSeriesConflictCount); 207 } 208 } 209 } 210 } 211 } 212