Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc04eee6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes Iac617598,I59fe4951,I374dc97a,Id882cff6,Ie3b4c571, ... into sc-v2-dev am: 3708e854

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16072876

Change-Id: I5b3167a308be3fac8fa3d9049a49d8d6e91dfce6
parents c71885b9 3708e854
Loading
Loading
Loading
Loading
+95 −3
Original line number Diff line number Diff line
@@ -1526,6 +1526,24 @@ public class NotificationPanelViewController extends PanelViewController {
        mNotificationStackScrollLayoutController.resetScrollPosition();
    }

    /** Collapses the panel. */
    public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
        boolean waiting = false;
        if (animate && !isFullyCollapsed()) {
            collapse(delayed, speedUpFactor);
            waiting = true;
        } else {
            resetViews(false /* animate */);
            setExpandedFraction(0); // just in case
        }
        if (!waiting) {
            // it's possible that nothing animated, so we replicate the termination
            // conditions of panelExpansionChanged here
            // TODO(b/200063118): This can likely go away in a future refactor CL.
            mBar.updateState(STATE_CLOSED);
        }
    }

    @Override
    public void collapse(boolean delayed, float speedUpFactor) {
        if (!canPanelBeCollapsed()) {
@@ -2967,7 +2985,7 @@ public class NotificationPanelViewController extends PanelViewController {

    @Override
    protected void onExpandingFinished() {
        super.onExpandingFinished();
        mScrimController.onExpandingFinished();
        mNotificationStackScrollLayoutController.onExpansionStopped();
        mHeadsUpManager.onExpandingFinished();
        mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed());
@@ -3042,6 +3060,7 @@ public class NotificationPanelViewController extends PanelViewController {
    protected void onTrackingStarted() {
        mFalsingCollector.onTrackingStarted(!mKeyguardStateController.canDismissLockScreen());
        super.onTrackingStarted();
        mScrimController.onTrackingStarted();
        if (mQsFullyExpanded) {
            mQsExpandImmediate = true;
            if (!mShouldUseSplitNotificationShade) {
@@ -3052,6 +3071,7 @@ public class NotificationPanelViewController extends PanelViewController {
            mAffordanceHelper.animateHideLeftRightIcon();
        }
        mNotificationStackScrollLayoutController.onPanelTrackingStarted();
        cancelPendingPanelCollapse();
    }

    @Override
@@ -3241,7 +3261,7 @@ public class NotificationPanelViewController extends PanelViewController {

    @Override
    protected void onClosingFinished() {
        super.onClosingFinished();
        mStatusBar.onClosingFinished();
        setClosingWithAlphaFadeout(false);
        mMediaHierarchyManager.closeGuts();
    }
@@ -3671,13 +3691,27 @@ public class NotificationPanelViewController extends PanelViewController {
        mNotificationStackScrollLayoutController.setScrollingEnabled(b);
    }

    private Runnable mHideExpandedRunnable;
    private final Runnable mMaybeHideExpandedRunnable = new Runnable() {
        @Override
        public void run() {
            if (getExpansionFraction() == 0.0f) {
                mView.post(mHideExpandedRunnable);
            }
        }
    };

    /**
     * Initialize objects instead of injecting to avoid circular dependencies.
     *
     * @param hideExpandedRunnable a runnable to run when we need to hide the expanded panel.
     */
    public void initDependencies(
            StatusBar statusBar,
            Runnable hideExpandedRunnable,
            NotificationShelfController notificationShelfController) {
        setStatusBar(statusBar);
        mHideExpandedRunnable = hideExpandedRunnable;
        mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
        mNotificationShelfController = notificationShelfController;
        mLockscreenShadeTransitionController.bindController(notificationShelfController);
@@ -3733,6 +3767,45 @@ public class NotificationPanelViewController extends PanelViewController {

            private long mLastTouchDownTime = -1L;

            @Override
            public boolean onTouchForwardedFromStatusBar(MotionEvent event) {
                // TODO(b/202981994): Move the touch debugging in this method to a central location.
                //  (Right now, it's split between StatusBar and here.)

                // If panels aren't enabled, ignore the gesture and don't pass it down to the
                // panel view.
                if (!mCommandQueue.panelsEnabled()) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        Log.v(
                                TAG,
                                String.format(
                                        "onTouchForwardedFromStatusBar: "
                                                + "panel disabled, ignoring touch at (%d,%d)",
                                        (int) event.getX(),
                                        (int) event.getY()
                                )
                        );
                    }
                    return false;
                }

                // If the view that would receive the touch is disabled, just have status bar eat
                // the gesture.
                if (event.getAction() == MotionEvent.ACTION_DOWN && !mView.isEnabled()) {
                    Log.v(TAG,
                            String.format(
                                    "onTouchForwardedFromStatusBar: "
                                            + "panel view disabled, eating touch at (%d,%d)",
                                    (int) event.getX(),
                                    (int) event.getY()
                            )
                    );
                    return true;
                }

                return mView.dispatchTouchEvent(event);
            }

            @Override
            public boolean onInterceptTouchEvent(MotionEvent event) {
                if (mBlockTouches || mQs.disallowPanelTouches()) {
@@ -3744,7 +3817,7 @@ public class NotificationPanelViewController extends PanelViewController {
                if (mStatusBar.isBouncerShowing()) {
                    return true;
                }
                if (mBar.panelEnabled()
                if (mCommandQueue.panelsEnabled()
                        && !mNotificationStackScrollLayoutController.isLongPressInProgress()
                        && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
                    mMetricsLogger.count(COUNTER_PANEL_OPEN, 1);
@@ -4568,6 +4641,11 @@ public class NotificationPanelViewController extends PanelViewController {
        }
    }

    /** Removes any pending runnables that would collapse the panel. */
    public void cancelPendingPanelCollapse() {
        mView.removeCallbacks(mMaybeHideExpandedRunnable);
    }

    private final PanelBar.PanelStateChangeListener mPanelStateChangeListener =
            new PanelBar.PanelStateChangeListener() {

@@ -4582,6 +4660,14 @@ public class NotificationPanelViewController extends PanelViewController {
                    if (state == STATE_OPEN && mCurrentState != state) {
                        mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
                    }
                    if (state == STATE_OPENING) {
                        mStatusBar.makeExpandedVisible(false);
                    }
                    if (state == STATE_CLOSED) {
                        // Close the status bar in the next frame so we can show the end of the
                        // animation.
                        mView.post(mMaybeHideExpandedRunnable);
                    }
                    mCurrentState = state;
                }
            };
@@ -4589,4 +4675,10 @@ public class NotificationPanelViewController extends PanelViewController {
    public PanelBar.PanelStateChangeListener getPanelStateChangeListener() {
        return mPanelStateChangeListener;
    }


    /** Returns the handler that the status bar should forward touches to. */
    public PhoneStatusBarView.TouchEventHandler getStatusBarTouchEventHandler() {
        return getTouchHandler()::onTouchForwardedFromStatusBar;
    }
}
+8 −82
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;
@@ -53,11 +52,18 @@ public abstract class PanelBar extends FrameLayout {
    public static final int STATE_OPENING = 1;
    public static final int STATE_OPEN = 2;

    private PanelViewController mPanel;
    @Nullable private PanelStateChangeListener mPanelStateChangeListener;
    private int mState = STATE_CLOSED;
    private boolean mTracking;

    /** Updates the panel state if necessary. */
    public void updateState(@PanelState int state) {
        if (DEBUG) LOG("update state: %d -> %d", mState, state);
        if (mState != state) {
            go(state);
        }
    }

    private void go(@PanelState int state) {
        if (DEBUG) LOG("go state: %d -> %d", mState, state);
        mState = state;
@@ -97,54 +103,11 @@ public abstract class PanelBar extends FrameLayout {
        super.onFinishInflate();
    }

    /** Set the PanelViewController */
    public void setPanel(PanelViewController pv) {
        mPanel = pv;
        pv.setBar(this);
    }

    /** Sets the listener that will be notified of panel state changes. */
    public void setPanelStateChangeListener(PanelStateChangeListener listener) {
        mPanelStateChangeListener = listener;
    }

    public boolean panelEnabled() {
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Allow subclasses to implement enable/disable semantics
        if (!panelEnabled()) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
                        (int) event.getX(), (int) event.getY()));
            }
            return false;
        }

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            final PanelViewController panel = mPanel;
            if (panel == null) {
                // panel is not there, so we'll eat the gesture
                Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
                        (int) event.getX(), (int) event.getY()));
                return true;
            }
            boolean enabled = panel.isEnabled();
            if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
                    (enabled ? "" : " (disabled)"));
            if (!enabled) {
                // panel is disabled, so we'll eat the gesture
                Log.v(TAG, String.format(
                        "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
                        panel, (int) event.getX(), (int) event.getY()));
                return true;
            }
        }
        return mPanel == null || mPanel.getView().dispatchTouchEvent(event);
    }

    /**
     * @param frac the fraction from the expansion in [0, 1]
     * @param expanded whether the panel is currently expanded; this is independent from the
@@ -162,7 +125,6 @@ public abstract class PanelBar extends FrameLayout {
        if (expanded) {
            if (mState == STATE_CLOSED) {
                go(STATE_OPENING);
                onPanelPeeked();
            }
            fullyClosed = false;
            fullyOpened = frac >= 1f;
@@ -171,44 +133,16 @@ public abstract class PanelBar extends FrameLayout {
            go(STATE_OPEN);
        } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
            go(STATE_CLOSED);
            onPanelCollapsed();
        }

        if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
                fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":"");
    }

    public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
        boolean waiting = false;
        PanelViewController pv = mPanel;
        if (animate && !pv.isFullyCollapsed()) {
            pv.collapse(delayed, speedUpFactor);
            waiting = true;
        } else {
            pv.resetViews(false /* animate */);
            pv.setExpandedFraction(0); // just in case
        }
        if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting);
        if (!waiting && mState != STATE_CLOSED) {
            // it's possible that nothing animated, so we replicate the termination
            // conditions of panelExpansionChanged here
            go(STATE_CLOSED);
            onPanelCollapsed();
        }
    }

    public void onPanelPeeked() {
        if (DEBUG) LOG("onPanelPeeked");
    }

    public boolean isClosed() {
        return mState == STATE_CLOSED;
    }

    public void onPanelCollapsed() {
        if (DEBUG) LOG("onPanelCollapsed");
    }

    public void onTrackingStarted() {
        mTracking = true;
    }
@@ -217,14 +151,6 @@ public abstract class PanelBar extends FrameLayout {
        mTracking = false;
    }

    public void onExpandingFinished() {
        if (DEBUG) LOG("onExpandingFinished");
    }

    public void onClosingFinished() {

    }

    /** An interface that will be notified of panel state changes. */
    public interface PanelStateChangeListener {
        /** Called when the state changes. */
+28 −16
Original line number Diff line number Diff line
@@ -185,10 +185,9 @@ public abstract class PanelViewController {
    protected final SysuiStatusBarStateController mStatusBarStateController;
    protected final AmbientState mAmbientState;
    protected final LockscreenGestureLogger mLockscreenGestureLogger;
    private final TouchHandler mTouchHandler;

    protected void onExpandingFinished() {
        mBar.onExpandingFinished();
    }
    protected abstract void onExpandingFinished();

    protected void onExpandingStarted() {
    }
@@ -226,6 +225,7 @@ public abstract class PanelViewController {
        mView = view;
        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
        mLockscreenGestureLogger = lockscreenGestureLogger;
        mTouchHandler = createTouchHandler();
        mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View v) {
@@ -238,7 +238,7 @@ public abstract class PanelViewController {
        });

        mView.addOnLayoutChangeListener(createLayoutChangeListener());
        mView.setOnTouchListener(createTouchHandler());
        mView.setOnTouchListener(mTouchHandler);
        mView.setOnConfigurationChangedListener(createOnConfigurationChangedListener());

        mResources = mView.getResources();
@@ -289,6 +289,10 @@ public abstract class PanelViewController {
                : mTouchSlop;
    }

    protected TouchHandler getTouchHandler() {
        return mTouchHandler;
    }

    private void addMovement(MotionEvent event) {
        // Add movement to velocity tracker using raw screen X and Y coordinates instead
        // of window coordinates because the window frame may be moving at the same time.
@@ -448,6 +452,7 @@ public abstract class PanelViewController {
    protected void onTrackingStopped(boolean expand) {
        mTracking = false;
        mBar.onTrackingStopped(expand);
        mStatusBar.onTrackingStopped(expand);
        updatePanelExpansionAndVisibility();
    }

@@ -455,6 +460,7 @@ public abstract class PanelViewController {
        endClosing();
        mTracking = true;
        mBar.onTrackingStarted();
        mStatusBar.onTrackingStarted();
        notifyExpandingStarted();
        updatePanelExpansionAndVisibility();
    }
@@ -927,10 +933,7 @@ public abstract class PanelViewController {
        mView.removeCallbacks(mFlingCollapseRunnable);
    }

    protected void onClosingFinished() {
        mBar.onClosingFinished();
    }

    protected abstract void onClosingFinished();

    protected void startUnlockHintAnimation() {

@@ -1153,23 +1156,28 @@ public abstract class PanelViewController {
        return mView;
    }

    public boolean isEnabled() {
        return mView.isEnabled();
    }

    public OnLayoutChangeListener createLayoutChangeListener() {
        return new OnLayoutChangeListener();
    }

    protected TouchHandler createTouchHandler() {
        return new TouchHandler();
    }
    protected abstract TouchHandler createTouchHandler();

    protected OnConfigurationChangedListener createOnConfigurationChangedListener() {
        return new OnConfigurationChangedListener();
    }

    public class TouchHandler implements View.OnTouchListener {
    public abstract class TouchHandler implements View.OnTouchListener {
        /**
         * Method called when a touch has occurred on {@link PhoneStatusBarView}.
         *
         * Touches that occur on the status bar view may have ramifications for the notification
         * panel (e.g. a touch that pulls down the shade could start on the status bar), so we need
         * to notify the panel controller when these touches occur.
         *
         * Returns true if the event was handled and false otherwise.
         */
        public abstract boolean onTouchForwardedFromStatusBar(MotionEvent event);

        public boolean onInterceptTouchEvent(MotionEvent event) {
            if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled || (mMotionAborted
                    && event.getActionMasked() != MotionEvent.ACTION_DOWN)) {
@@ -1435,4 +1443,8 @@ public abstract class PanelViewController {
    private void cancelJankMonitoring(int cuj) {
        InteractionJankMonitor.getInstance().cancel(cuj);
    }

    protected float getExpansionFraction() {
        return mExpandedFraction;
    }
}
+26 −102
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
import android.view.DisplayCutout;
@@ -37,7 +36,6 @@ import android.view.accessibility.AccessibilityEvent;
import android.widget.LinearLayout;

import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
@@ -55,14 +53,6 @@ public class PhoneStatusBarView extends PanelBar {
    StatusBar mBar;

    private ScrimController mScrimController;
    private Runnable mHideExpandedRunnable = new Runnable() {
        @Override
        public void run() {
            if (mPanelFraction == 0.0f) {
                mBar.makeExpandedInvisible();
            }
        }
    };
    private DarkReceiver mBattery;
    private DarkReceiver mClock;
    private int mRotationOrientation = -1;
@@ -76,15 +66,12 @@ public class PhoneStatusBarView extends PanelBar {
    @Nullable
    private List<StatusBar.ExpansionChangedListener> mExpansionChangedListeners;
    @Nullable
    private PanelExpansionStateChangedListener mPanelExpansionStateChangedListener;

    private PanelEnabledProvider mPanelEnabledProvider;
    private TouchEventHandler mTouchEventHandler;

    /**
     * Draw this many pixels into the left/right side of the cutout to optimally use the space
     */
    private int mCutoutSideNudge = 0;
    private boolean mHeadsUpVisible;

    public PhoneStatusBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -100,8 +87,8 @@ public class PhoneStatusBarView extends PanelBar {
        mExpansionChangedListeners = listeners;
    }

    void setPanelExpansionStateChangedListener(PanelExpansionStateChangedListener listener) {
        mPanelExpansionStateChangedListener = listener;
    void setTouchEventHandler(TouchEventHandler handler) {
        mTouchEventHandler = handler;
    }

    public void setScrimController(ScrimController scrimController) {
@@ -177,15 +164,6 @@ public class PhoneStatusBarView extends PanelBar {
        return changed;
    }

    @Override
    public boolean panelEnabled() {
        if (mPanelEnabledProvider == null) {
            Log.e(TAG, "panelEnabledProvider is null; defaulting to super class.");
            return super.panelEnabled();
        }
        return mPanelEnabledProvider.panelEnabled();
    }

    @Override
    public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
        if (super.onRequestSendAccessibilityEventInternal(child, event)) {
@@ -201,80 +179,32 @@ public class PhoneStatusBarView extends PanelBar {
        return false;
    }

    @Override
    public void onPanelPeeked() {
        super.onPanelPeeked();
        mBar.makeExpandedVisible(false);
    }

    @Override
    public void onPanelCollapsed() {
        super.onPanelCollapsed();
        // Close the status bar in the next frame so we can show the end of the animation.
        post(mHideExpandedRunnable);
    }

    public void removePendingHideExpandedRunnables() {
        removeCallbacks(mHideExpandedRunnable);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean barConsumedEvent = mBar.interceptTouchEvent(event);

        if (DEBUG_GESTURES) {
            if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
                EventLog.writeEvent(EventLogTags.SYSUI_PANELBAR_TOUCH,
                        event.getActionMasked(), (int) event.getX(), (int) event.getY(),
                        barConsumedEvent ? 1 : 0);
            }
        }

        return barConsumedEvent || super.onTouchEvent(event);
    }

    @Override
    public void onTrackingStarted() {
        super.onTrackingStarted();
        mBar.onTrackingStarted();
        mScrimController.onTrackingStarted();
        removePendingHideExpandedRunnables();
    }

    @Override
    public void onClosingFinished() {
        super.onClosingFinished();
        mBar.onClosingFinished();
    }

    @Override
    public void onTrackingStopped(boolean expand) {
        super.onTrackingStopped(expand);
        mBar.onTrackingStopped(expand);
        mBar.onTouchEvent(event);
        if (mTouchEventHandler == null) {
            Log.w(
                    TAG,
                    String.format(
                            "onTouch: No touch handler provided; eating gesture at (%d,%d)",
                            (int) event.getX(),
                            (int) event.getY()
                    )
            );
            return true;
        }

    @Override
    public void onExpandingFinished() {
        super.onExpandingFinished();
        mScrimController.onExpandingFinished();
        return mTouchEventHandler.handleTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return mBar.interceptTouchEvent(event) || super.onInterceptTouchEvent(event);
        mBar.onTouchEvent(event);
        return super.onInterceptTouchEvent(event);
    }

    @Override
    public void panelExpansionChanged(float frac, boolean expanded) {
        super.panelExpansionChanged(frac, expanded);
        if ((frac == 0 || frac == 1)) {
            if (mPanelExpansionStateChangedListener != null) {
                mPanelExpansionStateChangedListener.onPanelExpansionStateChanged();
            } else {
                Log.w(TAG, "No PanelExpansionStateChangedListener provided.");
            }
        }

        if (mExpansionChangedListeners != null) {
            for (StatusBar.ExpansionChangedListener listener : mExpansionChangedListeners) {
                listener.onExpansionChanged(frac, expanded);
@@ -282,11 +212,6 @@ public class PhoneStatusBarView extends PanelBar {
        }
    }

    /** Set the {@link PanelEnabledProvider} to use. */
    public void setPanelEnabledProvider(PanelEnabledProvider panelEnabledProvider) {
        mPanelEnabledProvider = panelEnabledProvider;
    }

    public void updateResources() {
        mCutoutSideNudge = getResources().getDimensionPixelSize(
                R.dimen.display_cutout_margin_consumption);
@@ -366,15 +291,14 @@ public class PhoneStatusBarView extends PanelBar {
                getPaddingBottom());
    }

    /** An interface that will provide whether panel is enabled. */
    interface PanelEnabledProvider {
        /** Returns true if the panel is enabled and false otherwise. */
        boolean panelEnabled();
    }

    /** A listener that will be notified when a panel's expansion state may have changed. */
    public interface PanelExpansionStateChangedListener {
        /** Called when a panel's expansion state may have changed. */
        void onPanelExpansionStateChanged();
    /**
     * A handler repsonsible for all touch event handling on the status bar.
     *
     * The handler will be notified each time {@link this#onTouchEvent} is called, and the return
     * value from the handler will be returned from {@link this#onTouchEvent}.
     **/
    public interface TouchEventHandler {
        /** Called each time {@link this#onTouchEvent} is called. */
        boolean handleTouchEvent(MotionEvent event);
    }
}
+2 −6
Original line number Diff line number Diff line
@@ -26,19 +26,15 @@ import com.android.systemui.util.ViewController
/** Controller for [PhoneStatusBarView].  */
class PhoneStatusBarViewController(
    view: PhoneStatusBarView,
    commandQueue: CommandQueue,
    statusBarMoveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
    panelExpansionStateChangedListener: PhoneStatusBarView.PanelExpansionStateChangedListener,
    touchEventHandler: PhoneStatusBarView.TouchEventHandler,
) : ViewController<PhoneStatusBarView>(view) {

    override fun onViewAttached() {}
    override fun onViewDetached() {}

    init {
        mView.setPanelEnabledProvider {
            commandQueue.panelsEnabled()
        }
        mView.setPanelExpansionStateChangedListener(panelExpansionStateChangedListener)
        mView.setTouchEventHandler(touchEventHandler)

        statusBarMoveFromCenterAnimationController?.let { animationController ->
            val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_left_side)
Loading