diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c4907fc..b1a850a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -43,7 +43,6 @@ android { } dependencies { - implementation("androidx.viewpager2:viewpager2:1.0.0") // Shizuku API implementation("dev.rikka.shizuku:api:13.1.5") diff --git a/app/src/main/java/com/dhangofa/networktoggle/MainActivity.java b/app/src/main/java/com/dhangofa/networktoggle/MainActivity.java index 60d77ee..4213ddc 100644 --- a/app/src/main/java/com/dhangofa/networktoggle/MainActivity.java +++ b/app/src/main/java/com/dhangofa/networktoggle/MainActivity.java @@ -33,12 +33,6 @@ import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.TextView; -import androidx.viewpager2.widget.ViewPager2; -import com.dhangofa.networktoggle.ui.SetupCarouselAdapter; -import java.util.ArrayList; -import java.util.List; -import android.widget.ImageView; -import android.widget.LinearLayout; import com.dhangofa.networktoggle.config.AppPreferences; import com.dhangofa.networktoggle.model.ExecutionMode; @@ -79,10 +73,32 @@ public class MainActivity extends Activity implements android.content.SharedPref private RadioButton radioSim1; private RadioButton radioSim2; private TextView autoSimWarningText; - private ViewPager2 setupCarouselPager; - private android.widget.LinearLayout setupCarouselContainer; - private LinearLayout carouselIndicators; + private ImageView faqLink; + + // Morphing View Carousel + private View carouselBackground; + private TextView carouselTitle; + private TextView carouselDesc; + private TextView carouselButtonText; + private ImageView carouselIcon; + private ImageView carouselButtonIcon; + private View carouselButton; + private View carouselIconContainer; + private LinearLayout carouselIndicators; + + private int currentCarouselIndex = 0; + private float touchStartX = 0f; + private CarouselItem[] carouselItems; + + private static class CarouselItem { + String title, desc, btnText, url; + int iconRes, bgColor, accentColor, btnBgColor; + CarouselItem(String title, String desc, String btnText, String url, int iconRes, int bgColor, int accentColor, int btnBgColor) { + this.title = title; this.desc = desc; this.btnText = btnText; this.url = url; + this.iconRes = iconRes; this.bgColor = bgColor; this.accentColor = accentColor; this.btnBgColor = btnBgColor; + } + } private View separatorRootShizuku; private View separatorAutoSim1; @@ -175,84 +191,7 @@ protected void onCreate(Bundle savedInstanceState) { updateAutoSimWarning(); bindSelectionListeners(); updateSeparatorVisibility(); - } - - private void setupCarousel() { - List carouselItems = new ArrayList<>(); - carouselItems.add(new SetupCarouselAdapter.SetupItem("New to NetToggle?", "Learn how to set up Execution Modes", "Read Guide", "https://github.com/Dhangofa/NetToggle/wiki/1.-Execution-Mode-Configuration", R.drawable.ic_terminal, R.color.first_pg_bg, R.color.exec_accent, R.color.view_guide_button_bg)); - carouselItems.add(new SetupCarouselAdapter.SetupItem("Target SIM & Cycle", "Learn how to configure your modes", "Read Guide", "https://github.com/Dhangofa/NetToggle/wiki/2.-Target-SIM-Setup-&-Quick-Tile-Cycle-Guide", R.drawable.ic_sim_card, R.color.second_pg_bg, R.color.accent_orange, R.color.view_guide_button_bg)); - carouselItems.add(new SetupCarouselAdapter.SetupItem("Quick Settings Ready", "Add the tile to your Control Center", "View Guide", "https://github.com/Dhangofa/NetToggle/wiki/3.-Adding-the-Tile-to-Quick-Settings", R.drawable.ic_network_bars, R.color.third_pg_bg, R.color.accent_pink, R.color.view_guide_button_bg)); - - if (setupCarouselContainer != null) { - setupCarouselContainer.removeAllViews(); - for (int i = 0; i < carouselItems.size(); i++) { - SetupCarouselAdapter.SetupItem item = carouselItems.get(i); - View view = getLayoutInflater().inflate(R.layout.item_setup_carousel, setupCarouselContainer, false); - android.widget.LinearLayout.LayoutParams params = new android.widget.LinearLayout.LayoutParams(0, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f); - if (i > 0) params.setMarginStart(12); - if (i < carouselItems.size() - 1) params.setMarginEnd(12); - view.setLayoutParams(params); - - ((TextView) view.findViewById(R.id.carouselTitle)).setText(item.title); - ((TextView) view.findViewById(R.id.carouselDesc)).setText(item.description); - ((TextView) view.findViewById(R.id.carouselButtonText)).setText(item.buttonText); - ((TextView) view.findViewById(R.id.carouselButtonText)).setTextColor(getColor(item.accentColorRes)); - - ImageView icon = view.findViewById(R.id.carouselIcon); - icon.setImageResource(item.iconRes); - icon.setColorFilter(getColor(item.accentColorRes)); - - ImageView btnIcon = view.findViewById(R.id.carouselButtonIcon); - btnIcon.setColorFilter(getColor(item.accentColorRes)); - - view.findViewById(R.id.carouselBackground).setBackgroundTintList(android.content.res.ColorStateList.valueOf(getColor(item.bgColorRes))); - view.findViewById(R.id.carouselButton).setBackgroundTintList(android.content.res.ColorStateList.valueOf(getColor(item.btnBgColorRes))); - view.findViewById(R.id.carouselIconContainer).setBackgroundTintList(android.content.res.ColorStateList.valueOf(getColor(item.btnBgColorRes))); - - view.findViewById(R.id.carouselButton).setOnClickListener(v -> { - try { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(item.url))); } catch (Exception e) {} - }); - - setupCarouselContainer.addView(view); - } - } else if (setupCarouselPager != null) { - SetupCarouselAdapter adapter = new SetupCarouselAdapter(this, carouselItems); - setupCarouselPager.setAdapter(adapter); - setupCarouselIndicators(carouselItems.size()); - setupCarouselPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { - @Override - public void onPageSelected(int position) { - super.onPageSelected(position); - updateCarouselIndicators(position); - } - }); - } - } - - - private void setupCarouselIndicators(int count) { - if (carouselIndicators == null) return; - carouselIndicators.removeAllViews(); - for (int i = 0; i < count; i++) { - android.widget.ImageView dot = new android.widget.ImageView(this); - dot.setImageDrawable(getDrawable(R.drawable.shape_dot_inactive)); - android.widget.LinearLayout.LayoutParams params = new android.widget.LinearLayout.LayoutParams(16, 16); - params.setMargins(8, 0, 8, 0); - dot.setLayoutParams(params); - carouselIndicators.addView(dot); - } - } - - private void updateCarouselIndicators(int position) { - if (carouselIndicators == null) return; - for (int i = 0; i < carouselIndicators.getChildCount(); i++) { - android.widget.ImageView dot = (android.widget.ImageView) carouselIndicators.getChildAt(i); - if (i == position) { - dot.setImageDrawable(getDrawable(R.drawable.shape_dot_active)); - } else { - dot.setImageDrawable(getDrawable(R.drawable.shape_dot_inactive)); - } - } + setupCarousel(); } private void configureStatusBar() { @@ -266,11 +205,6 @@ private void configureStatusBar() { } private void bindViews() { - setupCarouselPager = findViewById(R.id.setupCarouselPager); - setupCarouselContainer = findViewById(R.id.setupCarouselContainer); - carouselIndicators = findViewById(R.id.carouselIndicators); - faqLink = findViewById(R.id.faqLink); - setupCarousel(); radioGroup = findViewById(R.id.modeRadioGroup); radioRoot = findViewById(R.id.radioRoot); radioShizuku = findViewById(R.id.radioShizuku); @@ -283,6 +217,17 @@ private void bindViews() { autoSimWarningText = findViewById(R.id.autoSimWarningText); githubLink = findViewById(R.id.githubLink); telegramLink = findViewById(R.id.telegramLink); + + faqLink = findViewById(R.id.faqLink); + carouselBackground = findViewById(R.id.carouselBackground); + carouselTitle = findViewById(R.id.carouselTitle); + carouselDesc = findViewById(R.id.carouselDesc); + carouselButtonText = findViewById(R.id.carouselButtonText); + carouselIcon = findViewById(R.id.carouselIcon); + carouselButtonIcon = findViewById(R.id.carouselButtonIcon); + carouselButton = findViewById(R.id.carouselButton); + carouselIconContainer = findViewById(R.id.carouselIconContainer); + carouselIndicators = findViewById(R.id.carouselIndicators); separatorRootShizuku = findViewById(R.id.separatorRootShizuku); separatorAutoSim1 = findViewById(R.id.separatorAutoSim1); separatorSim1Sim2 = findViewById(R.id.separatorSim1Sim2); @@ -296,16 +241,142 @@ private void bindViews() { } private void bindLinks() { - if (faqLink != null) { - faqLink.setOnClickListener(v -> { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/Dhangofa/NetToggle/wiki/Frequently-Asked-Questions-(FAQ)")); - try { startActivity(browserIntent); } catch (Exception e) { android.widget.Toast.makeText(MainActivity.this, "No web browser installed to open this link.", android.widget.Toast.LENGTH_SHORT).show(); } - }); - } githubLink.setOnClickListener(v -> openUrl("https://github.com/Dhangofa/NetToggle")); telegramLink.setOnClickListener(v -> openUrl("https://t.me/dhangofas_projects_chat")); + if (faqLink != null) faqLink.setOnClickListener(v -> openUrl("https://github.com/Dhangofa/NetToggle/wiki")); } + + private void setupCarousel() { + if (carouselBackground == null) return; + carouselItems = new CarouselItem[]{ + new CarouselItem("New to NetToggle?", "Learn how to set up Execution Modes", "Read Guide", "https://github.com/Dhangofa/NetToggle/wiki/1.-Execution-Mode-Configuration", R.drawable.ic_terminal, R.color.first_pg_bg, R.color.exec_accent, R.color.view_guide_button_bg), + new CarouselItem("Target SIM & Cycle", "Learn how to configure your modes", "Read Guide", "https://github.com/Dhangofa/NetToggle/wiki/2.-Target-SIM-Setup-&-Quick-Tile-Cycle-Guide", R.drawable.ic_sim_card, R.color.second_pg_bg, R.color.accent_orange, R.color.view_guide_button_bg), + new CarouselItem("Quick Settings Ready", "Add the tile to your Control Center", "Read Guide", "https://github.com/Dhangofa/NetToggle/wiki/3.-Adding-the-Tile-to-Quick-Settings", R.drawable.ic_network_bars, R.color.third_pg_bg, R.color.accent_pink, R.color.view_guide_button_bg) + }; + + setupCarouselIndicators(carouselItems.length); + // Start state depends on initial auth state. + // We defer to updateCarouselContext which will be triggered by loadSavedExecutionMode -> setStatus -> updateAuthorizationUI + // But let's set a default page just in case + renderCarouselPage(isUIAuthorized ? 1 : 0, false, 0); + + carouselBackground.setOnTouchListener((v, event) -> { + switch (event.getAction()) { + case android.view.MotionEvent.ACTION_DOWN: + touchStartX = event.getX(); + return true; + case android.view.MotionEvent.ACTION_UP: + case android.view.MotionEvent.ACTION_CANCEL: + float deltaX = event.getX() - touchStartX; + if (Math.abs(deltaX) > 100) { + carouselHandler.removeCallbacks(carouselAutoRunnable); + if (deltaX > 0 && currentCarouselIndex > 0) { + currentCarouselIndex--; + renderCarouselPage(currentCarouselIndex, true, -1); + } else if (deltaX < 0 && currentCarouselIndex < carouselItems.length - 1) { + currentCarouselIndex++; + renderCarouselPage(currentCarouselIndex, true, 1); + } + // Resume after 10 seconds of inactivity + carouselHandler.postDelayed(carouselAutoRunnable, 10000); + } else if (event.getAction() == android.view.MotionEvent.ACTION_UP) { + v.performClick(); + } + return true; + } + return false; + }); + + carouselBackground.setOnClickListener(v -> { + // Needed to ensure ripple works when performClick is called + }); + } + + private void renderCarouselPage(int index, boolean animate, int direction) { + CarouselItem item = carouselItems[index]; + Runnable updateViews = () -> { + carouselTitle.setText(item.title); + carouselDesc.setText(item.desc); + carouselButtonText.setText(item.btnText); + carouselButtonText.setTextColor(getColor(item.accentColor)); + + carouselIcon.setImageResource(item.iconRes); + carouselIcon.setColorFilter(getColor(item.accentColor)); + carouselButtonIcon.setColorFilter(getColor(item.accentColor)); + + carouselBackground.setBackgroundTintList(android.content.res.ColorStateList.valueOf(getColor(item.bgColor))); + carouselButton.setBackgroundTintList(android.content.res.ColorStateList.valueOf(getColor(item.btnBgColor))); + carouselIconContainer.setBackgroundTintList(android.content.res.ColorStateList.valueOf(getColor(item.btnBgColor))); + + carouselButton.setOnClickListener(v -> { + try { startActivity(new Intent(Intent.ACTION_VIEW, android.net.Uri.parse(item.url))); } catch (Exception e) {} + }); + updateCarouselIndicators(index); + }; + + if (animate) { + float moveOutX = direction * -100f; // Swipe left (next) -> content moves left (-100). + float moveInX = direction * 100f; // Swipe left -> new content comes from right (+100). + long duration = 200; + + // Animate background color smoothly + android.animation.ValueAnimator colorAnim = android.animation.ValueAnimator.ofObject( + new android.animation.ArgbEvaluator(), + carouselBackground.getBackgroundTintList().getDefaultColor(), + getColor(item.bgColor) + ); + colorAnim.setDuration(duration); + colorAnim.addUpdateListener(animator -> { + carouselBackground.setBackgroundTintList(android.content.res.ColorStateList.valueOf((int) animator.getAnimatedValue())); + }); + colorAnim.start(); + + // Animate content out + android.view.View[] viewsToAnimate = {carouselTitle, carouselDesc, carouselButton, carouselIconContainer}; + for (android.view.View view : viewsToAnimate) { + view.animate().translationX(moveOutX).alpha(0f).setDuration(duration / 2) + .setInterpolator(new android.view.animation.AccelerateInterpolator()) + .withEndAction(() -> { + // Once out, swap data + if (view == carouselTitle) updateViews.run(); + + // Prepare for animate in + view.setTranslationX(moveInX); + view.animate().translationX(0f).alpha(1f).setDuration(duration) + .setInterpolator(new android.view.animation.DecelerateInterpolator()) + .start(); + }).start(); + } + } else { + updateViews.run(); + } + } + + private void setupCarouselIndicators(int count) { + if (carouselIndicators == null) return; + carouselIndicators.removeAllViews(); + for (int i = 0; i < count; i++) { + android.widget.ImageView dot = new android.widget.ImageView(this); + dot.setImageDrawable(getDrawable(R.drawable.shape_dot_inactive)); + android.widget.LinearLayout.LayoutParams params = new android.widget.LinearLayout.LayoutParams(16, 16); + params.setMargins(8, 0, 8, 0); + dot.setLayoutParams(params); + carouselIndicators.addView(dot); + } + } + + private void updateCarouselIndicators(int position) { + if (carouselIndicators == null) return; + for (int i = 0; i < carouselIndicators.getChildCount(); i++) { + android.widget.ImageView dot = (android.widget.ImageView) carouselIndicators.getChildAt(i); + if (i == position) { + dot.setImageDrawable(getDrawable(R.drawable.shape_dot_active)); + } else { + dot.setImageDrawable(getDrawable(R.drawable.shape_dot_inactive)); + } + } + } private void updateSeparatorVisibility() { // Execution Mode Separator int modeId = radioGroup.getCheckedRadioButtonId(); @@ -421,6 +492,18 @@ protected void onResume() { checkAndRequestPermission(); updateErrorBanner(); updateCapabilities(); + if (carouselHandler != null && carouselAutoRunnable != null) { + carouselHandler.removeCallbacks(carouselAutoRunnable); + carouselHandler.postDelayed(carouselAutoRunnable, 5000); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (carouselHandler != null && carouselAutoRunnable != null) { + carouselHandler.removeCallbacks(carouselAutoRunnable); + } } private void checkAndRequestPermission() { @@ -649,11 +732,55 @@ private void setStatus(String text, int color) { updateAuthorizationUI(color == 0xFF1B873F); } - private boolean isUIAuthorized = true; - private void updateAuthorizationUI(boolean authorized) { - if (setupCarouselPager != null) { - setupCarouselPager.setCurrentItem(authorized ? 2 : 0, true); + + private android.os.Handler carouselHandler = new android.os.Handler(android.os.Looper.getMainLooper()); + + private Runnable carouselAutoRunnable = new Runnable() { + @Override + public void run() { + if (carouselItems == null) return; + + int nextIndex; + if (!isUIAuthorized) { + // If unauthorized but user manually swiped away, bring them back to 0 eventually + nextIndex = 0; + } else { + // If authorized, cycle through logically + nextIndex = (currentCarouselIndex == 2) ? 1 : (currentCarouselIndex + 1); + } + + if (nextIndex != currentCarouselIndex) { + int direction = (nextIndex > currentCarouselIndex) ? 1 : -1; + currentCarouselIndex = nextIndex; + renderCarouselPage(currentCarouselIndex, true, direction); + } + carouselHandler.postDelayed(this, 5000); } + }; + + private void updateCarouselContext(boolean authorized) { + if (carouselBackground == null || carouselItems == null) return; + carouselHandler.removeCallbacks(carouselAutoRunnable); + + if (!authorized) { + if (currentCarouselIndex != 0) { + currentCarouselIndex = 0; + renderCarouselPage(0, true, -1); + } + // Will auto-correct to 0 every 5 seconds if user swipes away while unauthorized + carouselHandler.postDelayed(carouselAutoRunnable, 5000); + } else { + if (currentCarouselIndex == 0) { + currentCarouselIndex = 1; + renderCarouselPage(1, true, 1); + } + carouselHandler.postDelayed(carouselAutoRunnable, 5000); + } + } + + private boolean isUIAuthorized = false; + private void updateAuthorizationUI(boolean authorized) { + updateCarouselContext(authorized); if (isUIAuthorized == authorized) return; isUIAuthorized = authorized; @@ -690,7 +817,6 @@ private void openUrl(String url) { try { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } catch (Exception ignored) { - android.widget.Toast.makeText(MainActivity.this, "No web browser installed to open this link.", android.widget.Toast.LENGTH_SHORT).show(); } } diff --git a/app/src/main/java/com/dhangofa/networktoggle/ui/SetupCarouselAdapter.java b/app/src/main/java/com/dhangofa/networktoggle/ui/SetupCarouselAdapter.java deleted file mode 100644 index 792ecf8..0000000 --- a/app/src/main/java/com/dhangofa/networktoggle/ui/SetupCarouselAdapter.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.dhangofa.networktoggle.ui; - -import android.content.Context; -import android.content.Intent; -import android.content.res.ColorStateList; -import android.net.Uri; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; -import androidx.core.content.ContextCompat; - -import com.dhangofa.networktoggle.R; - -import java.util.List; - -public class SetupCarouselAdapter extends RecyclerView.Adapter { - - public static class SetupItem { - public String title; - public String description; - public String buttonText; - public String url; - public int iconRes; - public int bgColorRes; - public int accentColorRes; - public int btnBgColorRes; - - public SetupItem(String title, String description, String buttonText, String url, int iconRes, int bgColorRes, int accentColorRes, int btnBgColorRes) { - this.title = title; - this.description = description; - this.buttonText = buttonText; - this.url = url; - this.iconRes = iconRes; - this.bgColorRes = bgColorRes; - this.accentColorRes = accentColorRes; - this.btnBgColorRes = btnBgColorRes; - } - } - - private List items; - private Context context; - - public SetupCarouselAdapter(Context context, List items) { - this.context = context; - this.items = items; - } - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View view = LayoutInflater.from(context).inflate(R.layout.item_setup_carousel, parent, false); - // Important: Ensure the item fills the ViewPager2 width - view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - return new ViewHolder(view); - } - - @Override - public void onBindViewHolder(@NonNull ViewHolder holder, int position) { - SetupItem item = items.get(position); - holder.title.setText(item.title); - holder.desc.setText(item.description); - holder.buttonText.setText(item.buttonText); - holder.icon.setImageResource(item.iconRes); - - int bgColor = ContextCompat.getColor(context, item.bgColorRes); - int accentColor = ContextCompat.getColor(context, item.accentColorRes); - - holder.background.setBackgroundTintList(ColorStateList.valueOf(bgColor)); - - holder.buttonText.setTextColor(accentColor); - holder.buttonIcon.setColorFilter(accentColor); - holder.icon.setColorFilter(accentColor); - int btnBgColor = ContextCompat.getColor(context, item.btnBgColorRes); - holder.button.setBackgroundTintList(ColorStateList.valueOf(btnBgColor)); - holder.iconContainer.setBackgroundTintList(ColorStateList.valueOf(btnBgColor)); - - holder.button.setOnClickListener(v -> { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(item.url)); - try { context.startActivity(browserIntent); } catch (Exception e) { android.widget.Toast.makeText(context, "No web browser installed to open this link.", android.widget.Toast.LENGTH_SHORT).show(); } - }); - } - - @Override - public int getItemCount() { - return items.size(); - } - - static class ViewHolder extends RecyclerView.ViewHolder { - View background; - TextView title, desc, buttonText; - ImageView icon, buttonIcon; - LinearLayout button; - View iconContainer; - - public ViewHolder(@NonNull View itemView) { - super(itemView); - background = itemView.findViewById(R.id.carouselBackground); - title = itemView.findViewById(R.id.carouselTitle); - desc = itemView.findViewById(R.id.carouselDesc); - buttonText = itemView.findViewById(R.id.carouselButtonText); - icon = itemView.findViewById(R.id.carouselIcon); - buttonIcon = itemView.findViewById(R.id.carouselButtonIcon); - button = itemView.findViewById(R.id.carouselButton); - iconContainer = itemView.findViewById(R.id.carouselIconContainer); - } - } -} diff --git a/app/src/main/res/drawable/ripple_pill_mask.xml b/app/src/main/res/drawable/ripple_pill_mask.xml new file mode 100644 index 0000000..3a69113 --- /dev/null +++ b/app/src/main/res/drawable/ripple_pill_mask.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml index f3d2c27..a556e89 100644 --- a/app/src/main/res/layout-land/activity_main.xml +++ b/app/src/main/res/layout-land/activity_main.xml @@ -116,6 +116,7 @@ android:clickable="true" android:focusable="true" /> + + + @@ -171,16 +174,110 @@ android:textColor="@color/text_secondary" android:textSize="12sp" /> - + + android:orientation="vertical" + android:layout_marginTop="0dp" + android:layout_marginBottom="12dp"> + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index d65a5c1..8944e11 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -99,7 +99,7 @@ android:textColor="@color/text_secondary" android:textSize="13sp" /> - + - + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_setup_carousel.xml b/app/src/main/res/layout/item_setup_carousel.xml deleted file mode 100644 index 3eb5a12..0000000 --- a/app/src/main/res/layout/item_setup_carousel.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - -