/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.goanna.overlays.ui; import static org.mozilla.goanna.overlays.ui.SendTabList.State.LIST; import static org.mozilla.goanna.overlays.ui.SendTabList.State.LOADING; import static org.mozilla.goanna.overlays.ui.SendTabList.State.SHOW_DEVICES; import java.util.Arrays; import org.mozilla.goanna.AppConstants.Versions; import org.mozilla.goanna.Assert; import org.mozilla.goanna.R; import org.mozilla.goanna.Telemetry; import org.mozilla.goanna.TelemetryContract; import org.mozilla.goanna.overlays.service.sharemethods.ParcelableClientRecord; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ListAdapter; import android.widget.ListView; /** * The SendTab button has a few different states depending on the available devices (and whether * we've loaded them yet...) * * Initially, the view resembles a disabled button. (the LOADING state) * Once state is loaded from Sync's database, we know how many devices the user may send their tab * to. * * If there are no targets, the user was found to not have a Sync account, or their Sync account is * in a state that prevents it from being able to send a tab, we enter the NONE state and display * a generic button which launches an appropriate activity to fix the situation when tapped (such * as the set up Sync wizard). * * If the number of targets does not MAX_INLINE_SYNC_TARGETS, we present a button for each of them. * (the LIST state) * * Otherwise, we enter the SHOW_DEVICES state, in which we display a "Send to other devices" button * that takes the user to a menu for selecting a target device from their complete list of many * devices. */ public class SendTabList extends ListView { @SuppressWarnings("unused") private static final String LOGTAG = "GoannaSendTabList"; // The maximum number of target devices to show in the main list. Further devices are available // from a secondary menu. public static final int MAXIMUM_INLINE_ELEMENTS = 2; private SendTabDeviceListArrayAdapter clientListAdapter; // Listener to fire when a share target is selected (either directly or via the prompt) private SendTabTargetSelectedListener listener; private final State currentState = LOADING; /** * Enum defining the states this view may occupy. */ public enum State { // State when no sync targets exist (a generic "Send to Firefox Sync" button which launches // an activity to set it up) NONE, // As NONE, but disabled. Initial state. Used until we get information from Sync about what // we really want. LOADING, // A list of devices to share to. LIST, // A single button prompting the user to select a device to share to. SHOW_DEVICES } public SendTabList(Context context) { super(context); } public SendTabList(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void setAdapter(ListAdapter adapter) { Assert.isTrue(adapter instanceof SendTabDeviceListArrayAdapter); clientListAdapter = (SendTabDeviceListArrayAdapter) adapter; super.setAdapter(adapter); } public void setSendTabTargetSelectedListener(SendTabTargetSelectedListener aListener) { listener = aListener; } public void switchState(State state) { if (state == currentState) { return; } clientListAdapter.switchState(state); if (state == SHOW_DEVICES) { clientListAdapter.setDialog(getDialog()); } } public void setSyncClients(final ParcelableClientRecord[] c) { final ParcelableClientRecord[] clients = c == null ? new ParcelableClientRecord[0] : c; clientListAdapter.setClientRecordList(Arrays.asList(clients)); } /** * Get an AlertDialog listing all devices, allowing the user to select the one they want. * Used when more than MAXIMUM_INLINE_ELEMENTS devices are found (to avoid displaying them all * inline and looking crazy). */ public AlertDialog getDialog() { final Context context = getContext(); final AlertDialog.Builder builder; if (Versions.feature11Plus) { builder = new AlertDialog.Builder(context, R.style.Goanna_Dialog); } else { builder = new AlertDialog.Builder(context); } final ParcelableClientRecord[] records = clientListAdapter.toArray(); final String[] dialogElements = new String[records.length]; for (int i = 0; i < records.length; i++) { dialogElements[i] = records[i].name; } builder.setTitle(R.string.overlay_share_select_device) .setItems(dialogElements, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int index) { listener.onSendTabTargetSelected(records[index].guid); } }) .setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialogInterface) { Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL, TelemetryContract.Method.SHARE_OVERLAY, "device_selection_cancel"); } }); return builder.create(); } }