diff options
author | Thomas <tschneider.ac@gmail.com> | 2023-01-14 16:21:16 +0100 |
---|---|---|
committer | Thomas <tschneider.ac@gmail.com> | 2023-01-14 16:21:16 +0100 |
commit | 27423a6ab5254d103648bd00e07ae63e207b025b (patch) | |
tree | ffcc689f5f3ebfa2ce488baa75d0e70cb27b2ad9 | |
parent | a5d1e8efe006113612fc53b3b230fb5d8964d511 (diff) |
Improve behavior
-rw-r--r-- | app/build.gradle | 2 | ||||
-rw-r--r-- | app/src/main/java/app/fedilab/android/activities/MediaActivity.java | 32 | ||||
-rw-r--r-- | app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java | 98 | ||||
-rw-r--r-- | app/src/main/res/layout/activity_media_pager.xml | 147 | ||||
-rw-r--r-- | app/src/main/res/layout/fragment_slide_media.xml | 146 | ||||
-rw-r--r-- | app/src/main/res/values/themes.xml | 8 |
6 files changed, 199 insertions, 234 deletions
diff --git a/app/build.gradle b/app/build.gradle index 456658a0b..68926a269 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -142,7 +142,7 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.4' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' // debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1' - + implementation 'com.r0adkll:slidableactivity:2.1.0' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' } def getCurrentFlavor() { diff --git a/app/src/main/java/app/fedilab/android/activities/MediaActivity.java b/app/src/main/java/app/fedilab/android/activities/MediaActivity.java index 66dcb5b95..2934b361c 100644 --- a/app/src/main/java/app/fedilab/android/activities/MediaActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/MediaActivity.java @@ -110,7 +110,6 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload binding = ActivityMediaPagerBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - fullscreen = false; flags = getWindow().getDecorView().getSystemUiVisibility(); Bundle b = getIntent().getExtras(); @@ -119,21 +118,19 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload attachments = (ArrayList<Attachment>) b.getSerializable(Helper.ARG_MEDIA_ARRAY); status = (Status) b.getSerializable(Helper.ARG_STATUS); } + + if (attachments == null || attachments.size() == 0) + finish(); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); } - - if (attachments == null || attachments.size() == 0) - finish(); - setTitle(""); ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); binding.mediaViewpager.setAdapter(mPagerAdapter); binding.mediaViewpager.setSaveEnabled(false); binding.mediaViewpager.setCurrentItem(mediaPosition - 1); - binding.haulerView.setOnDragDismissedListener(dragDirection -> ActivityCompat.finishAfterTransition(MediaActivity.this)); registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); String description = attachments.get(mediaPosition - 1).description; handler = new Handler(); @@ -214,8 +211,6 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload } } }); - - setFullscreen(true); Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); @@ -401,6 +396,15 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload super.onPostResume(); } + // Shows the system bars by removing all the flags + // except for the ones that make the content appear under the system bars. + private void showSystemUI() { + View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility(flags | + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + } public boolean getFullScreen() { return this.fullscreen; @@ -416,10 +420,10 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload binding.originalMessage.setVisibility(View.VISIBLE); } } else { + hideSystemUI(); binding.mediaDescription.setVisibility(View.GONE); binding.translate.setVisibility(View.GONE); binding.originalMessage.setVisibility(View.INVISIBLE); - hideSystemUI(); } } @@ -440,16 +444,6 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload | View.SYSTEM_UI_FLAG_FULLSCREEN); } - // Shows the system bars by removing all the flags - // except for the ones that make the content appear under the system bars. - private void showSystemUI() { - View decorView = getWindow().getDecorView(); - decorView.setSystemUiVisibility(flags | - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); - } - public FragmentMedia getCurrentFragment() { return mCurrentFragment; } diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java b/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java index 061f756e0..869b9bed0 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java @@ -16,6 +16,7 @@ package app.fedilab.android.ui.fragment.media; import android.content.SharedPreferences; import android.graphics.Bitmap; +import android.graphics.Color; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; @@ -42,8 +43,11 @@ import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultDataSource; - -import java.util.Timer; +import com.r0adkll.slidr.Slidr; +import com.r0adkll.slidr.model.SlidrConfig; +import com.r0adkll.slidr.model.SlidrInterface; +import com.r0adkll.slidr.model.SlidrListener; +import com.r0adkll.slidr.model.SlidrPosition; import app.fedilab.android.R; import app.fedilab.android.activities.MediaActivity; @@ -58,13 +62,12 @@ public class FragmentMedia extends Fragment { private ExoPlayer player; - private Timer timer; private String url; private boolean canSwipe; private Attachment attachment; private boolean swipeEnabled; private FragmentSlideMediaBinding binding; - + private SlidrInterface slidrInterface; public FragmentMedia() { } @@ -113,9 +116,12 @@ public class FragmentMedia extends Fragment { url = attachment.remote_url; attachment.type = type; } - - binding.mediaPicture.setVisibility(View.VISIBLE); + binding.mediaPicture.setZoomable(false); binding.mediaPicture.setTransitionName(attachment.url); + binding.mediaPicture.setVisibility(View.VISIBLE); + binding.pbarInf.setScaleY(1f); + binding.pbarInf.setIndeterminate(true); + binding.loader.setVisibility(View.VISIBLE); if (Helper.isValidContextForGlide(requireActivity()) && isAdded()) { Glide.with(requireActivity()) .asBitmap() @@ -124,21 +130,15 @@ public class FragmentMedia extends Fragment { new CustomTarget<Bitmap>() { @Override public void onResourceReady(@NonNull final Bitmap resource, Transition<? super Bitmap> transition) { + if (binding == null || !isAdded() || getActivity() == null) { + return; + } binding.mediaPicture.setImageBitmap(resource); scheduleStartPostponedTransition(binding.mediaPicture); if (attachment.type.equalsIgnoreCase("image") && !attachment.url.toLowerCase().endsWith(".gif")) { + binding.mediaPicture.setVisibility(View.VISIBLE); final Handler handler = new Handler(); handler.postDelayed(() -> { - if (binding == null) { - return; - } - binding.pbarInf.setScaleY(1f); - binding.mediaPicture.setVisibility(View.VISIBLE); - binding.pbarInf.setIndeterminate(true); - binding.loader.setVisibility(View.VISIBLE); - if (binding == null || !isAdded() || getActivity() == null) { - return; - } if (Helper.isValidContextForGlide(requireActivity()) && isAdded()) { Glide.with(requireActivity()) .asBitmap() @@ -147,18 +147,12 @@ public class FragmentMedia extends Fragment { new CustomTarget<Bitmap>() { @Override public void onResourceReady(@NonNull final Bitmap resource, Transition<? super Bitmap> transition) { - if (binding != null) { - binding.loader.setVisibility(View.GONE); - if (binding.mediaPicture.getScale() < 1.1) { - binding.mediaPicture.setImageBitmap(resource); - } else { - binding.messageReady.setVisibility(View.VISIBLE); - } - binding.messageReady.setOnClickListener(view -> { - binding.mediaPicture.setImageBitmap(resource); - binding.messageReady.setVisibility(View.GONE); - }); + if (binding == null || !isAdded() || getActivity() == null) { + return; } + binding.loader.setVisibility(View.GONE); + binding.mediaPicture.setImageBitmap(resource); + binding.mediaPicture.setZoomable(true); } @Override @@ -168,16 +162,15 @@ public class FragmentMedia extends Fragment { } ); } - }, 1000); - - + }, 500); } else if (attachment.type.equalsIgnoreCase("image") && attachment.url.toLowerCase().endsWith(".gif")) { binding.loader.setVisibility(View.GONE); + binding.mediaPicture.setVisibility(View.VISIBLE); if (Helper.isValidContextForGlide(requireActivity())) { + binding.mediaPicture.setZoomable(true); Glide.with(requireActivity()) .load(url).into(binding.mediaPicture); } - scheduleStartPostponedTransition(binding.mediaPicture); } } @@ -271,10 +264,6 @@ public class FragmentMedia extends Fragment { } } catch (Exception ignored) { } - if (timer != null) { - timer.cancel(); - timer = null; - } } @Override @@ -283,6 +272,43 @@ public class FragmentMedia extends Fragment { if (player != null) { player.setPlayWhenReady(true); } + if (slidrInterface == null) { + slidrInterface = Slidr.replace(binding.mediaFragmentContainer, new SlidrConfig.Builder().sensitivity(1f) + .scrimColor(Color.BLACK) + .scrimStartAlpha(0.8f) + .scrimEndAlpha(0f) + .position(SlidrPosition.VERTICAL) + .velocityThreshold(2400) + .distanceThreshold(0.25f) + .edgeSize(0.18f) + .listener(new SlidrListener() { + @Override + public void onSlideStateChanged(int state) { + + } + + @Override + public void onSlideChange(float percent) { + if (percent < 0.70) { + binding.mediaVideo.setVisibility(View.GONE); + binding.videoLayout.setVisibility(View.GONE); + ActivityCompat.finishAfterTransition(requireActivity()); + } + + } + + @Override + public void onSlideOpened() { + + } + + @Override + public boolean onSlideClosed() { + return false; + } + }) + .build()); + } } private void scheduleStartPostponedTransition(final ImageView imageView) { @@ -299,7 +325,9 @@ public class FragmentMedia extends Fragment { private void enableSliding(boolean enable) { if (enable && !swipeEnabled) { swipeEnabled = true; + slidrInterface.unlock(); } else if (!enable && swipeEnabled) { + slidrInterface.lock(); swipeEnabled = false; } } diff --git a/app/src/main/res/layout/activity_media_pager.xml b/app/src/main/res/layout/activity_media_pager.xml index d4fdbd08b..497fe1397 100644 --- a/app/src/main/res/layout/activity_media_pager.xml +++ b/app/src/main/res/layout/activity_media_pager.xml @@ -14,92 +14,83 @@ You should have received a copy of the GNU General Public License along with Fedilab; if not, see <http://www.gnu.org/licenses>. --> -<app.futured.hauler.HaulerView xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/haulerView" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/transparent" - app:dragUpEnabled="true"> + android:animateLayoutChanges="true" + android:background="@android:color/transparent"> - <androidx.constraintlayout.widget.ConstraintLayout + <androidx.viewpager.widget.ViewPager + android:id="@+id/media_viewpager" android:layout_width="match_parent" android:layout_height="match_parent" - android:animateLayoutChanges="true" - android:background="@android:color/transparent"> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - <androidx.viewpager.widget.ViewPager - android:id="@+id/media_viewpager" - android:layout_width="match_parent" - android:layout_height="match_parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + <TextView + android:id="@+id/media_description" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal|bottom" + android:background="#AA000000" + android:gravity="center" + android:padding="12dp" + android:textColor="#ffffffff" + android:textIsSelectable="true" + android:visibility="gone" + app:layout_constraintBottom_toTopOf="@+id/original_message" + app:layout_constraintEnd_toStartOf="@+id/translate" + app:layout_constraintStart_toStartOf="parent" + tools:visibility="visible" /> - <TextView - android:id="@+id/media_description" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal|bottom" - android:background="#AA000000" - android:gravity="center" - android:padding="12dp" - android:textColor="#ffffffff" - android:textIsSelectable="true" - android:visibility="gone" - app:layout_constraintBottom_toTopOf="@+id/original_message" - app:layout_constraintEnd_toStartOf="@+id/translate" - app:layout_constraintStart_toStartOf="parent" - tools:visibility="visible" /> + <TextView + android:id="@+id/media_description_translated" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal|bottom" + android:layout_marginBottom="70dp" + android:background="#AA000000" + android:gravity="center" + android:padding="12dp" + android:textColor="#ffffffff" + android:textIsSelectable="true" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + tools:visibility="visible" /> - <TextView - android:id="@+id/media_description_translated" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal|bottom" - android:layout_marginBottom="70dp" - android:background="#AA000000" - android:gravity="center" - android:padding="12dp" - android:textColor="#ffffffff" - android:textIsSelectable="true" - android:visibility="gone" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - tools:visibility="visible" /> + <com.google.android.material.button.MaterialButton + android:id="@+id/translate" + style="@style/Widget.Material3.Button.IconButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/translate" + android:visibility="gone" + app:icon="@drawable/ic_baseline_translate_24" + app:iconPadding="0dp" + app:layout_constraintBottom_toBottomOf="@+id/media_description" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/media_description" + tools:visibility="visible" /> - <com.google.android.material.button.MaterialButton - android:id="@+id/translate" - style="@style/Widget.Material3.Button.IconButton" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:contentDescription="@string/translate" - android:visibility="gone" - app:icon="@drawable/ic_baseline_translate_24" - app:iconPadding="0dp" - app:layout_constraintBottom_toBottomOf="@+id/media_description" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@+id/media_description" - tools:visibility="visible" /> - - <TextView - android:id="@+id/original_message" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="10dp" - android:layout_marginBottom="70dp" - android:padding="5dp" - android:text="@string/view_the_original_message" - android:textSize="18sp" - android:visibility="invisible" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/translate" - tools:visibility="visible" /> - </androidx.constraintlayout.widget.ConstraintLayout> - -</app.futured.hauler.HaulerView> + <TextView + android:id="@+id/original_message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:layout_marginBottom="70dp" + android:padding="5dp" + android:text="@string/view_the_original_message" + android:textSize="18sp" + android:visibility="invisible" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/translate" + tools:visibility="visible" /> +</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/fragment_slide_media.xml b/app/src/main/res/layout/fragment_slide_media.xml index bb91ac89a..b5361e12c 100644 --- a/app/src/main/res/layout/fragment_slide_media.xml +++ b/app/src/main/res/layout/fragment_slide_media.xml @@ -1,125 +1,69 @@ <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent"> - <androidx.core.widget.NestedScrollView + <RelativeLayout + android:id="@+id/media_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" - android:fillViewport="true" - android:keepScreenOn="true"> - + android:background="@color/black"> + <!-- Main Loader --> <RelativeLayout - android:id="@+id/media_fragment_container" + android:id="@+id/loader" android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@color/black"> - <!-- Main Loader --> - <RelativeLayout - android:id="@+id/loader" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:gravity="center"> + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:gravity="center"> - <ProgressBar - android:id="@+id/pbar_inf" - style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:indeterminate="false" - android:max="100" - android:progress="0" /> - - <TextView - android:id="@+id/loader_progress" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:gravity="center" - android:textSize="12sp" /> - </RelativeLayout> - - <RelativeLayout - android:id="@+id/videoLayout" + <ProgressBar + android:id="@+id/pbar_inf" + style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal" android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@color/black" - android:visibility="gone" /> + android:layout_height="wrap_content" + android:indeterminate="false" + android:max="100" + android:progress="0" /> - <FrameLayout - android:id="@+id/media_picture_container" + <TextView + android:id="@+id/loader_progress" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_centerInParent="true"> - <!-- Description is set dynamically --> - <com.github.chrisbanes.photoview.PhotoView - android:id="@+id/media_picture" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:adjustViewBounds="true" - android:visibility="gone" /> - </FrameLayout> + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:textSize="12sp" /> + </RelativeLayout> + <RelativeLayout + android:id="@+id/videoLayout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/black" + android:visibility="gone" /> - <com.google.android.exoplayer2.ui.PlayerView - android:id="@+id/media_video" + <FrameLayout + android:id="@+id/media_picture_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_centerInParent="true"> + <!-- Description is set dynamically --> + <com.github.chrisbanes.photoview.PhotoView + android:id="@+id/media_picture" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_centerInParent="true" + android:adjustViewBounds="true" android:visibility="gone" /> + </FrameLayout> - <ImageView - android:id="@+id/media_prev" - android:layout_width="30dp" - android:layout_height="50dp" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:layout_marginStart="5dp" - android:layout_marginLeft="5dp" - android:layout_marginTop="5dp" - android:layout_marginEnd="5dp" - android:layout_marginRight="5dp" - android:layout_marginBottom="5dp" - android:background="@color/transparent_grey" - android:contentDescription="@string/previous" - android:src="@drawable/ic_baseline_first_page_24" - android:visibility="gone" - app:tint="@color/white" /> - - <ImageView - android:id="@+id/media_next" - android:layout_width="30dp" - android:layout_height="50dp" - android:layout_alignParentEnd="true" - android:layout_centerVertical="true" - android:layout_marginStart="5dp" - android:layout_marginLeft="5dp" - android:layout_marginTop="5dp" - android:layout_marginEnd="5dp" - android:layout_marginRight="5dp" - android:layout_marginBottom="5dp" - android:background="@color/transparent_grey" - android:contentDescription="@string/next" - android:src="@drawable/ic_baseline_last_page_24" - android:visibility="gone" /> - + <com.google.android.exoplayer2.ui.PlayerView + android:id="@+id/media_video" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_centerInParent="true" + android:visibility="gone" /> - <TextView - android:id="@+id/message_ready" - android:layout_width="match_parent" - android:layout_height="40dp" - android:layout_alignBottom="@+id/media_picture_container" - android:layout_marginBottom="40dp" - android:background="@drawable/media_message_border" - android:gravity="center" - android:text="@string/media_ready" - android:textSize="14sp" - android:visibility="gone" /> - </RelativeLayout> - </androidx.core.widget.NestedScrollView> + </RelativeLayout> </FrameLayout> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index d13d71d92..f3fba9825 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -90,6 +90,14 @@ <item name="android:windowIsFloating">false</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> + + <item name="android:windowBackground">@android:color/transparent</item> + <item name="android:windowContentTransitions">true</item> + <item name="android:windowActivityTransitions">true</item> + <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges + </item> + <item name="android:windowTranslucentStatus">true</item> + <item name="android:windowTranslucentNavigation">true</item> </style> <style name="AppThemeAlertDialog" parent="Theme.Material3.Light.Dialog.Alert"> |