diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/SessionStore.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/SessionStore.java index f1792768f..daaa292ef 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/SessionStore.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/SessionStore.java @@ -826,6 +826,10 @@ public void switchPrivateMode() { } } + public int getUaMode() { + return mCurrentSession.getSettings().getUserAgentMode(); + } + public void setUaMode(int mode) { if (mCurrentSession != null) { mCurrentSession.getSettings().setUserAgentMode(mode); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java index b786ae7bb..6393701f8 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java @@ -45,7 +45,10 @@ SettingsStore getInstance(final @NonNull Context aContext) { public final static boolean ENV_OVERRIDE_DEFAULT = false; public final static boolean MULTIPROCESS_DEFAULT = false; public final static boolean PERFORMANCE_MONITOR_DEFAULT = true; + public final static boolean DRM_PLAYBACK_DEFAULT = false; public final static boolean TRACKING_DEFAULT = true; + public final static boolean NOTIFICATIONS_DEFAULT = true; + public final static boolean SPEECH_DATA_COLLECTION_DEFAULT = false; public final static boolean SERVO_DEFAULT = false; public final static int UA_MODE_DEFAULT = GeckoSessionSettings.USER_AGENT_MODE_VR; public final static int INPUT_MODE_DEFAULT = 1; @@ -66,6 +69,7 @@ SettingsStore getInstance(final @NonNull Context aContext) { public final static int FOVEATED_APP_DEFAULT_LEVEL = 0; public final static int FOVEATED_WEBVR_DEFAULT_LEVEL = 0; private final static long CRASH_RESTART_DELTA = 2000; + public final static boolean AUTOPLAY_ENABLED = false; // Enable telemetry by default (opt-out). private final static boolean enableCrashReportingByDefault = false; @@ -146,6 +150,17 @@ public void setConsoleLogsEnabled(boolean isEnabled) { editor.commit(); } + public boolean isDrmContentPlaybackEnabled() { + return mPrefs.getBoolean( + mContext.getString(R.string.settings_key_drm_playback), DRM_PLAYBACK_DEFAULT); + } + + public void setDrmContentPlaybackEnabled(boolean isEnabled) { + SharedPreferences.Editor editor = mPrefs.edit(); + editor.putBoolean(mContext.getString(R.string.settings_key_drm_playback), isEnabled); + editor.commit(); + } + public boolean isTrackingProtectionEnabled() { return mPrefs.getBoolean( mContext.getString(R.string.settings_key_tracking_protection), TRACKING_DEFAULT); @@ -484,5 +499,27 @@ public synchronized void resetCrashRestartCount() { editor.putLong(mContext.getString(R.string.settings_key_crash_restart_count), 0); editor.commit(); } + + public boolean isSpeechDataCollectionEnabled() { + return mPrefs.getBoolean( + mContext.getString(R.string.settings_key_speech_data_collection), SPEECH_DATA_COLLECTION_DEFAULT); + } + + public void setSpeechDataCollectionEnabled(boolean isEnabled) { + SharedPreferences.Editor editor = mPrefs.edit(); + editor.putBoolean(mContext.getString(R.string.settings_key_speech_data_collection), isEnabled); + editor.commit(); + } + + public boolean isNotificationsEnabled() { + return mPrefs.getBoolean( + mContext.getString(R.string.settings_key_notifications), NOTIFICATIONS_DEFAULT); + } + + public void setNotificationsEnabled(boolean isEnabled) { + SharedPreferences.Editor editor = mPrefs.edit(); + editor.putBoolean(mContext.getString(R.string.settings_key_notifications), isEnabled); + editor.commit(); + } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/NavigationURLBar.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/NavigationURLBar.java index 621fe962a..0e6457be2 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/NavigationURLBar.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/NavigationURLBar.java @@ -14,24 +14,27 @@ import android.util.AttributeSet; import android.util.TypedValue; import android.view.GestureDetector; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.RelativeLayout; +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; + +import org.mozilla.geckoview.GeckoSessionSettings; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.browser.BookmarksStore; import org.mozilla.vrbrowser.browser.SessionStore; +import org.mozilla.vrbrowser.browser.SettingsStore; import org.mozilla.vrbrowser.search.SearchEngineWrapper; import org.mozilla.vrbrowser.telemetry.TelemetryWrapper; +import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.StringUtils; import org.mozilla.vrbrowser.utils.UIThreadExecutor; import org.mozilla.vrbrowser.utils.UrlUtils; @@ -41,7 +44,6 @@ import java.net.URL; import java.net.URLDecoder; -import androidx.annotation.StringRes; import kotlin.Unit; import mozilla.components.browser.domains.autocomplete.DomainAutocompleteResult; import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider; @@ -49,7 +51,8 @@ public class NavigationURLBar extends FrameLayout { private InlineAutocompleteEditText mURL; - private ImageButton mMicrophoneButton; + private UIButton mMicrophoneButton; + private UIButton mUAModeButton; private ImageView mInsecureIcon; private ImageView mLoadingView; private Animation mLoadingAnimation; @@ -61,10 +64,11 @@ public class NavigationURLBar extends FrameLayout { private int mURLWebsiteColor; private NavigationURLBarDelegate mDelegate; private ShippedDomainsProvider mAutocompleteProvider; - private ImageButton mBookmarkButton; + private UIButton mBookmarkButton; private AudioEngine mAudio; private boolean mIsBookmarkMode; private boolean mBookmarkEnabled = true; + private boolean mIsContextButtonsEnabled = true; private UIThreadExecutor mUIThreadExecutor = new UIThreadExecutor(); private Unit domainAutocompleteFilter(String text) { @@ -98,7 +102,6 @@ private void initialize(Context aContext) { mAudio = AudioEngine.fromContext(aContext); // Inflate this data binding layout - LayoutInflater inflater = LayoutInflater.from(aContext); inflate(aContext, R.layout.navigation_url, this); // Use Domain autocomplete provider from components @@ -118,6 +121,7 @@ private void initialize(Context aContext) { mURL.setOnFocusChangeListener((view, focused) -> { showVoiceSearch(!focused || (mURL.getText().length() == 0)); + showContextButtons(!focused && mIsContextButtonsEnabled); mURL.setSelection(mURL.getText().length(), 0); }); @@ -141,6 +145,12 @@ private void initialize(Context aContext) { mMicrophoneButton = findViewById(R.id.microphoneButton); mMicrophoneButton.setTag(R.string.view_id_tag, R.id.microphoneButton); mMicrophoneButton.setOnClickListener(mMicrophoneListener); + + mUAModeButton = findViewById(R.id.uaModeButton); + mUAModeButton.setTag(R.string.view_id_tag, R.id.uaModeButton); + mUAModeButton.setOnClickListener(mUAModeListener); + setUAMode(SettingsStore.getInstance(aContext).getUaMode()); + mURLLeftContainer = findViewById(R.id.urlLeftContainer); mInsecureIcon = findViewById(R.id.insecureIcon); mLoadingView = findViewById(R.id.loadingView); @@ -177,7 +187,6 @@ public void onResume() { if (mIsLoading) { mLoadingView.startAnimation(mLoadingAnimation); } - } public void setDelegate(NavigationURLBarDelegate delegate) { @@ -191,9 +200,12 @@ public void setIsBookmarkMode(boolean isBookmarkMode) { mIsBookmarkMode = isBookmarkMode; if (isBookmarkMode) { mMicrophoneButton.setVisibility(GONE); + mUAModeButton.setVisibility(GONE); mBookmarkButton.setVisibility(GONE); + } else { mMicrophoneButton.setVisibility(VISIBLE); + mUAModeButton.setVisibility(VISIBLE); if (mBookmarkEnabled) { mBookmarkButton.setVisibility(VISIBLE); } @@ -201,17 +213,6 @@ public void setIsBookmarkMode(boolean isBookmarkMode) { syncViews(); } - private void setBookmarkEnabled(boolean aEnabled) { - if (mBookmarkEnabled != aEnabled) { - mBookmarkEnabled = aEnabled; - mBookmarkButton.setVisibility(aEnabled ? View.VISIBLE : View.GONE); - ViewGroup.LayoutParams params = mMicrophoneButton.getLayoutParams(); - params.width = (int) getResources().getDimension(aEnabled ? R.dimen.url_bar_item_width : R.dimen.url_bar_last_item_width); - mMicrophoneButton.setLayoutParams(params); - mMicrophoneButton.setBackgroundResource(aEnabled ? R.drawable.url_button : R.drawable.url_button_end); - } - } - private void handleBookmarkClick() { if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); @@ -292,12 +293,17 @@ else if (aURL.startsWith("data:") && SessionStore.get().isCurrentSessionPrivate( mURL.setText(aURL); } } - setBookmarkEnabled(aURL.length() > 0 && !aURL.startsWith("about://")); + mIsContextButtonsEnabled = aURL.length() > 0 && !aURL.startsWith("about://"); + showContextButtons(mIsContextButtonsEnabled); } mURL.addTextChangedListener(mURLTextWatcher); } + private boolean isEmptyUrl(@NonNull String aURL) { + return aURL.length() == 0 || aURL.startsWith("about://"); + } + public String getText() { return mURL.getText().toString(); } @@ -330,32 +336,48 @@ public void setIsLoading(boolean aIsLoading) { } } + public void setUAMode(int uaMode) { + if (uaMode == GeckoSessionSettings.USER_AGENT_MODE_DESKTOP) { + mUAModeButton.setImageResource(R.drawable.ic_icon_ua_desktop); + + } else { + mUAModeButton.setImageResource(R.drawable.ic_icon_ua_default); + } + } + + private void showContextButtons(boolean aEnabled) { + if (mBookmarkEnabled != aEnabled) { + mBookmarkEnabled = aEnabled; + } + + if (aEnabled) { + mMicrophoneButton.setBackgroundResource(R.drawable.url_button); + mMicrophoneButton.getLayoutParams().width = (int)getContext().getResources().getDimension(R.dimen.url_bar_item_width); + mBookmarkButton.setVisibility(VISIBLE); + mUAModeButton.setVisibility(VISIBLE); + + } else { + mMicrophoneButton.setBackgroundResource(R.drawable.url_button_end); + mMicrophoneButton.getLayoutParams().width = (int)getContext().getResources().getDimension(R.dimen.url_bar_last_item_width); + mBookmarkButton.setVisibility(GONE); + mUAModeButton.setVisibility(GONE); + } + } + public void showVoiceSearch(boolean enabled) { if (enabled) { - if (mBookmarkEnabled) { - mMicrophoneButton.setBackgroundResource(R.drawable.url_button); - mMicrophoneButton.getLayoutParams().width = (int)getContext().getResources().getDimension(R.dimen.url_bar_item_width); - } + mURL.setPadding(mURL.getPaddingStart(), mURL.getPaddingTop(), WidgetPlacement.convertDpToPixel(getContext(), 100), mURL.getPaddingBottom()); + mMicrophoneButton.setImageResource(R.drawable.ic_icon_microphone); + mMicrophoneButton.setTooltip(getResources().getString(R.string.voice_search_tooltip)); mMicrophoneButton.setOnClickListener(mMicrophoneListener); - if (mIsBookmarkMode) { - mMicrophoneButton.setVisibility(GONE); - } else if (mBookmarkEnabled) { - mBookmarkButton.setVisibility(VISIBLE); - } - } else if (mURL.hasFocus()){ + mURL.setPadding(mURL.getPaddingStart(), mURL.getPaddingTop(), WidgetPlacement.convertDpToPixel(getContext(), 40), mURL.getPaddingBottom()); + mMicrophoneButton.setImageResource(R.drawable.ic_icon_clear); - mMicrophoneButton.setBackgroundResource(R.drawable.url_button_end); - mMicrophoneButton.getLayoutParams().width = (int)getContext().getResources().getDimension(R.dimen.url_bar_last_item_width); + mMicrophoneButton.setTooltip(getResources().getString(R.string.clear_tooltip)); mMicrophoneButton.setOnClickListener(mClearListener); - - if (mIsBookmarkMode) { - mMicrophoneButton.setVisibility(VISIBLE); - } - - mBookmarkButton.setVisibility(GONE); } } @@ -447,6 +469,26 @@ public void setClickable(boolean clickable) { TelemetryWrapper.voiceInputEvent(); }; + private OnClickListener mUAModeListener = view -> { + if (mAudio != null) { + mAudio.playSound(AudioEngine.Sound.CLICK); + } + + view.requestFocusFromTouch(); + + int uaMode = SessionStore.get().getUaMode(); + if (uaMode == GeckoSessionSettings.USER_AGENT_MODE_VR) { + setUAMode(GeckoSessionSettings.USER_AGENT_MODE_DESKTOP); + SessionStore.get().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_DESKTOP); + + }else { + setUAMode(GeckoSessionSettings.USER_AGENT_MODE_VR); + SessionStore.get().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_VR); + } + + TelemetryWrapper.voiceInputEvent(); + }; + private OnClickListener mClearListener = view -> { if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); @@ -463,12 +505,9 @@ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { - if (mURL.getText().length() > 0) { - showVoiceSearch(false); - - } else { - showVoiceSearch(true); - } + String aURL = mURL.getText().toString(); + showVoiceSearch(isEmptyUrl(aURL)); + showContextButtons(isEmptyUrl(aURL) && mIsContextButtonsEnabled); } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/settings/SwitchSetting.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/settings/SwitchSetting.java index 6c67fe899..7919b1fff 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/settings/SwitchSetting.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/settings/SwitchSetting.java @@ -9,9 +9,12 @@ import android.widget.Switch; import android.widget.TextView; +import androidx.annotation.NonNull; + import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.ui.views.UIButton; +import org.mozilla.vrbrowser.utils.ViewUtils; public class SwitchSetting extends LinearLayout { @@ -38,6 +41,10 @@ public SwitchSetting(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.SwitchSetting, defStyleAttr, 0); mText = attributes.getString(R.styleable.SwitchSetting_description); + int onResId = attributes.getResourceId(R.styleable.SwitchSetting_on_text, R.string.on); + mOnText = getResources().getString(onResId); + int offResId = attributes.getResourceId(R.styleable.SwitchSetting_off_text, R.string.off); + mOffText = getResources().getString(offResId); attributes.recycle(); initialize(context); @@ -47,8 +54,6 @@ private void initialize(Context aContext) { inflate(aContext, R.layout.setting_switch, this); mAudio = AudioEngine.fromContext(aContext); - mOnText = aContext.getString(R.string.on); - mOffText = aContext.getString(R.string.off); mSwitchDescription = findViewById(R.id.setting_description); mSwitchDescription.setText(mText); @@ -72,8 +77,11 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean b) { } }; - public void setValue(boolean value, boolean doApply) { + public void setLinkClickListner(@NonNull ViewUtils.LinkClickableSpan listener) { + ViewUtils.setTextViewHTML(mSwitchDescription, mText, (widget, url) -> listener.onClick(widget, url)); + } + public void setValue(boolean value, boolean doApply) { mSwitch.setOnCheckedChangeListener(null); mSwitch.setChecked(value); mSwitch.setOnCheckedChangeListener(mInternalSwitchListener); @@ -97,7 +105,6 @@ public void setChecked(boolean value) { updateSwitchText(); } - public String getDescription() { return mSwitchDescription.getText().toString(); } @@ -106,16 +113,6 @@ private void updateSwitchText() { mSwitchText.setText(mSwitch.isChecked() ? mOnText : mOffText); } - public void setOnText(String aText) { - mOnText = aText; - updateSwitchText(); - } - - public void setOffText(String aText) { - mOffText = aText; - updateSwitchText(); - } - public void setHelpDelegate(Runnable aDelegate) { if (aDelegate != null) { mHelpButton.setVisibility(View.VISIBLE); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java index 008db13b7..766073765 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java @@ -132,13 +132,10 @@ private void initialize(Context aContext) { mResizeBackHandler = () -> exitResizeMode(true); mFullScreenBackHandler = this::exitFullScreenMode; - mVRVideoBackHandler = new Runnable() { - @Override - public void run() { - exitVRVideo(); - if (mAutoEnteredVRVideo) { - exitFullScreenMode(); - } + mVRVideoBackHandler = () -> { + exitVRVideo(); + if (mAutoEnteredVRVideo) { + exitFullScreenMode(); } }; @@ -924,6 +921,9 @@ public void OnVoiceSearchError() { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key == mAppContext.getString(R.string.settings_key_servo)) { updateServoButton(); + + } else if (key == mAppContext.getString(R.string.settings_key_user_agent_version)) { + mURLBar.setUAMode(SettingsStore.getInstance(getContext()).getUaMode()); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TrayWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TrayWidget.java index 8a033bb04..1815b6190 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TrayWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TrayWidget.java @@ -29,7 +29,6 @@ public class TrayWidget extends UIWidget implements SessionStore.SessionChangeLi static final String LOGTAG = "VRB"; private static final int ICON_ANIMATION_DURATION = 200; - private UIButton mHelpButton; private UIButton mSettingsButton; private UIButton mPrivateButton; private UIButton mBookmarksButton; @@ -65,17 +64,6 @@ private void initialize(Context aContext) { mMinPadding = WidgetPlacement.pixelDimension(getContext(), R.dimen.tray_icon_padding_min); mMaxPadding = WidgetPlacement.pixelDimension(getContext(), R.dimen.tray_icon_padding_max); - mHelpButton = findViewById(R.id.helpButton); - mHelpButton.setOnHoverListener(mButtonScaleHoverListener); - mHelpButton.setOnClickListener(view -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } - - onHelpButtonClicked(); - view.requestFocusFromTouch(); - }); - mPrivateButton = findViewById(R.id.privateButton); mPrivateButton.setOnHoverListener(mButtonScaleHoverListener); mPrivateButton.setOnClickListener(view -> { @@ -317,16 +305,6 @@ public boolean isDialogOpened(int aHandle) { return false; } - private void onHelpButtonClicked() { - GeckoSession session = SessionStore.get().getCurrentSession(); - if (session == null) { - int sessionId = SessionStore.get().createSession(); - SessionStore.get().setCurrentSession(sessionId); - } - - SessionStore.get().loadUri(getContext().getString(R.string.help_url)); - } - // BookmarkListener @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java index 69a3c0375..6f08efa4e 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java @@ -89,8 +89,9 @@ private void initialize(Context aContext) { mMozillaSpeechService = MozillaSpeechService.getInstance(); mMozillaSpeechService.setProductTag(getContext().getString(R.string.voice_app_id)); - mMozillaSpeechService.storeSamples(false); - mMozillaSpeechService.storeTranscriptions(false); + boolean storeData = SettingsStore.getInstance(aContext).isSpeechDataCollectionEnabled(); + mMozillaSpeechService.storeSamples(storeData); + mMozillaSpeechService.storeTranscriptions(storeData); mVoiceSearchText1 = findViewById(R.id.voiceSearchText1); mVoiceSearchText2 = findViewById(R.id.voiceSearchText2); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ControllerOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ControllerOptionsView.java index e2efd1f5b..b3e475c5d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ControllerOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ControllerOptionsView.java @@ -22,7 +22,6 @@ class ControllerOptionsView extends SettingsView { private RadioGroupSetting mPointerColorRadio; private RadioGroupSetting mScrollDirectionRadio; private ButtonSetting mResetButton; - private ScrollView mScrollbar; public ControllerOptionsView(Context aContext, WidgetManagerDelegate aWidgetManager) { super(aContext, aWidgetManager); @@ -57,12 +56,6 @@ private void initialize(Context aContext) { mResetButton.setOnClickListener(v -> resetOptions()); } - @Override - public void onShown() { - super.onShown(); - mScrollbar.scrollTo(0, 0); - } - private void resetOptions() { if (!mPointerColorRadio.getValueForId(mPointerColorRadio.getCheckedRadioButtonId()).equals(SettingsStore.POINTER_COLOR_DEFAULT_DEFAULT)) { setPointerColor(mPointerColorRadio.getIdForValue(SettingsStore.POINTER_COLOR_DEFAULT_DEFAULT), true); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DeveloperOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DeveloperOptionsView.java index 4d04317c6..d38e7c248 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DeveloperOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DeveloperOptionsView.java @@ -7,7 +7,6 @@ import android.content.Context; import android.view.View; -import android.widget.ScrollView; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; @@ -15,7 +14,6 @@ import org.mozilla.vrbrowser.browser.SettingsStore; import org.mozilla.vrbrowser.ui.views.UIButton; import org.mozilla.vrbrowser.ui.views.settings.ButtonSetting; -import org.mozilla.vrbrowser.ui.views.settings.SingleEditSetting; import org.mozilla.vrbrowser.ui.views.settings.SwitchSetting; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; @@ -29,10 +27,7 @@ class DeveloperOptionsView extends SettingsView { private SwitchSetting mMultiprocessSwitch; private SwitchSetting mPerformanceSwitch; private SwitchSetting mServoSwitch; - private SingleEditSetting mHomepageEdit; - private String mDefaultHomepageUrl; private ButtonSetting mResetButton; - private ScrollView mScrollbar; public DeveloperOptionsView(Context aContext, WidgetManagerDelegate aWidgetManager) { super(aContext, aWidgetManager); @@ -53,15 +48,6 @@ private void initialize(Context aContext) { onDismiss(); }); - mDefaultHomepageUrl = getContext().getString(R.string.homepage_url); - - mHomepageEdit = findViewById(R.id.homepage_edit); - mHomepageEdit.setHint1(getContext().getString(R.string.homepage_hint, getContext().getString(R.string.app_name))); - mHomepageEdit.setDefaultFirstValue(mDefaultHomepageUrl); - mHomepageEdit.setFirstText(SettingsStore.getInstance(getContext()).getHomepage()); - mHomepageEdit.setOnClickListener(mHomepageListener); - setHomepage(SettingsStore.getInstance(getContext()).getHomepage()); - mRemoteDebuggingSwitch = findViewById(R.id.remote_debugging_switch); mRemoteDebuggingSwitch.setOnCheckedChangeListener(mRemoteDebuggingListener); setRemoteDebugging(SettingsStore.getInstance(getContext()).isRemoteDebuggingEnabled(), false); @@ -92,37 +78,6 @@ private void initialize(Context aContext) { mScrollbar = findViewById(R.id.scrollbar); } - @Override - public void onShown() { - super.onShown(); - mScrollbar.scrollTo(0, 0); - } - - @Override - public void onHidden() { - super.onHidden(); - mHomepageEdit.cancel(); - } - - @Override - protected void onDismiss() { - if (mHomepageEdit.isEditing()) { - mHomepageEdit.cancel(); - - } else { - super.onDismiss(); - } - } - - private OnClickListener mHomepageListener = (view) -> { - if (!mHomepageEdit.getFirstText().isEmpty()) { - setHomepage(mHomepageEdit.getFirstText()); - - } else { - setHomepage(mDefaultHomepageUrl); - } - }; - private SwitchSetting.OnCheckedChangeListener mRemoteDebuggingListener = (compoundButton, value, doApply) -> { setRemoteDebugging(value, doApply); }; @@ -159,20 +114,12 @@ protected void onDismiss() { if (mServoSwitch.isChecked() != SettingsStore.SERVO_DEFAULT) { setServo(SettingsStore.SERVO_DEFAULT, true); } - setHomepage(mDefaultHomepageUrl); if (restart && mDelegate != null) { showRestartDialog(); } }; - private void setHomepage(String newHomepage) { - mHomepageEdit.setOnClickListener(null); - mHomepageEdit.setFirstText(newHomepage); - SettingsStore.getInstance(getContext()).setHomepage(newHomepage); - mHomepageEdit.setOnClickListener(mHomepageListener); - } - private void setRemoteDebugging(boolean value, boolean doApply) { mRemoteDebuggingSwitch.setOnCheckedChangeListener(null); mRemoteDebuggingSwitch.setValue(value, doApply); @@ -229,13 +176,4 @@ private void setServo(boolean value, boolean doApply) { } } - @Override - public void onGlobalFocusChanged(View oldFocus, View newFocus) { - if (oldFocus != null) { - if (mHomepageEdit.contains(oldFocus) && mHomepageEdit.isEditing()) { - mHomepageEdit.cancel(); - } - } - } - } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayOptionsView.java index 89f0ccbe1..2c2368cfe 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayOptionsView.java @@ -6,14 +6,14 @@ package org.mozilla.vrbrowser.ui.widgets.settings; import android.content.Context; +import android.graphics.Point; import android.view.View; -import android.widget.ScrollView; +import org.mozilla.vrbrowser.BuildConfig; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.browser.SessionStore; import org.mozilla.vrbrowser.browser.SettingsStore; -import org.mozilla.vrbrowser.BuildConfig; import org.mozilla.vrbrowser.ui.views.UIButton; import org.mozilla.vrbrowser.ui.views.settings.ButtonSetting; import org.mozilla.vrbrowser.ui.views.settings.DoubleEditSetting; @@ -21,6 +21,7 @@ import org.mozilla.vrbrowser.ui.views.settings.SingleEditSetting; import org.mozilla.vrbrowser.ui.views.settings.SwitchSetting; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; +import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.DeviceType; class DisplayOptionsView extends SettingsView { @@ -29,6 +30,8 @@ class DisplayOptionsView extends SettingsView { private SwitchSetting mCurvedDisplaySwitch; private RadioGroupSetting mUaModeRadio; private RadioGroupSetting mMSAARadio; + private SwitchSetting mAutoplaySetting; + private SingleEditSetting mHomepageEdit; private RadioGroupSetting mFoveatedAppRadio; private RadioGroupSetting mFoveatedWebVRRadio; private SingleEditSetting mDensityEdit; @@ -36,14 +39,13 @@ class DisplayOptionsView extends SettingsView { private DoubleEditSetting mWindowSizeEdit; private DoubleEditSetting mMaxWindowSizeEdit; private ButtonSetting mResetButton; - private ScrollView mScrollbar; + private String mDefaultHomepageUrl; public DisplayOptionsView(Context aContext, WidgetManagerDelegate aWidgetManager) { super(aContext, aWidgetManager); initialize(aContext); } - private void initialize(Context aContext) { inflate(aContext, R.layout.options_display, this); @@ -72,6 +74,19 @@ private void initialize(Context aContext) { mMSAARadio.setOnCheckedChangeListener(mMSSAChangeListener); setMSAAMode(mMSAARadio.getIdForValue(msaaLevel), false); + mAutoplaySetting = findViewById(R.id.autoplaySwitch); + mAutoplaySetting.setOnCheckedChangeListener(mAutoplayListener); + setAutoplay(SessionStore.get().getAutoplayEnabled(), false); + + mDefaultHomepageUrl = getContext().getString(R.string.homepage_url); + + mHomepageEdit = findViewById(R.id.homepage_edit); + mHomepageEdit.setHint1(getContext().getString(R.string.homepage_hint, getContext().getString(R.string.app_name))); + mHomepageEdit.setDefaultFirstValue(mDefaultHomepageUrl); + mHomepageEdit.setFirstText(SettingsStore.getInstance(getContext()).getHomepage()); + mHomepageEdit.setOnClickListener(mHomepageListener); + setHomepage(SettingsStore.getInstance(getContext()).getHomepage()); + mFoveatedAppRadio = findViewById(R.id.foveated_app_radio); mFoveatedWebVRRadio = findViewById(R.id.foveated_webvr_radio); if (BuildConfig.FLAVOR_platform == "oculusvr" || @@ -135,49 +150,50 @@ private void initialize(Context aContext) { } @Override - public void onShown() { - super.onShown(); - mScrollbar.scrollTo(0, 0); + public void onHidden() { + if (!isEditing()) { + super.onHidden(); + } } @Override - public void onHidden() { - super.onHidden(); - mDensityEdit.cancel(); - mDpiEdit.cancel(); - mWindowSizeEdit.cancel(); - mMaxWindowSizeEdit.cancel(); + protected void onDismiss() { + if (!isEditing()) { + super.onDismiss(); + } } @Override - protected void onDismiss() { - boolean dismiss = true; + public boolean isEditing() { + boolean editing = false; if (mDensityEdit.isEditing()) { - dismiss = false; + editing = true; mDensityEdit.cancel(); } if (mDpiEdit.isEditing()) { - dismiss = false; + editing = true; mDpiEdit.cancel(); } if (mWindowSizeEdit.isEditing()) { - dismiss = false; + editing = true; mWindowSizeEdit.cancel(); } if (mMaxWindowSizeEdit.isEditing()) { - dismiss = false; + editing = true; mMaxWindowSizeEdit.cancel(); } - if (dismiss) { - super.onDismiss(); + if (mHomepageEdit.isEditing()) { + editing = true; + mHomepageEdit.cancel(); } - } + return editing; + } private RadioGroupSetting.OnCheckedChangeListener mUaModeListener = (radioGroup, checkedId, doApply) -> { setUaMode(checkedId, true); @@ -187,6 +203,19 @@ protected void onDismiss() { setMSAAMode(checkedId, true); }; + private SwitchSetting.OnCheckedChangeListener mAutoplayListener = (compoundButton, enabled, apply) -> { + setAutoplay(enabled, true); + }; + + private OnClickListener mHomepageListener = (view) -> { + if (!mHomepageEdit.getFirstText().isEmpty()) { + setHomepage(mHomepageEdit.getFirstText()); + + } else { + setHomepage(mDefaultHomepageUrl); + } + }; + private OnClickListener mDensityListener = (view) -> { try { float newDensity = Float.parseFloat(mDensityEdit.getFirstText()); @@ -272,10 +301,30 @@ protected void onDismiss() { setMaxWindowSize(SettingsStore.MAX_WINDOW_WIDTH_DEFAULT, SettingsStore.MAX_WINDOW_HEIGHT_DEFAULT, true); } + setHomepage(mDefaultHomepageUrl); + setAutoplay(SettingsStore.AUTOPLAY_ENABLED, true); + if (restart) showRestartDialog(); }; + private void setAutoplay(boolean value, boolean doApply) { + mAutoplaySetting.setOnCheckedChangeListener(null); + mAutoplaySetting.setValue(value, false); + mAutoplaySetting.setOnCheckedChangeListener(mAutoplayListener); + + if (doApply) { + SessionStore.get().setAutoplayEnabled(value); + } + } + + private void setHomepage(String newHomepage) { + mHomepageEdit.setOnClickListener(null); + mHomepageEdit.setFirstText(newHomepage); + SettingsStore.getInstance(getContext()).setHomepage(newHomepage); + mHomepageEdit.setOnClickListener(mHomepageListener); + } + private void setUaMode(int checkId, boolean doApply) { mUaModeRadio.setOnCheckedChangeListener(null); mUaModeRadio.setChecked(checkId, doApply); @@ -449,7 +498,16 @@ public void onGlobalFocusChanged(View oldFocus, View newFocus) { mMaxWindowSizeEdit.isEditing()) { mMaxWindowSizeEdit.cancel(); } + if (mHomepageEdit.contains(oldFocus) && mHomepageEdit.isEditing()) { + mHomepageEdit.cancel(); + } } } + @Override + public Point getDimensions() { + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.display_options_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.display_options_height)); + } + } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/EnvironmentOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/EnvironmentOptionsView.java index 19a166daf..19151af49 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/EnvironmentOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/EnvironmentOptionsView.java @@ -25,7 +25,6 @@ class EnvironmentOptionsView extends SettingsView { private SwitchSetting mEnvOverrideSwitch; private ImageRadioGroupSetting mEnvironmentsRadio; private ButtonSetting mResetButton; - private ScrollView mScrollbar; public EnvironmentOptionsView(Context aContext, WidgetManagerDelegate aWidgetManager) { super(aContext, aWidgetManager); @@ -68,14 +67,6 @@ private void initialize(Context aContext) { mScrollbar = findViewById(R.id.scrollbar); } - @Override - public void onShown() { - super.onShown(); - - mScrollbar.scrollTo(0, 0); - mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_NO_DIM_BRIGHTNESS); - } - @Override public void onHidden() { mWidgetManager.popWorldBrightness(this); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java index 67c18b621..16cd87a60 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java @@ -6,14 +6,16 @@ package org.mozilla.vrbrowser.ui.widgets.settings; import android.Manifest; +import android.app.Activity; +import android.app.Application; import android.content.Context; +import android.graphics.Point; +import android.os.Bundle; import android.util.Pair; import android.view.View; -import android.widget.ScrollView; import android.widget.TextView; import org.mozilla.geckoview.GeckoSession; -import org.mozilla.vrbrowser.BuildConfig; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.browser.SessionStore; @@ -22,6 +24,7 @@ import org.mozilla.vrbrowser.ui.views.settings.ButtonSetting; import org.mozilla.vrbrowser.ui.views.settings.SwitchSetting; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; +import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.DeviceType; import java.util.ArrayList; @@ -29,12 +32,14 @@ class PrivacyOptionsView extends SettingsView { private AudioEngine mAudio; private UIButton mBackButton; + private SwitchSetting mDrmContentPlaybackSwitch; private SwitchSetting mTrackingSetting; - private SwitchSetting mAutoplaySetting; + private SwitchSetting mNotificationsPermissionSwitch; private ButtonSetting mResetButton; - private ArrayList> mPermissionButtons; - private int mAlertDialogHandle; - private ScrollView mScrollbar; + private ArrayList> mPermissionButtons; + private SwitchSetting mSpeechDataSwitch; + private SwitchSetting mTelemetryDataSwitch; + private SwitchSetting mCrashreportsDataSwitch; public PrivacyOptionsView(Context aContext, WidgetManagerDelegate aWidgetManager) { super(aContext, aWidgetManager); @@ -45,6 +50,8 @@ private void initialize(Context aContext) { inflate(aContext, R.layout.options_privacy, this); mAudio = AudioEngine.fromContext(aContext); + ((Application)aContext.getApplicationContext()).registerActivityLifecycleCallbacks(mLifeCycleListener); + mBackButton = findViewById(R.id.backButton); mBackButton.setOnClickListener(view -> { if (mAudio != null) { @@ -70,67 +77,78 @@ private void initialize(Context aContext) { exitWholeSettings(); }); - mTrackingSetting = findViewById(R.id.trackingProtectionButton); + mDrmContentPlaybackSwitch = findViewById(R.id.drmContentPlaybackSwitch); + mDrmContentPlaybackSwitch.setChecked(SettingsStore.getInstance(getContext()).isDrmContentPlaybackEnabled()); + mDrmContentPlaybackSwitch.setOnCheckedChangeListener((compoundButton, enabled, apply) -> { + SettingsStore.getInstance(getContext()).setDrmContentPlaybackEnabled(enabled); + // TODO Enable/Disable DRM content playback + }); + mDrmContentPlaybackSwitch.setLinkClickListner((widget, url) -> { + SessionStore.get().loadUri(url); + exitWholeSettings(); + }); + + mTrackingSetting = findViewById(R.id.trackingProtectionSwitch); mTrackingSetting.setChecked(SettingsStore.getInstance(getContext()).isTrackingProtectionEnabled()); mTrackingSetting.setOnCheckedChangeListener((compoundButton, enabled, apply) -> { SettingsStore.getInstance(getContext()).setTrackingProtectionEnabled(enabled); SessionStore.get().setTrackingProtection(enabled); }); - mAutoplaySetting = findViewById(R.id.autoplaySwitch); - mAutoplaySetting.setChecked(SessionStore.get().getAutoplayEnabled()); - mAutoplaySetting.setOnCheckedChangeListener((compoundButton, enabled, apply) -> { - SessionStore.get().setAutoplayEnabled(enabled); - }); - TextView permissionsTitleText = findViewById(R.id.permissionsTitle); permissionsTitleText.setText(getContext().getString(R.string.security_options_permissions_title, getContext().getString(R.string.app_name))); mPermissionButtons = new ArrayList<>(); - mPermissionButtons.add(Pair.create(findViewById(R.id.cameraPermissionButton), Manifest.permission.CAMERA)); - mPermissionButtons.add(Pair.create(findViewById(R.id.microphonePermissionButton), Manifest.permission.RECORD_AUDIO)); - mPermissionButtons.add(Pair.create(findViewById(R.id.locationPermissionButton), Manifest.permission.ACCESS_FINE_LOCATION)); - mPermissionButtons.add(Pair.create(findViewById(R.id.storagePermissionButton), Manifest.permission.READ_EXTERNAL_STORAGE)); + mPermissionButtons.add(Pair.create(findViewById(R.id.cameraPermissionSwitch), Manifest.permission.CAMERA)); + mPermissionButtons.add(Pair.create(findViewById(R.id.microphonePermissionSwitch), Manifest.permission.RECORD_AUDIO)); + mPermissionButtons.add(Pair.create(findViewById(R.id.locationPermissionSwitch), Manifest.permission.ACCESS_FINE_LOCATION)); + mPermissionButtons.add(Pair.create(findViewById(R.id.storagePermissionSwitch), Manifest.permission.READ_EXTERNAL_STORAGE)); if (DeviceType.isOculusBuild()) { - findViewById(R.id.cameraPermissionButton).setVisibility(View.GONE); + findViewById(R.id.cameraPermissionSwitch).setVisibility(View.GONE); } - for (Pair button: mPermissionButtons) { - if (mWidgetManager.isPermissionGranted(button.second)) { - button.first.setShowAsLabel(true); - button.first.setButtonText(getContext().getString(R.string.permission_enabled)); - } - button.first.setOnClickListener(v -> { - togglePermission(button.first, button.second); - }); + for (Pair button: mPermissionButtons) { + button.first.setChecked(mWidgetManager.isPermissionGranted(button.second)); + button.first.setOnCheckedChangeListener((compoundButton, enabled, apply) -> + togglePermission(button.first, button.second)); } + mNotificationsPermissionSwitch = findViewById(R.id.notificationsPermissionSwitch); + mNotificationsPermissionSwitch.setChecked(SettingsStore.getInstance(getContext()).isNotificationsEnabled()); + mNotificationsPermissionSwitch.setOnCheckedChangeListener((compoundButton, enabled, apply) -> { + SettingsStore.getInstance(getContext()).setNotificationsEnabled(enabled); + }); - mResetButton = findViewById(R.id.resetButton); - mResetButton.setOnClickListener(v -> resetOptions()); - } + mSpeechDataSwitch = findViewById(R.id.speechDataSwitch); + mSpeechDataSwitch.setChecked(SettingsStore.getInstance(getContext()).isSpeechDataCollectionEnabled()); + mSpeechDataSwitch.setOnCheckedChangeListener((compoundButton, enabled, apply) -> + SettingsStore.getInstance(getContext()).setSpeechDataCollectionEnabled(enabled)); - @Override - public void onShown() { - super.onShown(); - mScrollbar.scrollTo(0, 0); - } + mTelemetryDataSwitch = findViewById(R.id.telemetryDataSwitch); + mTelemetryDataSwitch.setChecked(SettingsStore.getInstance(getContext()).isTelemetryEnabled()); + mTelemetryDataSwitch.setOnCheckedChangeListener((compoundButton, enabled, apply) -> + SettingsStore.getInstance(getContext()).setTelemetryEnabled(enabled)); - @Override - public void onHidden() { - super.onHidden(); + mCrashreportsDataSwitch = findViewById(R.id.crashReportsDataSwitch); + mCrashreportsDataSwitch.setChecked(SettingsStore.getInstance(getContext()).isCrashReportingEnabled()); + mCrashreportsDataSwitch.setOnCheckedChangeListener((compoundButton, enabled, apply) -> + SettingsStore.getInstance(getContext()).setCrashReportingEnabled(enabled)); + + mResetButton = findViewById(R.id.resetButton); + mResetButton.setOnClickListener(v -> resetOptions()); } - private void togglePermission(ButtonSetting aButton, String aPermission) { + private void togglePermission(SwitchSetting aButton, String aPermission) { if (mWidgetManager.isPermissionGranted(aPermission)) { showAlert(aButton.getDescription(), getContext().getString(R.string.security_options_permissions_reject_message)); + aButton.setChecked(true); + } else { mWidgetManager.requestPermission("", aPermission, new GeckoSession.PermissionDelegate.Callback() { @Override public void grant() { - aButton.setShowAsLabel(true); - aButton.setButtonText(getContext().getString(R.string.permission_enabled)); + aButton.setChecked(true); } @Override public void reject() { @@ -145,4 +163,58 @@ private void resetOptions() { mTrackingSetting.setChecked(SettingsStore.TRACKING_DEFAULT); } } + + @Override + public Point getDimensions() { + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.privacy_options_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.privacy_options_height)); + } + + @Override + public void releasePointerCapture() { + super.releasePointerCapture(); + ((Application)getContext().getApplicationContext()).unregisterActivityLifecycleCallbacks(mLifeCycleListener); + } + + private Application.ActivityLifecycleCallbacks mLifeCycleListener = new Application.ActivityLifecycleCallbacks() { + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + + } + + @Override + public void onActivityStarted(Activity activity) { + + } + + @Override + public void onActivityResumed(Activity activity) { + // Refresh permission settings status after a permission has been requested + for (Pair button: mPermissionButtons) { + button.first.setValue(mWidgetManager.isPermissionGranted(button.second), false); + } + } + + @Override + public void onActivityPaused(Activity activity) { + + } + + @Override + public void onActivityStopped(Activity activity) { + + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + + } + + @Override + public void onActivityDestroyed(Activity activity) { + + } + }; + } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsView.java index 382161145..84fde3a78 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsView.java @@ -1,17 +1,22 @@ package org.mozilla.vrbrowser.ui.widgets.settings; import android.content.Context; +import android.graphics.Point; import android.view.View; import android.widget.FrameLayout; +import android.widget.ScrollView; import androidx.annotation.NonNull; +import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.ui.widgets.UIWidget; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; +import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; abstract class SettingsView extends FrameLayout { protected Delegate mDelegate; protected WidgetManagerDelegate mWidgetManager; + protected ScrollView mScrollbar; public interface Delegate { void onDismiss(); @@ -58,6 +63,9 @@ protected boolean isVisible() { } public void onShown() { + if (mScrollbar != null) + mScrollbar.scrollTo(0, 0); + setFocusableInTouchMode(true); requestFocusFromTouch(); } @@ -66,5 +74,14 @@ public void onHidden() { clearFocus(); } + public boolean isEditing() { + return false; + } + public void onGlobalFocusChanged(View oldFocus, View newFocus) {} + + public Point getDimensions() { + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.developer_options_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.developer_options_height)); + } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java index add3baae3..e1581070f 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java @@ -8,6 +8,7 @@ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.graphics.Point; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; @@ -24,9 +25,7 @@ import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.browser.SessionStore; -import org.mozilla.vrbrowser.browser.SettingsStore; import org.mozilla.vrbrowser.ui.views.HoneycombButton; -import org.mozilla.vrbrowser.ui.views.HoneycombSwitch; import org.mozilla.vrbrowser.ui.widgets.UIWidget; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; @@ -45,7 +44,7 @@ public class SettingsWidget extends UIDialog implements WidgetManagerDelegate.Wo private AudioEngine mAudio; private SettingsView mCurrentView; private TextView mBuildText; - private LinearLayout mMainLayout; + private ViewGroup mMainLayout; private int mViewMarginH; private int mViewMarginV; private int mRestartDialogHandle = -1; @@ -86,8 +85,7 @@ private void initialize(Context aContext) { mWidgetManager.addWorldClickListener(this); mMainLayout = findViewById(R.id.optionsLayout); - ImageButton cancelButton = findViewById(R.id.settingsCancelButton); - + ImageButton cancelButton = findViewById(R.id.backButton); cancelButton.setOnClickListener(v -> { if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); @@ -96,6 +94,12 @@ private void initialize(Context aContext) { onDismiss(); }); + LinearLayout reportIssue = findViewById(R.id.reportIssueLayout); + reportIssue.setOnClickListener(v -> { + SessionStore.get().loadUri(getContext().getString(R.string.bug_report_url)); + onDismiss(); + }); + HoneycombButton languageButton = findViewById(R.id.languageButton); languageButton.setOnClickListener(view -> { if (mAudio != null) { @@ -114,26 +118,6 @@ private void initialize(Context aContext) { onSettingsPrivacyClick(); }); - HoneycombSwitch crashSwitch = findViewById(R.id.crashReportingSwitch); - crashSwitch.setChecked(SettingsStore.getInstance(getContext()).isCrashReportingEnabled()); - crashSwitch.setOnCheckedChangeListener((compoundButton, b) -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } - - onSettingsCrashReportingChange(b); - }); - - HoneycombSwitch telemetrySwitch = findViewById(R.id.telemetry_switch); - telemetrySwitch.setChecked(SettingsStore.getInstance(getContext()).isTelemetryEnabled()); - telemetrySwitch.setOnCheckedChangeListener((compoundButton, b) -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } - - onSettingsTelemetryChange(b); - }); - HoneycombButton displayButton = findViewById(R.id.displayButton); displayButton.setOnClickListener(view -> { if (mAudio != null) { @@ -173,7 +157,7 @@ private void initialize(Context aContext) { return view.performClick(); }); - HoneycombButton reportButton = findViewById(R.id.reportButton); + HoneycombButton reportButton = findViewById(R.id.helpButton); reportButton.setOnClickListener(view -> { if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); @@ -228,15 +212,6 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_z); } - private void onSettingsCrashReportingChange(boolean isEnabled) { - SettingsStore.getInstance(getContext()).setCrashReportingEnabled(isEnabled); - } - - private void onSettingsTelemetryChange(boolean isEnabled) { - SettingsStore.getInstance(getContext()).setTelemetryEnabled(isEnabled); - // TODO: Waiting for Telemetry to be merged - } - private void onSettingsPrivacyClick() { showView(new PrivacyOptionsView(getContext(), mWidgetManager)); } @@ -327,9 +302,15 @@ private void showView(SettingsView aView) { } mCurrentView = aView; if (mCurrentView != null) { + Point viewDimensions = mCurrentView.getDimensions(); + mViewMarginH = mWidgetPlacement.width - viewDimensions.x; + mViewMarginH = WidgetPlacement.convertDpToPixel(getContext(), mViewMarginH); + mViewMarginV = mWidgetPlacement.height - viewDimensions.y; + mViewMarginV = WidgetPlacement.convertDpToPixel(getContext(), mViewMarginV); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); params.leftMargin = params.rightMargin = mViewMarginH / 2; - params.topMargin = params.bottomMargin = mViewMarginH / 2; + params.topMargin = params.bottomMargin = mViewMarginV / 2; this.addView(mCurrentView, params); mCurrentView.setDelegate(this); mCurrentView.onShown(); @@ -393,7 +374,8 @@ public void onWorldClick() { @Override public void onDismiss() { if (mCurrentView != null) { - showView(null); + if (!mCurrentView.isEditing()) + showView(null); } else { super.onDismiss(); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java index 63c8cee87..87548881c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java @@ -6,6 +6,7 @@ package org.mozilla.vrbrowser.ui.widgets.settings; import android.content.Context; +import android.graphics.Point; import android.view.View; import android.widget.ScrollView; @@ -16,6 +17,7 @@ import org.mozilla.vrbrowser.ui.views.settings.ButtonSetting; import org.mozilla.vrbrowser.ui.views.settings.RadioGroupSetting; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; +import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.LocaleUtils; class VoiceSearchLanguageOptionsView extends SettingsView { @@ -35,6 +37,7 @@ private void initialize(Context aContext) { mAudio = AudioEngine.fromContext(aContext); + mScrollbar = findViewById(R.id.scrollbar); mBackButton = findViewById(R.id.backButton); mBackButton.setOnClickListener(view -> { @@ -56,12 +59,6 @@ private void initialize(Context aContext) { mScrollbar = findViewById(R.id.scrollbar); } - @Override - public void onShown() { - super.onShown(); - mScrollbar.scrollTo(0, 0); - } - private RadioGroupSetting.OnCheckedChangeListener mLanguageListener = (radioGroup, checkedId, doApply) -> { setLanguage(checkedId, true); }; @@ -80,4 +77,10 @@ private void setLanguage(int checkedId, boolean doApply) { SettingsStore.getInstance(getContext()).setVoiceSearchLanguage(mLanguage.getValueForId(checkedId).toString()); } + + @Override + public Point getDimensions() { + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_height)); + } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/utils/ViewUtils.java b/app/src/common/shared/org/mozilla/vrbrowser/utils/ViewUtils.java index 07b3cb65e..efe89c221 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/utils/ViewUtils.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/utils/ViewUtils.java @@ -1,14 +1,50 @@ package org.mozilla.vrbrowser.utils; +import android.text.SpannableStringBuilder; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; +import android.text.style.URLSpan; import android.view.View; import android.view.ViewParent; +import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.core.text.HtmlCompat; import org.mozilla.vrbrowser.ui.widgets.UIWidget; public class ViewUtils { + public interface LinkClickableSpan { + void onClick(@NonNull View widget, @NonNull String url); + } + + public static void makeLinkClickable(@NonNull SpannableStringBuilder strBuilder, @NonNull final URLSpan span, @NonNull LinkClickableSpan listener) + { + int start = strBuilder.getSpanStart(span); + int end = strBuilder.getSpanEnd(span); + int flags = strBuilder.getSpanFlags(span); + ClickableSpan clickable = new ClickableSpan() { + public void onClick(View view) { + listener.onClick(view, span.getURL()); + } + }; + strBuilder.setSpan(clickable, start, end, flags); + strBuilder.removeSpan(span); + } + + public static void setTextViewHTML(@NonNull TextView text, @NonNull String html, @NonNull LinkClickableSpan listener) + { + CharSequence sequence = HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY); + SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence); + URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class); + for(URLSpan span : urls) { + makeLinkClickable(strBuilder, span, listener); + } + text.setText(strBuilder); + text.setMovementMethod(LinkMovementMethod.getInstance()); + } + public enum TooltipPosition { TOP(0), BOTTOM(1); int id; diff --git a/app/src/main/res/color/fog_void_tint.xml b/app/src/main/res/color/fog_void_tint.xml new file mode 100644 index 000000000..8ddbd75ee --- /dev/null +++ b/app/src/main/res/color/fog_void_tint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/rhino_void_tint.xml b/app/src/main/res/color/rhino_void_tint.xml new file mode 100644 index 000000000..bc67a9dd5 --- /dev/null +++ b/app/src/main/res/color/rhino_void_tint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/void_fog_tint.xml b/app/src/main/res/color/void_fog_tint.xml new file mode 100644 index 000000000..e3c37f612 --- /dev/null +++ b/app/src/main/res/color/void_fog_tint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_icon_ua_default.xml b/app/src/main/res/drawable/ic_icon_ua_default.xml new file mode 100644 index 000000000..2cfdde58c --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_ua_default.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_icon_ua_desktop.xml b/app/src/main/res/drawable/ic_icon_ua_desktop.xml new file mode 100644 index 000000000..f3d07584f --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_ua_desktop.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings_help.xml b/app/src/main/res/drawable/ic_settings_help.xml new file mode 100644 index 000000000..a0c0d6a86 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_help.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/switch_track.xml b/app/src/main/res/drawable/switch_track.xml index 6d83a88ba..d70a034d5 100644 --- a/app/src/main/res/drawable/switch_track.xml +++ b/app/src/main/res/drawable/switch_track.xml @@ -54,8 +54,8 @@ android:visible="true"> + android:endColor="@color/jade" + android:startColor="@color/jade"/> + android:endColor="@color/garnet" + android:startColor="@color/garnet"/> + android:visibility="gone" + android:contentDescription="Loading animation"/> + android:visibility="gone" + android:contentDescription="SSL icon"/> @@ -69,6 +71,13 @@ android:tooltipText="@string/voice_search_tooltip" android:tint="@color/fog" /> + + + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> - + + - + + diff --git a/app/src/main/res/layout/options_developer.xml b/app/src/main/res/layout/options_developer.xml index bfb434740..29c57a57e 100644 --- a/app/src/main/res/layout/options_developer.xml +++ b/app/src/main/res/layout/options_developer.xml @@ -44,15 +44,6 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - + + + + + android:visibility="gone" + app:description="@string/security_options_drm_content" /> + app:description="@string/security_options_tracking_protection" /> - - - - + + + + + + + + + + diff --git a/app/src/main/res/layout/settings.xml b/app/src/main/res/layout/settings.xml index e1b446785..f60d7ca73 100644 --- a/app/src/main/res/layout/settings.xml +++ b/app/src/main/res/layout/settings.xml @@ -2,42 +2,108 @@ - + + + + + + + + + + + + + + + android:contentDescription="Firefox logo" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + android:layout_marginStart="108dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="108dp" + android:scrollbars="none" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/settingsMasthead"> @@ -91,15 +157,22 @@ - + + - - - - - - - - - + diff --git a/app/src/main/res/layout/tray.xml b/app/src/main/res/layout/tray.xml index 9ddbe97f3..8c662a4cb 100644 --- a/app/src/main/res/layout/tray.xml +++ b/app/src/main/res/layout/tray.xml @@ -11,17 +11,12 @@ android:layout_height="wrap_content" android:orientation="horizontal"> - - + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index a4d267985..1716c6a32 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -24,8 +24,10 @@ #c2c6cb #8dc63f #579334 + #336016 #ef4136 #cc332f + #932525 #25003e #ff921e #5d5d5d diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimen.xml index a0cd6170b..e35e3869b 100644 --- a/app/src/main/res/values/dimen.xml +++ b/app/src/main/res/values/dimen.xml @@ -12,8 +12,8 @@ 720dp 44dp - 24dp - 44dp + 28dp + 36dp 3.25 @@ -61,8 +61,8 @@ 1.6 -2.0 - 730dp - 520dp + 770dp + 490dp 320dp 100dp 125dp @@ -193,4 +193,20 @@ 0.02 1000 + + + 145dp + 65dp + + + 585dp + 490dp + + + 585dp + 490dp + + + 585dp + 420dp \ No newline at end of file diff --git a/app/src/main/res/values/non_L10n.xml b/app/src/main/res/values/non_L10n.xml index 5313a7575..a9ad26d23 100644 --- a/app/src/main/res/values/non_L10n.xml +++ b/app/src/main/res/values/non_L10n.xml @@ -13,7 +13,9 @@ settings_environment_multiprocess settings_performance_monitor settings_environment_servo + settings_key_drm_playback settings_tracking_protection + settings_key_speech_data_collection settings_user_agent_version settings_touch_mode settings_display_density @@ -37,6 +39,7 @@ https://support.mozilla.org/kb/private-mode-firefox-reality settings_browser_world_width settings_browser_world_height + settings_key_notifications https://github.com/MozillaReality/FirefoxReality/wiki/Environments https://www.mozilla.org/privacy/firefox/ https://mixedreality.mozilla.org/fxr/report?src=browser-fxr&label=browser-firefox-reality&url=%1$s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d73c973e1..b31605269 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -193,6 +193,10 @@ a developer-build version of the app. --> Developer Build + + Help + Restart Required @@ -379,6 +383,10 @@ for the home page. --> Homepage + + Play DRM-Controlled Content (<a href="http://somesite.com/">Learn More</a>) + Tracking Protection @@ -418,6 +426,24 @@ of this storage even though the storage may not reside on external removable media. --> Read External Storage + + Firefox Data Collection and Use + + + Allow Firefox to collect speech data + + + Allow Firefox to send technical and interaction data to Mozilla + + + + Allow Firefox to send backlogged crash reports on your behalf + + On @@ -631,7 +657,11 @@ - User Agent + Switch User Agent + + + Clear diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 6c62154b0..21138f698 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -157,6 +157,7 @@ @dimen/url_bar_item_width match_parent centerInside + center