feat: better back button

This commit is contained in:
neoapps-dev 2026-08-07 22:45:59 +03:00
parent 0f44a3761c
commit cfdc295f0b
8 changed files with 174 additions and 109 deletions

View file

@ -3,11 +3,18 @@ package com.emerald.legacy
import android.os.Bundle
import android.webkit.WebView
import androidx.activity.enableEdgeToEdge
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
class MainActivity : TauriActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
WindowCompat.getInsetsController(window, window.decorView).apply {
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
hide(WindowInsetsCompat.Type.statusBars())
}
}
override fun onWebViewCreate(webView: WebView) {

View file

@ -1,6 +1,7 @@
import { useEffect, memo, useState } from "react";
import { motion } from "framer-motion";
import { useUI, useAudio } from "../../context/LauncherContext";
import { usePlatform } from "../../hooks/usePlatform";
interface CreditCategory {
category: string;
@ -31,6 +32,7 @@ interface CreditCategory {
const CreditsView = memo(function CreditsView() {
const { setActiveView } = useUI();
const { playPressSound } = useAudio();
const { isAndroid } = usePlatform();
const [isHovered, setIsHovered] = useState(false);
const credits: CreditCategory[] = [
@ -242,25 +244,27 @@ const CreditsView = memo(function CreditsView() {
return (
<div className="relative w-full h-full flex items-center justify-center overflow-hidden">
<button
onClick={() => {
playPressSound();
setActiveView("main");
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
className="fixed bottom-8 left-8 z-50 h-10 flex items-center justify-center gap-2 px-4 text-xl mc-text-shadow outline-none border-none"
style={{
backgroundImage: isHovered
? "url('/images/button_highlighted.png')"
: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
color: isHovered ? "#FFFF55" : "white",
}}
>
Back to Menu
</button>
{!isAndroid && (
<button
onClick={() => {
playPressSound();
setActiveView("main");
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
className="fixed bottom-8 left-8 z-50 h-10 flex items-center justify-center gap-2 px-4 text-xl mc-text-shadow outline-none border-none"
style={{
backgroundImage: isHovered
? "url('/images/button_highlighted.png')"
: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
color: isHovered ? "#FFFF55" : "white",
}}
>
Back to Menu
</button>
)}
<motion.div
initial={{ y: "50%" }}

View file

@ -1,5 +1,6 @@
import { useState, useEffect, memo } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { usePlatform } from "../../hooks/usePlatform";
import {
useUI,
useAudio,
@ -15,6 +16,7 @@ import { ScreenshotImage } from "../common/ScreenshotImage";
const ScreenshotsView = memo(function ScreenshotsView() {
const { setActiveView } = useUI();
const { playPressSound, playBackSound } = useAudio();
const { isAndroid } = usePlatform();
const { editions } = useGame();
const { animationsEnabled } = useConfig();
const [screenshots, setScreenshots] = useState<ScreenshotInfo[]>([]);
@ -239,30 +241,32 @@ const ScreenshotsView = memo(function ScreenshotsView() {
</div>
</div>
<div className="w-full mt-6 mb-4 flex justify-center">
<button
onClick={handleBack}
className={`
w-72 h-10 flex items-center justify-center text-xl mc-text-shadow border-none outline-none transition-all text-white
hover:text-[#FFFF55]
`}
style={{
backgroundImage: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/button_highlighted.png')";
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/Button_Background.png')";
}}
>
Back
</button>
</div>
{!isAndroid && (
<div className="w-full mt-6 mb-4 flex justify-center">
<button
onClick={handleBack}
className={`
w-72 h-10 flex items-center justify-center text-xl mc-text-shadow border-none outline-none transition-all text-white
hover:text-[#FFFF55]
`}
style={{
backgroundImage: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/button_highlighted.png')";
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/Button_Background.png')";
}}
>
Back
</button>
</div>
)}
<AnimatePresence>
{selectedScreenshot && (

View file

@ -925,7 +925,7 @@ const SettingsView = memo(function SettingsView() {
</div>
)}
{(() => {
{!isAndroid && (() => {
const backIndex = settingsItems.findIndex((i) => i.id === "back");
const backItem = settingsItems[backIndex];
if (!backItem || backItem.type !== "button") return null;

View file

@ -10,6 +10,7 @@ import {
} from "../../context/LauncherContext";
import SkinViewer from "../common/SkinViewer";
import CapePreview from "../common/CapePreview";
import { usePlatform } from "../../hooks/usePlatform";
interface SavedSkin {
id: string;
@ -101,6 +102,7 @@ const HeadPreview = memo(function HeadPreview({ src }: { src: string }) {
const SkinsView = memo(function SkinsView() {
const { setActiveView, setIsUiHidden } = useUI();
const { playPressSound, playBackSound } = useAudio();
const { isAndroid } = usePlatform();
const { skinUrl, setSkinUrl, setSkinIsSlim, capeUrl, setCapeUrl } = useSkin();
const [focusIndex, setFocusIndex] = useState<number | null>(null);
@ -722,25 +724,27 @@ const SkinsView = memo(function SkinsView() {
/>
</div>
<button
data-index={BACK_BUTTON_INDEX}
onMouseEnter={() => setFocusIndex(BACK_BUTTON_INDEX)}
onClick={() => {
playBackSound();
setActiveView("main");
}}
className={`w-72 h-14 shrink-0 flex items-center justify-center transition-colors text-2xl mc-text-shadow mt-2 outline-none border-none hover:text-[#FFFF55] ${focusIndex === BACK_BUTTON_INDEX ? "text-[#FFFF55]" : "text-white"}`}
style={{
backgroundImage:
focusIndex === BACK_BUTTON_INDEX
? "url('/images/button_highlighted.png')"
: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
>
Back
</button>
{!isAndroid && (
<button
data-index={BACK_BUTTON_INDEX}
onMouseEnter={() => setFocusIndex(BACK_BUTTON_INDEX)}
onClick={() => {
playBackSound();
setActiveView("main");
}}
className={`w-72 h-14 shrink-0 flex items-center justify-center transition-colors text-2xl mc-text-shadow mt-2 outline-none border-none hover:text-[#FFFF55] ${focusIndex === BACK_BUTTON_INDEX ? "text-[#FFFF55]" : "text-white"}`}
style={{
backgroundImage:
focusIndex === BACK_BUTTON_INDEX
? "url('/images/button_highlighted.png')"
: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
>
Back
</button>
)}
{showImportModal && viewMode === "skin" && (
<div className="fixed inset-0 z-[200] flex items-center justify-center bg-black/60 backdrop-blur-sm p-4">

View file

@ -914,27 +914,29 @@ const VersionsView = memo(function VersionsView() {
</div>
</div>
<div className="flex justify-center">
<button
data-index={editions.length + 2}
onMouseEnter={() => setFocusIndex(editions.length + 2)}
onClick={() => {
playBackSound();
setActiveView("main");
}}
className="w-48 h-10 flex items-center justify-center text-xl mc-text-shadow outline-none border-none text-white"
style={{
backgroundImage:
focusIndex === editions.length + 2
? "url('/images/button_highlighted.png')"
: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
>
Done
</button>
</div>
{!isAndroid && (
<div className="flex justify-center">
<button
data-index={editions.length + 2}
onMouseEnter={() => setFocusIndex(editions.length + 2)}
onClick={() => {
playBackSound();
setActiveView("main");
}}
className="w-48 h-10 flex items-center justify-center text-xl mc-text-shadow outline-none border-none text-white"
style={{
backgroundImage:
focusIndex === editions.length + 2
? "url('/images/button_highlighted.png')"
: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
>
Done
</button>
</div>
)}
<CustomTUModal
isOpen={isImportModalOpen}

View file

@ -25,6 +25,7 @@ import {
type CustomEdition,
} from "../../services/TauriService";
import { PluginManager } from "../../plugins/PluginManager";
import { usePlatform } from "../../hooks/usePlatform";
import { BASE_EDITIONS } from "../../hooks/useGameManager";
const REGISTRY_URL =
"https://raw.githubusercontent.com/LCE-Hub/LCE-Workshop/refs/heads/main/registry.json";
@ -183,6 +184,7 @@ const WorkshopView = memo(function WorkshopView({
}: WorkshopViewProps) {
const { setActiveView } = useUI();
const { playPressSound, playBackSound } = useAudio();
const { isAndroid } = usePlatform();
const config = useConfig();
const containerRef = useRef<HTMLDivElement>(null);
const gridRef = useRef<HTMLDivElement>(null);
@ -1109,30 +1111,32 @@ const WorkshopView = memo(function WorkshopView({
)}
</div>
<div className="w-full mt-6 mb-4 flex justify-center">
<button
onClick={() => {
playBackSound();
setActiveView("main");
}}
className="w-72 h-10 flex items-center justify-center text-xl mc-text-shadow hover:text-[#FFFF55] text-white border-none outline-none transition-all"
style={{
backgroundImage: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/button_highlighted.png')";
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/Button_Background.png')";
}}
>
Back
</button>
</div>
{!isAndroid && (
<div className="w-full mt-6 mb-4 flex justify-center">
<button
onClick={() => {
playBackSound();
setActiveView("main");
}}
className="w-72 h-10 flex items-center justify-center text-xl mc-text-shadow hover:text-[#FFFF55] text-white border-none outline-none transition-all"
style={{
backgroundImage: "url('/images/Button_Background.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/button_highlighted.png')";
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/Button_Background.png')";
}}
>
Back
</button>
</div>
)}
<AnimatePresence>
{selectedPkg && (

View file

@ -455,7 +455,7 @@ export default function App() {
animate={{ opacity: 1 }}
className={`flex flex-col h-full z-10 w-full relative ${showHeader ? "pt-12" : ""}`}
>
{!config.legacyMode && (
{!config.legacyMode && !isAndroid && (
<motion.div {...uiFade} className="absolute top-10 left-8 z-50">
<button
onClick={() => {
@ -477,6 +477,46 @@ export default function App() {
</motion.div>
)}
{isAndroid && activeView !== "main" && (
<motion.div {...uiFade} className="absolute top-10 left-8 z-50">
<button
onClick={() => {
audio.playBackSound();
setActiveView("main");
}}
className="outline-none border-none flex items-center justify-center w-10 h-10 cursor-pointer"
aria-label="Back"
style={{
backgroundImage: "url('/images/Button_Square.png')",
backgroundSize: "100% 100%",
imageRendering: "pixelated",
}}
onMouseEnter={(e) =>
((e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/Button_Square_Highlighted.png')")
}
onMouseLeave={(e) =>
((e.currentTarget as HTMLButtonElement).style.backgroundImage =
"url('/images/Button_Square.png')")
}
>
<svg
width="26"
height="26"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2.5"
strokeLinecap="square"
strokeLinejoin="miter"
className="drop-shadow-[2px_2px_0_rgba(0,0,0,0.8)]"
>
<polyline points="15 18 9 12 15 6" />
</svg>
</button>
</motion.div>
)}
{!config.legacyMode && (
<motion.div
{...uiFade}