Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1c55066 authored by calderwoodra's avatar calderwoodra Committed by android-build-merger
Browse files

Merge "Implemented context menu actions." am: 54468190 am: dc53c57a

am: e3948da3

Change-Id: I72eda95259ee349bd3741cf8fb916db873f64339
parents e8cb5e9c e3948da3
Loading
Loading
Loading
Loading
+53 −12
Original line number Diff line number Diff line
@@ -21,14 +21,23 @@ import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
import com.android.dialer.speeddial.loader.SpeedDialUiItem;

/** Floating menu which presents contact options available to the contact. */
public class ContextMenu extends LinearLayout {

  private SpeedDialUiItem speedDialUiItem;
  private ContextMenuItemListener listener;

  private TextView videoView;
  private TextView smsView;

  private SpeedDialUiItem speedDialUiItem;
  private Channel voiceChannel;
  private Channel videoChannel;
  private Channel smsChannel;

  public ContextMenu(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
  }
@@ -36,12 +45,14 @@ public class ContextMenu extends LinearLayout {
  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();
    findViewById(R.id.voice_call_container)
        .setOnClickListener(v -> listener.placeVoiceCall(speedDialUiItem));
    findViewById(R.id.video_call_container)
        .setOnClickListener(v -> listener.placeVideoCall(speedDialUiItem));
    findViewById(R.id.send_message_container)
        .setOnClickListener(v -> listener.openSmsConversation(speedDialUiItem));

    videoView = findViewById(R.id.video_call_container);
    videoView.setOnClickListener(v -> placeVideoCall());

    smsView = findViewById(R.id.send_message_container);
    smsView.setOnClickListener(v -> listener.openSmsConversation(smsChannel.number()));

    findViewById(R.id.voice_call_container).setOnClickListener(v -> placeVoiceCall());
    findViewById(R.id.remove_container)
        .setOnClickListener(v -> listener.removeFavoriteContact(speedDialUiItem));
    findViewById(R.id.contact_info_container)
@@ -65,6 +76,15 @@ public class ContextMenu extends LinearLayout {
    setX((float) (childLocation[0] + .5 * childLayout.getWidth() - .5 * getWidth()));
    setY(childLocation[1] - parentLocation[1] + childLayout.getHeight());

    voiceChannel = speedDialUiItem.getDeterministicVoiceChannel();
    videoChannel = speedDialUiItem.getDeterministicVideoChannel();
    videoView.setVisibility(
        videoChannel == null && !speedDialUiItem.hasVideoChannels() ? View.GONE : View.VISIBLE);

    // TODO(calderwoodra): disambig dialog for texts?
    smsChannel = voiceChannel;
    smsView.setVisibility(smsChannel == null ? View.GONE : View.VISIBLE);

    // TODO(calderwoodra): a11y
    // TODO(calderwoodra): animate this similar to the bubble menu
    setVisibility(View.VISIBLE);
@@ -81,6 +101,22 @@ public class ContextMenu extends LinearLayout {
    }
  }

  private void placeVoiceCall() {
    if (voiceChannel == null) {
      listener.disambiguateCall(speedDialUiItem);
    } else {
      listener.placeCall(voiceChannel);
    }
  }

  private void placeVideoCall() {
    if (videoChannel == null) {
      listener.disambiguateCall(speedDialUiItem);
    } else {
      listener.placeCall(videoChannel);
    }
  }

  public boolean isVisible() {
    return getVisibility() == View.VISIBLE;
  }
@@ -88,14 +124,19 @@ public class ContextMenu extends LinearLayout {
  /** Listener to report user clicks on menu items. */
  public interface ContextMenuItemListener {

    /** Called when the user selects "voice call" option from the context menu. */
    void placeVoiceCall(SpeedDialUiItem speedDialUiItem);
    /** Called when the user selects "voice call" or "video call" option from the context menu. */
    void placeCall(Channel channel);

    /** Called when the user selects "video call" option from the context menu. */
    void placeVideoCall(SpeedDialUiItem speedDialUiItem);
    /**
     * Called when the user selects "voice call" or "video call" option from the context menu, but
     * it's not clear which channel they want to call.
     *
     * <p>TODO(calderwoodra): discuss with product how we want to handle these cases
     */
    void disambiguateCall(SpeedDialUiItem speedDialUiItem);

    /** Called when the user selects "send message" from the context menu. */
    void openSmsConversation(SpeedDialUiItem speedDialUiItem);
    void openSmsConversation(String number);

    /** Called when the user selects "remove" from the context menu. */
    void removeFavoriteContact(SpeedDialUiItem speedDialUiItem);
+53 −12
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
package com.android.dialer.speeddial;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
@@ -49,6 +51,7 @@ import com.android.dialer.speeddial.draghelper.SpeedDialItemTouchHelperCallback;
import com.android.dialer.speeddial.draghelper.SpeedDialLayoutManager;
import com.android.dialer.speeddial.loader.SpeedDialUiItem;
import com.android.dialer.speeddial.loader.UiItemLoaderComponent;
import com.android.dialer.util.IntentUtil;
import com.google.common.collect.ImmutableList;

/**
@@ -78,8 +81,6 @@ public class SpeedDialFragment extends Fragment {
   */
  private boolean updateSpeedDialItemsOnResume = true;

  private FavoriteContactsListener favoritesListener;

  public static SpeedDialFragment newInstance() {
    return new SpeedDialFragment();
  }
@@ -103,14 +104,14 @@ public class SpeedDialFragment extends Fragment {
    // Setup our RecyclerView
    SpeedDialLayoutManager layoutManager =
        new SpeedDialLayoutManager(getContext(), 3 /* spanCount */);
    favoritesListener =
    FavoriteContactsListener favoritesListener =
        new SpeedDialFavoritesListener(
            getActivity(),
            getChildFragmentManager(),
            rootLayout,
            contextMenu,
            contextMenuBackground,
            new SpeedDialContextMenuItemListener(),
            new SpeedDialContextMenuItemListener(getActivity(), getChildFragmentManager()),
            layoutManager);
    adapter =
        new SpeedDialAdapter(getContext(), favoritesListener, suggestedListener, headerListener);
@@ -181,6 +182,22 @@ public class SpeedDialFragment extends Fragment {
    }
  }

  @Override
  public void onPause() {
    super.onPause();
    contextMenu.hideMenu();
    contextMenuBackground.setVisibility(View.GONE);
  }

  @Override
  public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) {
      contextMenu.hideMenu();
      contextMenuBackground.setVisibility(View.GONE);
    }
  }

  private class SpeedDialFragmentHeaderListener implements SpeedDialHeaderListener {

    @Override
@@ -294,29 +311,53 @@ public class SpeedDialFragment extends Fragment {

  private static final class SpeedDialContextMenuItemListener implements ContextMenuItemListener {

    private final FragmentActivity activity;
    private final FragmentManager childFragmentManager;

    SpeedDialContextMenuItemListener(
        FragmentActivity activity, FragmentManager childFragmentManager) {
      this.activity = activity;
      this.childFragmentManager = childFragmentManager;
    }

    @Override
    public void placeVoiceCall(SpeedDialUiItem speedDialUiItem) {
      // TODO(calderwoodra)
    public void disambiguateCall(SpeedDialUiItem speedDialUiItem) {
      // TODO(calderwoodra): show only video or voice channels in the disambig dialog
      DisambigDialog.show(speedDialUiItem, childFragmentManager);
    }

    @Override
    public void placeVideoCall(SpeedDialUiItem speedDialUiItem) {
      // TODO(calderwoodra)
    public void placeCall(Channel channel) {
      if (channel.technology() == Channel.DUO) {
        Logger.get(activity)
            .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT);
        Intent intent = DuoComponent.get(activity).getDuo().getIntent(activity, channel.number());
        activity.startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO);
        return;
      }
      PreCall.start(
          activity,
          new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL)
              .setIsVideoCall(channel.isVideoTechnology()));
    }

    @Override
    public void openSmsConversation(SpeedDialUiItem speedDialUiItem) {
      // TODO(calderwoodra)
    public void openSmsConversation(String number) {
      activity.startActivity(IntentUtil.getSendSmsIntent(number));
    }

    @Override
    public void removeFavoriteContact(SpeedDialUiItem speedDialUiItem) {
      // TODO(calderwoodra)
      // TODO(calderwoodra): implement remove
    }

    @Override
    public void openContactInfo(SpeedDialUiItem speedDialUiItem) {
      // TODO(calderwoodra)
      activity.startActivity(
          new Intent(
              Intent.ACTION_VIEW,
              Uri.withAppendedPath(
                  Contacts.CONTENT_URI, String.valueOf(speedDialUiItem.contactId()))));
    }
  }
}
+58 −0
Original line number Diff line number Diff line
@@ -118,6 +118,64 @@ public abstract class SpeedDialUiItem {
    return builder.build();
  }

  /**
   * Returns a video channel if there is exactly one video channel or the default channel is a video
   * channel.
   */
  @Nullable
  public Channel getDeterministicVideoChannel() {
    if (defaultChannel() != null && defaultChannel().isVideoTechnology()) {
      return defaultChannel();
    }

    Channel videoChannel = null;
    for (Channel channel : channels()) {
      if (channel.isVideoTechnology()) {
        if (videoChannel != null) {
          // We found two video channels, so we can't determine which one is correct..
          return null;
        }
        videoChannel = channel;
      }
    }
    // Only found one channel, so return it
    return videoChannel;
  }

  /** Returns true if any channels are video channels. */
  public boolean hasVideoChannels() {
    for (Channel channel : channels()) {
      if (channel.isVideoTechnology()) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns a voice channel if there is exactly one voice channel or the default channel is a voice
   * channel.
   */
  @Nullable
  public Channel getDeterministicVoiceChannel() {
    if (defaultChannel() != null && !defaultChannel().isVideoTechnology()) {
      return defaultChannel();
    }

    Channel voiceChannel = null;
    for (Channel channel : channels()) {
      if (!channel.isVideoTechnology()) {
        if (voiceChannel != null) {
          // We found two voice channels, so we can't determine which one is correct..
          return null;
        }
        voiceChannel = channel;
      }
    }
    // Only found one channel, so return it
    return voiceChannel;
  }

  /**
   * The id of the corresponding SpeedDialEntry. Null if the UI item does not have an entry, for
   * example suggested contacts (isStarred() will also be false)
+30 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2017 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License
  -->

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <shape android:shape="oval">
      <solid android:color="@color/secondary_text_color"/>
      <size android:width="24dp" android:height="24dp"/>
    </shape>
  </item>
  <item
      android:width="24dp"
      android:height="24dp"
      android:gravity="center"
      android:drawable="@drawable/product_logo_avatar_anonymous_white_color_120"/>
</layer-list>
 No newline at end of file
+0 −21
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
 ~ Copyright (C) 2017 The Android Open Source Project
 ~
 ~ Licensed under the Apache License, Version 2.0 (the "License");
 ~ you may not use this file except in compliance with the License.
 ~ You may obtain a copy of the License at
 ~
 ~      http://www.apache.org/licenses/LICENSE-2.0
 ~
 ~ Unless required by applicable law or agreed to in writing, software
 ~ distributed under the License is distributed on an "AS IS" BASIS,
 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License
 -->
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/add_favorite_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
 No newline at end of file
Loading