Merge "NIU Actions: Add privacy confirmation dialog" into sc-dev
This commit is contained in:
commit
4e0bc773c8
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="@dimen/modal_dialog_corner_radius" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,94 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/niu_actions_confirmation_dialog_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_gravity="center">
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="@dimen/modal_dialog_width"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/round_rect_dialog"
|
||||||
|
android:backgroundTint="?attr/modalDialogBackground"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:paddingTop="@dimen/modal_dialog_padding"
|
||||||
|
android:paddingLeft="@dimen/modal_dialog_padding"
|
||||||
|
android:paddingRight="@dimen/modal_dialog_padding"
|
||||||
|
android:paddingBottom="@dimen/modal_dialog_padding_bottom">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/ModalDialogTitle"
|
||||||
|
android:id="@+id/niu_actions_confirmation_header"
|
||||||
|
android:text="@string/niu_actions_confirmation_title"/>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="@dimen/modal_dialog_vertical_spacer"/>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/confirmation_dialog_text_height">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/ModalDialogText"
|
||||||
|
android:id="@+id/niu_actions_confirmation_description"
|
||||||
|
android:text="@string/niu_actions_confirmation_text"/>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="@dimen/modal_dialog_vertical_spacer"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/niu_actions_confirmation_buttons"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/ModalDialogButton"
|
||||||
|
android:id="@+id/niu_actions_confirmation_reject"
|
||||||
|
android:text="@string/niu_actions_confirmation_no"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/ModalDialogButton"
|
||||||
|
android:id="@+id/niu_actions_confirmation_accept"
|
||||||
|
android:text="@string/niu_actions_confirmation_yes"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<!-- Modal Dialogs -->
|
||||||
|
<dimen name="modal_dialog_width">360dp</dimen>
|
||||||
|
<dimen name="confirmation_dialog_text_height">168dp</dimen>
|
||||||
|
</resources>
|
|
@ -19,4 +19,6 @@
|
||||||
<attr name="overviewButtonTextColor" format="color" />
|
<attr name="overviewButtonTextColor" format="color" />
|
||||||
<attr name="overviewButtonIconColor" format="color" />
|
<attr name="overviewButtonIconColor" format="color" />
|
||||||
<attr name="overviewButtonBackgroundColor" format="color" />
|
<attr name="overviewButtonBackgroundColor" format="color" />
|
||||||
|
<!-- Modal dialog theming -->
|
||||||
|
<attr name="modalDialogBackground" format="color" />
|
||||||
</resources>
|
</resources>
|
|
@ -20,4 +20,7 @@
|
||||||
<color name="go_overview_text_color_dark">#F8F9FA</color>
|
<color name="go_overview_text_color_dark">#F8F9FA</color>
|
||||||
<color name="go_overview_button_color">#70FFFFFF</color>
|
<color name="go_overview_button_color">#70FFFFFF</color>
|
||||||
<color name="go_overview_button_color_dark">#474747</color>
|
<color name="go_overview_button_color_dark">#474747</color>
|
||||||
|
<!-- Modal Dialogs -->
|
||||||
|
<color name="go_modal_dialog_background">#FFFFFF</color>
|
||||||
|
<color name="go_modal_dialog_background_dark">#424242</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -28,4 +28,12 @@
|
||||||
<dimen name="overview_proactive_row_height">0dp</dimen>
|
<dimen name="overview_proactive_row_height">0dp</dimen>
|
||||||
<dimen name="overview_proactive_row_bottom_margin">24dp</dimen>
|
<dimen name="overview_proactive_row_bottom_margin">24dp</dimen>
|
||||||
<dimen name="task_corner_radius_override">28dp</dimen>
|
<dimen name="task_corner_radius_override">28dp</dimen>
|
||||||
|
|
||||||
|
<!-- Modal Dialogs -->
|
||||||
|
<dimen name="modal_dialog_width">288dp</dimen>
|
||||||
|
<dimen name="modal_dialog_padding">24dp</dimen>
|
||||||
|
<dimen name="modal_dialog_padding_bottom">8dp</dimen>
|
||||||
|
<dimen name="modal_dialog_vertical_spacer">12dp</dimen>
|
||||||
|
<dimen name="modal_dialog_corner_radius">8dp</dimen>
|
||||||
|
<dimen name="confirmation_dialog_text_height">216dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -11,4 +11,13 @@
|
||||||
<string name="action_translate">Translate</string>
|
<string name="action_translate">Translate</string>
|
||||||
<!-- Label for a button that triggers Search on a screenshot of the current app. [CHAR_LIMIT=40] -->
|
<!-- Label for a button that triggers Search on a screenshot of the current app. [CHAR_LIMIT=40] -->
|
||||||
<string name="action_search">Lens</string>
|
<string name="action_search">Lens</string>
|
||||||
|
<!-- ******* NIU Actions First-Run Confirmation Dialog ******* -->
|
||||||
|
<!-- Dialog title -->
|
||||||
|
<string name="niu_actions_confirmation_title">Translate or listen to text on screen</string>
|
||||||
|
<!-- Dialog content -->
|
||||||
|
<string name="niu_actions_confirmation_text">Information such as text on your screen, web addresses, and screenshots may be shared with Google.\n\nTo change what information you share, go to <b>Settings > Apps > Default apps > Digital assistant app</b>.</string>
|
||||||
|
<!-- Label for a button that rejects the feature. [CHAR_LIMIT=40] -->
|
||||||
|
<string name="niu_actions_confirmation_no">CANCEL</string>
|
||||||
|
<!-- Label for a button that accepts the feature. [CHAR_LIMIT=40] -->
|
||||||
|
<string name="niu_actions_confirmation_yes">GOT IT</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -20,12 +20,14 @@
|
||||||
<item name="overviewButtonTextColor">@color/go_overview_text_color</item>
|
<item name="overviewButtonTextColor">@color/go_overview_text_color</item>
|
||||||
<item name="overviewButtonIconColor">@color/go_overview_text_color</item>
|
<item name="overviewButtonIconColor">@color/go_overview_text_color</item>
|
||||||
<item name="overviewButtonBackgroundColor">@color/go_overview_button_color</item>
|
<item name="overviewButtonBackgroundColor">@color/go_overview_button_color</item>
|
||||||
|
<item name="modalDialogBackground">@color/go_modal_dialog_background</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.Dark" parent="@style/LauncherTheme.Dark">
|
<style name="AppTheme.Dark" parent="@style/LauncherTheme.Dark">
|
||||||
<item name="overviewButtonTextColor">@color/go_overview_text_color_dark</item>
|
<item name="overviewButtonTextColor">@color/go_overview_text_color_dark</item>
|
||||||
<item name="overviewButtonIconColor">@color/go_overview_text_color_dark</item>
|
<item name="overviewButtonIconColor">@color/go_overview_text_color_dark</item>
|
||||||
<item name="overviewButtonBackgroundColor">@color/go_overview_button_color_dark</item>
|
<item name="overviewButtonBackgroundColor">@color/go_overview_button_color_dark</item>
|
||||||
|
<item name="modalDialogBackground">@color/go_modal_dialog_background_dark</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Overview -->
|
<!-- Overview -->
|
||||||
|
@ -56,4 +58,33 @@
|
||||||
<item name="android:layout_height">wrap_content</item>
|
<item name="android:layout_height">wrap_content</item>
|
||||||
<item name="android:orientation">vertical</item>
|
<item name="android:orientation">vertical</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Modal Dialogs -->
|
||||||
|
<style name="ModalDialogTitle">
|
||||||
|
<item name="android:fontFamily">sans-serif-medium</item>
|
||||||
|
<item name="android:textSize">20sp</item>
|
||||||
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
|
<item name="android:lineHeight">24dp</item>
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:layout_gravity">center_horizontal</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="ModalDialogText">
|
||||||
|
<item name="android:fontFamily">sans-serif-medium</item>
|
||||||
|
<item name="android:textSize">16sp</item>
|
||||||
|
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||||
|
<item name="android:lineHeight">24dp</item>
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:layout_gravity">center_horizontal</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="ModalDialogButton" parent="@style/Widget.AppCompat.Button.Borderless">
|
||||||
|
<item name="android:textSize">14sp</item>
|
||||||
|
<item name="android:textColor">?android:attr/colorAccent</item>
|
||||||
|
<item name="android:lineHeight">20dp</item>
|
||||||
|
<item name="android:layout_width">wrap_content</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
|
@ -20,20 +20,31 @@ import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBN
|
||||||
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
|
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.app.assist.AssistContent;
|
import android.app.assist.AssistContent;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import com.android.launcher3.BaseActivity;
|
||||||
|
import com.android.launcher3.BaseDraggingActivity;
|
||||||
|
import com.android.launcher3.R;
|
||||||
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.quickstep.util.AssistContentRequester;
|
import com.android.quickstep.util.AssistContentRequester;
|
||||||
import com.android.quickstep.views.OverviewActionsView;
|
import com.android.quickstep.views.OverviewActionsView;
|
||||||
import com.android.quickstep.views.TaskThumbnailView;
|
import com.android.quickstep.views.TaskThumbnailView;
|
||||||
|
@ -53,6 +64,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||||
public static final String ACTIONS_ERROR_CODE = "niu_actions_app_error_code";
|
public static final String ACTIONS_ERROR_CODE = "niu_actions_app_error_code";
|
||||||
public static final int ERROR_PERMISSIONS_STRUCTURE = 1;
|
public static final int ERROR_PERMISSIONS_STRUCTURE = 1;
|
||||||
public static final int ERROR_PERMISSIONS_SCREENSHOT = 2;
|
public static final int ERROR_PERMISSIONS_SCREENSHOT = 2;
|
||||||
|
private static final String NIU_ACTIONS_CONFIRMED = "launcher_go.niu_actions_confirmed";
|
||||||
private static final String TAG = "TaskOverlayFactoryGo";
|
private static final String TAG = "TaskOverlayFactoryGo";
|
||||||
|
|
||||||
private AssistContentRequester mContentRequester;
|
private AssistContentRequester mContentRequester;
|
||||||
|
@ -79,6 +91,9 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||||
private boolean mAssistStructurePermitted;
|
private boolean mAssistStructurePermitted;
|
||||||
private boolean mAssistScreenshotPermitted;
|
private boolean mAssistScreenshotPermitted;
|
||||||
private AssistContentRequester mFactoryContentRequester;
|
private AssistContentRequester mFactoryContentRequester;
|
||||||
|
private SharedPreferences mSharedPreferences;
|
||||||
|
private String mPreviousAction;
|
||||||
|
private AlertDialog mConfirmationDialog;
|
||||||
|
|
||||||
private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
|
private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
|
||||||
AssistContentRequester assistContentRequester) {
|
AssistContentRequester assistContentRequester) {
|
||||||
|
@ -92,6 +107,12 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||||
@Override
|
@Override
|
||||||
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
|
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
|
||||||
boolean rotated) {
|
boolean rotated) {
|
||||||
|
if (mConfirmationDialog != null && mConfirmationDialog.isShowing()) {
|
||||||
|
// Redraw the dialog in case the layout changed
|
||||||
|
mConfirmationDialog.dismiss();
|
||||||
|
showConfirmationDialog();
|
||||||
|
}
|
||||||
|
|
||||||
getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
|
getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
|
||||||
checkSettings();
|
checkSettings();
|
||||||
if (thumbnail == null || TextUtils.isEmpty(mNIUPackageName)) {
|
if (thumbnail == null || TextUtils.isEmpty(mNIUPackageName)) {
|
||||||
|
@ -105,6 +126,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||||
boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot() && !isManagedProfileTask;
|
boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot() && !isManagedProfileTask;
|
||||||
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
|
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
|
||||||
mTaskPackageName = task.key.getPackageName();
|
mTaskPackageName = task.key.getPackageName();
|
||||||
|
mSharedPreferences = Utilities.getPrefs(mApplicationContext);
|
||||||
|
|
||||||
if (!mAssistStructurePermitted || !mAssistScreenshotPermitted) {
|
if (!mAssistStructurePermitted || !mAssistScreenshotPermitted) {
|
||||||
return;
|
return;
|
||||||
|
@ -131,6 +153,12 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||||
* Creates and sends an Intent corresponding to the button that was clicked
|
* Creates and sends an Intent corresponding to the button that was clicked
|
||||||
*/
|
*/
|
||||||
private void sendNIUIntent(String actionType) {
|
private void sendNIUIntent(String actionType) {
|
||||||
|
if (!mSharedPreferences.getBoolean(NIU_ACTIONS_CONFIRMED, false)) {
|
||||||
|
mPreviousAction = actionType;
|
||||||
|
showConfirmationDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Intent intent = createNIUIntent(actionType);
|
Intent intent = createNIUIntent(actionType);
|
||||||
// Only add and send the image if the appropriate permissions are held
|
// Only add and send the image if the appropriate permissions are held
|
||||||
if (mAssistStructurePermitted && mAssistScreenshotPermitted) {
|
if (mAssistStructurePermitted && mAssistScreenshotPermitted) {
|
||||||
|
@ -218,6 +246,35 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||||
public void setImageActionsAPI(ImageActionsApi imageActionsApi) {
|
public void setImageActionsAPI(ImageActionsApi imageActionsApi) {
|
||||||
mImageApi = imageActionsApi;
|
mImageApi = imageActionsApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showConfirmationDialog() {
|
||||||
|
BaseDraggingActivity activity = BaseActivity.fromContext(getActionsView().getContext());
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(activity);
|
||||||
|
View view = inflater.inflate(R.layout.niu_actions_confirmation_dialog, /* root */ null);
|
||||||
|
|
||||||
|
Button acceptButton = view.findViewById(R.id.niu_actions_confirmation_accept);
|
||||||
|
acceptButton.setOnClickListener(this::onNiuActionsConfirmationAccept);
|
||||||
|
|
||||||
|
Button rejectButton = view.findViewById(R.id.niu_actions_confirmation_reject);
|
||||||
|
rejectButton.setOnClickListener(this::onNiuActionsConfirmationReject);
|
||||||
|
|
||||||
|
mConfirmationDialog = new AlertDialog.Builder(activity)
|
||||||
|
.setView(view)
|
||||||
|
.create();
|
||||||
|
mConfirmationDialog.getWindow()
|
||||||
|
.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||||
|
mConfirmationDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onNiuActionsConfirmationAccept(View v) {
|
||||||
|
mConfirmationDialog.dismiss();
|
||||||
|
mSharedPreferences.edit().putBoolean(NIU_ACTIONS_CONFIRMED, true).apply();
|
||||||
|
sendNIUIntent(mPreviousAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onNiuActionsConfirmationReject(View v) {
|
||||||
|
mConfirmationDialog.cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue