Commit 4562d5e8 authored by Gayane Petrosyan's avatar Gayane Petrosyan Committed by Commit Bot

[SH-Clank] Add basic Link to text feature

Add basic Link to text feature without link generation request.

This CL also adds a new version of Sharing hub with a message.
Success case: https://screenshot.googleplex.com/2KiLEciz0uS.png
Failure case: https://screenshot.googleplex.com/jQgcyd6kpjg.png

Bug: 1102382
Change-Id: I3508169170d657c0538bb6b450e7e33a93191fa0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2309003
Commit-Queue: Gayane Petrosyan <gayane@chromium.org>
Reviewed-by: default avatarLijin Shen <lazzzis@google.com>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarKyle Milka <kmilka@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792875}
parent 5deced75
......@@ -9,6 +9,16 @@
android:layout_height="wrap_content"
android:minHeight="@dimen/min_touch_target_size"
android:orientation="vertical">
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:paddingStart="16dp"
android:gravity="center_vertical"
android:background="@color/default_bg_color_blue"
android:textAppearance="@style/TextAppearance.TextSmall.Primary.Inverse"
android:visibility="gone"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/share_sheet_chrome_apps"
android:clipToPadding="false"
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.share.link_to_text;
import android.content.Context;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.share.ChromeShareExtras;
import org.chromium.chrome.browser.share.share_sheet.ChromeOptionShareCallback;
import org.chromium.components.browser_ui.share.ShareParams;
import org.chromium.ui.base.WindowAndroid;
/**
* Handles the Link To Text action in the Sharing Hub.
*/
public class LinkToTextCoordinator {
private static final String SHARE_TEXT_TEMPLATE = "\"%s\"\n%s";
private static final String URL_TEMPLATE = "%s:~:text=%s";
private final Context mContext;
private final WindowAndroid mWindow;
private final ChromeOptionShareCallback mChromeOptionShareCallback;
private final String mVisibleUrl;
private final String mSelectedText;
public LinkToTextCoordinator(Context context, WindowAndroid window,
ChromeOptionShareCallback chromeOptionShareCallback, String visibleUrl,
String selectedText) {
mContext = context;
mWindow = window;
mChromeOptionShareCallback = chromeOptionShareCallback;
mVisibleUrl = visibleUrl;
mSelectedText = selectedText;
// TODO(1102382): Replace following line with a request to create text fragment selector and
// pass |OnSelectorReady| as callback.
onSelectorReady("");
}
public void onSelectorReady(String selector) {
String successMessage =
mContext.getResources().getString(R.string.link_to_text_success_message);
String failureMessage =
mContext.getResources().getString(R.string.link_to_text_failure_message);
// TODO(1102382): Consider creating SharedParams on sharesheet side. In that case there will
// be no need to keep the WindowAndroid in this class.
String textToShare = getTextToShare(selector);
ShareParams params = new ShareParams.Builder(mWindow, /*title=*/"", /*url=*/"")
.setText(textToShare)
.build();
ChromeShareExtras chromeShareExtras = new ChromeShareExtras.Builder().build();
mChromeOptionShareCallback.showThirdPartyShareSheetWithMessage(
!selector.isEmpty() ? successMessage : failureMessage, params, chromeShareExtras,
System.currentTimeMillis());
}
public String getTextToShare(String selector) {
// TODO(1102382): visbileUrl might need a cleanup. For example, if already has text fragment
// selector.
String url = mVisibleUrl;
if (!selector.isEmpty()) url = String.format(URL_TEMPLATE, mVisibleUrl, selector);
return String.format(SHARE_TEXT_TEMPLATE, mSelectedText, url);
}
}
\ No newline at end of file
......@@ -21,4 +21,13 @@ public interface ChromeOptionShareCallback {
*/
public void showThirdPartyShareSheet(
ShareParams params, ChromeShareExtras chromeShareExtras, long shareStartTime);
/**
* Used to show only the bottom bar of the share sheet with a message.
* @param message The message to show along with bottom bar.
* @param params The share parameters.
* @param chromeShareExtras The extras not contained in {@code params}.
*/
public void showThirdPartyShareSheetWithMessage(String message, ShareParams params,
ChromeShareExtras chromeShareExtras, long shareStartTime);
}
\ No newline at end of file
......@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfShareActivity;
import org.chromium.chrome.browser.share.ChromeShareExtras;
import org.chromium.chrome.browser.share.link_to_text.LinkToTextCoordinator;
import org.chromium.chrome.browser.share.qrcode.QrCodeCoordinator;
import org.chromium.chrome.browser.share.screenshot.ScreenshotCoordinator;
import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder.ContentType;
......@@ -319,8 +320,11 @@ class ChromeProvidedSharingOptionsProvider {
-> {
RecordUserAction.record("SharingHubAndroid.LinkToTextSelected");
recordTimeToShare(mShareStartTime);
LinkToTextCoordinator linkToTextCoordinator = new LinkToTextCoordinator(
mActivity, mTabProvider.get().getWindowAndroid(),
mChromeOptionShareCallback, mShareParams.getUrl(),
mShareParams.getText());
mBottomSheetController.hideContent(mBottomSheetContent, true);
// TODO(1102382): Init and call link-to-text feature.
},
/*isFirstParty=*/true);
return new FirstPartyOption(
......
......@@ -61,9 +61,16 @@ class ShareSheetBottomSheetContent implements BottomSheetContent, OnItemClickLis
* @param activity The activity the share sheet belongs to.
* @param topRowModels The PropertyModels used to build the top row.
* @param bottomRowModels The PropertyModels used to build the bottom row.
* @param message The message to show on top of the share sheet.
*/
void createRecyclerViews(
List<PropertyModel> topRowModels, List<PropertyModel> bottomRowModels) {
List<PropertyModel> topRowModels, List<PropertyModel> bottomRowModels, String message) {
if (!message.isEmpty()) {
TextView messageView = this.getContentView().findViewById(R.id.message);
messageView.setVisibility(View.VISIBLE);
messageView.setText(message);
}
RecyclerView topRow = this.getContentView().findViewById(R.id.share_sheet_chrome_apps);
if (topRowModels != null && topRowModels.size() > 0) {
View divider = this.getContentView().findViewById(R.id.share_sheet_divider);
......
......@@ -37,6 +37,7 @@ import java.util.Set;
// TODO(crbug/1022172): Should be package-protected once modularization is complete.
public class ShareSheetCoordinator
implements ActivityStateObserver, ChromeOptionShareCallback, View.OnLayoutChangeListener {
private static final String NO_SHARE_SHEET_MESSAGE = "";
private final BottomSheetController mBottomSheetController;
private final Supplier<Tab> mTabProvider;
private final ShareSheetPropertyModelBuilder mPropertyModelBuilder;
......@@ -87,6 +88,12 @@ public class ShareSheetCoordinator
// TODO(crbug/1022172): Should be package-protected once modularization is complete.
public void showShareSheet(
ShareParams params, ChromeShareExtras chromeShareExtras, long shareStartTime) {
showShareSheetWithMessage(
NO_SHARE_SHEET_MESSAGE, params, chromeShareExtras, shareStartTime);
}
void showShareSheetWithMessage(String message, ShareParams params,
ChromeShareExtras chromeShareExtras, long shareStartTime) {
Activity activity = params.getWindow().getActivity().get();
if (activity == null) return;
......@@ -107,7 +114,7 @@ public class ShareSheetCoordinator
List<PropertyModel> thirdPartyApps = createBottomRowPropertyModels(
activity, params, contentTypes, chromeShareExtras.saveLastUsed());
mBottomSheet.createRecyclerViews(chromeFeatures, thirdPartyApps);
mBottomSheet.createRecyclerViews(chromeFeatures, thirdPartyApps, message);
boolean shown = mBottomSheetController.requestShowContent(mBottomSheet, true);
if (shown) {
......@@ -125,6 +132,14 @@ public class ShareSheetCoordinator
showShareSheet(params, chromeShareExtras, shareStartTime);
}
// Used by first party features to share with only non-chrome apps along with a message.
@Override
public void showThirdPartyShareSheetWithMessage(String message, ShareParams params,
ChromeShareExtras chromeShareExtras, long shareStartTime) {
mExcludeFirstParty = true;
showShareSheetWithMessage(message, params, chromeShareExtras, shareStartTime);
}
List<PropertyModel> createTopRowPropertyModels(Activity activity, ShareParams shareParams,
ChromeShareExtras chromeShareExtras, Set<Integer> contentTypes) {
if (mExcludeFirstParty) {
......
......@@ -7,6 +7,7 @@
share_java_sources = [
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/BitmapDownloadRequest.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProvider.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QRCodeGenerationRequest.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeCoordinator.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialog.java",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.share.link_to_text;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.support.test.rule.ActivityTestRule;
import androidx.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.chromium.chrome.browser.share.share_sheet.ChromeOptionShareCallback;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.test.util.DummyUiActivity;
/**
* Tests for {@link LinkToTextCoordinator}.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
public class LinkToTextCoordinatorTest {
@Rule
public ActivityTestRule<DummyUiActivity> mActivityTestRule =
new ActivityTestRule<>(DummyUiActivity.class);
@Mock
private ChromeOptionShareCallback mShareCallback;
@Mock
private WindowAndroid mWindow;
private Context mContext;
private static final String SELECTED_TEXT = "selection";
private static final String VISIBLE_URL = "www.example.com";
@Before
public void setUp() {
mContext = mActivityTestRule.getActivity();
MockitoAnnotations.initMocks(this);
doNothing()
.when(mShareCallback)
.showThirdPartyShareSheetWithMessage(anyString(), any(), any(), anyLong());
}
@Test
@SmallTest
public void getTextToShareTest() {
String selector = "selector";
String expectedTextToShare = "\"selection\"\nwww.example.com:~:text=selector";
LinkToTextCoordinator coordinator = new LinkToTextCoordinator(
mContext, mWindow, mShareCallback, VISIBLE_URL, SELECTED_TEXT);
Assert.assertEquals(expectedTextToShare, coordinator.getTextToShare(selector));
}
@Test
@SmallTest
public void getTextToShareTest_EmptySelector() {
String selector = "";
String expectedTextToShare = "\"selection\"\nwww.example.com";
LinkToTextCoordinator coordinator = new LinkToTextCoordinator(
mContext, mWindow, mShareCallback, VISIBLE_URL, SELECTED_TEXT);
Assert.assertEquals(expectedTextToShare, coordinator.getTextToShare(selector));
}
@Test
@SmallTest
public void onSelectorReadyTest() {
LinkToTextCoordinator coordinator = new LinkToTextCoordinator(
mContext, mWindow, mShareCallback, VISIBLE_URL, SELECTED_TEXT);
// OnSelectorReady should call back the share sheet.
verify(mShareCallback)
.showThirdPartyShareSheetWithMessage(anyString(), any(), any(), anyLong());
}
}
......@@ -5,6 +5,7 @@
# TODO(crbug.com/1022172): This should be a separate build target when circular dependencies are removed.
share_test_java_sources = [
"//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProviderTest.java",
"//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java",
"//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java",
"//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java",
"//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java",
......
......@@ -3861,6 +3861,14 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
chrome_qrcode_<ph name="CURRENT_TIMESTAMP_MS">%1$s<ex>1582667748515</ex></ph>
</message>
<message name="IDS_LINK_TO_TEXT_SUCCESS_MESSAGE" desc="Message displayed when link to highlighted text is successfully created.">
Share link to the highlighted text in an app
</message>
<message name="IDS_LINK_TO_TEXT_FAILURE_MESSAGE" desc="Message displayed when link to highlighted text was not possible to create.">
Can't create link to text. Share link to page in an app.
</message>
<!-- Share Screenshot strings -->
<message name="IDS_SCREENSHOT_EDIT_TITLE" desc="The text shown on the share option for screenshots.">
Edit
......
......@@ -295,6 +295,9 @@
<style name="TextAppearance.TextMedium.Primary.Inverse" tools:ignore="UnusedResources">
<item name="android:textColor">@color/default_text_color_inverse</item>
</style>
<style name="TextAppearance.TextSmall.Primary.Inverse" tools:ignore="UnusedResources">
<item name="android:textColor">@color/default_text_color_inverse</item>
</style>
<!-- Blue And Button Text Styles -->
<style name="TextAppearance.TextLarge.Blue">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment