blob: d223da9ba8c5d9fe533ec1fe9eecd6780d9e2f9c [file] [log] [blame]
Adrien Béraud04d822c2015-04-02 17:44:36 -04001/*
Sébastien Blinab53ada2019-01-02 17:23:00 -05002 * Copyright (C) 2004-2019 Savoir-faire Linux Inc.
Adrien Béraud04d822c2015-04-02 17:44:36 -04003 *
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04004 * Author: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
Adrien Béraudbc0898e2018-08-23 14:31:11 -04005 * Adrien Béraud <adrien.beraud@savoirfairelinux.com>
Adrien Béraud04d822c2015-04-02 17:44:36 -04006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
Adrien Béraudda712a42015-11-22 23:45:26 -050019 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Adrien Béraud04d822c2015-04-02 17:44:36 -040020 */
Adrien Béraud04d822c2015-04-02 17:44:36 -040021package cx.ring.fragments;
22
Adrien Béraudde0d4522018-12-12 12:11:02 -050023import android.app.Activity;
Adrien Béraud79808d02018-02-20 00:16:28 +010024import android.app.PendingIntent;
25import android.app.PictureInPictureParams;
26import android.app.RemoteAction;
Adrien Béraud162427f2016-04-12 18:04:08 -040027import android.content.Context;
28import android.content.Intent;
Adrien Béraudde0d4522018-12-12 12:11:02 -050029import android.graphics.Matrix;
Adrien Béraudfb6341f2016-03-07 16:18:54 -050030import android.graphics.PixelFormat;
Adrien Béraud79808d02018-02-20 00:16:28 +010031import android.graphics.Rect;
Adrien Béraudde0d4522018-12-12 12:11:02 -050032import android.graphics.RectF;
33import android.graphics.SurfaceTexture;
Adrien Béraud79808d02018-02-20 00:16:28 +010034import android.graphics.drawable.Icon;
Adrien Béraud8d6a4832016-04-12 18:06:11 -040035import android.os.Build;
Adrien Béraud04d822c2015-04-02 17:44:36 -040036import android.os.Bundle;
37import android.os.PowerManager;
Adrien Béraud3f9f6cd2018-12-12 15:05:28 -050038
Adrien Béraud8bc95102018-08-25 22:34:51 -040039import androidx.annotation.NonNull;
40import androidx.annotation.Nullable;
Adrien Béraudbcbb4d42018-12-08 16:06:39 -050041
42import android.text.Editable;
43import android.text.TextWatcher;
Adrien Béraud79808d02018-02-20 00:16:28 +010044import android.util.Rational;
Adrien Béraud86a1e372018-11-23 23:24:30 -050045import android.view.LayoutInflater;
Adrien Béraud162427f2016-04-12 18:04:08 -040046import android.view.Menu;
47import android.view.MenuInflater;
48import android.view.MenuItem;
Adrien Béraudeb4bb002019-03-14 15:52:48 -040049import android.view.OrientationEventListener;
Adrien Béraudde0d4522018-12-12 12:11:02 -050050import android.view.Surface;
Adrien Béraud162427f2016-04-12 18:04:08 -040051import android.view.SurfaceHolder;
Adrien Béraudde0d4522018-12-12 12:11:02 -050052import android.view.TextureView;
Adrien Béraud162427f2016-04-12 18:04:08 -040053import android.view.View;
Adrien Béraud162427f2016-04-12 18:04:08 -040054import android.view.ViewGroup;
Adrien Béraudeb4bb002019-03-14 15:52:48 -040055import android.view.WindowManager;
Romain Bertozziad8fd842016-05-11 14:30:35 -040056import android.view.inputmethod.InputMethodManager;
Adrien Béraud162427f2016-04-12 18:04:08 -040057import android.widget.RelativeLayout;
Adrien Béraud04d822c2015-04-02 17:44:36 -040058
Pierre Ducheminbb833672018-03-09 16:18:33 -050059import com.rodolfonavalon.shaperipplelibrary.model.Circle;
Thibault Wittembergb70d5b02016-07-08 16:50:14 -040060
Adrien Béraud79808d02018-02-20 00:16:28 +010061import java.util.ArrayList;
Romain Bertozzi64a66782016-08-02 12:10:38 -040062import java.util.Locale;
Adrien Béraud79808d02018-02-20 00:16:28 +010063import java.util.Random;
Adrien Béraud04d822c2015-04-02 17:44:36 -040064
Adrien Béraud8bc95102018-08-25 22:34:51 -040065import androidx.appcompat.app.ActionBar;
66import androidx.appcompat.app.AppCompatActivity;
Adrien Béraud86a1e372018-11-23 23:24:30 -050067import androidx.databinding.DataBindingUtil;
Adrien Béraud162427f2016-04-12 18:04:08 -040068import cx.ring.R;
Adrien Béraud86a1e372018-11-23 23:24:30 -050069import cx.ring.application.RingApplication;
Hadrien De Sousaccc947d2017-04-12 14:26:52 -040070import cx.ring.call.CallPresenter;
71import cx.ring.call.CallView;
Adrien Béraud162427f2016-04-12 18:04:08 -040072import cx.ring.client.ConversationActivity;
Thibault Wittemberg4f33d072016-10-06 17:11:41 -040073import cx.ring.client.HomeActivity;
Adrien Béraud86a1e372018-11-23 23:24:30 -050074import cx.ring.databinding.FragCallBinding;
Hadrien De Sousa73d6dd72017-09-07 10:54:51 -040075import cx.ring.dependencyinjection.RingInjectionComponent;
Adrien Béraud04d822c2015-04-02 17:44:36 -040076import cx.ring.model.CallContact;
Adrien Béraud04d822c2015-04-02 17:44:36 -040077import cx.ring.model.SipCall;
Adrien Bérauda373e3b2018-12-12 11:14:50 -050078import cx.ring.mvp.BaseSupportFragment;
Alexandre Lision5da46fa2017-08-09 10:25:50 -040079import cx.ring.service.DRingService;
Adrien Béraud79808d02018-02-20 00:16:28 +010080import cx.ring.services.NotificationService;
Alexandre Lision4865f7d2016-11-16 18:03:35 -050081import cx.ring.utils.ActionHelper;
Pierre Duchemin42788c32018-03-08 16:21:15 -050082import cx.ring.utils.DeviceUtils;
Romain Bertozziad8fd842016-05-11 14:30:35 -040083import cx.ring.utils.KeyboardVisibilityManager;
Adrien Béraud5f8c3f72018-03-09 14:49:39 -050084import cx.ring.utils.Log;
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -050085import cx.ring.utils.MediaButtonsHelper;
Adrien Béraud8f9d2702018-09-16 18:24:01 -040086import cx.ring.views.AvatarDrawable;
Adrien Béraud2c378b32018-07-11 15:24:02 -040087import io.reactivex.disposables.CompositeDisposable;
Adrien Béraud04d822c2015-04-02 17:44:36 -040088
Adrien Bérauda373e3b2018-12-12 11:14:50 -050089public class CallFragment extends BaseSupportFragment<CallPresenter> implements CallView, MediaButtonsHelper.MediaButtonsHelperCallback {
Adrien Béraud04d822c2015-04-02 17:44:36 -040090
Hadrien De Sousaccc947d2017-04-12 14:26:52 -040091 public static final String TAG = CallFragment.class.getSimpleName();
Adrien Béraud04d822c2015-04-02 17:44:36 -040092
Hadrien De Sousaccc947d2017-04-12 14:26:52 -040093 public static final String ACTION_PLACE_CALL = "PLACE_CALL";
94 public static final String ACTION_GET_CALL = "GET_CALL";
Adrien Béraud04d822c2015-04-02 17:44:36 -040095
Hadrien De Sousaccc947d2017-04-12 14:26:52 -040096 public static final String KEY_ACTION = "action";
97 public static final String KEY_ACCOUNT_ID = "accountId";
98 public static final String KEY_CONF_ID = "confId";
Hadrien De Sousa203164c2017-12-05 17:41:42 -050099 public static final String KEY_AUDIO_ONLY = "AUDIO_ONLY";
Thibault Wittembergb70d5b02016-07-08 16:50:14 -0400100
Adrien Béraud86a1e372018-11-23 23:24:30 -0500101 private FragCallBinding binding;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400102 private OrientationEventListener mOrientationListener;
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400103
Romain Bertozziad8fd842016-05-11 14:30:35 -0400104 private MenuItem dialPadBtn = null;
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400105 private boolean restartVideo = false;
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400106 private PowerManager.WakeLock mScreenWakeLock;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400107 private int mCurrentOrientation = 0;
108
109 private int mVideoWidth = -1;
110 private int mVideoHeight = -1;
Adrien Béraudde0d4522018-12-12 12:11:02 -0500111 private int mPreviewWidth = 720, mPreviewHeight = 1280;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400112 private int mPreviewSurfaceWidth = 0, mPreviewSurfaceHeight = 0;
Adrien Béraud8d6a4832016-04-12 18:06:11 -0400113
Adrien Béraud2c378b32018-07-11 15:24:02 -0400114 private final CompositeDisposable mCompositeDisposable = new CompositeDisposable();
115
Hadrien De Sousa203164c2017-12-05 17:41:42 -0500116 public static CallFragment newInstance(@NonNull String action, @Nullable String accountID, @Nullable String contactRingId, boolean audioOnly) {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400117 Bundle bundle = new Bundle();
118 bundle.putString(KEY_ACTION, action);
119 bundle.putString(KEY_ACCOUNT_ID, accountID);
Hadrien De Sousa0dc83162017-11-10 16:15:18 -0500120 bundle.putString(ConversationFragment.KEY_CONTACT_RING_ID, contactRingId);
Hadrien De Sousa203164c2017-12-05 17:41:42 -0500121 bundle.putBoolean(KEY_AUDIO_ONLY, audioOnly);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400122 CallFragment countDownFragment = new CallFragment();
123 countDownFragment.setArguments(bundle);
124 return countDownFragment;
125 }
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500126
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400127 public static CallFragment newInstance(@NonNull String action, @Nullable String confId) {
128 Bundle bundle = new Bundle();
129 bundle.putString(KEY_ACTION, action);
130 bundle.putString(KEY_CONF_ID, confId);
131 CallFragment countDownFragment = new CallFragment();
132 countDownFragment.setArguments(bundle);
133 return countDownFragment;
134 }
135
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400136 public static int callStateToHumanState(final SipCall.State state) {
Loïc Siret0202fbf2017-09-28 16:34:28 -0400137 switch (state) {
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400138 case SEARCHING:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400139 return R.string.call_human_state_searching;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400140 case CONNECTING:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400141 return R.string.call_human_state_connecting;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400142 case RINGING:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400143 return R.string.call_human_state_ringing;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400144 case CURRENT:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400145 return R.string.call_human_state_current;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400146 case HUNGUP:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400147 return R.string.call_human_state_hungup;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400148 case BUSY:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400149 return R.string.call_human_state_busy;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400150 case FAILURE:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400151 return R.string.call_human_state_failure;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400152 case HOLD:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400153 return R.string.call_human_state_hold;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400154 case UNHOLD:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400155 return R.string.call_human_state_unhold;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400156 case OVER:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400157 return R.string.call_human_state_over;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400158 case NONE:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400159 default:
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400160 return 0;
Loïc Siret0202fbf2017-09-28 16:34:28 -0400161 }
162 }
163
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400164 @Override
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400165 protected void initPresenter(CallPresenter presenter) {
166 super.initPresenter(presenter);
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400167 Bundle args = getArguments();
168 if (args != null) {
169 String action = args.getString(KEY_ACTION);
170 if (action != null) {
171 if (action.equals(ACTION_PLACE_CALL)) {
172 presenter.initOutGoing(getArguments().getString(KEY_ACCOUNT_ID),
173 getArguments().getString(ConversationFragment.KEY_CONTACT_RING_ID),
174 getArguments().getBoolean(KEY_AUDIO_ONLY));
175 } else if (action.equals(ACTION_GET_CALL)) {
176 presenter.initIncoming(getArguments().getString(KEY_CONF_ID));
177 }
Pierre Duchemin45707ca2018-01-15 15:05:23 -0500178 }
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500179 }
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500180 }
181
Adrien Béraud79808d02018-02-20 00:16:28 +0100182 public void onUserLeave() {
183 presenter.requestPipMode();
184 }
185
186 @Override
187 public void enterPipMode(SipCall sipCall) {
188 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
189 return;
190 }
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400191 Context context = requireContext();
Adrien Béraud79808d02018-02-20 00:16:28 +0100192 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
193 PictureInPictureParams.Builder paramBuilder = new PictureInPictureParams.Builder();
Adrien Béraud86a1e372018-11-23 23:24:30 -0500194 if (binding.videoSurface.getVisibility() == View.VISIBLE) {
Adrien Béraud79808d02018-02-20 00:16:28 +0100195 int[] l = new int[2];
Adrien Béraud86a1e372018-11-23 23:24:30 -0500196 binding.videoSurface.getLocationInWindow(l);
Adrien Béraud79808d02018-02-20 00:16:28 +0100197 int x = l[0];
198 int y = l[1];
Adrien Béraud86a1e372018-11-23 23:24:30 -0500199 int w = binding.videoSurface.getWidth();
200 int h = binding.videoSurface.getHeight();
Adrien Béraud79808d02018-02-20 00:16:28 +0100201 Rect videoBounds = new Rect(x, y, x + w, y + h);
202 paramBuilder.setAspectRatio(new Rational(w, h));
203 paramBuilder.setSourceRectHint(videoBounds);
204 }
205 ArrayList<RemoteAction> actions = new ArrayList<>(1);
206 actions.add(new RemoteAction(
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400207 Icon.createWithResource(context, R.drawable.baseline_call_end_24),
Adrien Béraud79808d02018-02-20 00:16:28 +0100208 getString(R.string.action_call_hangup),
209 getString(R.string.action_call_hangup),
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400210 PendingIntent.getService(context, new Random().nextInt(),
Adrien Béraud79808d02018-02-20 00:16:28 +0100211 new Intent(DRingService.ACTION_CALL_END)
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400212 .setClass(context, DRingService.class)
Adrien Béraud79808d02018-02-20 00:16:28 +0100213 .putExtra(NotificationService.KEY_CALL_ID, sipCall.getCallId()), PendingIntent.FLAG_ONE_SHOT)));
214 paramBuilder.setActions(actions);
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400215 requireActivity().enterPictureInPictureMode(paramBuilder.build());
216 } else if (DeviceUtils.isTv(context)) {
217 requireActivity().enterPictureInPictureMode();
Adrien Béraud79808d02018-02-20 00:16:28 +0100218 }
219 }
220
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500221 @Override
Hadrien De Sousa73d6dd72017-09-07 10:54:51 -0400222 public int getLayout() {
223 return R.layout.frag_call;
224 }
225
226 @Override
227 public void injectFragment(RingInjectionComponent component) {
228 component.inject(this);
229 }
230
231 @Override
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400232 public void onStart() {
233 super.onStart();
234 if (restartVideo) {
235 displayVideoSurface(true);
236 restartVideo = false;
237 }
238 }
239
240 @Override
241 public void onStop() {
242 super.onStop();
Adrien Béraud86a1e372018-11-23 23:24:30 -0500243 if (binding.videoSurface.getVisibility() == View.VISIBLE) {
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400244 restartVideo = true;
245 }
246 }
247
Adrien Béraud86a1e372018-11-23 23:24:30 -0500248 @Nullable
249 @Override
Adrien Béraudc14d55d2019-01-02 16:33:40 -0500250 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400251 injectFragment(((RingApplication) requireActivity().getApplication()).getRingInjectionComponent());
Adrien Béraud86a1e372018-11-23 23:24:30 -0500252 binding = DataBindingUtil.inflate(inflater, R.layout.frag_call, container, false);
253 binding.setPresenter(this);
254 return binding.getRoot();
255 }
256
Adrien Béraudde0d4522018-12-12 12:11:02 -0500257 private TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() {
258 @Override
259 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400260 mPreviewSurfaceWidth = width;
261 mPreviewSurfaceHeight = height;
Adrien Béraudde0d4522018-12-12 12:11:02 -0500262 presenter.previewVideoSurfaceCreated(binding.previewSurface);
263 }
264
265 @Override
266 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400267 mPreviewSurfaceWidth = width;
268 mPreviewSurfaceHeight = height;
Adrien Béraudde0d4522018-12-12 12:11:02 -0500269 }
270
271 @Override
272 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
273 presenter.previewVideoSurfaceDestroyed();
274 return true;
275 }
276
277 @Override
278 public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
279 };
280
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400281 @Override
Adrien Béraudc14d55d2019-01-02 16:33:40 -0500282 public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400283 setHasOptionsMenu(true);
Hadrien De Sousa73d6dd72017-09-07 10:54:51 -0400284 super.onViewCreated(view, savedInstanceState);
Adrien Béraud79808d02018-02-20 00:16:28 +0100285 mCurrentOrientation = getResources().getConfiguration().orientation;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400286 PowerManager powerManager = (PowerManager) requireContext().getSystemService(Context.POWER_SERVICE);
Adrien Béraud87810c72018-06-11 15:55:03 -0400287 mScreenWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "ring:callLock");
Adrien Béraud04d822c2015-04-02 17:44:36 -0400288 mScreenWakeLock.setReferenceCounted(false);
289
Adrien Béraud04d822c2015-04-02 17:44:36 -0400290 if (mScreenWakeLock != null && !mScreenWakeLock.isHeld()) {
291 mScreenWakeLock.acquire();
292 }
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500293
Adrien Béraud86a1e372018-11-23 23:24:30 -0500294 binding.videoSurface.getHolder().setFormat(PixelFormat.RGBA_8888);
295 binding.videoSurface.getHolder().addCallback(new SurfaceHolder.Callback() {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400296 @Override
297 public void surfaceCreated(SurfaceHolder holder) {
298 presenter.videoSurfaceCreated(holder);
299 }
300
301 @Override
302 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
303
304 }
305
306 @Override
307 public void surfaceDestroyed(SurfaceHolder holder) {
308 presenter.videoSurfaceDestroyed();
309 }
310 });
Pierre Duchemin45707ca2018-01-15 15:05:23 -0500311 view.setOnSystemUiVisibilityChangeListener(visibility -> {
312 boolean ui = (visibility & (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN)) == 0;
313 presenter.uiVisibilityChanged(ui);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400314 });
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400315 view.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
316 resetVideoSize(mVideoWidth, mVideoHeight));
317
318 WindowManager windowManager = (WindowManager) requireContext().getSystemService(Context.WINDOW_SERVICE);
319 mOrientationListener = new OrientationEventListener(getContext()) {
320 @Override
321 public void onOrientationChanged(int orientation) {
322 int rot = windowManager.getDefaultDisplay().getRotation();
323 if (mCurrentOrientation != rot) {
324 mCurrentOrientation = rot;
325 presenter.configurationChanged(rot);
326 }
327 }
328 };
329 if (mOrientationListener.canDetectOrientation()) {
330 mOrientationListener.enable();
331 }
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400332
Adrien Béraud86a1e372018-11-23 23:24:30 -0500333 binding.shapeRipple.setRippleShape(new Circle());
334 binding.callSpeakerBtn.setChecked(presenter.isSpeakerphoneOn());
Adrien Béraudec19fad2018-12-30 16:51:05 -0500335 binding.callMicBtn.setChecked(presenter.isMicrophoneMuted());
Adrien Béraudde0d4522018-12-12 12:11:02 -0500336 binding.previewSurface.setSurfaceTextureListener(listener);
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400337 binding.previewSurface.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
338 configureTransform(mPreviewSurfaceWidth, mPreviewSurfaceHeight));
Adrien Béraudbcbb4d42018-12-08 16:06:39 -0500339
340 binding.dialpadEditText.addTextChangedListener(new TextWatcher() {
341 @Override
342 public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
343
344 @Override
345 public void onTextChanged(CharSequence s, int start, int before, int count) {
346 presenter.sendDtmf(s.subSequence(start, start + count));
347 }
348
349 @Override
350 public void afterTextChanged(Editable s) {}
351 });
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500352 }
353
354 @Override
Adrien Béraud2c378b32018-07-11 15:24:02 -0400355 public void onDestroyView() {
356 super.onDestroyView();
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400357 if (mOrientationListener != null) {
358 mOrientationListener.disable();
359 mOrientationListener = null;
360 }
Adrien Béraud2c378b32018-07-11 15:24:02 -0400361 mCompositeDisposable.clear();
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500362 if (mScreenWakeLock != null && mScreenWakeLock.isHeld()) {
363 mScreenWakeLock.release();
364 }
Adrien Béraud04d822c2015-04-02 17:44:36 -0400365 }
366
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400367 @Override
Adrien Béraud04d822c2015-04-02 17:44:36 -0400368 public void onCreateOptionsMenu(Menu m, MenuInflater inf) {
Adrien Béraudda712a42015-11-22 23:45:26 -0500369 super.onCreateOptionsMenu(m, inf);
Adrien Béraudda2eb1a2016-01-11 13:15:12 -0500370 inf.inflate(R.menu.ac_call, m);
Romain Bertozziad8fd842016-05-11 14:30:35 -0400371 dialPadBtn = m.findItem(R.id.menuitem_dialpad);
Adrien Béraudda712a42015-11-22 23:45:26 -0500372 }
373
374 @Override
375 public void onPrepareOptionsMenu(Menu menu) {
376 super.onPrepareOptionsMenu(menu);
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400377 presenter.prepareOptionMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400378 }
379
380 @Override
381 public boolean onOptionsItemSelected(MenuItem item) {
382 super.onOptionsItemSelected(item);
383 switch (item.getItemId()) {
384 case android.R.id.home:
385 case R.id.menuitem_chat:
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400386 presenter.chatClick();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400387 break;
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400388 case R.id.menuitem_dialpad:
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400389 presenter.dialpadClick();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400390 break;
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400391 }
392 return true;
393 }
394
Adrien Béraud79808d02018-02-20 00:16:28 +0100395 @Override
Adrien Bérauda373e3b2018-12-12 11:14:50 -0500396 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400397 AppCompatActivity activity = (AppCompatActivity) getActivity();
398 ActionBar actionBar = activity == null ? null : activity.getSupportActionBar();
399 if (actionBar != null) {
400 if (isInPictureInPictureMode)
401 actionBar.hide();
402 else
403 actionBar.show();
404 }
Adrien Béraud79808d02018-02-20 00:16:28 +0100405 presenter.pipModeChanged(isInPictureInPictureMode);
406 }
407
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400408 @Override
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400409 public void displayContactBubble(final boolean display) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500410 binding.contactBubbleLayout.getHandler().post(() -> binding.contactBubbleLayout.setVisibility(display ? View.VISIBLE : View.GONE));
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400411 }
412
413 @Override
414 public void displayVideoSurface(final boolean display) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500415 binding.videoSurface.setVisibility(display ? View.VISIBLE : View.GONE);
Adrien Béraud76dec1d2018-12-14 18:58:19 -0500416 binding.previewContainer.setVisibility(display ? View.VISIBLE : View.GONE);
Adrien Béraudace37a22018-06-22 14:58:36 -0400417 updateMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400418 }
419
420 @Override
Adrien Béraud79808d02018-02-20 00:16:28 +0100421 public void displayPreviewSurface(final boolean display) {
422 if (display) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500423 binding.videoSurface.setZOrderOnTop(false);
Adrien Béraud86a1e372018-11-23 23:24:30 -0500424 binding.videoSurface.setZOrderMediaOverlay(false);
Adrien Béraud79808d02018-02-20 00:16:28 +0100425 } else {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500426 binding.videoSurface.setZOrderMediaOverlay(true);
427 binding.videoSurface.setZOrderOnTop(true);
Adrien Béraud79808d02018-02-20 00:16:28 +0100428 }
429 }
430
431 @Override
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400432 public void displayHangupButton(boolean display) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500433 binding.callControlGroup.setVisibility(display ? View.VISIBLE : View.GONE);
434 binding.callHangupBtn.setVisibility(display ? View.VISIBLE : View.GONE);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400435 }
436
437 @Override
438 public void displayDialPadKeyboard() {
Adrien Béraudbcbb4d42018-12-08 16:06:39 -0500439 KeyboardVisibilityManager.showKeyboard(getActivity(), binding.dialpadEditText, InputMethodManager.SHOW_FORCED);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400440 }
441
442 @Override
443 public void switchCameraIcon(boolean isFront) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500444 binding.callCameraFlipBtn.setImageResource(isFront ? R.drawable.ic_camera_front_white : R.drawable.ic_camera_rear_white);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400445 }
446
447 @Override
Adrien Béraudd3bf4e42018-02-14 14:44:41 +0100448 public void updateMenu() {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400449 requireActivity().invalidateOptionsMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400450 }
451
452 @Override
453 public void updateTime(final long duration) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500454 if (binding.callStatusTxt != null)
455 binding.callStatusTxt.setText(String.format(Locale.getDefault(), "%d:%02d:%02d", duration / 3600, duration % 3600 / 60, duration % 60));
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400456 }
457
458 @Override
Adrien Beraud8e6e2ff2017-06-14 14:40:27 +0200459 public void updateContactBubble(@NonNull final CallContact contact) {
Adrien Béraud5f8c3f72018-03-09 14:49:39 -0500460 String username = contact.getRingUsername();
461 String displayName = contact.getDisplayName();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400462
Adrien Béraud5f8c3f72018-03-09 14:49:39 -0500463 String ringId = contact.getIds().get(0);
Adrien Béraudafcdd962018-07-06 21:38:41 -0400464 Log.d(TAG, "updateContactBubble: contact=" + contact + " username=" + username + ", ringId=" + ringId);
Adrien Béraud5f8c3f72018-03-09 14:49:39 -0500465
Adrien Béraudafcdd962018-07-06 21:38:41 -0400466 boolean hasProfileName = displayName != null && !displayName.contentEquals(username);
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400467
468 AppCompatActivity activity = (AppCompatActivity) getActivity();
469 if (activity != null) {
470 ActionBar ab = activity.getSupportActionBar();
471 if (ab != null) {
472 if (hasProfileName) {
473 ab.setTitle(displayName);
474 ab.setSubtitle(username);
475 } else {
476 ab.setTitle(username);
477 ab.setSubtitle(null);
478 }
479 ab.setDisplayShowTitleEnabled(true);
480 }
481 }
482
Adrien Béraudafcdd962018-07-06 21:38:41 -0400483 if (hasProfileName) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500484 binding.contactBubbleNumTxt.setVisibility(View.VISIBLE);
485 binding.contactBubbleTxt.setText(displayName);
486 binding.contactBubbleNumTxt.setText(username);
Adrien Béraudafcdd962018-07-06 21:38:41 -0400487 } else {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500488 binding.contactBubbleNumTxt.setVisibility(View.GONE);
489 binding.contactBubbleTxt.setText(username);
Adrien Béraudafcdd962018-07-06 21:38:41 -0400490 }
Adrien Béraud5f8c3f72018-03-09 14:49:39 -0500491
Adrien Béraud86a1e372018-11-23 23:24:30 -0500492 binding.contactBubble.setImageDrawable(new AvatarDrawable(getActivity(), contact));
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400493 }
494
495 @Override
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400496 public void updateCallStatus(final SipCall.State callState) {
Adrien Béraud3f9f6cd2018-12-12 15:05:28 -0500497 switch (callState) {
498 case NONE:
499 binding.callStatusTxt.setText("");
500 break;
501 default:
502 binding.callStatusTxt.setText(callStateToHumanState(callState));
503 break;
504 }
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400505 }
506
507 @Override
508 public void initMenu(boolean isSpeakerOn, boolean hasContact, boolean displayFlip, boolean canDial, boolean onGoingCall) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500509 if (binding.callCameraFlipBtn != null) {
510 binding.callCameraFlipBtn.setVisibility(displayFlip ? View.VISIBLE : View.GONE);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400511 }
Romain Bertozziad8fd842016-05-11 14:30:35 -0400512 if (dialPadBtn != null) {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400513 dialPadBtn.setVisible(canDial);
Romain Bertozziad8fd842016-05-11 14:30:35 -0400514 }
Adrien Béraud04d822c2015-04-02 17:44:36 -0400515 }
516
517 @Override
Adrien Béraudec19fad2018-12-30 16:51:05 -0500518 public void initNormalStateDisplay(final boolean audioOnly, boolean isSpeakerphoneOn, boolean isMuted) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500519 binding.shapeRipple.stopRipple();
Pierre Ducheminbb833672018-03-09 16:18:33 -0500520
Adrien Béraud86a1e372018-11-23 23:24:30 -0500521 binding.callAcceptBtn.setVisibility(View.GONE);
522 binding.callRefuseBtn.setVisibility(View.GONE);
523 binding.callControlGroup.setVisibility(View.VISIBLE);
524 binding.callHangupBtn.setVisibility(View.VISIBLE);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400525
Adrien Béraud86a1e372018-11-23 23:24:30 -0500526 binding.contactBubbleLayout.setVisibility(audioOnly ? View.VISIBLE : View.GONE);
527 binding.callSpeakerBtn.setChecked(isSpeakerphoneOn);
Adrien Béraudec19fad2018-12-30 16:51:05 -0500528 binding.callMicBtn.setChecked(isMuted);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400529
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400530 requireActivity().invalidateOptionsMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400531 }
532
533 @Override
534 public void initIncomingCallDisplay() {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500535 binding.callAcceptBtn.setVisibility(View.VISIBLE);
536 binding.callRefuseBtn.setVisibility(View.VISIBLE);
537 binding.callControlGroup.setVisibility(View.GONE);
538 binding.callHangupBtn.setVisibility(View.GONE);
Hadrien De Sousa841d15a2017-06-02 11:52:10 -0400539
Adrien Béraud86a1e372018-11-23 23:24:30 -0500540 binding.contactBubbleLayout.setVisibility(View.VISIBLE);
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400541 requireActivity().invalidateOptionsMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400542 }
543
544 @Override
545 public void initOutGoingCallDisplay() {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500546 binding.callAcceptBtn.setVisibility(View.GONE);
547 binding.callRefuseBtn.setVisibility(View.VISIBLE);
548 binding.callControlGroup.setVisibility(View.GONE);
549 binding.callHangupBtn.setVisibility(View.GONE);
Hadrien De Sousa841d15a2017-06-02 11:52:10 -0400550
Adrien Béraud86a1e372018-11-23 23:24:30 -0500551 binding.contactBubbleLayout.setVisibility(View.VISIBLE);
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400552 requireActivity().invalidateOptionsMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400553 }
554
555 @Override
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400556 public void resetPreviewVideoSize(int previewWidth, int previewHeight, int rot) {
557 if (previewWidth == -1 && previewHeight == -1)
558 return;
559 mPreviewWidth = previewWidth;
560 mPreviewHeight = previewHeight;
561 boolean flip = (rot % 180) != 0;
562 binding.previewSurface.setAspectRatio(flip ? mPreviewHeight : mPreviewWidth, flip ? mPreviewWidth : mPreviewHeight);
563 }
564
565 @Override
566 public void resetVideoSize(int videoWidth, int videoHeight) {
Adrien Béraudace37a22018-06-22 14:58:36 -0400567 ViewGroup rootView = (ViewGroup) getView();
568 if (rootView == null)
569 return;
Adrien Béraudace37a22018-06-22 14:58:36 -0400570 double videoRatio = videoWidth / (double) videoHeight;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400571 double screenRatio = rootView.getWidth() / (double) rootView.getHeight();
Adrien Béraud86a1e372018-11-23 23:24:30 -0500572 RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) binding.videoSurface.getLayoutParams();
Adrien Béraudace37a22018-06-22 14:58:36 -0400573 int oldW = params.width;
574 int oldH = params.height;
575 if (videoRatio >= screenRatio) {
576 params.width = RelativeLayout.LayoutParams.MATCH_PARENT;
577 params.height = (int) (videoHeight * (double) rootView.getWidth() / (double) videoWidth);
578 } else {
579 params.height = RelativeLayout.LayoutParams.MATCH_PARENT;
580 params.width = (int) (videoWidth * (double) rootView.getHeight() / (double) videoHeight);
581 }
Thibault Wittembergb3280502016-12-16 17:34:53 -0500582
Adrien Béraudace37a22018-06-22 14:58:36 -0400583 if (oldW != params.width || oldH != params.height) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500584 binding.videoSurface.setLayoutParams(params);
Adrien Béraudace37a22018-06-22 14:58:36 -0400585 }
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400586 mVideoWidth = videoWidth;
587 mVideoHeight = videoHeight;
Adrien Béraudde0d4522018-12-12 12:11:02 -0500588 }
Adrien Béraud30532a52018-09-11 15:10:05 -0400589
Adrien Béraudde0d4522018-12-12 12:11:02 -0500590 private void configureTransform(int viewWidth, int viewHeight) {
591 Activity activity = getActivity();
Adrien Béraud3f9f6cd2018-12-12 15:05:28 -0500592 if (null == binding.previewSurface || null == activity) {
Adrien Béraudde0d4522018-12-12 12:11:02 -0500593 return;
Adrien Béraud30532a52018-09-11 15:10:05 -0400594 }
Adrien Béraudde0d4522018-12-12 12:11:02 -0500595 int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
596 boolean rot = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400597 // Log.w(TAG, "configureTransform " + viewWidth + "x" + viewHeight + " rot=" + rot + " mPreviewWidth=" + mPreviewWidth + " mPreviewHeight=" + mPreviewHeight);
Adrien Béraudde0d4522018-12-12 12:11:02 -0500598 Matrix matrix = new Matrix();
599 RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
600 float centerX = viewRect.centerX();
601 float centerY = viewRect.centerY();
602 if (rot) {
603 RectF bufferRect = new RectF(0, 0, mPreviewHeight, mPreviewWidth);
604 bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
605 matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
606 float scale = Math.max(
607 (float) viewHeight / mPreviewHeight,
608 (float) viewWidth / mPreviewWidth);
609 matrix.postScale(scale, scale, centerX, centerY);
610 matrix.postRotate(90 * (rotation - 2), centerX, centerY);
611 } else if (Surface.ROTATION_180 == rotation) {
612 matrix.postRotate(180, centerX, centerY);
Adrien Béraudace37a22018-06-22 14:58:36 -0400613 }
Adrien Béraudde0d4522018-12-12 12:11:02 -0500614 binding.previewSurface.setTransform(matrix);
Adrien Béraud04d822c2015-04-02 17:44:36 -0400615 }
616
617 @Override
Hadrien De Sousa0dc83162017-11-10 16:15:18 -0500618 public void goToConversation(String accountId, String conversationId) {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400619 Intent intent = new Intent();
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400620 if (DeviceUtils.isTablet(requireActivity())) {
621 intent.setClass(requireActivity(), HomeActivity.class)
Alexandre Lision5da46fa2017-08-09 10:25:50 -0400622 .setAction(DRingService.ACTION_CONV_ACCEPT)
Hadrien De Sousa0dc83162017-11-10 16:15:18 -0500623 .putExtra(ConversationFragment.KEY_CONTACT_RING_ID, conversationId);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400624 startActivity(intent);
Adrien Béraudda712a42015-11-22 23:45:26 -0500625 } else {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400626 intent.setClass(requireActivity(), ConversationActivity.class)
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400627 .setAction(Intent.ACTION_VIEW)
628 .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
Hadrien De Sousa0dc83162017-11-10 16:15:18 -0500629 .putExtra(ConversationFragment.KEY_ACCOUNT_ID, accountId)
630 .putExtra(ConversationFragment.KEY_CONTACT_RING_ID, conversationId);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400631 startActivityForResult(intent, HomeActivity.REQUEST_CODE_CONVERSATION);
Adrien Béraudda712a42015-11-22 23:45:26 -0500632 }
Adrien Béraud04d822c2015-04-02 17:44:36 -0400633 }
634
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400635 @Override
636 public void goToAddContact(CallContact callContact) {
637 startActivityForResult(ActionHelper.getAddNumberIntentForContact(callContact),
638 ConversationFragment.REQ_ADD_CONTACT);
639 }
640
641 @Override
642 public void finish() {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400643 Activity activity = getActivity();
644 if (activity != null)
645 activity.finish();
Alexandre Lision1532d952016-11-17 09:41:00 -0500646 }
647
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400648 public void speakerClicked() {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500649 presenter.speakerClick(binding.callSpeakerBtn.isChecked());
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400650 }
651
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400652 public void micClicked() {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500653 presenter.muteMicrophoneToggled(binding.callMicBtn.isChecked());
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400654 }
655
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400656 public void hangUpClicked() {
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400657 presenter.hangupCall();
Alexandre Lision1532d952016-11-17 09:41:00 -0500658 }
659
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400660 public void refuseClicked() {
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400661 presenter.refuseCall();
Thibault Wittembergb70d5b02016-07-08 16:50:14 -0400662 }
663
Thibault Wittembergb70d5b02016-07-08 16:50:14 -0400664 public void acceptClicked() {
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400665 presenter.acceptCall();
Thibault Wittembergb70d5b02016-07-08 16:50:14 -0400666 }
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -0500667
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400668 public void cameraFlip() {
669 presenter.switchVideoInputClick();
670 }
671
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -0500672 @Override
Pierre Duchemin1fa61922018-01-18 10:09:02 -0500673 public void positiveMediaButtonClicked() {
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -0500674 presenter.positiveButtonClicked();
675 }
676
677 @Override
Pierre Duchemin1fa61922018-01-18 10:09:02 -0500678 public void negativeMediaButtonClicked() {
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -0500679 presenter.negativeButtonClicked();
680 }
681
682 @Override
Pierre Duchemin1fa61922018-01-18 10:09:02 -0500683 public void toggleMediaButtonClicked() {
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -0500684 presenter.toggleButtonClicked();
685 }
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400686}