From 3ad2320be9584b2c5d99f33264c31afc30342f29 Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Wed, 28 Aug 2019 17:34:41 +0200 Subject: [PATCH 01/62] Fix resize border z-fighting on non-Oculus devices (#1691) --- app/src/main/cpp/BrowserWorld.cpp | 31 ++++++++++++++++++------------ app/src/main/cpp/Widget.cpp | 16 ++++++++++++--- app/src/main/cpp/Widget.h | 5 ++++- app/src/main/cpp/WidgetResizer.cpp | 17 ++++++++++++++-- app/src/main/cpp/WidgetResizer.h | 4 +++- 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/app/src/main/cpp/BrowserWorld.cpp b/app/src/main/cpp/BrowserWorld.cpp index f1fe20d5df..dbdb5e95ab 100644 --- a/app/src/main/cpp/BrowserWorld.cpp +++ b/app/src/main/cpp/BrowserWorld.cpp @@ -18,6 +18,7 @@ #include "Pointer.h" #include "Widget.h" #include "WidgetMover.h" +#include "WidgetResizer.h" #include "WidgetPlacement.h" #include "Cylinder.h" #include "Quad.h" @@ -182,6 +183,7 @@ struct BrowserWorld::State { VRVideoPtr vrVideo; PerformanceMonitorPtr monitor; WidgetMoverPtr movingWidget; + WidgetResizerPtr widgetResizer; State() : paused(true), glInitialized(false), modelsLoaded(false), env(nullptr), cylinderDensity(0.0f), nearClip(0.1f), farClip(300.0f), activity(nullptr), windowsInitialized(false), exitImmersiveRequested(false), loaderDelay(0) { @@ -937,7 +939,8 @@ BrowserWorld::StartWidgetResize(int32_t aHandle, const vrb::Vector& aMaxSize, co ASSERT_ON_RENDER_THREAD(); WidgetPtr widget = m.GetWidget(aHandle); if (widget) { - widget->StartResize(aMaxSize, aMinSize); + m.widgetResizer = widget->StartResize(aMaxSize, aMinSize); + m.rootTransparent->AddNode(m.widgetResizer->GetRoot()); } } @@ -949,6 +952,10 @@ BrowserWorld::FinishWidgetResize(int32_t aHandle) { return; } widget->FinishResize(); + if (m.widgetResizer) { + m.widgetResizer->GetRoot()->RemoveFromParents(); + m.widgetResizer = nullptr; + } } void @@ -1354,24 +1361,29 @@ BrowserWorld::CreateSkyBox(const std::string& aBasePath, const std::string& aExt float BrowserWorld::ComputeNormalizedZ(const vrb::NodePtr& aNode) const { - WidgetPtr target; - bool pointer = false; + Widget * target = nullptr; + float zDelta = 0.0f; for (const auto & widget: m.widgets) { if (widget->GetRoot() == aNode) { - target = widget; + target = widget.get(); break; } } if (!target) { for (Controller& controller: m.controllers->GetControllers()) { if (controller.pointer && controller.pointer->GetRoot() == aNode) { - target = controller.pointer->GetHitWidget(); - pointer = true; + target = controller.pointer->GetHitWidget().get(); + zDelta = 0.02f; break; } } } + if (!target && m.widgetResizer && m.widgetResizer ->GetRoot() == aNode) { + target = m.widgetResizer->GetWidget(); + zDelta = 0.01f; + } + if (!target) { return 1.0f; } @@ -1395,12 +1407,7 @@ BrowserWorld::ComputeNormalizedZ(const vrb::NodePtr& aNode) const { vrb::Vector ndc = viewProjection.MultiplyPosition(hitPoint); - float z = ndc.z(); - - if (pointer) { - z-= 0.001f; - } - return z; + return ndc.z() - zDelta; } } // namespace crow diff --git a/app/src/main/cpp/Widget.cpp b/app/src/main/cpp/Widget.cpp index 5b1f666e26..12cf0c3ec9 100644 --- a/app/src/main/cpp/Widget.cpp +++ b/app/src/main/cpp/Widget.cpp @@ -163,6 +163,7 @@ struct Widget::State { vrb::Matrix translation = vrb::Matrix::Translation(vrb::Vector(0.0f, 0.0f, radius * scale)); cylinder->SetTransform(translation.PostMultiply(scaleMatrix)); AdjustCylinderRotation(radius * scale); + UpdateResizerTransform(); } void AdjustCylinderRotation(const float radius) { @@ -195,6 +196,12 @@ struct Widget::State { } borders.clear(); } + + void UpdateResizerTransform() { + if (resizer) { + resizer->SetTransform(transformContainer->GetTransform().PostMultiply(transform->GetTransform())); + } + } }; WidgetPtr @@ -347,6 +354,7 @@ Widget::SetTransform(const vrb::Matrix& aTransform) { if (m.cylinder) { m.UpdateCylinderMatrix(); } + m.UpdateResizerTransform(); } void @@ -443,7 +451,7 @@ Widget::SetPlacement(const WidgetPlacementPtr& aPlacement) { } } -void +WidgetResizerPtr Widget::StartResize(const vrb::Vector& aMaxSize, const vrb::Vector& aMinSize) { vrb::Vector worldMin, worldMax; GetWidgetMinAndMax(worldMin, worldMax); @@ -452,11 +460,10 @@ Widget::StartResize(const vrb::Vector& aMaxSize, const vrb::Vector& aMinSize) { } else { vrb::RenderContextPtr render = m.context.lock(); if (!render) { - return; + return nullptr; } vrb::CreationContextPtr create = render->GetRenderThreadCreationContext(); m.resizer = WidgetResizer::Create(create, this); - m.transform->InsertNode(m.resizer->GetRoot(), 0); } m.resizer->SetResizeLimits(aMaxSize, aMinSize); m.resizing = true; @@ -465,6 +472,8 @@ Widget::StartResize(const vrb::Vector& aMaxSize, const vrb::Vector& aMinSize) { m.quad->SetScaleMode(Quad::ScaleMode::AspectFit); m.quad->SetBackgroundColor(vrb::Color(1.0f, 1.0f, 1.0f, 1.0f)); } + m.UpdateResizerTransform(); + return m.resizer; } void @@ -601,6 +610,7 @@ void Widget::LayoutQuadWithCylinderParent(const CylinderPtr& aCylinder) { } else { m.transformContainer->SetTransform(vrb::Matrix::Identity()); } + m.UpdateResizerTransform(); } Widget::Widget(State& aState, vrb::RenderContextPtr& aContext) : m(aState) { diff --git a/app/src/main/cpp/Widget.h b/app/src/main/cpp/Widget.h index 3b77815dbb..cba282ccf7 100644 --- a/app/src/main/cpp/Widget.h +++ b/app/src/main/cpp/Widget.h @@ -30,6 +30,9 @@ typedef std::shared_ptr QuadPtr; class Widget; typedef std::shared_ptr WidgetPtr; +class WidgetResizer; +typedef std::shared_ptr WidgetResizerPtr; + class WidgetPlacement; typedef std::shared_ptr WidgetPlacementPtr; @@ -66,7 +69,7 @@ class Widget { vrb::TransformPtr GetTransformNode() const; const WidgetPlacementPtr& GetPlacement() const; void SetPlacement(const WidgetPlacementPtr& aPlacement); - void StartResize(const vrb::Vector& aMaxSize, const vrb::Vector& aMinSize); + WidgetResizerPtr StartResize(const vrb::Vector& aMaxSize, const vrb::Vector& aMinSize); void FinishResize(); bool IsResizing() const; bool IsResizingActive() const; diff --git a/app/src/main/cpp/WidgetResizer.cpp b/app/src/main/cpp/WidgetResizer.cpp index cf2b0e3c9e..4231333dea 100644 --- a/app/src/main/cpp/WidgetResizer.cpp +++ b/app/src/main/cpp/WidgetResizer.cpp @@ -14,6 +14,7 @@ #include "vrb/Color.h" #include "vrb/CreationContext.h" #include "vrb/Matrix.h" +#include "vrb/GLError.h" #include "vrb/Geometry.h" #include "vrb/RenderState.h" #include "vrb/SurfaceTextureFactory.h" @@ -255,6 +256,7 @@ struct WidgetResizer::State { vrb::Vector minSize; bool resizing; vrb::TogglePtr root; + vrb::TransformPtr transform; std::vector resizeHandles; std::vector resizeBars; ResizeHandlePtr activeHandle; @@ -272,6 +274,8 @@ struct WidgetResizer::State { return; } root = vrb::Toggle::Create(create); + transform = vrb::Transform::Create(create); + root->AddNode(transform); currentMin = min; currentMax = max; maxSize = kDefaultMaxResize; @@ -313,7 +317,7 @@ struct WidgetResizer::State { } ResizeBarPtr result = ResizeBar::Create(create, aCenter, aScale, aBorder, aMode); resizeBars.push_back(result); - root->AddNode(result->border->GetTransformNode()); + transform->AddNode(result->border->GetTransformNode()); return result; } @@ -325,7 +329,7 @@ struct WidgetResizer::State { ResizeHandlePtr result = ResizeHandle::Create(create, aCenter, aResizeMode, aBars); result->touchRatio = aTouchRatio; resizeHandles.push_back(result); - root->InsertNode(result->root, 0); + transform->InsertNode(result->root, 0); return result; } @@ -629,6 +633,15 @@ WidgetResizer::IsActive() const { return m.activeHandle && m.activeHandle->resizeState == ResizeState::Active; } +void +WidgetResizer::SetTransform(const vrb::Matrix &aTransform){ + m.transform->SetTransform(aTransform); +} + +Widget* +WidgetResizer::GetWidget() const { + return m.widget; +} WidgetResizer::WidgetResizer(State& aState, vrb::CreationContextPtr& aContext) : m(aState) { m.context = aContext; diff --git a/app/src/main/cpp/WidgetResizer.h b/app/src/main/cpp/WidgetResizer.h index bf7cb193f6..b7c26b381f 100644 --- a/app/src/main/cpp/WidgetResizer.h +++ b/app/src/main/cpp/WidgetResizer.h @@ -22,7 +22,7 @@ typedef std::shared_ptr WidgetResizerPtr; class WidgetResizer { public: - static WidgetResizerPtr Create(vrb::CreationContextPtr& aContext, Widget * aWidget); + static WidgetResizerPtr Create(vrb::CreationContextPtr& aContext, Widget* aWidget); vrb::NodePtr GetRoot() const; void SetSize(const vrb::Vector& aMin, const vrb::Vector& aMax); void SetResizeLimits(const vrb::Vector& aMaxSize, const vrb::Vector& aMinSize); @@ -33,6 +33,8 @@ class WidgetResizer { const vrb::Vector& GetResizeMin() const; const vrb::Vector& GetResizeMax() const; bool IsActive() const; + Widget* GetWidget() const; + void SetTransform(const vrb::Matrix& aTransform); protected: struct State; WidgetResizer(State& aState, vrb::CreationContextPtr& aContext); From 7667417d38c95f31572c17f37611f5590573536a Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Wed, 28 Aug 2019 19:56:41 +0200 Subject: [PATCH 02/62] Allow multiple listeners for media state updates (#1693) * Allow multiple listeners for media state updates * Fix PR review issues * Instance the correct class --- .../org/mozilla/vrbrowser/browser/Media.java | 56 ++++++++----------- .../ui/widgets/MediaControlsWidget.java | 4 +- .../vrbrowser/ui/widgets/TitleBarWidget.java | 3 +- 3 files changed, 26 insertions(+), 37 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Media.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/Media.java index 2b1c49ba0a..7e25b96d1e 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Media.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Media.java @@ -1,9 +1,10 @@ package org.mozilla.vrbrowser.browser; +import androidx.annotation.NonNull; + import org.mozilla.geckoview.MediaElement; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; +import java.util.concurrent.CopyOnWriteArrayList; public class Media implements MediaElement.Delegate { private static final String LOGTAG = "VRB"; @@ -17,17 +18,22 @@ public class Media implements MediaElement.Delegate { private double mVolume = 1.0f; private boolean mIsMuted = false; private boolean mIsUnloaded = false; - private org.mozilla.geckoview.MediaElement mMedia; - private MediaElement.Delegate mDelegate; + private MediaElement mMedia; + private CopyOnWriteArrayList mMediaListeners; private ResizeDelegate mResizeDelegate; public Media(@NonNull MediaElement aMediaElement) { mMedia = aMediaElement; + mMediaListeners = new CopyOnWriteArrayList<>(); aMediaElement.setDelegate(this); } - public void setDelegate(@Nullable MediaElement.Delegate aDelegate) { - mDelegate = aDelegate; + public void addMediaListener(MediaElement.Delegate aListener) { + mMediaListeners.add(aListener); + } + + public void removeMediaListener(MediaElement.Delegate aListener) { + mMediaListeners.remove(aListener); } public double getDuration() { @@ -103,7 +109,7 @@ public void setMuted(boolean aIsMuted) { public void unload() { mIsUnloaded = true; - mDelegate = null; + mMediaListeners.clear(); } public int getWidth() { @@ -132,17 +138,13 @@ public void onPlaybackStateChange(MediaElement mediaElement, int playbackState) } else if (playbackState == MediaElement.MEDIA_STATE_ENDED) { mEnded = true; } - if (mDelegate != null) { - mDelegate.onPlaybackStateChange(mediaElement, playbackState); - } + mMediaListeners.forEach(listener -> listener.onPlaybackStateChange(mediaElement, playbackState)); } @Override public void onReadyStateChange(MediaElement mediaElement, int readyState) { mReadyState = readyState; - if (mDelegate != null) { - mDelegate.onReadyStateChange(mediaElement, readyState); - } + mMediaListeners.forEach(listener -> listener.onReadyStateChange(mediaElement, readyState)); } @Override @@ -150,9 +152,7 @@ public void onMetadataChange(MediaElement mediaElement, MediaElement.Metadata me final int oldWidth = getWidth(); final int oldHeight = getHeight(); mMetaData = metaData; - if (mDelegate != null) { - mDelegate.onMetadataChange(mediaElement, metaData); - } + mMediaListeners.forEach(listener -> listener.onMetadataChange(mediaElement, metaData)); if (mResizeDelegate!= null && metaData != null) { final int w = getWidth(); @@ -165,18 +165,14 @@ public void onMetadataChange(MediaElement mediaElement, MediaElement.Metadata me @Override public void onLoadProgress(MediaElement mediaElement, MediaElement.LoadProgressInfo progressInfo) { - if (mDelegate != null) { - mDelegate.onLoadProgress(mediaElement, progressInfo); - } + mMediaListeners.forEach(listener -> listener.onLoadProgress(mediaElement, progressInfo)); } @Override public void onVolumeChange(MediaElement mediaElement, double volume, boolean muted) { mVolume = volume; mIsMuted = muted; - if (mDelegate != null) { - mDelegate.onVolumeChange(mediaElement, volume, muted); - } + mMediaListeners.forEach(listener -> listener.onVolumeChange(mediaElement, volume, muted)); } @Override @@ -186,31 +182,23 @@ public void onTimeChange(MediaElement mediaElement, double time) { if (duration <= 0 || mCurrentTime < getDuration()) { mEnded = false; } - if (mDelegate != null) { - mDelegate.onTimeChange(mediaElement, time); - } + mMediaListeners.forEach(listener -> listener.onTimeChange(mediaElement, time)); } @Override public void onPlaybackRateChange(MediaElement mediaElement, double rate) { mPlaybackRate = rate; - if (mDelegate != null) { - mDelegate.onPlaybackRateChange(mediaElement, rate); - } + mMediaListeners.forEach(listener -> listener.onPlaybackRateChange(mediaElement, rate)); } @Override public void onFullscreenChange(MediaElement mediaElement, boolean fullscreen) { mIsFullscreen = fullscreen; - if (mDelegate != null) { - mDelegate.onFullscreenChange(mediaElement, fullscreen); - } + mMediaListeners.forEach(listener -> listener.onFullscreenChange(mediaElement, fullscreen)); } @Override public void onError(MediaElement mediaElement, int code) { - if (mDelegate != null) { - mDelegate.onError(mediaElement, code); - } + mMediaListeners.forEach(listener -> listener.onError(mediaElement, code)); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/MediaControlsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/MediaControlsWidget.java index 5e2fcde104..5ce2313e51 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/MediaControlsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/MediaControlsWidget.java @@ -244,7 +244,7 @@ public void setMedia(Media aMedia) { return; } if (mMedia != null) { - mMedia.setDelegate(null); + mMedia.removeMediaListener(this); } mMedia = aMedia; boolean enabled = mMedia != null; @@ -266,7 +266,7 @@ public void setMedia(Media aMedia) { onPlaybackStateChange(mMedia.getMediaElement(), MediaElement.MEDIA_STATE_PLAY); } - mMedia.setDelegate(this); + mMedia.addMediaListener(this); } public void setProjectionSelectorEnabled(boolean aEnabled) { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TitleBarWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TitleBarWidget.java index 21b018c5e7..7af5105407 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TitleBarWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TitleBarWidget.java @@ -181,7 +181,8 @@ public void mediaAvailabilityChanged(boolean available) { mMedia = mAttachedWindow.getSessionStack().getFullScreenVideo(); if (mMedia != null) { mBinding.setIsMediaPlaying(mMedia.isPlaying()); - mMedia.setDelegate(mMediaDelegate); + mMedia.removeMediaListener(mMediaDelegate); + mMedia.addMediaListener(mMediaDelegate); } } } From 9ae347257a9f40dc9fe1db546c848dff1976d263 Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Thu, 29 Aug 2019 00:31:48 +0200 Subject: [PATCH 03/62] Use flat tooltips on tray. Fix math for tray tooltips. (#1698) --- .../org/mozilla/vrbrowser/ui/views/UIButton.java | 9 +++++++++ .../vrbrowser/ui/widgets/TooltipWidget.java | 4 ++++ .../mozilla/vrbrowser/ui/widgets/TrayWidget.java | 5 +++++ app/src/main/cpp/BrowserWorld.cpp | 4 ++-- app/src/main/cpp/Widget.cpp | 16 ++++++++++++---- app/src/main/cpp/Widget.h | 2 +- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/UIButton.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/UIButton.java index 594bb9b8be..d3dd988e82 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/UIButton.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/UIButton.java @@ -44,6 +44,7 @@ private enum State { private State mState; private int mTooltipDelay; private float mTooltipDensity; + private boolean mCurvedTooltip = true; private ViewUtils.TooltipPosition mTooltipPosition; public UIButton(Context context, AttributeSet attrs) { @@ -98,6 +99,13 @@ public void setTooltip(String text) { } } + public void setCurvedTooltip(boolean aEnabled) { + mCurvedTooltip = aEnabled; + if (mTooltipView != null) { + mTooltipView.setCurvedMode(aEnabled); + } + } + public void setTooltipText(@NonNull String text) { mTooltipText = text; } @@ -204,6 +212,7 @@ public void run() { } mTooltipView = new TooltipWidget(getContext()); + mTooltipView.setCurvedMode(mCurvedTooltip); mTooltipView.setText(getTooltip()); mTooltipView.setLayoutParams(UIButton.this, mTooltipPosition, mTooltipDensity); mTooltipView.show(UIWidget.CLEAR_FOCUS); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TooltipWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TooltipWidget.java index b86f37a853..95fa284fa3 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TooltipWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TooltipWidget.java @@ -94,6 +94,10 @@ public void setLayoutParams(View targetView, ViewUtils.TooltipPosition position, } } + public void setCurvedMode(boolean enabled) { + mWidgetPlacement.cylinder = enabled; + } + public void setText(String text) { mText.setText(text); } 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 ad7635d0b8..a700716337 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 @@ -84,6 +84,7 @@ private void initialize(Context aContext) { notifyPrivateBrowsingClicked(); view.requestFocusFromTouch(); }); + mPrivateButton.setCurvedTooltip(false); mSettingsButton = findViewById(R.id.settingsButton); mSettingsButton.setOnHoverListener(mButtonScaleHoverListener); @@ -97,6 +98,7 @@ private void initialize(Context aContext) { view.requestFocusFromTouch(); } }); + mSettingsButton.setCurvedTooltip(false); mBookmarksButton = findViewById(R.id.bookmarksButton); mBookmarksButton.setOnHoverListener(mButtonScaleHoverListener); @@ -108,6 +110,7 @@ private void initialize(Context aContext) { notifyBookmarksClicked(); view.requestFocusFromTouch(); }); + mBookmarksButton.setCurvedTooltip(false); mHistoryButton = findViewById(R.id.historyButton); mHistoryButton.setOnHoverListener(mButtonScaleHoverListener); @@ -119,6 +122,7 @@ private void initialize(Context aContext) { notifyHistoryClicked(); view.requestFocusFromTouch(); }); + mHistoryButton.setCurvedTooltip(false); UIButton addWindowButton = findViewById(R.id.addwindowButton); addWindowButton.setOnHoverListener(mButtonScaleHoverListener); @@ -133,6 +137,7 @@ private void initialize(Context aContext) { notifyAddWindowClicked(); }); + addWindowButton.setCurvedTooltip(false); mAudio = AudioEngine.fromContext(aContext); diff --git a/app/src/main/cpp/BrowserWorld.cpp b/app/src/main/cpp/BrowserWorld.cpp index dbdb5e95ab..ebdb24546d 100644 --- a/app/src/main/cpp/BrowserWorld.cpp +++ b/app/src/main/cpp/BrowserWorld.cpp @@ -1070,8 +1070,8 @@ BrowserWorld::LayoutWidget(int32_t aHandle) { } widget->SetTransform(parent ? parent->GetTransform().PostMultiply(transform) : transform); - if (!widget->GetCylinder()) { - widget->LayoutQuadWithCylinderParent(parent && parent->GetCylinder() ? parent->GetCylinder() : nullptr); + if (!widget->GetCylinder() && parent) { + widget->LayoutQuadWithCylinderParent(parent); } } diff --git a/app/src/main/cpp/Widget.cpp b/app/src/main/cpp/Widget.cpp index 12cf0c3ec9..4ac1e97f68 100644 --- a/app/src/main/cpp/Widget.cpp +++ b/app/src/main/cpp/Widget.cpp @@ -603,12 +603,20 @@ Widget::SetProxifyLayer(const bool aValue) { m.layerProxy->ToggleAll(true); } -void Widget::LayoutQuadWithCylinderParent(const CylinderPtr& aCylinder) { - if (aCylinder) { - const float radius = aCylinder->GetTransformNode()->GetTransform().GetScale().x(); +void Widget::LayoutQuadWithCylinderParent(const WidgetPtr& aParent) { + CylinderPtr cylinder = aParent->GetCylinder(); + if (cylinder) { + // The widget is flat and the parent is a cylinder. + // Adjust the widget rotation based on the parent cylinder + // e.g. rotate the tray based on the parent cylindrical window. + const float radius = cylinder->GetTransformNode()->GetTransform().GetScale().x(); m.AdjustCylinderRotation(radius); } else { - m.transformContainer->SetTransform(vrb::Matrix::Identity()); + // The widget is flat and the parent is flat. Copy the parent transformContainer matrix (used for cylinder rotations) + // because the parent widget can still be recursively rotated based on a parent cylinder. + // e.g. Place the tray tooltips on the correct tray position which may be rotated based on the + // parent cylindrical window. + m.transformContainer->SetTransform(aParent->m.transformContainer->GetTransform()); } m.UpdateResizerTransform(); } diff --git a/app/src/main/cpp/Widget.h b/app/src/main/cpp/Widget.h index cba282ccf7..400c732e35 100644 --- a/app/src/main/cpp/Widget.h +++ b/app/src/main/cpp/Widget.h @@ -79,7 +79,7 @@ class Widget { float GetCylinderDensity() const; void SetBorderColor(const vrb::Color& aColor); void SetProxifyLayer(const bool aValue); - void LayoutQuadWithCylinderParent(const CylinderPtr& aCylinder); + void LayoutQuadWithCylinderParent(const WidgetPtr& aParent); protected: struct State; Widget(State& aState, vrb::RenderContextPtr& aContext); From 5ccdcabc22281f906e5e68f7e46ff108542ccc36 Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Thu, 29 Aug 2019 15:32:27 +0200 Subject: [PATCH 04/62] Fix suggestions list padding to avoid exceeding the dropdown's borders (#1702) --- app/src/main/res/layout/list_popup_window.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/layout/list_popup_window.xml b/app/src/main/res/layout/list_popup_window.xml index 88b4198b9e..881cb8cfe7 100644 --- a/app/src/main/res/layout/list_popup_window.xml +++ b/app/src/main/res/layout/list_popup_window.xml @@ -11,6 +11,8 @@ android:background="@drawable/dialog_background" android:divider="@android:color/transparent" android:dividerHeight="0dp" + android:paddingLeft="1dp" + android:paddingRight="1dp" android:paddingTop="15dp" android:paddingBottom="15dp" app:layout_constraintBottom_toBottomOf="parent" From 42af969b7c0d40f1aa9e58c5d21580d880126206 Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Thu, 29 Aug 2019 17:15:37 +0200 Subject: [PATCH 05/62] Layout the crash dialog checkbox using relative layout center rules instead of using a topMargin (#1703) --- app/src/main/res/layout/crash_dialog.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/crash_dialog.xml b/app/src/main/res/layout/crash_dialog.xml index 8e435e19d8..eb08eb733c 100644 --- a/app/src/main/res/layout/crash_dialog.xml +++ b/app/src/main/res/layout/crash_dialog.xml @@ -38,7 +38,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/headerText" + android:layout_centerInParent="true" android:layout_centerHorizontal="true" + android:layout_centerVertical="true" android:layout_marginStart="50dp" android:layout_marginTop="15dp" android:layout_marginEnd="50dp" @@ -51,9 +53,9 @@ android:id="@+id/crashSendDataCheckbox" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_below="@+id/crashMessage" android:layout_centerHorizontal="true" - android:layout_marginTop="25dp" + android:layout_above="@id/buttonsLayout" + android:layout_below="@+id/crashMessage" android:background="@android:color/transparent" android:button="@drawable/checkbox" android:gravity="center_vertical" From 03e33037e80d9785d4ec9b646a70a94a8bf33b04 Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Thu, 29 Aug 2019 17:28:46 +0200 Subject: [PATCH 06/62] Hide scrollbar in Awesome bar suggestion list if all the content fits. (#1701) --- .../vrbrowser/ui/views/CustomListView.java | 20 +++++++++---------- .../ui/widgets/SuggestionsWidget.java | 3 ++- app/src/main/res/layout/list_popup_window.xml | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/CustomListView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/CustomListView.java index 3fb794d12c..2780a540b1 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/CustomListView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/CustomListView.java @@ -45,18 +45,18 @@ public boolean isInTouchMode() { protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); - boolean scrollVisible = false; - - if (getChildCount() > 0) { - View first = getChildAt(0); - View last = getChildAt(getChildCount() - 1); - if (first.getTop() < 0 || last.getBottom() > getHeight()) { - scrollVisible = true; - } + boolean fits = getCount() == 0; + + // Check if all the items fit on the ListView + int last = getLastVisiblePosition(); + int first = getFirstVisiblePosition(); + if (!fits && first == 0 && last == getCount() - 1) { + fits = getChildAt(first).getTop() >= 0 && getChildAt(last).getBottom() <= getHeight(); } - setVerticalScrollBarEnabled(scrollVisible); - setFastScrollAlwaysVisible(scrollVisible); + // Hide scrollbar is all item fit. + setVerticalScrollBarEnabled(!fits); + setFastScrollAlwaysVisible(!fits); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/SuggestionsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/SuggestionsWidget.java index f6f414fc94..aba8ab9148 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/SuggestionsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/SuggestionsWidget.java @@ -23,13 +23,14 @@ import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; +import org.mozilla.vrbrowser.ui.views.CustomListView; import java.util.ArrayList; import java.util.List; public class SuggestionsWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { - private ListView mList; + private CustomListView mList; private SuggestionsAdapter mAdapter; private Animation mScaleUpAnimation; private Animation mScaleDownAnimation; diff --git a/app/src/main/res/layout/list_popup_window.xml b/app/src/main/res/layout/list_popup_window.xml index 881cb8cfe7..b32c18d82e 100644 --- a/app/src/main/res/layout/list_popup_window.xml +++ b/app/src/main/res/layout/list_popup_window.xml @@ -4,7 +4,7 @@ android:layout_height="match_parent" android:layout_width="match_parent"> - Date: Thu, 29 Aug 2019 17:32:29 +0200 Subject: [PATCH 07/62] Fix flickering when closing a window (#1700) --- .../common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java index 261bafc620..2d6c96478b 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java @@ -770,7 +770,6 @@ public void onHistoryClicked() { public void onCloseClicked(TopBarWidget aWidget) { WindowWidget window = aWidget.getAttachedWindow(); if (window != null) { - focusWindow(window); closeWindow(window); } } From 1e0af3e37da1ee2a0e654ed6f2c7171a29e4d066 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 29 Aug 2019 18:21:48 +0200 Subject: [PATCH 08/62] Updated scrollbar theme (#1706) --- app/src/main/res/drawable/scrollbar_thumb.xml | 8 ++++---- app/src/main/res/layout/options_language_content.xml | 6 ------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/app/src/main/res/drawable/scrollbar_thumb.xml b/app/src/main/res/drawable/scrollbar_thumb.xml index 2268c50b2f..c500866961 100644 --- a/app/src/main/res/drawable/scrollbar_thumb.xml +++ b/app/src/main/res/drawable/scrollbar_thumb.xml @@ -1,6 +1,6 @@ - + @@ -16,9 +16,9 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/options_language_content.xml b/app/src/main/res/layout/options_language_content.xml index 59140a31d1..d3c40c58bb 100644 --- a/app/src/main/res/layout/options_language_content.xml +++ b/app/src/main/res/layout/options_language_content.xml @@ -42,9 +42,6 @@ android:layout_height="wrap_content" android:paddingBottom="5dp" style="@style/settingsText" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:layout_toStartOf="@+id/button" android:gravity="center_vertical" android:text="@string/language_options_preferred_languages" tools:text="@string/language_options_preferred_languages" /> @@ -69,9 +66,6 @@ android:layout_height="wrap_content" android:paddingBottom="5dp" style="@style/settingsText" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:layout_toStartOf="@+id/button" android:gravity="center_vertical" android:text="@string/language_options_available_languages" tools:text="@string/language_options_available_languages" /> From 357f7e126f7a0ae4d649a57e71d6cc2e22a07edc Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 29 Aug 2019 18:33:18 +0200 Subject: [PATCH 09/62] Update Bookmarks UI (#1704) * Update Bookmarks UI * Fixed crash when scrolling --- .../vrbrowser/browser/BookmarksStore.kt | 13 + .../ui/adapters/BindingAdapters.java | 16 +- .../ui/adapters/BookmarkAdapter.java | 65 ++++- .../vrbrowser/ui/adapters/HistoryAdapter.java | 4 +- .../ui/callbacks/BookmarkClickCallback.java | 8 - .../ui/callbacks/BookmarkItemCallback.java | 11 + .../ui/callbacks/BookmarksCallback.java | 12 + .../ui/callbacks/HistoryCallback.java | 6 +- .../HistoryItemContextMenuClickCallback.java | 9 - .../LibraryItemContextMenuClickCallback.java | 9 + .../vrbrowser/ui/views/BookmarksView.java | 68 +++-- .../ui/views/HistoryItemContextMenu.java | 67 ----- .../vrbrowser/ui/views/HistoryView.java | 7 +- .../ui/views/LibraryItemContextMenu.java | 113 +++++++++ .../mozilla/vrbrowser/ui/views/UIButton.java | 50 +++- .../vrbrowser/ui/widgets/TooltipWidget.java | 79 ++---- .../vrbrowser/ui/widgets/TrayWidget.java | 52 ++++ .../vrbrowser/ui/widgets/WindowWidget.java | 235 +++++++++++------- ...java => LibraryItemContextMenuWidget.java} | 35 ++- .../vrbrowser/utils/AnimationHelper.java | 31 +++ ...y_context_menu_item_background_bottom.xml} | 0 ...y_context_menu_item_background_middle.xml} | 0 ...ry_context_menu_item_background_single.xml | 21 ++ ...rary_context_menu_item_background_top.xml} | 0 ....xml => library_item_background_color.xml} | 0 .../library_notification_background.xml | 16 ++ ...brary_notification_background_triangle.xml | 35 +++ .../main_button_icon_color_notification.xml | 9 + app/src/main/res/layout/bookmark_item.xml | 172 ++++++++----- app/src/main/res/layout/bookmarks.xml | 78 ++++-- app/src/main/res/layout/history.xml | 6 +- app/src/main/res/layout/history_item.xml | 14 +- ...menu.xml => library_item_context_menu.xml} | 20 +- .../main/res/layout/library_notification.xml | 55 ++++ app/src/main/res/values/attrs.xml | 1 + app/src/main/res/values/dimen.xml | 20 +- app/src/main/res/values/strings.xml | 13 + app/src/main/res/values/styles.xml | 1 + versions.gradle | 3 +- 39 files changed, 975 insertions(+), 379 deletions(-) delete mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/callbacks/BookmarkClickCallback.java create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/callbacks/BookmarkItemCallback.java create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/callbacks/BookmarksCallback.java delete mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/callbacks/HistoryItemContextMenuClickCallback.java create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/callbacks/LibraryItemContextMenuClickCallback.java delete mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryItemContextMenu.java create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/views/LibraryItemContextMenu.java rename app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/{HistoryItemContextMenuWidget.java => LibraryItemContextMenuWidget.java} (77%) rename app/src/main/res/drawable/{library_panel_context_menu_item_background_color_bottom.xml => library_context_menu_item_background_bottom.xml} (100%) rename app/src/main/res/drawable/{library_panel_context_menu_item_background_color_middle.xml => library_context_menu_item_background_middle.xml} (100%) create mode 100644 app/src/main/res/drawable/library_context_menu_item_background_single.xml rename app/src/main/res/drawable/{library_panel_context_menu_item_background_color_top.xml => library_context_menu_item_background_top.xml} (100%) rename app/src/main/res/drawable/{library_panel_item_background_color.xml => library_item_background_color.xml} (100%) create mode 100644 app/src/main/res/drawable/library_notification_background.xml create mode 100644 app/src/main/res/drawable/library_notification_background_triangle.xml create mode 100644 app/src/main/res/drawable/main_button_icon_color_notification.xml rename app/src/main/res/layout/{history_item_context_menu.xml => library_item_context_menu.xml} (81%) create mode 100644 app/src/main/res/layout/library_notification.xml diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/BookmarksStore.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/BookmarksStore.kt index aaa7ecfbfb..93c994df2d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/BookmarksStore.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/BookmarksStore.kt @@ -21,6 +21,7 @@ class BookmarksStore constructor(val context: Context) { interface BookmarkListener { fun onBookmarksUpdated() + fun onBookmarkAdded() } fun addListener(aListener: BookmarkListener) { @@ -44,6 +45,7 @@ class BookmarksStore constructor(val context: Context) { fun addBookmark(aURL: String, aTitle: String) = GlobalScope.future { storage.addItem(BookmarkRoot.Mobile.id, aURL, aTitle, null) notifyListeners() + notifyAddedListeners() } fun deleteBookmarkByURL(aURL: String) = GlobalScope.future { @@ -89,4 +91,15 @@ class BookmarksStore constructor(val context: Context) { } } } + + private fun notifyAddedListeners() { + if (listeners.size > 0) { + val listenersCopy = ArrayList(listeners) + Handler(Looper.getMainLooper()).post { + for (listener in listenersCopy) { + listener.onBookmarkAdded() + } + } + } + } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/BindingAdapters.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/BindingAdapters.java index 17cabbf1c6..208405cb0c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/BindingAdapters.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/BindingAdapters.java @@ -1,17 +1,20 @@ package org.mozilla.vrbrowser.ui.adapters; import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.ImageSpan; import android.view.View; import android.widget.TextView; +import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.databinding.BindingAdapter; -import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; -import java.util.TimeZone; public class BindingAdapters { @@ -53,4 +56,13 @@ public static void bindDate(@NonNull TextView textView, long timestamp) { } textView.setText(androidDateTime.concat(AmPm)); } + + @BindingAdapter(value={"textDrawable", "textString"}) + public static void setSpannableString(@NonNull TextView textView, Drawable drawable, String text) { + SpannableString spannableString = new SpannableString(text); + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM); + spannableString.setSpan(span, spannableString.toString().indexOf("@"), spannableString.toString().indexOf("@")+1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + textView.setText(spannableString); + } } \ No newline at end of file diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/BookmarkAdapter.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/BookmarkAdapter.java index a96bada138..43b828851e 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/BookmarkAdapter.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/BookmarkAdapter.java @@ -16,7 +16,7 @@ import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.databinding.BookmarkItemBinding; -import org.mozilla.vrbrowser.ui.callbacks.BookmarkClickCallback; +import org.mozilla.vrbrowser.ui.callbacks.BookmarkItemCallback; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.AnimationHelper; @@ -39,13 +39,13 @@ public class BookmarkAdapter extends RecyclerView.Adapter { + int ev = motionEvent.getActionMasked(); + switch (ev) { + case MotionEvent.ACTION_HOVER_ENTER: + binding.setIsHovered(true); + return false; + + case MotionEvent.ACTION_HOVER_EXIT: + binding.setIsHovered(false); + return false; + } + + return false; + }); + binding.layout.setOnTouchListener((view, motionEvent) -> { + int ev = motionEvent.getActionMasked(); + switch (ev) { + case MotionEvent.ACTION_UP: + return false; + + case MotionEvent.ACTION_DOWN: + binding.setIsHovered(true); + return false; + } + return false; + }); + binding.more.setOnHoverListener(mIconHoverListener); + binding.more.setOnTouchListener((view, motionEvent) -> { + int ev = motionEvent.getActionMasked(); + switch (ev) { + case MotionEvent.ACTION_UP: + mBookmarkItemCallback.onMore(view, binding.getItem()); + return true; + + case MotionEvent.ACTION_DOWN: + return true; + } + return false; + }); binding.trash.setOnHoverListener(mIconHoverListener); binding.trash.setOnTouchListener((view, motionEvent) -> { int ev = motionEvent.getActionMasked(); switch (ev) { case MotionEvent.ACTION_UP: - mBookmarkClickCallback.onDelete(binding.getBookmark()); + mBookmarkItemCallback.onDelete(view, binding.getItem()); return true; case MotionEvent.ACTION_DOWN: @@ -127,7 +174,7 @@ public BookmarkViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view @Override public void onBindViewHolder(@NonNull BookmarkViewHolder holder, int position) { - holder.binding.setBookmark(mBookmarkList.get(position)); + holder.binding.setItem(mBookmarkList.get(position)); holder.binding.executePendingBindings(); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/HistoryAdapter.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/HistoryAdapter.java index abb2822959..50c2a5d2e8 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/HistoryAdapter.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/HistoryAdapter.java @@ -44,8 +44,8 @@ public class HistoryAdapter extends RecyclerView.Adapter { + v.requestFocusFromTouch(); + return false; + }); mBinding.setIsLoading(true); mBinding.executePendingBindings(); syncBookmarks(); SessionStore.get().getBookmarkStore().addListener(this); setVisibility(GONE); + + setOnTouchListener((v, event) -> { + v.requestFocusFromTouch(); + return false; + }); } public void onDestroy() { SessionStore.get().getBookmarkStore().removeListener(this); } - private final BookmarkClickCallback mBookmarkClickCallback = new BookmarkClickCallback() { + private final BookmarkItemCallback mBookmarkItemCallback = new BookmarkItemCallback() { @Override - public void onClick(BookmarkNode bookmark) { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } + public void onClick(View view, BookmarkNode item) { + mBinding.bookmarksList.requestFocusFromTouch(); SessionStack sessionStack = SessionStore.get().getActiveStore(); - sessionStack.loadUri(bookmark.getUrl()); + sessionStack.loadUri(item.getUrl()); } @Override - public void onDelete(BookmarkNode bookmark) { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } + public void onDelete(View view, BookmarkNode item) { + mBinding.bookmarksList.requestFocusFromTouch(); mIgnoreNextListener = true; - SessionStore.get().getBookmarkStore().deleteBookmarkById(bookmark.getGuid()); - mBookmarkAdapter.removeItem(bookmark); + SessionStore.get().getBookmarkStore().deleteBookmarkById(item.getGuid()); + mBookmarkAdapter.removeItem(item); if (mBookmarkAdapter.itemCount() == 0) { mBinding.setIsEmpty(true); mBinding.setIsLoading(false); mBinding.executePendingBindings(); } } + + @Override + public void onMore(View view, BookmarkNode item) { + mBinding.bookmarksList.requestFocusFromTouch(); + + int rowPosition = mBookmarkAdapter.getItemPosition(item.getGuid()); + RecyclerView.ViewHolder row = mBinding.bookmarksList.findViewHolderForLayoutPosition(rowPosition); + boolean isLastVisibleItem = false; + if (mBinding.bookmarksList.getLayoutManager() instanceof LinearLayoutManager) { + LinearLayoutManager layoutManager = (LinearLayoutManager) mBinding.bookmarksList.getLayoutManager(); + if (rowPosition == layoutManager.findLastVisibleItemPosition()) { + isLastVisibleItem = true; + } + } + + mBinding.getCallback().onShowContextMenu( + row.itemView, + item, + isLastVisibleItem); + } }; + public void setBookmarksCallback(@NonNull BookmarksCallback callback) { + mBinding.setCallback(callback); + } private void syncBookmarks() { SessionStore.get().getBookmarkStore().getBookmarks().thenAcceptAsync(this::showBookmarks, new UIThreadExecutor()); @@ -113,6 +146,8 @@ private void showBookmarks(List aBookmarks) { mBookmarkAdapter.setBookmarkList(aBookmarks); } mBinding.executePendingBindings(); + mBinding.bookmarksList.post(() -> mBinding.bookmarksList.smoothScrollToPosition( + mBookmarkAdapter.getItemCount() > 0 ? mBookmarkAdapter.getItemCount() - 1 : 0)); } // BookmarksStore.BookmarksViewListener @@ -124,4 +159,9 @@ public void onBookmarksUpdated() { } syncBookmarks(); } + + @Override + public void onBookmarkAdded() { + // Nothing to do + } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryItemContextMenu.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryItemContextMenu.java deleted file mode 100644 index 47bc9e585d..0000000000 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryItemContextMenu.java +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.vrbrowser.ui.views; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.LayoutInflater; -import android.widget.FrameLayout; - -import androidx.databinding.DataBindingUtil; - -import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.browser.engine.SessionStore; -import org.mozilla.vrbrowser.databinding.HistoryItemContextMenuBinding; -import org.mozilla.vrbrowser.ui.callbacks.HistoryItemContextMenuClickCallback; - -import mozilla.components.concept.storage.VisitInfo; - -public class HistoryItemContextMenu extends FrameLayout { - - private static final String LOGTAG = HistoryItemContextMenu.class.getSimpleName(); - - private HistoryItemContextMenuBinding mBinding; - - public HistoryItemContextMenu(Context aContext) { - super(aContext); - initialize(aContext); - } - - public HistoryItemContextMenu(Context aContext, AttributeSet aAttrs) { - super(aContext, aAttrs); - initialize(aContext); - } - - public HistoryItemContextMenu(Context aContext, AttributeSet aAttrs, int aDefStyle) { - super(aContext, aAttrs, aDefStyle); - initialize(aContext); - } - - private void initialize(Context aContext) { - LayoutInflater inflater = LayoutInflater.from(aContext); - - mBinding = DataBindingUtil.inflate(inflater, R.layout.history_item_context_menu, this, true); - } - - public void setItem(VisitInfo item) { - SessionStore.get().getBookmarkStore().isBookmarked(item.getUrl()).thenAccept((isBookmarked -> { - mBinding.setItem(item); - mBinding.setIsBookmarked(isBookmarked); - mBinding.bookmark.setText(isBookmarked ? R.string.history_context_remove_bookmarks : R.string.history_context_add_bookmarks); - invalidate(); - - })).exceptionally(throwable -> { - Log.d(LOGTAG, "Couldn't get the bookmarked status of the history item"); - return null; - }); - } - - public void setContextMenuClickCallback(HistoryItemContextMenuClickCallback callback) { - mBinding.setCallback(callback); - } - -} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java index e9e333b210..2918ea2fb0 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java @@ -92,7 +92,8 @@ public void onDestroy() { private final HistoryItemCallback mHistoryItemCallback = new HistoryItemCallback() { @Override public void onClick(View view, VisitInfo item) { - view.requestFocusFromTouch(); + mBinding.historyList.requestFocusFromTouch(); + SessionStack sessionStack = SessionStore.get().getActiveStore(); sessionStack.loadUri(item.getUrl()); } @@ -100,6 +101,7 @@ public void onClick(View view, VisitInfo item) { @Override public void onDelete(View view, VisitInfo item) { mBinding.historyList.requestFocusFromTouch(); + mIgnoreNextListener = true; SessionStore.get().getHistoryStore().deleteHistory(item.getUrl(), item.getVisitTime()); mHistoryAdapter.removeItem(item); @@ -112,7 +114,7 @@ public void onDelete(View view, VisitInfo item) { @Override public void onMore(View view, VisitInfo item) { - view.requestFocusFromTouch(); + mBinding.historyList.requestFocusFromTouch(); int rowPosition = mHistoryAdapter.getItemPosition(item.getVisitTime()); RecyclerView.ViewHolder row = mBinding.historyList.findViewHolderForLayoutPosition(rowPosition); @@ -193,6 +195,7 @@ private void showHistory(List historyItems) { mHistoryAdapter.setHistoryList(historyItems); } mBinding.executePendingBindings(); + mBinding.historyList.post(() -> mBinding.historyList.smoothScrollToPosition(0)); } // HistoryStore.HistoryListener diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/LibraryItemContextMenu.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/LibraryItemContextMenu.java new file mode 100644 index 0000000000..c217f9a40a --- /dev/null +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/LibraryItemContextMenu.java @@ -0,0 +1,113 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.vrbrowser.ui.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.databinding.DataBindingUtil; + +import org.mozilla.vrbrowser.R; +import org.mozilla.vrbrowser.browser.engine.SessionStore; +import org.mozilla.vrbrowser.databinding.LibraryItemContextMenuBinding; +import org.mozilla.vrbrowser.ui.callbacks.LibraryItemContextMenuClickCallback; +import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; + +public class LibraryItemContextMenu extends FrameLayout { + + private static final String LOGTAG = LibraryItemContextMenu.class.getSimpleName(); + + public enum LibraryItemType { + BOOKMARKS, + HISTORY + } + + public static class LibraryContextMenuItem { + + private String url; + private String title; + private LibraryItemType type; + + public LibraryContextMenuItem(@NonNull String url, String title, LibraryItemType type) { + this.url = url; + this.title = title; + this.type = type; + } + + public String getUrl() { + return url; + } + + public String getTitle() { + return title; + } + + public LibraryItemType getType() { + return type; + } + + } + + private LibraryItemContextMenuBinding mBinding; + + public LibraryItemContextMenu(Context aContext) { + super(aContext); + initialize(aContext); + } + + public LibraryItemContextMenu(Context aContext, AttributeSet aAttrs) { + super(aContext, aAttrs); + initialize(aContext); + } + + public LibraryItemContextMenu(Context aContext, AttributeSet aAttrs, int aDefStyle) { + super(aContext, aAttrs, aDefStyle); + initialize(aContext); + } + + private void initialize(Context aContext) { + LayoutInflater inflater = LayoutInflater.from(aContext); + + mBinding = DataBindingUtil.inflate(inflater, R.layout.library_item_context_menu, this, true); + } + + public void setItem(@NonNull LibraryContextMenuItem item) { + SessionStore.get().getBookmarkStore().isBookmarked(item.getUrl()).thenAccept((isBookmarked -> { + mBinding.setItem(item); + mBinding.setIsBookmarked(isBookmarked); + mBinding.bookmark.setText(isBookmarked ? R.string.history_context_remove_bookmarks : R.string.history_context_add_bookmarks); + invalidate(); + + })).exceptionally(throwable -> { + Log.d(LOGTAG, "Couldn't get the bookmarked status of the history item"); + return null; + }); + } + + public void setContextMenuClickCallback(LibraryItemContextMenuClickCallback callback) { + mBinding.setCallback(callback); + } + + public int getMenuHeight() { + switch (mBinding.getItem().getType()) { + case BOOKMARKS: + mBinding.bookmarkLayout.setVisibility(GONE); + mBinding.newWindowLayout.setBackgroundResource(R.drawable.library_context_menu_item_background_single); + return WidgetPlacement.dpDimension(getContext(), R.dimen.library_item_row_height); + case HISTORY: + mBinding.bookmarkLayout.setVisibility(VISIBLE); + mBinding.newWindowLayout.setBackgroundResource(R.drawable.library_context_menu_item_background_top); + return WidgetPlacement.dpDimension(getContext(), R.dimen.library_item_row_height) * 2; + } + + return WidgetPlacement.dpDimension(getContext(), R.dimen.library_item_row_height) * 2; + } + +} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/UIButton.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/UIButton.java index d3dd988e82..bdf426e17c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/UIButton.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/UIButton.java @@ -9,6 +9,8 @@ import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; +import android.graphics.PointF; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; @@ -22,6 +24,7 @@ import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.ui.widgets.TooltipWidget; import org.mozilla.vrbrowser.ui.widgets.UIWidget; +import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.ViewUtils; public class UIButton extends AppCompatImageButton implements CustomUIButton { @@ -29,7 +32,8 @@ public class UIButton extends AppCompatImageButton implements CustomUIButton { private enum State { NORMAL, PRIVATE, - ACTIVE + ACTIVE, + NOTIFICATION } private ColorStateList mTintColorList; @@ -39,6 +43,7 @@ private enum State { private @IdRes int mTintColorListRes; private @IdRes int mPrivateModeTintColorListRes; private @IdRes int mActiveModeTintColorListRes; + private @IdRes int mNotificationModeTintColorListRes; private TooltipWidget mTooltipView; private String mTooltipText; private State mState; @@ -63,6 +68,7 @@ public UIButton(Context context, AttributeSet attrs, int defStyleAttr) { mActiveModeBackground = attributes.getDrawable(R.styleable.UIButton_activeModeBackground); mPrivateModeTintColorListRes = attributes.getResourceId(R.styleable.UIButton_privateModeTintColorList, 0); mActiveModeTintColorListRes = attributes.getResourceId(R.styleable.UIButton_activeModeTintColorList, 0); + mNotificationModeTintColorListRes = attributes.getResourceId(R.styleable.UIButton_notificationModeTintColorList, 0); mTooltipDelay = attributes.getInt(R.styleable.UIButton_tooltipDelay, getResources().getInteger(R.integer.tooltip_delay)); mTooltipPosition = ViewUtils.TooltipPosition.fromId(attributes.getInt(R.styleable.UIButton_tooltipPosition, ViewUtils.TooltipPosition.BOTTOM.ordinal())); mTooltipDensity = attributes.getFloat(R.styleable.UIButton_tooltipDensity, getContext().getResources().getDisplayMetrics().density); @@ -163,6 +169,15 @@ public void setActiveMode(boolean isActive) { } } + public void setNotificationMode(boolean isNotification) { + if (isNotification) { + setNotification(); + + } else { + setNormal(); + } + } + public boolean isActive() { return mState == State.ACTIVE; } @@ -204,6 +219,13 @@ private void setActive() { } } + private void setNotification() { + mState = State.NOTIFICATION; + if (mActiveModeTintColorListRes != 0) { + setTintColorList(mNotificationModeTintColorListRes); + } + } + private Runnable mShowTooltipRunnable = new Runnable() { @Override public void run() { @@ -214,7 +236,31 @@ public void run() { mTooltipView = new TooltipWidget(getContext()); mTooltipView.setCurvedMode(mCurvedTooltip); mTooltipView.setText(getTooltip()); - mTooltipView.setLayoutParams(UIButton.this, mTooltipPosition, mTooltipDensity); + + Rect offsetViewBounds = new Rect(); + getDrawingRect(offsetViewBounds); + UIWidget parent = ViewUtils.getParentWidget(UIButton.this); + parent.offsetDescendantRectToMyCoords(UIButton.this, offsetViewBounds); + + float ratio = WidgetPlacement.viewToWidgetRatio(getContext(), parent); + + mTooltipView.getPlacement().parentHandle = parent.getHandle(); + mTooltipView.getPlacement().density = mTooltipDensity; + // At the moment we only support showing tooltips on top or bottom of the target view + if (mTooltipPosition == ViewUtils.TooltipPosition.BOTTOM) { + mTooltipView.getPlacement().anchorY = 1.0f; + mTooltipView.getPlacement().parentAnchorY = 0.0f; + mTooltipView.getPlacement().translationX = (offsetViewBounds.left + UIButton.this.getWidth() / 2.0f) * ratio; + mTooltipView.getPlacement().translationY = -offsetViewBounds.top * ratio; + + } else { + mTooltipView.getPlacement().anchorY = 0.0f; + mTooltipView.getPlacement().parentAnchorY = 1.0f; + mTooltipView.getPlacement().translationX = (offsetViewBounds.left + UIButton.this.getHeight() / 2.0f) * ratio; + mTooltipView.getPlacement().translationY = offsetViewBounds.top * ratio; + } + + mTooltipView.setCurvedMode(false); mTooltipView.show(UIWidget.CLEAR_FOCUS); } }; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TooltipWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TooltipWidget.java index 95fa284fa3..bd0cb56563 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TooltipWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/TooltipWidget.java @@ -1,32 +1,37 @@ package org.mozilla.vrbrowser.ui.widgets; import android.content.Context; -import android.graphics.PointF; -import android.graphics.Rect; -import android.view.View; +import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; + import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.utils.ViewUtils; +import org.mozilla.vrbrowser.utils.AnimationHelper; public class TooltipWidget extends UIWidget { - private View mTargetView; - private UIWidget mParentWidget; protected TextView mText; - private PointF mTranslation; - private float mRatio; - private float mDensityRatio; + protected ViewGroup mLayout; + + public TooltipWidget(@NonNull Context aContext, @NonNull @LayoutRes int layoutRes) { + super(aContext); + + initialize(layoutRes); + } public TooltipWidget(Context aContext) { super(aContext); - initialize(); + initialize(R.layout.tooltip); } - private void initialize() { - inflate(getContext(), R.layout.tooltip, this); + private void initialize(@NonNull @LayoutRes int layoutRes) { + inflate(getContext(), layoutRes, this); + mLayout = findViewById(R.id.layout); mText = findViewById(R.id.tooltipText); } @@ -46,58 +51,28 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { public void show(@ShowFlags int aShowFlags) { measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - mWidgetPlacement.translationX = mTranslation.x * (mRatio / mWidgetPlacement.density); - mWidgetPlacement.translationY = mTranslation.y * (mRatio / mWidgetPlacement.density); int paddingH = getPaddingStart() + getPaddingEnd(); int paddingV = getPaddingTop() + getPaddingBottom(); - mWidgetPlacement.width = (int)(WidgetPlacement.convertPixelsToDp(getContext(), getMeasuredWidth() + paddingH)/mDensityRatio); - mWidgetPlacement.height = (int)(WidgetPlacement.convertPixelsToDp(getContext(), getMeasuredHeight() + paddingV)/mDensityRatio); + mWidgetPlacement.width = (int)((getMeasuredWidth() + paddingH)/mWidgetPlacement.density); + mWidgetPlacement.height = (int)((getMeasuredHeight() + paddingV)/mWidgetPlacement.density); super.show(aShowFlags); + AnimationHelper.scaleIn(mLayout, 100, 0, null); } - public void setLayoutParams(View targetView) { - this.setLayoutParams(targetView, ViewUtils.TooltipPosition.BOTTOM); - } - - public void setLayoutParams(View targetView, ViewUtils.TooltipPosition position) { - this.setLayoutParams(targetView, position, mWidgetPlacement.density); - } - - public void setLayoutParams(View targetView, ViewUtils.TooltipPosition position, float density) { - mTargetView = targetView; - mParentWidget = ViewUtils.getParentWidget(mTargetView); - if (mParentWidget != null) { - mRatio = WidgetPlacement.worldToWidgetRatio(mParentWidget); - mWidgetPlacement.density = density; - mDensityRatio = mWidgetPlacement.density / getContext().getResources().getDisplayMetrics().density; - - Rect offsetViewBounds = new Rect(); - getDrawingRect(offsetViewBounds); - mParentWidget.offsetDescendantRectToMyCoords(mTargetView, offsetViewBounds); - - mWidgetPlacement.parentHandle = mParentWidget.getHandle(); - // At the moment we only support showing tooltips on top or bottom of the target view - if (position == ViewUtils.TooltipPosition.BOTTOM) { - mWidgetPlacement.anchorY = 1.0f; - mWidgetPlacement.parentAnchorY = 0.0f; - mTranslation = new PointF( - (offsetViewBounds.left + mTargetView.getWidth() / 2) * mDensityRatio, - -offsetViewBounds.top * mDensityRatio); - } else { - mWidgetPlacement.anchorY = 0.0f; - mWidgetPlacement.parentAnchorY = 1.0f; - mTranslation = new PointF( - (offsetViewBounds.left + mTargetView.getWidth() / 2) * mDensityRatio, - offsetViewBounds.top * mDensityRatio); - } - } + @Override + public void hide(int aHideFlags) { + AnimationHelper.scaleOut(mLayout, 100, 0, () -> TooltipWidget.super.hide(aHideFlags)); } public void setCurvedMode(boolean enabled) { mWidgetPlacement.cylinder = enabled; } + public void setText(@StringRes int stringRes) { + mText.setText(stringRes); + } + public void setText(String text) { mText.setText(text); } 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 a700716337..0859fba81c 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 @@ -8,6 +8,8 @@ import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; +import android.graphics.PointF; +import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -16,11 +18,14 @@ import androidx.annotation.NonNull; +import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.geckoview.GeckoSession; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; +import org.mozilla.vrbrowser.browser.BookmarksStore; import org.mozilla.vrbrowser.browser.SessionChangeListener; import org.mozilla.vrbrowser.browser.engine.SessionStack; +import org.mozilla.vrbrowser.browser.engine.SessionStore; import org.mozilla.vrbrowser.telemetry.TelemetryWrapper; import org.mozilla.vrbrowser.ui.views.UIButton; import org.mozilla.vrbrowser.ui.widgets.settings.SettingsWidget; @@ -35,6 +40,7 @@ public class TrayWidget extends UIWidget implements SessionChangeListener, Windo static final String LOGTAG = TrayWidget.class.getSimpleName(); private static final int ICON_ANIMATION_DURATION = 200; + private static final int LIBRARY_NOTIFICATION_DURATION = 3000; private UIButton mSettingsButton; private UIButton mPrivateButton; @@ -50,6 +56,7 @@ public class TrayWidget extends UIWidget implements SessionChangeListener, Windo private boolean mTrayVisible = true; private SessionStack mSessionStack; private WindowWidget mAttachedWindow; + private TooltipWidget mLibraryNotification; public TrayWidget(Context aContext) { super(aContext); @@ -291,6 +298,7 @@ public void detachFromWindow() { mSessionStack = null; } if (mAttachedWindow != null) { + SessionStore.get().getBookmarkStore().addListener(mBookmarksListener); mAttachedWindow.removeBookmarksViewListener(this); mAttachedWindow.removeHistoryViewListener(this); } @@ -310,6 +318,8 @@ public void attachToWindow(@NonNull WindowWidget aWindow) { mAttachedWindow.addBookmarksViewListener(this); mAttachedWindow.addHistoryViewListener(this); + SessionStore.get().getBookmarkStore().addListener(mBookmarksListener); + mSessionStack = aWindow.getSessionStack(); if (mSessionStack != null) { mSessionStack.addSessionChangeListener(this); @@ -441,4 +451,46 @@ public void onWidgetUpdate(Widget aWidget) { } } + private BookmarksStore.BookmarkListener mBookmarksListener = new BookmarksStore.BookmarkListener() { + @Override + public void onBookmarksUpdated() { + // Nothing to do + } + + @Override + public void onBookmarkAdded() { + mBookmarksButton.setNotificationMode(true); + ThreadUtils.postToUiThread(() -> { + if (mLibraryNotification != null && mLibraryNotification.isVisible()) { + return; + } + + Rect offsetViewBounds = new Rect(); + getDrawingRect(offsetViewBounds); + offsetDescendantRectToMyCoords(mBookmarksButton, offsetViewBounds); + + float ratio = WidgetPlacement.viewToWidgetRatio(getContext(), TrayWidget.this); + + mLibraryNotification = new TooltipWidget(getContext(), R.layout.library_notification); + mLibraryNotification.getPlacement().parentHandle = getHandle(); + mLibraryNotification.getPlacement().anchorY = 0.0f; + mLibraryNotification.getPlacement().translationX = (offsetViewBounds.left + mBookmarksButton.getWidth() / 2.0f) * ratio; + mLibraryNotification.getPlacement().translationY = ((offsetViewBounds.top - 60) * ratio); + mLibraryNotification.getPlacement().translationZ = 25.0f; + mLibraryNotification.getPlacement().density = 3.0f; + mLibraryNotification.setText(R.string.bookmarks_saved_notification); + mLibraryNotification.setCurvedMode(false); + mLibraryNotification.show(UIWidget.CLEAR_FOCUS); + + ThreadUtils.postDelayedToUiThread(() -> { + if (mLibraryNotification != null) { + mLibraryNotification.hide(UIWidget.REMOVE_WIDGET); + } + mBookmarksButton.setNotificationMode(false); + }, LIBRARY_NOTIFICATION_DURATION); + }); + } + }; + + } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java index eb207addfa..b58ec1a16a 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java @@ -25,6 +25,7 @@ import androidx.annotation.StringRes; import androidx.annotation.UiThread; +import org.jetbrains.annotations.NotNull; import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.geckoview.GeckoDisplay; import org.mozilla.geckoview.GeckoResult; @@ -37,14 +38,16 @@ import org.mozilla.vrbrowser.browser.engine.SessionStack; import org.mozilla.vrbrowser.browser.engine.SessionStore; import org.mozilla.vrbrowser.telemetry.TelemetryWrapper; +import org.mozilla.vrbrowser.ui.callbacks.BookmarksCallback; import org.mozilla.vrbrowser.ui.callbacks.HistoryCallback; -import org.mozilla.vrbrowser.ui.callbacks.HistoryItemContextMenuClickCallback; +import org.mozilla.vrbrowser.ui.callbacks.LibraryItemContextMenuClickCallback; import org.mozilla.vrbrowser.ui.views.BookmarksView; import org.mozilla.vrbrowser.ui.views.HistoryView; +import org.mozilla.vrbrowser.ui.views.LibraryItemContextMenu; import org.mozilla.vrbrowser.ui.widgets.dialogs.BaseAppDialogWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.ClearCacheDialogWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.ContextMenuWidget; -import org.mozilla.vrbrowser.ui.widgets.dialogs.HistoryItemContextMenuWidget; +import org.mozilla.vrbrowser.ui.widgets.dialogs.LibraryItemContextMenuWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.MaxWindowsWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.MessageDialogWidget; import org.mozilla.vrbrowser.ui.widgets.prompts.AlertPromptWidget; @@ -61,6 +64,7 @@ import java.util.Calendar; import java.util.GregorianCalendar; +import mozilla.components.concept.storage.BookmarkNode; import mozilla.components.concept.storage.PageObservation; import mozilla.components.concept.storage.VisitInfo; import mozilla.components.concept.storage.VisitType; @@ -76,12 +80,12 @@ public class WindowWidget extends UIWidget implements SessionChangeListener, public interface HistoryViewDelegate { default void onHistoryViewShown(WindowWidget aWindow) {} - default void onHistoryViewHidden(WindowWidget aWindow) {}; + default void onHistoryViewHidden(WindowWidget aWindow) {} } public interface BookmarksViewDelegate { - default void onBookmarksShown(WindowWidget aWindow) {}; - default void onBookmarksHidden(WindowWidget aWindow) {}; + default void onBookmarksShown(WindowWidget aWindow) {} + default void onBookmarksHidden(WindowWidget aWindow) {} } private int mSessionId; @@ -104,7 +108,7 @@ public interface BookmarksViewDelegate { private MessageDialogWidget mAppDialog; private ClearCacheDialogWidget mClearCacheDialog; private ContextMenuWidget mContextMenu; - private HistoryItemContextMenuWidget mHistoryContextMenu; + private LibraryItemContextMenuWidget mLibraryItemContextMenu; private int mWidthBackup; private int mHeightBackup; private int mBorderWidth; @@ -150,6 +154,7 @@ public WindowWidget(Context aContext, int windowId, boolean privateMode) { mSessionStack.newSession(); mBookmarksView = new BookmarksView(aContext); + mBookmarksView.setBookmarksCallback(mBookmarksCallback); mBookmarksViewListeners = new ArrayList<>(); mHistoryView = new HistoryView(aContext); @@ -262,45 +267,54 @@ protected void setRestored(boolean restored) { mIsRestored = restored; } - private void setView(View view) { - pauseCompositor(); + private void setView(View view, boolean switchSurface) { + if (switchSurface) { + pauseCompositor(); + } + mView = view; removeView(view); mView.setVisibility(VISIBLE); addView(mView); - mWidgetPlacement.density = getContext().getResources().getDisplayMetrics().density; - if (mTexture != null && mSurface != null && mRenderer == null) { - // Create the UI Renderer for the current surface. - // Surface must be released when switching back to WebView surface or the browser - // will not render it correctly. See release code in unsetView(). - mRenderer = new UISurfaceTextureRenderer(mSurface, mWidgetPlacement.textureWidth(), mWidgetPlacement.textureHeight()); + + if (switchSurface) { + mWidgetPlacement.density = getContext().getResources().getDisplayMetrics().density; + if (mTexture != null && mSurface != null && mRenderer == null) { + // Create the UI Renderer for the current surface. + // Surface must be released when switching back to WebView surface or the browser + // will not render it correctly. See release code in unsetView(). + mRenderer = new UISurfaceTextureRenderer(mSurface, mWidgetPlacement.textureWidth(), mWidgetPlacement.textureHeight()); + } + mWidgetManager.updateWidget(this); + mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS); + mWidgetManager.pushBackHandler(mBackHandler); + setWillNotDraw(false); + postInvalidate(); } - mWidgetManager.updateWidget(this); - mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS); - mWidgetManager.pushBackHandler(mBackHandler); - setWillNotDraw(false); - postInvalidate(); } - private void unsetView(View view) { + private void unsetView(View view, boolean switchSurface) { if (mView != null && mView == view) { mView = null; removeView(view); view.setVisibility(GONE); - setWillNotDraw(true); - if (mTexture != null) { - // Surface must be recreated here when not using layers. - // When using layers the new Surface is received via the setSurface() method. - if (mRenderer != null) { - mRenderer.release(); - mRenderer = null; + + if (switchSurface) { + setWillNotDraw(true); + if (mTexture != null) { + // Surface must be recreated here when not using layers. + // When using layers the new Surface is received via the setSurface() method. + if (mRenderer != null) { + mRenderer.release(); + mRenderer = null; + } + mSurface = new Surface(mTexture); } - mSurface = new Surface(mTexture); + mWidgetPlacement.density = 1.0f; + mWidgetManager.updateWidget(this); + mWidgetManager.popWorldBrightness(this); + mWidgetManager.popBackHandler(mBackHandler); } - mWidgetPlacement.density = 1.0f; - mWidgetManager.updateWidget(this); - mWidgetManager.popWorldBrightness(this); - mWidgetManager.popBackHandler(mBackHandler); } } @@ -330,8 +344,8 @@ public void removeHistoryViewListener(@NonNull HistoryViewDelegate listener) { public void switchBookmarks() { if (isHistoryVisible()) { - hideHistory(); - showBookmarks(); + hideHistory(false); + showBookmarks(false); } else if (isBookmarksVisible()) { hideBookmarks(); @@ -342,8 +356,12 @@ public void switchBookmarks() { } public void showBookmarks() { + showBookmarks(true); + } + + public void showBookmarks(boolean switchSurface) { if (mView == null) { - setView(mBookmarksView); + setView(mBookmarksView, switchSurface); for (BookmarksViewDelegate listener : mBookmarksViewListeners) { listener.onBookmarksShown(this); } @@ -354,8 +372,12 @@ public void showBookmarks() { } public void hideBookmarks() { + hideBookmarks(true); + } + + public void hideBookmarks(boolean switchSurface) { if (mView != null) { - unsetView(mBookmarksView); + unsetView(mBookmarksView, switchSurface); for (BookmarksViewDelegate listener : mBookmarksViewListeners) { listener.onBookmarksHidden(this); } @@ -365,8 +387,8 @@ public void hideBookmarks() { public void switchHistory() { if (isBookmarksVisible()) { - hideBookmarks(); - showHistory(); + hideBookmarks(false); + showHistory(false); } else if (isHistoryVisible()) { hideHistory(); @@ -377,8 +399,12 @@ public void switchHistory() { } public void showHistory() { + showHistory(true); + } + + public void showHistory(boolean switchSurface) { if (mView == null) { - setView(mHistoryView); + setView(mHistoryView, switchSurface); for (HistoryViewDelegate listener : mHistoryViewListeners) { listener.onHistoryViewShown(this); } @@ -387,8 +413,12 @@ public void showHistory() { } public void hideHistory() { + hideHistory(true); + } + + public void hideHistory(boolean switchSurface) { if (mView != null) { - unsetView(mHistoryView); + unsetView(mHistoryView, switchSurface); for (HistoryViewDelegate listener : mHistoryViewListeners) { listener.onHistoryViewHidden(this); } @@ -1066,66 +1096,95 @@ private int getWindowWidth(float aWorldWidth) { return (int) Math.floor(SettingsStore.WINDOW_WIDTH_DEFAULT * aWorldWidth / WidgetPlacement.floatDimension(getContext(), R.dimen.window_world_width)); } - private HistoryCallback mHistoryCallback = new HistoryCallback() { - @Override - public void onClearHistory(View view) { - view.requestFocusFromTouch(); - showClearCacheDialog(); + private void showLibraryItemContextMenu(@NotNull View view, LibraryItemContextMenu.LibraryContextMenuItem item, boolean isLastVisibleItem) { + view.requestFocusFromTouch(); + + if (mLibraryItemContextMenu != null) { + mLibraryItemContextMenu.hide(REMOVE_WIDGET); } - @Override - public void onShowContextMenu(View view, VisitInfo item, boolean isLastVisibleItem) { - view.requestFocusFromTouch(); + float ratio = WidgetPlacement.viewToWidgetRatio(getContext(), WindowWidget.this); - if (mHistoryContextMenu != null) { - mHistoryContextMenu.hide(REMOVE_WIDGET); - } + Rect offsetViewBounds = new Rect(); + getDrawingRect(offsetViewBounds); + offsetDescendantRectToMyCoords(view, offsetViewBounds); - float ratio = WidgetPlacement.viewToWidgetRatio(getContext(), WindowWidget.this); + mLibraryItemContextMenu = new LibraryItemContextMenuWidget(getContext()); + mLibraryItemContextMenu.mWidgetPlacement.parentHandle = getHandle(); - Rect offsetViewBounds = new Rect(); - getDrawingRect(offsetViewBounds); - offsetDescendantRectToMyCoords(view, offsetViewBounds); + PointF position; + if (isLastVisibleItem) { + mLibraryItemContextMenu.mWidgetPlacement.anchorY = 0.0f; + position = new PointF( + (offsetViewBounds.left + view.getWidth()) * ratio, + -(offsetViewBounds.top) * ratio); - mHistoryContextMenu = new HistoryItemContextMenuWidget(getContext()); - mHistoryContextMenu.mWidgetPlacement.parentHandle = getHandle(); + } else { + mLibraryItemContextMenu.mWidgetPlacement.anchorY = 1.0f; + position = new PointF( + (offsetViewBounds.left + view.getWidth()) * ratio, + -(offsetViewBounds.top + view.getHeight()) * ratio); + } - PointF position; - if (isLastVisibleItem) { - mHistoryContextMenu.mWidgetPlacement.anchorY = 0.0f; - position = new PointF( - (offsetViewBounds.left + view.getWidth()) * ratio, - -(offsetViewBounds.top) * ratio); + mLibraryItemContextMenu.setPosition(position); + mLibraryItemContextMenu.setItem(item); + mLibraryItemContextMenu.setHistoryContextMenuItemCallback((new LibraryItemContextMenuClickCallback() { + @Override + public void onOpenInNewWindowClick(LibraryItemContextMenu.LibraryContextMenuItem item) { + mWidgetManager.openNewWindow(item.getUrl()); + mLibraryItemContextMenu.hide(REMOVE_WIDGET); + } - } else { - mHistoryContextMenu.mWidgetPlacement.anchorY = 1.0f; - position = new PointF( - (offsetViewBounds.left + view.getWidth()) * ratio, - -(offsetViewBounds.top + view.getHeight()) * ratio); + @Override + public void onAddToBookmarks(LibraryItemContextMenu.LibraryContextMenuItem item) { + SessionStore.get().getBookmarkStore().addBookmark(item.getUrl(), item.getTitle()); + mLibraryItemContextMenu.hide(REMOVE_WIDGET); } - mHistoryContextMenu.setPosition(position); - mHistoryContextMenu.setItem(item); - mHistoryContextMenu.setHistoryContextMenuItemCallback((new HistoryItemContextMenuClickCallback() { - @Override - public void onOpenInNewWindowClick(VisitInfo item) { - mWidgetManager.openNewWindow(item.getUrl()); - mHistoryContextMenu.hide(REMOVE_WIDGET); - } + @Override + public void onRemoveFromBookmarks(LibraryItemContextMenu.LibraryContextMenuItem item) { + SessionStore.get().getBookmarkStore().deleteBookmarkByURL(item.getUrl()); + mLibraryItemContextMenu.hide(REMOVE_WIDGET); + } + })); + mLibraryItemContextMenu.show(REQUEST_FOCUS); + } - @Override - public void onAddToBookmarks(VisitInfo item) { - SessionStore.get().getBookmarkStore().addBookmark(item.getUrl(), item.getTitle()); - mHistoryContextMenu.hide(REMOVE_WIDGET); - } + private BookmarksCallback mBookmarksCallback = new BookmarksCallback() { - @Override - public void onRemoveFromBookmarks(VisitInfo item) { - SessionStore.get().getBookmarkStore().deleteBookmarkByURL(item.getUrl()); - mHistoryContextMenu.hide(REMOVE_WIDGET); - } - })); - mHistoryContextMenu.show(REQUEST_FOCUS); + @Override + public void onClearBookmarks(View view) { + // Not used ATM + } + + @Override + public void onShowContextMenu(@NonNull View view, @NotNull BookmarkNode item, boolean isLastVisibleItem) { + showLibraryItemContextMenu( + view, + new LibraryItemContextMenu.LibraryContextMenuItem( + item.getUrl(), + item.getTitle(), + LibraryItemContextMenu.LibraryItemType.BOOKMARKS), + isLastVisibleItem); + } + }; + + private HistoryCallback mHistoryCallback = new HistoryCallback() { + @Override + public void onClearHistory(@NonNull View view) { + view.requestFocusFromTouch(); + showClearCacheDialog(); + } + + @Override + public void onShowContextMenu(@NonNull View view, @NonNull VisitInfo item, boolean isLastVisibleItem) { + showLibraryItemContextMenu( + view, + new LibraryItemContextMenu.LibraryContextMenuItem( + item.getUrl(), + item.getTitle(), + LibraryItemContextMenu.LibraryItemType.HISTORY), + isLastVisibleItem); } }; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/HistoryItemContextMenuWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/LibraryItemContextMenuWidget.java similarity index 77% rename from app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/HistoryItemContextMenuWidget.java rename to app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/LibraryItemContextMenuWidget.java index f32d6f9920..9de3aac870 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/HistoryItemContextMenuWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/LibraryItemContextMenuWidget.java @@ -14,39 +14,38 @@ import androidx.annotation.NonNull; import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.ui.callbacks.HistoryItemContextMenuClickCallback; -import org.mozilla.vrbrowser.ui.views.HistoryItemContextMenu; +import org.mozilla.vrbrowser.ui.callbacks.LibraryItemContextMenuClickCallback; +import org.mozilla.vrbrowser.ui.views.LibraryItemContextMenu; import org.mozilla.vrbrowser.ui.widgets.UIWidget; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.ViewUtils; -import mozilla.components.concept.storage.VisitInfo; +public class LibraryItemContextMenuWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { -public class HistoryItemContextMenuWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { - - private HistoryItemContextMenu mContextMenu; + private LibraryItemContextMenu mContextMenu; private int mMaxHeight; private PointF mTranslation; + private int height; - public HistoryItemContextMenuWidget(Context aContext) { + public LibraryItemContextMenuWidget(Context aContext) { super(aContext); - mContextMenu = new HistoryItemContextMenu(aContext); + mContextMenu = new LibraryItemContextMenu(aContext); initialize(); } - public HistoryItemContextMenuWidget(Context aContext, AttributeSet aAttrs) { + public LibraryItemContextMenuWidget(Context aContext, AttributeSet aAttrs) { super(aContext, aAttrs); - mContextMenu = new HistoryItemContextMenu(aContext, aAttrs); + mContextMenu = new LibraryItemContextMenu(aContext, aAttrs); initialize(); } - public HistoryItemContextMenuWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { + public LibraryItemContextMenuWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { super(aContext, aAttrs, aDefStyle); - mContextMenu = new HistoryItemContextMenu(aContext, aAttrs, aDefStyle); + mContextMenu = new LibraryItemContextMenu(aContext, aAttrs, aDefStyle); initialize(); } @@ -71,7 +70,7 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { @Override public void show(@ShowFlags int aShowFlags) { - mWidgetManager.addFocusChangeListener(HistoryItemContextMenuWidget.this); + mWidgetManager.addFocusChangeListener(LibraryItemContextMenuWidget.this); measure(View.MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); @@ -89,9 +88,9 @@ public void onGlobalLayout() { mWidgetPlacement.translationX = mTranslation.x - (getWidth()/mWidgetPlacement.density); mWidgetPlacement.translationY = mTranslation.y + getResources().getDimension(R.dimen.library_context_menu_top_margin)/mWidgetPlacement.density; - mWidgetPlacement.width = (int)(getWidth()/mWidgetPlacement.density); - mWidgetPlacement.height = (int)(getHeight()/mWidgetPlacement.density); - mWidgetManager.updateWidget(HistoryItemContextMenuWidget.this); + mWidgetPlacement.width = (int)((getWidth() + 5)/mWidgetPlacement.density); + mWidgetPlacement.height = mContextMenu.getMenuHeight() + 5; + mWidgetManager.updateWidget(LibraryItemContextMenuWidget.this); } }); } @@ -109,11 +108,11 @@ protected void onDismiss() { hide(REMOVE_WIDGET); } - public void setHistoryContextMenuItemCallback(HistoryItemContextMenuClickCallback callback) { + public void setHistoryContextMenuItemCallback(LibraryItemContextMenuClickCallback callback) { mContextMenu.setContextMenuClickCallback(callback); } - public void setItem(@NonNull VisitInfo item) { + public void setItem(@NonNull LibraryItemContextMenu.LibraryContextMenuItem item) { mContextMenu.setItem(item); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/utils/AnimationHelper.java b/app/src/common/shared/org/mozilla/vrbrowser/utils/AnimationHelper.java index fefd683f20..c5f83f4063 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/utils/AnimationHelper.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/utils/AnimationHelper.java @@ -1,6 +1,7 @@ package org.mozilla.vrbrowser.utils; import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.util.Log; import android.view.View; @@ -10,6 +11,10 @@ import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; +import androidx.annotation.NonNull; + +import org.mozilla.gecko.util.ThreadUtils; + public class AnimationHelper { public static final long FADE_ANIMATION_DURATION = 150; @@ -110,4 +115,30 @@ public void onAnimationRepeat(Animator animator) { }); animation.start(); } + + public static void scaleIn(@NonNull View aView, long duration, long delay, final Runnable aCallback) { + aView.setScaleX(0); + aView.setScaleY(0); + aView.animate().setStartDelay(delay).scaleX(1f).scaleY(1f).setDuration(duration).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (aCallback != null) + ThreadUtils.postToUiThread(aCallback); + } + }).setUpdateListener(animation -> aView.invalidate()); + } + + public static void scaleOut(@NonNull View aView, long duration, long delay, final Runnable aCallback) { + aView.setScaleX(1); + aView.setScaleY(1); + aView.animate().setStartDelay(delay).scaleX(0f).scaleY(0f).setDuration(duration).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (aCallback != null) + ThreadUtils.postToUiThread(aCallback); + } + }).setUpdateListener(animation -> aView.invalidate()); + } } diff --git a/app/src/main/res/drawable/library_panel_context_menu_item_background_color_bottom.xml b/app/src/main/res/drawable/library_context_menu_item_background_bottom.xml similarity index 100% rename from app/src/main/res/drawable/library_panel_context_menu_item_background_color_bottom.xml rename to app/src/main/res/drawable/library_context_menu_item_background_bottom.xml diff --git a/app/src/main/res/drawable/library_panel_context_menu_item_background_color_middle.xml b/app/src/main/res/drawable/library_context_menu_item_background_middle.xml similarity index 100% rename from app/src/main/res/drawable/library_panel_context_menu_item_background_color_middle.xml rename to app/src/main/res/drawable/library_context_menu_item_background_middle.xml diff --git a/app/src/main/res/drawable/library_context_menu_item_background_single.xml b/app/src/main/res/drawable/library_context_menu_item_background_single.xml new file mode 100644 index 0000000000..7c243ee02e --- /dev/null +++ b/app/src/main/res/drawable/library_context_menu_item_background_single.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/library_panel_context_menu_item_background_color_top.xml b/app/src/main/res/drawable/library_context_menu_item_background_top.xml similarity index 100% rename from app/src/main/res/drawable/library_panel_context_menu_item_background_color_top.xml rename to app/src/main/res/drawable/library_context_menu_item_background_top.xml diff --git a/app/src/main/res/drawable/library_panel_item_background_color.xml b/app/src/main/res/drawable/library_item_background_color.xml similarity index 100% rename from app/src/main/res/drawable/library_panel_item_background_color.xml rename to app/src/main/res/drawable/library_item_background_color.xml diff --git a/app/src/main/res/drawable/library_notification_background.xml b/app/src/main/res/drawable/library_notification_background.xml new file mode 100644 index 0000000000..fe67ba0a17 --- /dev/null +++ b/app/src/main/res/drawable/library_notification_background.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/library_notification_background_triangle.xml b/app/src/main/res/drawable/library_notification_background_triangle.xml new file mode 100644 index 0000000000..4d409349aa --- /dev/null +++ b/app/src/main/res/drawable/library_notification_background_triangle.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/main_button_icon_color_notification.xml b/app/src/main/res/drawable/main_button_icon_color_notification.xml new file mode 100644 index 0000000000..c9847983e1 --- /dev/null +++ b/app/src/main/res/drawable/main_button_icon_color_notification.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/bookmark_item.xml b/app/src/main/res/layout/bookmark_item.xml index 2ad2b3872e..708497091d 100644 --- a/app/src/main/res/layout/bookmark_item.xml +++ b/app/src/main/res/layout/bookmark_item.xml @@ -1,73 +1,133 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> + type="org.mozilla.vrbrowser.ui.callbacks.BookmarkItemCallback" /> + + - - - + android:layout_height="@dimen/library_item_row_height" + android:background="@color/void_color"> - + android:layout_height="match_parent" + android:background="@drawable/library_item_background_color" + android:clickable="true" + android:descendantFocusability="blocksDescendants" + android:focusable="true" + android:gravity="center_vertical" + android:onClick="@{(view) -> callback.onClick(view, item)}" + android:paddingStart="10dp" + android:paddingEnd="10dp" + android:soundEffectsEnabled="false"> + + + + + + + + + + + + + - - + + + + + diff --git a/app/src/main/res/layout/bookmarks.xml b/app/src/main/res/layout/bookmarks.xml index 62300df871..514cff3833 100644 --- a/app/src/main/res/layout/bookmarks.xml +++ b/app/src/main/res/layout/bookmarks.xml @@ -1,5 +1,6 @@ - @@ -11,6 +12,10 @@ + + + android:paddingStart="30dp" + android:paddingTop="30dp" + android:paddingEnd="30dp" + android:paddingBottom="30dp"> + app:visibleGone="@{!isLoading && isEmpty}"> + + - + android:layout_marginEnd="20dp" + android:layout_marginBottom="20dp" + app:visibleGone="@{!isLoading && !isEmpty}"> + + + + + @@ -47,7 +47,7 @@ android:layout_height="wrap_content" android:layout_marginTop="35dp" android:fontFamily="sans-serif" - android:text="@string/history_title" + android:text="@string/history_empty" android:textAlignment="center" android:textAllCaps="false" android:textColor="@color/fog" diff --git a/app/src/main/res/layout/history_item.xml b/app/src/main/res/layout/history_item.xml index 863a1af66c..55d7b87534 100644 --- a/app/src/main/res/layout/history_item.xml +++ b/app/src/main/res/layout/history_item.xml @@ -21,7 +21,7 @@ + tools:text="Item Title" /> @@ -94,7 +94,7 @@ android:singleLine="true" android:text="@{item.url}" android:textColor="@color/library_panel_description_color" - android:textSize="@dimen/history_url_text_size" + android:textSize="@dimen/library_item_url_text_size" tools:text="http://mozilla.org" /> @@ -116,7 +116,7 @@ android:scrollHorizontally="true" android:singleLine="true" android:textColor="@color/library_panel_description_color" - android:textSize="@dimen/history_date_text_size" + android:textSize="@dimen/library_item_date_text_size" app:bindDate="@{item.visitTime}" app:visibleInvisible="@{!isHovered}" tools:text="8/2/19, 2:18 PM" /> diff --git a/app/src/main/res/layout/history_item_context_menu.xml b/app/src/main/res/layout/library_item_context_menu.xml similarity index 81% rename from app/src/main/res/layout/history_item_context_menu.xml rename to app/src/main/res/layout/library_item_context_menu.xml index c5fafc2468..f61f2eb835 100644 --- a/app/src/main/res/layout/history_item_context_menu.xml +++ b/app/src/main/res/layout/library_item_context_menu.xml @@ -3,13 +3,15 @@ xmlns:tools="http://schemas.android.com/tools"> + + + type="org.mozilla.vrbrowser.ui.callbacks.LibraryItemContextMenuClickCallback" /> + type="org.mozilla.vrbrowser.ui.views.LibraryItemContextMenu.LibraryContextMenuItem" /> diff --git a/app/src/main/res/layout/library_notification.xml b/app/src/main/res/layout/library_notification.xml new file mode 100644 index 0000000000..e6a2302dad --- /dev/null +++ b/app/src/main/res/layout/library_notification.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 8cc0bee6e2..1c159db98f 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -18,6 +18,7 @@ + diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimen.xml index 3e800275b2..6e9475779a 100644 --- a/app/src/main/res/values/dimen.xml +++ b/app/src/main/res/values/dimen.xml @@ -127,7 +127,7 @@ 1.2 206dp 40dp - 4.0 + 4.5 585dp @@ -197,15 +197,15 @@ 2dp 0dp - - 64dp - - - 38dp - 18sp - 20sp - 16sp - 16sp + + 55dp + 18sp + 20sp + 16sp + 16sp + 2dp + 0dp + 13sp 22dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f34dedcbc3..0abf750022 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -636,6 +636,12 @@ Bookmarks + + Your Bookmarks List is Empty + + + Click the @ icon when you’re on a page to add it to your bookmarks. + Loading Bookmarks @@ -644,6 +650,10 @@ item listed in the Bookmarks List. --> Remove Bookmark + + Saved to Bookmarks! + @@ -666,6 +676,9 @@ History + + Your History is Empty + You can access your browsing history here diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 761c2e2ed7..d4a57879b1 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -65,6 +65,7 @@ @drawable/main_button_icon_color @drawable/main_button_icon_color_private @drawable/main_button_icon_color_active + @drawable/main_button_icon_color_notification