[Android] Brave news on NTP, integration with mojom and feature flag

This commit is contained in:
Alex C
2021-11-24 14:23:24 -08:00
committed by Pete Miller
parent 9e029ef0f4
commit df2f0906ae
83 changed files with 4483 additions and 198 deletions
@@ -12,6 +12,7 @@ import org.chromium.base.annotations.NativeMethods;
public abstract class BraveFeatureList {
public static final String BRAVE_REWARDS = "BraveRewards";
public static final String NATIVE_BRAVE_WALLET = "NativeBraveWallet";
public static final String BRAVE_NEWS = "BraveNews";
public static final String USE_DEV_UPDATER_URL = "UseDevUpdaterUrl";
public static final String FORCE_WEB_CONTENTS_DARK_MODE = "WebContentsForceDark";
public static final String ENABLE_FORCE_DARK = "enable-force-dark";
@@ -17,6 +17,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.BitmapDrawable;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -31,6 +32,9 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
@@ -61,6 +65,7 @@ import org.chromium.base.task.TaskTraits;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ApplicationLifetime;
import org.chromium.chrome.browser.BraveConfig;
import org.chromium.chrome.browser.BraveFeatureList;
import org.chromium.chrome.browser.BraveHelper;
import org.chromium.chrome.browser.BraveRelaunchUtils;
import org.chromium.chrome.browser.BraveRewardsHelper;
@@ -74,23 +79,27 @@ import org.chromium.chrome.browser.LaunchIntentDispatcher;
import org.chromium.chrome.browser.SetDefaultBrowserActivity;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
import org.chromium.chrome.browser.bookmarks.BookmarkModel;
import org.chromium.chrome.browser.brave_news.models.FeedItemsCard;
import org.chromium.chrome.browser.brave_stats.BraveStatsUtil;
import org.chromium.chrome.browser.browsing_data.BrowsingDataBridge;
import org.chromium.chrome.browser.browsing_data.BrowsingDataType;
import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataFragmentAdvanced;
import org.chromium.chrome.browser.browsing_data.TimePeriod;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.compositor.layouts.Layout;
import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout;
import org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletActivity;
import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
import org.chromium.chrome.browser.informers.BraveAndroidSyncDisabledInformer;
import org.chromium.chrome.browser.notifications.BraveSetDefaultBrowserNotificationService;
import org.chromium.chrome.browser.notifications.retention.RetentionNotificationUtil;
import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.ntp_background_images.util.NewTabPageListener;
import org.chromium.chrome.browser.onboarding.BraveTalkOptInPopupListener;
import org.chromium.chrome.browser.onboarding.OnboardingActivity;
import org.chromium.chrome.browser.onboarding.OnboardingPrefManager;
@@ -142,6 +151,7 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Brave's extension for ChromeActivity
@@ -192,6 +202,8 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
private String mPurchaseToken = "";
private String mProductId = "";
private boolean mIsVerification;
public CompositorViewHolder compositorView;
public View inflatedSettingsBarLayout;
@SuppressLint("VisibleForTests")
public BraveActivity() {
@@ -217,6 +229,8 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
super.onPauseWithNative();
}
private NewTabPageListener newTabPageListener;
@Override
public boolean onMenuOrKeyboardAction(int id, boolean fromMenu) {
final TabImpl currentTab = (TabImpl) getActivityTab();
@@ -317,7 +331,6 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
@Override
public void initializeState() {
super.initializeState();
if (isNoRestoreState()) {
CommandLine.getInstance().appendSwitch(ChromeSwitches.NO_RESTORE_STATE);
}
@@ -334,9 +347,30 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
this, dataTypesArray, TimePeriod.ALL_TIME);
}
setLoadedFeed(false);
setNewsItemsFeedCards(null);
BraveSearchEngineUtils.initializeBraveSearchEngineStates(getTabModelSelector());
}
public boolean loadedFeed;
public CopyOnWriteArrayList<FeedItemsCard> newsItemsFeedCards;
public boolean isLoadedFeed() {
return loadedFeed;
}
public void setLoadedFeed(boolean loadedFeed) {
this.loadedFeed = loadedFeed;
}
public CopyOnWriteArrayList<FeedItemsCard> getNewsItemsFeedCards() {
return newsItemsFeedCards;
}
public void setNewsItemsFeedCards(CopyOnWriteArrayList<FeedItemsCard> newsItemsFeedCards) {
this.newsItemsFeedCards = newsItemsFeedCards;
}
@Override
public void onBrowsingDataCleared() {}
@@ -357,7 +391,6 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
@Override
public void onPause() {
super.onPause();
Tab tab = getActivityTab();
if (tab == null)
return;
@@ -389,7 +422,6 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
@Override
public void finishNativeInitialization() {
super.finishNativeInitialization();
if (SharedPreferencesManager.getInstance().readBoolean(
BravePreferenceKeys.BRAVE_DOUBLE_RESTART, false)) {
SharedPreferencesManager.getInstance().writeBoolean(
@@ -515,6 +547,23 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
}
checkSetDefaultBrowserModal();
checkFingerPrintingOnUpgrade();
compositorView = null;
inflatedSettingsBarLayout = null;
if (ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_NEWS)) {
Tab tab = getActivityTab();
if (tab != null) {
// if it's new tab add the brave news settings bar to the layout
if (tab != null && tab.getUrl().getSpec() != null
&& UrlUtilities.isNTPUrl(tab.getUrl().getSpec())
&& BravePrefServiceBridge.getInstance().getNewsOptIn()) {
inflateNewsSettingsBar();
} else {
removeSettingsBar();
}
}
}
if (BraveVpnUtils.isBraveVpnFeatureEnable()) {
ConnectivityManager connectivityManager =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -584,6 +633,74 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
getSupportFragmentManager(), "BraveVpnCalloutDialogFragment");
}
public void inflateNewsSettingsBar() {
// get the main compositor view that we'll use to manipulate the views
compositorView = findViewById(R.id.compositor_view_holder);
ViewGroup controlContainer = findViewById(R.id.control_container);
if (findViewById(R.id.news_settings_bar) != null) {
return;
}
if (compositorView != null && controlContainer != null) {
int[] coords = {0, 0};
controlContainer.getLocationOnScreen(coords);
int absoluteTop = coords[1];
int absoluteBottom = coords[1] + controlContainer.getHeight();
LayoutInflater inflater = LayoutInflater.from(this);
// inflate the settings bar layout
View inflatedSettingsBarLayout =
inflater.inflate(R.layout.brave_news_settings_bar_layout, null);
RelativeLayout newContentButtonLayout =
(RelativeLayout) inflater.inflate(R.layout.brave_news_load_new_content, null);
// add the bar to the layout stack
compositorView.addView(inflatedSettingsBarLayout, 2);
compositorView.addView(newContentButtonLayout, 3);
inflatedSettingsBarLayout.setAlpha(0f);
FrameLayout.LayoutParams inflatedLayoutParams =
new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, 100);
FrameLayout.LayoutParams newContentButtonLayoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
// position bellow the control_container element (nevigation bar) with 25dp compensation
inflatedLayoutParams.setMargins(0, controlContainer.getBottom() - 5, 0, 0);
newContentButtonLayoutParams.setMargins(0, 400, 0, 0);
newContentButtonLayoutParams.gravity = Gravity.CENTER_HORIZONTAL;
newContentButtonLayout.setGravity(Gravity.CENTER_HORIZONTAL);
inflatedSettingsBarLayout.setLayoutParams(inflatedLayoutParams);
newContentButtonLayout.setLayoutParams(newContentButtonLayoutParams);
inflatedSettingsBarLayout.setVisibility(View.VISIBLE);
compositorView.invalidate();
}
}
public void removeSettingsBar() {
CompositorViewHolder compositorView = findViewById(R.id.compositor_view_holder);
if (compositorView != null) {
View settingsBar = compositorView.getChildAt(2);
if (settingsBar != null) {
if (settingsBar.getId() == R.id.news_settings_bar) {
compositorView.removeView(settingsBar);
}
}
}
}
// Sets NTP background
public void setBackground(BitmapDrawable bgWallpaper) {
CompositorViewHolder compositorView = findViewById(R.id.compositor_view_holder);
ViewGroup root = (ViewGroup) compositorView.getChildAt(1);
ScrollView scrollView = (ScrollView) root.getChildAt(0);
scrollView.setId(View.generateViewId());
//@TODO alex use Glide to set the image?
scrollView.setBackground(bgWallpaper);
}
private void checkFingerPrintingOnUpgrade() {
if (!PackageUtils.isFirstInstall(this)
&& SharedPreferencesManager.getInstance().readInt(
@@ -895,7 +1012,6 @@ public abstract class BraveActivity<C extends ChromeActivityComponent> extends C
public Tab openNewOrSelectExistingTab(String url) {
TabModel tabModel = getCurrentTabModel();
int tabRewardsIndex = TabModelUtils.getTabIndexByUrl(tabModel, url);
Tab tab = selectExistingTab(url);
if (tab != null) {
return tab;
@@ -135,6 +135,13 @@ public class BraveTabbedAppMenuPropertiesDelegate extends TabbedAppMenuPropertie
braveWallet.setVisible(false);
}
}
if (ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_NEWS)) {
MenuItem braveNews =
menu.add(Menu.NONE, R.id.brave_news_id, 0, R.string.brave_news_title);
if (shouldShowIconBeforeItem()) {
braveNews.setIcon(AppCompatResources.getDrawable(mContext, R.drawable.ic_news));
}
}
MenuItem exit = menu.add(Menu.NONE, R.id.exit_id, 0, R.string.menu_exit);
if (shouldShowIconBeforeItem()) {
exit.setIcon(AppCompatResources.getDrawable(mContext, R.drawable.brave_menu_exit));
@@ -0,0 +1,105 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.brave_news;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.chromium.brave_news.mojom.BraveNewsController;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.brave_news.BraveNewsUtils;
import org.chromium.chrome.browser.brave_news.models.FeedItemCard;
import org.chromium.chrome.browser.brave_news.models.FeedItemsCard;
import java.util.concurrent.CopyOnWriteArrayList;
public class BraveNewsAdapterFeedCard
extends RecyclerView.Adapter<BraveNewsAdapterFeedCard.ViewHolder> {
private LayoutInflater mInflater;
private Activity mActivity;
private View mView;
public CopyOnWriteArrayList<FeedItemsCard> mNewsItems;
private FeedItemsCard mNewsItem;
private ViewHolder mHolder;
private final String TAG = "BN";
private BraveNewsController mBraveNewsController;
public BraveNewsAdapterFeedCard(Activity activity,
CopyOnWriteArrayList<FeedItemsCard> newsItems,
BraveNewsController braveNewsController) {
this.mInflater = LayoutInflater.from(activity);
this.mActivity = activity;
this.mNewsItems = newsItems;
this.mBraveNewsController = braveNewsController;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
mView = mInflater.inflate(R.layout.brave_news_row, parent, false);
mHolder = new ViewHolder(mView);
return mHolder;
}
@Override
public void onBindViewHolder(
@NonNull BraveNewsAdapterFeedCard.ViewHolder holder, int position) {
LinearLayout.LayoutParams params1;
if (mNewsItems != null) {
mNewsItem = mNewsItems.get(position);
try {
if (mBraveNewsController != null) {
new CardBuilderFeedCard(mBraveNewsController, mHolder.linearLayout, mActivity,
position, mNewsItems.get(position),
mNewsItems.get(position).getCardType());
}
} catch (Exception e) {
Log.e(TAG, "crashinvestigation onBindViewHolder e: " + e);
}
}
}
@Override
public int getItemCount() {
return mNewsItems.size();
}
public class ViewHolderWidget extends RecyclerView.ViewHolder {
ViewHolderWidget(View itemView) {
super(itemView);
}
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
LinearLayout linearLayout;
ViewHolder(View itemView) {
super(itemView);
linearLayout = itemView.findViewById(R.id.card_layout);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {}
}
public FeedItemsCard getItem(int id) {
return mNewsItems.get(id);
}
}
@@ -0,0 +1,124 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.brave_news;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.chromium.brave_news.mojom.BraveNewsController;
import org.chromium.brave_news.mojom.UserEnabled;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.preferences.BravePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.util.TabUtils;
public class BraveNewsBottomSheetDialogFragment extends BottomSheetDialogFragment {
private String mUrl;
private String mPublisherId;
private String mPublisherName;
private BraveNewsController mBraveNewsController;
private Context mContext;
public static BraveNewsBottomSheetDialogFragment newInstance() {
return new BraveNewsBottomSheetDialogFragment();
}
public void setController(BraveNewsController controller) {
mBraveNewsController = controller;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NORMAL, R.style.AppBottomSheetDialogTheme);
}
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (getArguments() != null) {
mUrl = getArguments().getString("url");
mPublisherId = getArguments().getString("publisherId");
mPublisherName = getArguments().getString("publisherName");
}
View view = inflater.inflate(R.layout.brave_news_card_menu, container, false);
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
}
@Override
public void onDetach() {
super.onDetach();
mContext = null;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
TextView title = view.findViewById(R.id.item_menu_title_text);
Button newTab = view.findViewById(R.id.new_tab);
Button privateTab = view.findViewById(R.id.new_private_tab);
Button disable = view.findViewById(R.id.disable_content);
title.setText(mUrl);
StringBuilder disableText = new StringBuilder();
disableText.append(
getResources().getString(R.string.brave_news_disable_content, mPublisherName));
disable.setText(disableText);
newTab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TabUtils.openUrlInNewTab(false, mUrl);
dismiss();
}
});
privateTab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TabUtils.openUrlInNewTab(true, mUrl);
dismiss();
}
});
disable.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mBraveNewsController != null) {
// Removes the news source from the fetch list by setting a UserEnabled.DISABLED
// prop for the publisher in question
SharedPreferencesManager.getInstance().writeBoolean(
BravePreferenceKeys.BRAVE_NEWS_CHANGE_SOURCE, true);
mBraveNewsController.setPublisherPref(mPublisherId, UserEnabled.DISABLED);
}
dismiss();
Toast.makeText(mContext,
getResources().getString(
R.string.brave_news_disabled_content, mPublisherName),
Toast.LENGTH_SHORT)
.show();
}
});
}
}
@@ -0,0 +1,53 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.brave_news;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.brave_news.mojom.BraveNewsController;
import org.chromium.mojo.bindings.ConnectionErrorHandler;
import org.chromium.mojo.bindings.Interface;
import org.chromium.mojo.bindings.Interface.Proxy.Handler;
import org.chromium.mojo.system.MessagePipeHandle;
import org.chromium.mojo.system.impl.CoreImpl;
@JNINamespace("chrome::android")
public class BraveNewsControllerFactory {
private static final Object sLock = new Object();
private static BraveNewsControllerFactory sInstance;
public static BraveNewsControllerFactory getInstance() {
synchronized (sLock) {
if (sInstance == null) {
sInstance = new BraveNewsControllerFactory();
}
}
return sInstance;
}
private BraveNewsControllerFactory() {}
public BraveNewsController getBraveNewsController(
ConnectionErrorHandler connectionErrorHandler) {
int nativeHandle = BraveNewsControllerFactoryJni.get().getInterfaceToBraveNewsController();
MessagePipeHandle handle = wrapNativeHandle(nativeHandle);
BraveNewsController braveNewsController =
BraveNewsController.MANAGER.attachProxy(handle, 0);
Handler handler = ((Interface.Proxy) braveNewsController).getProxyHandler();
handler.setErrorHandler(connectionErrorHandler);
return braveNewsController;
}
private MessagePipeHandle wrapNativeHandle(int nativeHandle) {
return CoreImpl.getInstance().acquireNativeHandle(nativeHandle).toMessagePipeHandle();
}
@NativeMethods
interface Natives {
int getInterfaceToBraveNewsController();
}
}
@@ -0,0 +1,82 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.brave_news;
import android.content.Context;
import org.chromium.base.Log;
import org.chromium.brave_news.mojom.Article;
import org.chromium.brave_news.mojom.CardType;
import org.chromium.brave_news.mojom.Deal;
import org.chromium.brave_news.mojom.DisplayAd;
import org.chromium.brave_news.mojom.FeedItem;
import org.chromium.brave_news.mojom.FeedItemMetadata;
import org.chromium.brave_news.mojom.PromotedArticle;
import org.chromium.brave_news.mojom.Publisher;
import org.chromium.chrome.browser.brave_news.models.FeedItemCard;
import org.chromium.chrome.browser.brave_news.models.FeedItemsCard;
public class BraveNewsUtils {
public static final int BRAVE_NEWS_VIEWD_CARD_TIME = 100; // milliseconds
public static String getPromotionIdItem(FeedItemsCard items) {
String creativeInstanceId = "null";
if (items.getFeedItems() != null) {
for (FeedItemCard itemCard : items.getFeedItems()) {
FeedItem item = itemCard.getFeedItem();
FeedItemMetadata itemMetaData = new FeedItemMetadata();
if (item.which() == FeedItem.Tag.PromotedArticle) {
PromotedArticle promotedArticle = item.getPromotedArticle();
creativeInstanceId = promotedArticle.creativeInstanceId;
break;
}
}
}
return creativeInstanceId;
}
// method for logging news object. works by putting Log.d in the desired places of the parsing
// of the object
public static void logFeedItem(FeedItemsCard items, String id) {
if (items != null) {
if (items.getCardType() == CardType.DISPLAY_AD) {
DisplayAd displayAd = items.getDisplayAd();
if (displayAd != null) {
Log.d("bn", id + " DISPLAY_AD title: " + displayAd.title);
}
} else {
if (items.getFeedItems() != null) {
int index = 0;
for (FeedItemCard itemCard : items.getFeedItems()) {
if (index > 50) {
return;
}
FeedItem item = itemCard.getFeedItem();
switch (item.which()) {
case FeedItem.Tag.Article:
Article article = item.getArticle();
FeedItemMetadata articleData = article.data;
break;
case FeedItem.Tag.PromotedArticle:
PromotedArticle promotedArticle = item.getPromotedArticle();
FeedItemMetadata promotedArticleData = promotedArticle.data;
String creativeInstanceId = promotedArticle.creativeInstanceId;
break;
case FeedItem.Tag.Deal:
Deal deal = item.getDeal();
FeedItemMetadata dealData = deal.data;
String offersCategory = deal.offersCategory;
break;
}
index++;
}
}
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,49 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.brave_news.models;
import org.chromium.brave_news.mojom.FeedItem;
import java.util.Arrays;
public class FeedItemCard {
private FeedItem feedItem;
private int cardType;
private byte[] imageByte;
public FeedItemCard() {}
public FeedItem getFeedItem() {
return feedItem;
}
public void setFeedItem(FeedItem feedItem) {
this.feedItem = feedItem;
}
public int getCardType() {
return cardType;
}
public void setCardType(int cardType) {
this.cardType = cardType;
}
public byte[] getImageByte() {
return imageByte;
}
public void setImageByte(byte[] imageByte) {
this.imageByte = imageByte;
}
@Override
public String toString() {
return "FeedItemCard{"
+ "feedItem=" + feedItem + ", cardType=" + cardType + ", imageByte='"
+ Arrays.toString(imageByte) + '\'' + '}';
}
}
@@ -0,0 +1,79 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.brave_news.models;
import org.chromium.brave_news.mojom.DisplayAd;
import java.util.Arrays;
import java.util.List;
public class FeedItemsCard {
private List<FeedItemCard> feedItems;
private int cardType;
private byte[] imageByte;
private String uuid;
private boolean viewStatSent;
private DisplayAd displayAd;
public FeedItemsCard() {
this.viewStatSent = false;
}
public List<FeedItemCard> getFeedItems() {
return feedItems;
}
public void setFeedItems(List<FeedItemCard> feedItems) {
this.feedItems = feedItems;
}
public int getCardType() {
return cardType;
}
public void setCardType(int cardType) {
this.cardType = cardType;
}
public byte[] getImageByte() {
return imageByte;
}
public void setImageByte(byte[] imageByte) {
this.imageByte = imageByte;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public boolean isViewStatSent() {
return viewStatSent;
}
public void setViewStatSent(boolean viewStatSent) {
this.viewStatSent = viewStatSent;
}
public DisplayAd getDisplayAd() {
return displayAd;
}
public void setDisplayAd(DisplayAd displayAd) {
this.displayAd = displayAd;
}
@Override
public String toString() {
return "FeedItemsCard{"
+ "feedItems=" + feedItems + ", cardType=" + cardType + ", displayAd=" + displayAd
+ ", imageByte=" + Arrays.toString(imageByte) + '}';
}
}
File diff suppressed because it is too large Load Diff
@@ -18,9 +18,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.util.DisplayMetrics;
import android.view.Gravity;
@@ -36,13 +33,16 @@ import androidx.cardview.widget.CardView;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.brave_news.mojom.DisplayAd;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.BraveAdsNativeHelper;
import org.chromium.chrome.browser.BraveFeatureList;
import org.chromium.chrome.browser.BraveRewardsHelper;
import org.chromium.chrome.browser.BraveRewardsNativeWorker;
import org.chromium.chrome.browser.BraveRewardsPanelPopup;
import org.chromium.chrome.browser.app.BraveActivity;
import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.ntp_background_images.NTPBackgroundImagesBridge;
import org.chromium.chrome.browser.ntp_background_images.RewardsBottomSheetDialogFragment;
import org.chromium.chrome.browser.ntp_background_images.model.BackgroundImage;
@@ -51,21 +51,19 @@ import org.chromium.chrome.browser.ntp_background_images.model.SponsoredTab;
import org.chromium.chrome.browser.ntp_background_images.model.Wallpaper;
import org.chromium.chrome.browser.ntp_background_images.util.SponsoredImageUtil;
import org.chromium.chrome.browser.preferences.BravePref;
import org.chromium.chrome.browser.preferences.BravePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.preferences.BravePrefServiceBridge;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.settings.BackgroundImagesPreferences;
import org.chromium.chrome.browser.tab.TabLaunchType;
import org.chromium.chrome.browser.util.ConfigurationUtils;
import org.chromium.chrome.browser.util.ImageUtils;
import org.chromium.chrome.browser.util.PackageUtils;
import org.chromium.components.user_prefs.UserPrefs;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.ui.base.DeviceFormFactor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
@@ -73,6 +71,15 @@ import java.util.Set;
public class NTPUtil {
private static final int BOTTOM_TOOLBAR_HEIGHT = 56;
private static final String REMOVED_SITES = "removed_sites";
private static DisplayAd sCurrentDisplayAd;
public static void setsCurrentDisplayAd(DisplayAd displayAd) {
sCurrentDisplayAd = displayAd;
}
public static DisplayAd getsCurrentDisplayAd() {
return sCurrentDisplayAd;
}
public static HashMap<String, SoftReference<Bitmap>> imageCache =
new HashMap<String, SoftReference<Bitmap>>();
@@ -82,25 +89,79 @@ public class NTPUtil {
BraveRewardsNativeWorker.getInstance().SetAutoContributeEnabled(true);
}
public static void updateOrientedUI(Context context, ViewGroup view, Point size) {
public static int correctImageCreditLayoutTopPosition(NTPImage ntpImage) {
int imageCreditCorrection = 0;
boolean isCompensate = false;
if (ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_NEWS)) {
if (BravePrefServiceBridge.getInstance().getNewsOptIn()
&& BravePrefServiceBridge.getInstance().getShowNews()) {
isCompensate = true;
}
}
if (BraveActivity.getBraveActivity() != null) {
BraveActivity activity = BraveActivity.getBraveActivity();
float dpHeight = ConfigurationUtils.getDpDisplayMetrics(activity).get("height");
int pxHeight = dpToPx(activity, dpHeight);
boolean isTablet = ConfigurationUtils.isTablet(activity);
boolean isLandscape = ConfigurationUtils.isLandscape(activity);
imageCreditCorrection = isLandscape ? (int) (pxHeight * (isCompensate ? 0.46 : 0.54))
: (int) (pxHeight * (isCompensate ? 0.70 : 0.30));
if (ntpImage instanceof BackgroundImage) {
if (!isTablet) {
imageCreditCorrection = isLandscape
? (int) (pxHeight * (isCompensate ? 0.12 : 0.88))
: (int) (pxHeight * (isCompensate ? 0.46 : 0.59));
}
if (!ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_NEWS)) {
imageCreditCorrection = (int) imageCreditCorrection - (int) (pxHeight * 0.04);
}
} else {
if (!isTablet) {
imageCreditCorrection = isLandscape
? (int) (pxHeight * (isCompensate ? 0.02 : 0.98))
: (int) (pxHeight * (isCompensate ? 0.30 : 0.50));
} else {
imageCreditCorrection = isLandscape
? (int) (pxHeight * (isCompensate ? 0.28 : 0.72))
: (int) (pxHeight * (isCompensate ? 0.56 : 0.44));
}
if (!ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_NEWS)) {
imageCreditCorrection = (int) imageCreditCorrection - (int) (pxHeight * 0.12);
}
}
}
return imageCreditCorrection;
}
public static void updateOrientedUI(
Context context, ViewGroup view, Point size, NTPImage ntpImage) {
LinearLayout parentLayout = (LinearLayout)view.findViewById(R.id.parent_layout);
ViewGroup mainLayout = view.findViewById(R.id.ntp_main_layout);
CompositorViewHolder compositorView = view.findViewById(R.id.compositor_view_holder);
ViewGroup imageCreditLayout = view.findViewById(R.id.image_credit_layout);
ViewGroup newsRecyclerLayout = view.findViewById(R.id.newsRecycler);
ViewGroup mainLayout = view.findViewById(R.id.ntp_main_layout);
ImageView sponsoredLogo = (ImageView)view.findViewById(R.id.sponsored_logo);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(dpToPx(context, 170), dpToPx(context, 170));
parentLayout.removeView(mainLayout);
parentLayout.removeView(imageCreditLayout);
parentLayout.removeView(newsRecyclerLayout);
parentLayout.addView(mainLayout);
parentLayout.addView(imageCreditLayout);
parentLayout.setOrientation(LinearLayout.VERTICAL);
parentLayout.addView(newsRecyclerLayout);
boolean isTablet = DeviceFormFactor.isNonMultiDisplayContextOnTablet(context);
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
CardView widgetLayout = (CardView) view.findViewById(R.id.ntp_widget_cardview_layout);
LinearLayout.LayoutParams widgetLayoutParams = new LinearLayout.LayoutParams(
(isTablet ? (int) (dpWidth * 0.75)
@@ -117,10 +178,36 @@ public class NTPUtil {
LinearLayout.LayoutParams imageCreditLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
imageCreditLayout.setLayoutParams(imageCreditLayoutParams);
layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
layoutParams.setMargins(0, 0, 0, dpToPx(context, 5));
if (ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_NEWS)) {
int topMargin = correctImageCreditLayoutTopPosition(ntpImage);
if ((BravePrefServiceBridge.getInstance().getNewsOptIn()
&& BravePrefServiceBridge.getInstance().getShowNews())) {
imageCreditLayoutParams.setMargins(0, topMargin, 0, 50);
}
ViewGroup optinLayout = view.findViewById(R.id.optin_layout_id);
LinearLayout.LayoutParams optinLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
optinLayoutParams.setMargins(30, imageCreditLayout.getBottom(), 30, 500);
optinLayout.setLayoutParams(optinLayoutParams);
View feedSpinner = (View) view.findViewById(R.id.feed_spinner);
FrameLayout.LayoutParams feedSpinnerParams =
(FrameLayout.LayoutParams) feedSpinner.getLayoutParams();
feedSpinnerParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
feedSpinnerParams.setMargins(0, 0, 0, dpToPx(context, 35));
feedSpinner.setLayoutParams(feedSpinnerParams);
layoutParams.gravity = Gravity.CENTER_HORIZONTAL;
} else {
layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
layoutParams.setMargins(0, 0, 0, dpToPx(context, 5));
}
parentLayout.setOrientation(LinearLayout.VERTICAL);
imageCreditLayout.setLayoutParams(imageCreditLayoutParams);
sponsoredLogo.setLayoutParams(layoutParams);
}
@@ -264,6 +264,23 @@ public class BravePrefServiceBridge {
return BravePrefServiceBridgeJni.get().getWebrtcPolicy();
}
public void setNewsOptIn(boolean value) {
BravePrefServiceBridgeJni.get().setNewsOptIn(value);
}
public boolean getNewsOptIn() {
boolean getNewsOptIn = BravePrefServiceBridgeJni.get().getNewsOptIn();
return BravePrefServiceBridgeJni.get().getNewsOptIn();
}
public void setShowNews(boolean value) {
BravePrefServiceBridgeJni.get().setShowNews(value);
}
public boolean getShowNews() {
boolean getShowNews = BravePrefServiceBridgeJni.get().getShowNews();
return BravePrefServiceBridgeJni.get().getShowNews();
}
@NativeMethods
interface Natives {
void setCosmeticFilteringControlType(int type);
@@ -338,5 +355,11 @@ public class BravePrefServiceBridge {
void setWebrtcPolicy(int policy);
int getWebrtcPolicy();
void setNewsOptIn(boolean value);
boolean getNewsOptIn();
void setShowNews(boolean value);
boolean getShowNews();
}
}
@@ -25,4 +25,8 @@ public final class BravePreferenceKeys {
"org.chromium.chrome.browser.Brave_Tab_Groups_Enabled";
public static final String BRAVE_DISABLE_SHARING_HUB =
"org.chromium.chrome.browser.Brave_Disable_Sharing_Hub";
public static final String BRAVE_NEWS_CARDS_VISITED = "brave_news_cards_visited";
public static final String BRAVE_NEWS_CHANGE_SOURCE = "brave_news_change_source";
public static final String BRAVE_NEWS_FEED_HASH = "brave_news_feed_hash";
public static final String BRAVE_NEWS_PREF_SHOW_NEWS = "kNewTabPageShowToday";
}
@@ -0,0 +1,154 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.settings;
import android.os.Bundle;
import android.widget.EditText;
import androidx.preference.CheckBoxPreference;
import androidx.preference.EditTextPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import org.chromium.base.ContextUtils;
import org.chromium.brave_news.mojom.BraveNewsController;
import org.chromium.brave_news.mojom.Publisher;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.BraveLaunchIntentDispatcher;
import org.chromium.chrome.browser.brave_news.BraveNewsControllerFactory;
import org.chromium.chrome.browser.settings.BravePreferenceFragment;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import org.chromium.mojo.bindings.ConnectionErrorHandler;
import org.chromium.mojo.system.MojoException;
import java.util.ArrayList;
import java.util.Map;
public class BraveAddNewsSources extends BravePreferenceFragment
implements Preference.OnPreferenceChangeListener, ConnectionErrorHandler {
private static final String PREF_ADD_SOURCES = "news_source_1";
private EditTextPreference addSource;
private EditText mEditText;
private PreferenceScreen mainScreen;
private BraveNewsController mBraveNewsController;
private ArrayList<Publisher> mPublishers;
public static int getPreferenceSummary() {
return BraveLaunchIntentDispatcher.useCustomTabs() ? R.string.text_on : R.string.text_off;
}
@Override
public void onConnectionError(MojoException e) {
if (mBraveNewsController != null) {
mBraveNewsController.close();
}
mBraveNewsController = null;
InitBraveNewsController();
}
private void InitBraveNewsController() {
if (mBraveNewsController != null) {
return;
}
mBraveNewsController =
BraveNewsControllerFactory.getInstance().getBraveNewsController(this);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.news_add_source);
SettingsUtils.addPreferencesFromResource(this, R.xml.brave_news_sources_default);
findPreference(PREF_ADD_SOURCES).setOnPreferenceChangeListener(this);
InitBraveNewsController();
mainScreen = getPreferenceManager().getPreferenceScreen();
addSource = (EditTextPreference) findPreference(PREF_ADD_SOURCES);
addSource.setPositiveButtonText(R.string.search_title);
mPublishers = new ArrayList<>();
mBraveNewsController.getPublishers((publishers) -> {
for (Map.Entry<String, Publisher> entry : publishers.entrySet()) {
String key = entry.getKey();
Publisher publisher = entry.getValue();
mPublishers.add(publisher);
CheckBoxPreference source =
new CheckBoxPreference(ContextUtils.getApplicationContext());
source.setTitle(publisher.publisherName);
mainScreen.addPreference(source);
}
});
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = preference.getKey();
if (PREF_ADD_SOURCES.equals(key)) {
PreferenceManager manager = getPreferenceManager();
PreferenceScreen sourcesScreen =
manager.createPreferenceScreen(ContextUtils.getApplicationContext());
sourcesScreen.setTitle((String) newValue);
// fetch results from API
// populate checkboxes
CheckBoxPreference source1 =
new CheckBoxPreference(ContextUtils.getApplicationContext());
source1.setTitle((String) newValue + " 1");
source1.setChecked(true);
sourcesScreen.addPreference(source1);
CheckBoxPreference source2 =
new CheckBoxPreference(ContextUtils.getApplicationContext());
source2.setTitle((String) newValue + " 2");
source2.setChecked(true);
sourcesScreen.addPreference(source2);
// end fetch. finish the layout
Preference button = new Preference(ContextUtils.getApplicationContext());
button.setTitle("Add");
button.setKey("add_news_source");
button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
setPreferencesFromResource(R.xml.brave_news_preferences, null);
return true;
}
});
sourcesScreen.addPreference(button);
setPreferenceScreen(sourcesScreen);
return true;
}
return true;
}
@Override
public void onDestroy() {
super.onDestroy();
if (mBraveNewsController != null) {
mBraveNewsController.close();
}
}
private ArrayList<Preference> getPreferenceList(Preference p, ArrayList<Preference> list) {
if (p instanceof PreferenceCategory || p instanceof PreferenceScreen) {
PreferenceGroup pGroup = (PreferenceGroup) p;
int pCount = pGroup.getPreferenceCount();
for (int i = 0; i < pCount; i++) {
getPreferenceList(pGroup.getPreference(i), list); // recursive call
}
} else {
list.add(p);
}
return list;
}
}
@@ -65,6 +65,7 @@ public class BraveMainPreferencesBase
private static final String PREF_PRIVACY = "privacy";
private static final String PREF_SHIELDS_AND_PRIVACY = "brave_shields_and_privacy";
private static final String PREF_BRAVE_SEARCH_ENGINES = "brave_search_engines";
private static final String PREF_BRAVE_NEWS = "brave_news";
private static final String PREF_SYNC = "brave_sync_layout";
private static final String PREF_PASSWORDS = "passwords";
private static final String PREF_NOTIFICATIONS = "notifications";
@@ -133,7 +134,9 @@ public class BraveMainPreferencesBase
removePreferenceIfPresent(PREF_ADVANCED_SECTION);
removePreferenceIfPresent(PREF_PRIVACY);
removePreferenceIfPresent(PREF_BRAVE_VPN_CALLOUT);
if (!ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_NEWS)) {
removePreferenceIfPresent(PREF_BRAVE_NEWS);
}
updateSearchEnginePreference();
updateSummaries();
@@ -0,0 +1,185 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.settings;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.preference.SwitchPreferenceCompat;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.brave_news.mojom.BraveNewsController;
import org.chromium.brave_news.mojom.Publisher;
import org.chromium.brave_news.mojom.UserEnabled;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.brave_news.BraveNewsControllerFactory;
import org.chromium.chrome.browser.preferences.BravePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.settings.SearchPreference;
import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
import org.chromium.mojo.bindings.ConnectionErrorHandler;
import org.chromium.mojo.system.MojoException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
public class BraveNewsCategorySources
extends PreferenceFragmentCompat implements ConnectionErrorHandler {
private PreferenceManager mPreferenceManager;
private BraveNewsController mBraveNewsController;
private String mCategoryArg;
private TreeMap<String, List<Publisher>> mCategsPublishers;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
mCategoryArg = args.getString("category");
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
InitBraveNewsController();
addPreferencesFromResource(R.xml.brave_news_sources_default);
getActivity().setTitle(mCategoryArg);
mCategsPublishers = new TreeMap<>();
mPreferenceManager = getPreferenceManager();
mBraveNewsController.getPublishers((publishers) -> {
List<Publisher> allPublishers = new ArrayList<>();
List<Publisher> categoryPublishers = new ArrayList<>();
for (Map.Entry<String, Publisher> entry : publishers.entrySet()) {
String key = entry.getKey();
Publisher publisher = entry.getValue();
if (publisher.categoryName.toLowerCase(Locale.ROOT)
.equals(mCategoryArg.toLowerCase(Locale.ROOT))) {
categoryPublishers.add(publisher);
}
mCategsPublishers.put(publisher.categoryName, categoryPublishers);
allPublishers.add(publisher);
}
Comparator<Publisher> compareByName =
(Publisher o1, Publisher o2) -> o1.publisherName.compareTo(o2.publisherName);
Collections.sort(categoryPublishers, compareByName);
Collections.sort(allPublishers, compareByName);
mCategsPublishers.put("All Sources", allPublishers);
addCategs(mCategsPublishers);
});
}
@Override
public void onConnectionError(MojoException e) {
if (mBraveNewsController != null) {
mBraveNewsController.close();
}
mBraveNewsController = null;
InitBraveNewsController();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mBraveNewsController != null) {
mBraveNewsController.close();
}
}
private void InitBraveNewsController() {
if (mBraveNewsController != null) {
return;
}
mBraveNewsController =
BraveNewsControllerFactory.getInstance().getBraveNewsController(this);
}
private void addCategs(TreeMap<String, List<Publisher>> publisherCategories) {
PreferenceScreen sourcesScreen = getPreferenceScreen();
SearchPreference search = new SearchPreference(ContextUtils.getApplicationContext());
search.setKey("search_pref");
sourcesScreen.addPreference(search);
final List<Publisher> publishers = publisherCategories.get(mCategoryArg);
if (publishers == null) {
return;
}
search.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
for (Publisher publisher : publishers) {
SwitchPreference publisherSource =
mPreferenceManager.findPreference(publisher.publisherName);
if (publisher.publisherName.toLowerCase(Locale.ROOT)
.contains((String) newValue)) {
publisherSource.setVisible(true);
} else {
publisherSource.setVisible(false);
}
}
return false;
}
});
for (Publisher publisher : publishers) {
SwitchPreference source = new SwitchPreference(ContextUtils.getApplicationContext());
source.setOnPreferenceChangeListener(null);
boolean enabled = false;
if (publisher.userEnabledStatus == UserEnabled.ENABLED) {
enabled = true;
} else if (publisher.userEnabledStatus == UserEnabled.NOT_MODIFIED) {
enabled = publisher.isEnabled;
}
source.setTitle(publisher.publisherName);
source.setKey(publisher.publisherName);
source.setChecked(enabled);
source.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
@UserEnabled.EnumType
int type = UserEnabled.NOT_MODIFIED;
if ((boolean) newValue) {
type = UserEnabled.ENABLED;
} else {
type = UserEnabled.DISABLED;
}
SharedPreferencesManager.getInstance().writeBoolean(
BravePreferenceKeys.BRAVE_NEWS_CHANGE_SOURCE, true);
if (mBraveNewsController != null) {
mBraveNewsController.setPublisherPref(publisher.publisherId, type);
}
source.setChecked((boolean) newValue);
return false;
}
});
sourcesScreen.addPreference(source);
}
}
}
@@ -0,0 +1,197 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.settings;
import android.os.Bundle;
import android.widget.EditText;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import org.chromium.base.ContextUtils;
import org.chromium.brave_news.mojom.BraveNewsController;
import org.chromium.brave_news.mojom.Publisher;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.BraveLaunchIntentDispatcher;
import org.chromium.chrome.browser.brave_news.BraveNewsControllerFactory;
import org.chromium.chrome.browser.preferences.BravePrefServiceBridge;
import org.chromium.chrome.browser.settings.BravePreferenceFragment;
import org.chromium.components.browser_ui.settings.ChromeBasePreference;
import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import org.chromium.mojo.bindings.ConnectionErrorHandler;
import org.chromium.mojo.system.MojoException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class BraveNewsPreferences extends BravePreferenceFragment
implements Preference.OnPreferenceChangeListener, ConnectionErrorHandler {
public static final String PREF_TURN_ON_NEWS = "kBraveTodayOptedIn";
public static final String PREF_SHOW_NEWS = "kNewTabPageShowToday";
public static final String PREF_SHOW_OPTIN = "show_optin";
public static final String PREF_SOURCES_SECTION = "your_sources_section";
public static final String PREF_ADD_SOURCES = "add_source_news";
private ChromeSwitchPreference mTurnOnNews;
private ChromeSwitchPreference mShowNews;
private PreferenceScreen mMainScreen;
private PreferenceManager mPreferenceManager;
private TreeMap<String, List<Publisher>> mCategsPublishers;
private final HashMap<String, Preference> mRemovedPreferences = new HashMap<>();
private BraveNewsController mBraveNewsController;
private PreferenceFragmentCompat mSettingsFragment;
public static int getPreferenceSummary() {
return BraveLaunchIntentDispatcher.useCustomTabs() ? R.string.text_on : R.string.text_off;
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
SettingsUtils.addPreferencesFromResource(this, R.xml.brave_news_preferences);
InitBraveNewsController();
mTurnOnNews = (ChromeSwitchPreference) findPreference(PREF_TURN_ON_NEWS);
mShowNews = (ChromeSwitchPreference) findPreference(PREF_SHOW_NEWS);
mSettingsFragment = this;
mTurnOnNews.setOnPreferenceChangeListener(this);
mShowNews.setOnPreferenceChangeListener(this);
mCategsPublishers = new TreeMap<>();
mBraveNewsController.getPublishers((publishers) -> {
List<Publisher> allPublishers = new ArrayList<>();
List<Publisher> categoryPublishers = new ArrayList<>();
for (Map.Entry<String, Publisher> entry : publishers.entrySet()) {
Publisher publisher = entry.getValue();
categoryPublishers.add(publisher);
mCategsPublishers.put(publisher.categoryName, categoryPublishers);
}
mCategsPublishers.put("All Sources", allPublishers);
addCategs(mCategsPublishers);
});
}
private void addCategs(TreeMap<String, List<Publisher>> publisherCategories) {
for (Map.Entry<String, List<Publisher>> map : publisherCategories.entrySet()) {
String category = map.getKey();
ChromeBasePreference source =
new ChromeBasePreference(ContextUtils.getApplicationContext());
source.setTitle(category);
source.setKey(category);
Bundle prefExtras = source.getExtras();
prefExtras.putString("category", category);
source.setFragment("org.chromium.chrome.browser.settings.BraveNewsCategorySources");
mMainScreen.addPreference(source);
}
}
@Override
public void onConnectionError(MojoException e) {
if (mBraveNewsController != null) {
mBraveNewsController.close();
}
mBraveNewsController = null;
InitBraveNewsController();
}
private void InitBraveNewsController() {
if (mBraveNewsController != null) {
return;
}
mBraveNewsController =
BraveNewsControllerFactory.getInstance().getBraveNewsController(this);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.brave_news_title);
mPreferenceManager = getPreferenceManager();
mMainScreen = mPreferenceManager.getPreferenceScreen();
boolean isNewsOn = BravePrefServiceBridge.getInstance().getNewsOptIn();
if (!isNewsOn) {
mTurnOnNews.setChecked(false);
mShowNews.setVisible(false);
} else {
mTurnOnNews.setChecked(true);
mTurnOnNews.setVisible(false);
mShowNews.setVisible(true);
if (BravePrefServiceBridge.getInstance().getShowNews()) {
mShowNews.setChecked(true);
} else {
mShowNews.setChecked(false);
}
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = preference.getKey();
if (PREF_TURN_ON_NEWS.equals(key)) {
BravePrefServiceBridge.getInstance().setNewsOptIn((boolean) newValue);
if ((boolean) newValue) {
mShowNews.setVisible(true);
mShowNews.setChecked(true);
BravePrefServiceBridge.getInstance().setShowNews(true);
} else {
mShowNews.setVisible(false);
}
} else if (PREF_SHOW_NEWS.equals(key)) {
BravePrefServiceBridge.getInstance().setShowNews((boolean) newValue);
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
Preference pref = getPreferenceScreen().getPreference(i);
if (!pref.getKey().equals(PREF_SHOW_NEWS)
&& !pref.getKey().equals(PREF_TURN_ON_NEWS)) {
pref.setVisible((boolean) newValue);
}
}
}
return true;
}
private void removePreferenceIfPresent(String key) {
Preference preference = getPreferenceScreen().findPreference(key);
if (preference != null) {
getPreferenceScreen().removePreference(preference);
mRemovedPreferences.put(preference.getKey(), preference);
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mBraveNewsController != null) {
mBraveNewsController.close();
}
}
/**
* We need to override it to avoid NullPointerException in Chromium's child classes
*/
@Override
public <T extends Preference> T findPreference(CharSequence key) {
T result = super.findPreference(key);
if (result == null) {
result = (T) mRemovedPreferences.get((String) key);
}
return result;
}
}
@@ -0,0 +1,45 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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.chromium.chrome.browser.settings;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.appcompat.widget.SearchView;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import org.chromium.chrome.R;
public class SearchPreference extends Preference {
public SearchPreference(Context context) {
super(context);
setLayoutResource(R.layout.custom_layout_preference);
setWidgetLayoutResource(R.layout.search_preference);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
SearchView searchView = (SearchView) holder.findViewById(R.id.search_preference);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
getOnPreferenceChangeListener().onPreferenceChange(SearchPreference.this, s);
return false;
}
@Override
public boolean onQueryTextChange(String s) {
getOnPreferenceChangeListener().onPreferenceChange(SearchPreference.this, s);
return false;
}
});
}
}
@@ -76,7 +76,6 @@ import org.chromium.chrome.browser.local_database.BraveStatsTable;
import org.chromium.chrome.browser.local_database.DatabaseHelper;
import org.chromium.chrome.browser.local_database.SavedBandwidthTable;
import org.chromium.chrome.browser.notifications.retention.RetentionNotificationUtil;
import org.chromium.chrome.browser.ntp.BraveNewTabPageLayout;
import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.onboarding.BraveTalkOptInPopup;
import org.chromium.chrome.browser.onboarding.BraveTalkOptInPopupListener;
@@ -7,8 +7,14 @@
package org.chromium.chrome.browser.util;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.util.DisplayMetrics;
import org.chromium.ui.base.DeviceFormFactor;
import java.util.HashMap;
public class ConfigurationUtils {
public static boolean isLandscape(Context context) {
@@ -19,4 +25,34 @@ public class ConfigurationUtils {
return false;
}
}
}
public static boolean isTablet(Context context) {
return DeviceFormFactor.isNonMultiDisplayContextOnTablet(context);
}
public static HashMap<String, Integer> getDisplayMetrics(Activity activity) {
DisplayMetrics displayMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int deviceWidth = displayMetrics.widthPixels;
int deviceHeight = displayMetrics.heightPixels;
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("width", deviceWidth);
map.put("height", deviceHeight);
return map;
}
public static HashMap<String, Float> getDpDisplayMetrics(Activity activity) {
DisplayMetrics displayMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
HashMap<String, Float> map = new HashMap<String, Float>();
map.put("width", dpWidth);
map.put("height", dpHeight);
return map;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/card_background"/>
<stroke android:width="3dp" android:color="@color/card_background" />
<corners android:radius="10dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
+9
View File
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:fillColor="#FFFFFF"
android:pathData="M24.9227 24.9345C25.3014 24.5558 25.3261 23.9279 24.9403 23.5421L21.2139 19.8156L24.8288 16.2007C25.2069 15.8226 25.2153 15.1771 24.8288 14.7906C24.4398 14.4015 23.8001 14.4209 23.4246 14.7965L19.8097 18.4114L16.0773 14.6791C15.6916 14.2933 15.0636 14.318 14.6849 14.6967C14.3036 15.078 14.2899 15.7 14.6731 16.0833L18.4055 19.8156L14.7905 23.4305C14.415 23.8061 14.3956 24.4457 14.7847 24.8347C15.1712 25.2213 15.8166 25.2128 16.1947 24.8347L19.8097 21.2198L23.5361 24.9463C23.9194 25.3295 24.5414 25.3158 24.9227 24.9345Z" />
</vector>
+11
View File
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M13.4218,15.9907c-0.0153,0.0013 -0.0286,0.0093 -0.0446,0.0093L2.6225,16c-0.016,0 -0.0293,-0.008 -0.0447,-0.0093C1.5165,15.9433 0.6665,15.072 0.6665,14L0.6665,4.6667C0.6665,4.298 0.9652,4 1.3332,4h1.956c0.0153,0 0.0287,0.008 0.044,0.0087v-3.342C3.3332,0.298 3.6318,0 3.9998,0L14.6665,0c0.368,0 0.6667,0.298 0.6667,0.6667L15.3332,14c0,1.072 -0.85,1.9433 -1.9114,1.9907zM3.3332,5.3247c-0.0153,0.0007 -0.0287,0.0087 -0.044,0.0087L1.9998,5.3333L1.9998,14c0,0.368 0.2993,0.6667 0.6667,0.6667 0.3673,0 0.6667,-0.2987 0.6667,-0.6667L3.3332,5.3247zM13.9998,1.3333L4.6665,1.3333L4.6665,14c0,0.2353 -0.048,0.4573 -0.1227,0.6667h8.7894c0.3673,0 0.6666,-0.2987 0.6666,-0.6667L13.9998,1.3333zM12.6665,11.3333L5.9998,11.3333c-0.368,0 -0.6667,-0.298 -0.6667,-0.6666 0,-0.368 0.2987,-0.6667 0.6667,-0.6667h6.6667c0.368,0 0.6667,0.2987 0.6667,0.6667 0,0.3686 -0.2987,0.6666 -0.6667,0.6666zM12.6665,8.6667L5.9998,8.6667c-0.368,0 -0.6667,-0.298 -0.6667,-0.6667s0.2987,-0.6667 0.6667,-0.6667h6.6667c0.368,0 0.6667,0.298 0.6667,0.6667s-0.2987,0.6667 -0.6667,0.6667zM9.9998,5.3333h-4c-0.368,0 -0.6667,-0.298 -0.6667,-0.6667C5.3332,4.298 5.6318,4 5.9998,4h4c0.368,0 0.6667,0.298 0.6667,0.6667 0,0.3687 -0.2987,0.6667 -0.6667,0.6667z"
android:fillColor="@color/shield_text_color"
android:scaleType="fitCenter"
android:fillType="evenOdd"/>
</vector>
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="18dp"
android:viewportWidth="18"
android:viewportHeight="18">
<path
android:pathData="M12.5748,9.6875C12.196,9.6875 11.8873,9.3795 11.8873,9C11.8873,8.6205 12.196,8.3125 12.5748,8.3125C12.9536,8.3125 13.2623,8.6205 13.2623,9C13.2623,9.3795 12.9536,9.6875 12.5748,9.6875ZM16.5623,8.3125H14.5108C14.2261,7.5136 13.4699,6.9375 12.5748,6.9375C11.6796,6.9375 10.9234,7.5136 10.6388,8.3125L1.4373,8.3125C1.0578,8.3125 0.7498,8.6205 0.7498,9C0.7498,9.3795 1.0578,9.6875 1.4373,9.6875L10.6388,9.6875C10.9241,10.4864 11.6796,11.0625 12.5748,11.0625C13.4699,11.0625 14.2261,10.4864 14.5108,9.6875H16.5623C16.9424,9.6875 17.2498,9.3795 17.2498,9C17.2498,8.6205 16.9424,8.3125 16.5623,8.3125ZM5.5623,15.875C5.1834,15.875 4.8748,15.567 4.8748,15.1875C4.8748,14.808 5.1834,14.5 5.5623,14.5C5.9418,14.5 6.2498,14.808 6.2498,15.1875C6.2498,15.567 5.9418,15.875 5.5623,15.875ZM16.5623,14.5L7.4983,14.5C7.2136,13.7011 6.4574,13.125 5.5623,13.125C4.6678,13.125 3.9116,13.7011 3.6263,14.5H1.4373C1.0578,14.5 0.7498,14.808 0.7498,15.1875C0.7498,15.567 1.0578,15.875 1.4373,15.875H3.6269C3.9116,16.6739 4.6678,17.25 5.5623,17.25C6.4574,17.25 7.2136,16.6739 7.4983,15.875L16.5623,15.875C16.9424,15.875 17.2498,15.567 17.2498,15.1875C17.2498,14.808 16.9424,14.5 16.5623,14.5ZM7.7623,2.125C8.1411,2.125 8.4498,2.433 8.4498,2.8125C8.4498,3.192 8.1411,3.5 7.7623,3.5C7.3835,3.5 7.0748,3.192 7.0748,2.8125C7.0748,2.433 7.3835,2.125 7.7623,2.125ZM1.4373,3.5L5.8263,3.5C6.1116,4.2989 6.8671,4.875 7.7623,4.875C8.6574,4.875 9.4136,4.2989 9.6983,3.5L16.5623,3.5C16.9424,3.5 17.2498,3.192 17.2498,2.8125C17.2498,2.433 16.9424,2.125 16.5623,2.125L9.6983,2.125C9.4136,1.3261 8.6574,0.75 7.7623,0.75C6.8671,0.75 6.1109,1.3261 5.8263,2.125L1.4373,2.125C1.0578,2.125 0.7498,2.433 0.7498,2.8125C0.7498,3.192 1.0578,3.5 1.4373,3.5Z"
android:fillColor="#ffffff"
android:scaleType="fitCenter"
android:fillType="evenOdd"/>
</vector>
+10
View File
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="9dp"
android:viewportWidth="16"
android:viewportHeight="9">
<path
android:pathData="M14.56,4.77a0.9,0.9 0,0 1,-0.9 -0.9v-0.83L8.73,7.27a0.9,0.9 0,0 1,-1.23 -0.05L5.36,5.08 1.47,8.19A0.9,0.9 0,0 1,0.2 8.05a0.9,0.9 0,0 1,0.14 -1.27l4.52,-3.62a0.9,0.9 0,0 1,1.2 0.07L8.2,5.35l3.84,-3.3h-0.18a0.9,0.9 0,1 1,0 -1.8h2.71c0.4,0 0.67,0.26 0.77,0.62v0.05c0.02,0.08 0.05,0.15 0.05,0.23v2.72c0,0.5 -0.32,0.9 -0.82,0.9z"
android:fillColor="#fff"
android:fillType="evenOdd"/>
</vector>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#737ADE"/>
<corners android:radius="30dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/card_background_solid" />
<corners android:topLeftRadius="30dp" android:topRightRadius="30dp"/>
</shape>
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_marginStart="50dp"
android:layout_marginEnd="50dp"
android:background="@drawable/rounded_top_corners"
android:orientation="vertical">
<TextView
android:id="@+id/item_menu_title_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="50dp"
android:textColor="@color/news_text_color"
android:paddingTop="30dp"
android:paddingEnd="50dp"
android:paddingBottom="30dp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/news_time_color"
android:paddingStart="50dp"
android:paddingTop="30dp"
android:paddingEnd="50dp" />
<Button
android:id="@+id/new_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@android:color/transparent"
android:padding="8dp"
android:paddingStart="50dp"
android:textAllCaps="false"
android:paddingTop="30dp"
android:paddingEnd="50dp"
android:textSize="15sp"
android:text="@string/brave_news_open_new_tab"
android:textColor="@color/news_text_color" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/news_time_color" />
<Button
android:id="@+id/new_private_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@android:color/transparent"
android:padding="8dp"
android:paddingStart="50dp"
android:paddingTop="30dp"
android:textAllCaps="false"
android:textSize="15sp"
android:paddingEnd="50dp"
android:text="@string/brave_news_open_new_private_tab"
android:textColor="@color/news_text_color" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/news_time_color" />
<Button
android:id="@+id/disable_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@android:color/transparent"
android:padding="8dp"
android:textSize="15sp"
android:textAllCaps="false"
android:text="@string/brave_news_disable_content"
android:textColor="@color/news_text_color" />
</LinearLayout>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2021 The Brave Authors. All rights reserved.
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/.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/new_content_layout_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:visibility="invisible"
android:layout_marginTop="400dp"
android:background="@drawable/rounded_filled"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/new_content_loading_spinner"
style="?android:progressBarStyleLarge"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:visibility="gone" />
<TextView
android:id="@+id/new_content_button_text"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:gravity="center"
android:paddingHorizontal="20dp"
android:text="@string/brave_news_load_new_content"
android:textAlignment="center"
android:textAllCaps="false"
android:textColor="@color/news_text_color"
android:textSize="14sp"
android:textStyle="normal" />
</RelativeLayout>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="500dp"
android:id="@+id/card_layout"
android:orientation="horizontal"
android:background="@android:color/transparent"
android:layout_margin="20dp"
>
</LinearLayout>
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/news_settings_bar"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@color/card_background_solid"
android:orientation="horizontal"
android:alpha="0"
android:paddingHorizontal="20dp">
<TextView
android:id="@+id/news_settings_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"
android:textSize = "17sp"
android:gravity="center_vertical"
android:text="@string/brave_news_title"
android:textColor="@color/news_text_color" />
<ImageView
android:id="@+id/news_settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:gravity="center"
tools:ignore="ContentDescription"
android:background="@drawable/ic_news_settings"/>
</LinearLayout>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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/. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/widget_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"/>
@@ -152,6 +152,24 @@
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/newsRecycler"
android:layout_width="match_parent"
android:layout_height="750dp"
android:visibility="gone"
android:layout_marginTop="-50dp"
/>
<include
android:id="@+id/optin_layout_id"
layout="@layout/optin_layout"
android:layout_marginTop="-66dp"
android:layout_marginBottom="300dp"
android:layout_marginHorizontal="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<FrameLayout
android:id="@+id/image_credit_layout"
android:layout_width="match_parent"
@@ -180,6 +198,14 @@
</LinearLayout>
<ProgressBar
android:id="@+id/feed_spinner"
style="?android:progressBarStyleLarge"
android:layout_width="40dp"
android:layout_height="40dp"
android:visibility="gone"
android:layout_gravity="center" />
<include layout="@layout/ntp_non_disruptive_banner"/>
<include layout="@layout/bre_bottom_banner"/>
+97
View File
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/card_bg"
android:orientation="vertical">
<ImageView
android:id="@+id/close_optin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="10dp"
tools:ignore="ContentDescription"
android:src="@drawable/ic_close" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="ContentDescription"
app:srcCompat="@drawable/sparkling_newsreader" />
<TextView
android:id="@+id/optin_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:paddingHorizontal="30dp"
android:text="@string/brave_news_optin_title"
android:textAlignment="center"
android:textColor="@color/news_text_color"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/optin_subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="30dp"
android:paddingHorizontal="30dp"
android:text="@string/brave_news_optin_subtitle"
android:textAlignment="center"
android:textColor="@color/news_text_color"
android:textSize="15sp" />
<FrameLayout
android:id="@+id/optin_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/news_button_bg"
android:layout_marginHorizontal="60dp"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/optin_loading_spinner"
style="?android:progressBarStyleLarge"
android:layout_width="40dp"
android:layout_height="40dp"
android:visibility="gone"
android:layout_gravity="center" />
<TextView
android:id="@+id/optin_button_text"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:paddingHorizontal="40dp"
android:textAlignment="center"
android:text="@string/brave_news_optin_button"
android:textColor="@color/news_text_color"
android:layout_gravity="center"
android:textAllCaps="false"
android:textSize="14sp"
android:textStyle="normal"
android:gravity="center" />
</FrameLayout>
<TextView
android:id="@+id/optin_learnmore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="30dp"
android:paddingHorizontal="30dp"
android:text="@string/brave_news_optin_learn_more"
android:textAlignment="center"
android:textColor="@color/news_text_color"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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/. -->
<androidx.appcompat.widget.SearchView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/search_preference"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:focusable="true"
/>
@@ -25,6 +25,13 @@
<color name="onboarding_progressbar_secondary_bg">#212529</color>
<!-- Brave news colors -->
<color name="card_background">#F23B3E4F</color>
<color name="card_background_solid">#353535</color>
<!-- <color name="turn_on_button">#737ADE</color> -->
<color name="news_text_color">@android:color/white</color>
<color name="news_time_color">#9CD2D5CF</color>
<!-- Sync colors -->
<color name="brave_sync_bg_color">@color/modern_grey_800</color>
<color name="brave_sync_border_color">@color/modern_grey_800</color>
+10
View File
@@ -50,6 +50,16 @@
<color name="brave_theme_color">#fb542b</color>
<color name="brave_rewards_theme_color">#392DD1</color>
<!-- Brave news colors -->
<!-- <color name="card_background">#DC353535</color> -->
<color name="card_background">#F23B3E4F</color>
<color name="card_background_solid">#353535</color>
<!-- <color name="turn_on_button">#737ADE</color> -->
<color name="news_text_color">@android:color/white</color>
<color name="news_time_color">#9CD2D5CF</color>
<color name="news_promoted_background_color">#495057</color>
<!-- Incognito mode colors -->
<color name="ntp_bg_incognito">@color/incognito_modern_primary_color</color>
+1
View File
@@ -8,6 +8,7 @@
<item name="set_default_browser" type="id"/>
<item name="brave_rewards_id" type="id"/>
<item name="brave_wallet_id" type="id"/>
<item name="brave_news_id" type="id"/>
<item name="exit_id" type="id"/>
<item name="help_id" type="id"/>
<item name="request_brave_vpn_row_menu_id" type="id"/>
+9
View File
@@ -20,6 +20,15 @@
<item name="switchStyle">@style/Widget.MaterialComponents.CompoundButton.Switch</item>
</style>
<style name="AppBottomSheetDialogTheme"
parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/AppModalStyle</item>
</style>
<style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@drawable/rounded_top_corners</item>
</style>
<!-- Buttons for Brave Sync -->
<style name="BraveSyncButton">
<item name="android:textColor">@android:color/white</item>
@@ -28,18 +28,18 @@
android:icon="@drawable/ic_crypto_wallets"
android:order="3"
android:title="@string/brave_ui_brave_wallet"/>
<!-- <org.chromium.components.browser_ui.settings.ChromeBasePreference
android:fragment="org.chromium.chrome.browser.settings.BraveRewardsPreferences"
android:key="brave_today"
android:icon="@drawable/btn_bat"
<org.chromium.components.browser_ui.settings.ChromeBasePreference
android:fragment="org.chromium.chrome.browser.settings.BraveNewsPreferences"
android:key="brave_news"
android:icon="@drawable/ic_news"
android:order="3"
android:title="@string/brave_today"/> -->
android:title="@string/brave_news_title"/>
<org.chromium.components.browser_ui.settings.ChromeBasePreference
android:fragment="org.chromium.chrome.browser.settings.BraveVpnPreferences"
android:key="brave_vpn"
android:icon="@drawable/ic_vpn"
android:order="4"
android:title="@string/brave_firewall_vpn"/>
android:title="@string/brave_firewall_vpn"/>
<PreferenceCategory
android:key="general_section"
android:order="5"
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!--* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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/. -->
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<org.chromium.components.browser_ui.settings.ChromeSwitchPreference
android:key="kBraveTodayOptedIn"
android:title="@string/news_turn_on_button"
android:summaryOff="@string/brave_news_optin_subtitle" />
<org.chromium.components.browser_ui.settings.ChromeSwitchPreference
android:key="kNewTabPageShowToday"
android:title="@string/news_show"
android:dependency="kBraveTodayOptedIn"
android:summaryOn="@string/brave_news_optin_subtitle"
android:summaryOff="@string/brave_news_optin_subtitle" />
<!-- <PreferenceCategory
android:key="your_sources_section"
android:dependency="kNewTabPageShowToday"
android:title="@string/news_your_sources_section"/> -->
<PreferenceCategory
android:key="default_sources_section"
android:dependency="kNewTabPageShowToday"
android:title="@string/news_default_sources_section"/>
</androidx.preference.PreferenceScreen>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!--* Copyright (c) 2021 The Brave Authors. All rights reserved.
* 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/. -->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
</PreferenceScreen>