From 58e5bb8927ad3599b329ededa107c627c5ef115e Mon Sep 17 00:00:00 2001 From: ammarasyad Date: Mon, 18 Dec 2023 15:52:28 +0700 Subject: [PATCH] Convert ChimuWebView and DownloadingFragment to Kotlin --- src/com/reco1l/legacy/ui/ChimuWebView.java | 236 ------------------ src/com/reco1l/legacy/ui/ChimuWebView.kt | 185 ++++++++++++++ .../reco1l/legacy/ui/DownloadingFragment.java | 88 ------- .../reco1l/legacy/ui/DownloadingFragment.kt | 59 +++++ src/com/reco1l/legacy/ui/MainMenu.kt | 2 +- .../reco1l/legacy/ui/entity/BeatmapButton.kt | 4 +- 6 files changed, 247 insertions(+), 327 deletions(-) delete mode 100644 src/com/reco1l/legacy/ui/ChimuWebView.java create mode 100644 src/com/reco1l/legacy/ui/ChimuWebView.kt delete mode 100644 src/com/reco1l/legacy/ui/DownloadingFragment.java create mode 100644 src/com/reco1l/legacy/ui/DownloadingFragment.kt diff --git a/src/com/reco1l/legacy/ui/ChimuWebView.java b/src/com/reco1l/legacy/ui/ChimuWebView.java deleted file mode 100644 index 2bfc8402e..000000000 --- a/src/com/reco1l/legacy/ui/ChimuWebView.java +++ /dev/null @@ -1,236 +0,0 @@ -package com.reco1l.legacy.ui; - -import android.content.Intent; -import android.graphics.Bitmap; -import android.net.Uri; -import android.view.View; -import com.edlplan.ui.fragment.LoadingFragment; -import com.edlplan.ui.fragment.WebViewFragment; -import com.reco1l.framework.extensions.StringUtil; -import com.reco1l.framework.net.Downloader; -import com.reco1l.framework.net.IDownloaderObserver; -import com.reco1l.framework.net.SizeMeasure; -import com.reco1l.legacy.Multiplayer; -import com.reco1l.legacy.ui.multiplayer.RoomScene; -import im.delight.android.webview.AdvancedWebView; -import net.lingala.zip4j.ZipFile; -import org.apache.commons.io.FilenameUtils; -import ru.nsu.ccfit.zuev.osu.*; -import ru.nsu.ccfit.zuev.osu.helper.FileUtils; -import ru.nsu.ccfit.zuev.osu.helper.StringTable; -import ru.nsu.ccfit.zuev.osuplus.R; - -import java.io.File; -import java.io.IOException; - -import static android.content.Intent.ACTION_VIEW; -import static android.os.Environment.DIRECTORY_DOWNLOADS; - -@SuppressWarnings("DataFlowIssue") -public class ChimuWebView extends WebViewFragment implements IDownloaderObserver -{ - - public static final Uri MIRROR = Uri.parse("https://chimu.moe/en/beatmaps?mode=0"); - - public static final ChimuWebView INSTANCE = new ChimuWebView(); - - public static final String FILE_EXTENSION = ".osz"; - - //----------------------------------------------------------------------------------------------------------------// - - private DownloadingFragment mFragment; - - private AdvancedWebView mWebView; - - private String mCurrentFilename; - - private final MainActivity mActivity = GlobalManager.getInstance().getMainActivity(); - - //----------------------------------------------------------------------------------------------------------------// - - public ChimuWebView() - { - super.setURL(MIRROR.toString()); - } - - //----------------------------------------------------------------------------------------------------------------// - - @Override - protected int getLayoutID() - { - return R.layout.fragment_chimu; - } - - //----------------------------------------------------------------------------------------------------------------// - - @Override - protected void onLoadView() - { - super.onLoadView(); - - mWebView = findViewById(R.id.web); - assert mWebView != null; - - mWebView.addPermittedHostname(MIRROR.getHost()); - mWebView.setListener(mActivity, new AdvancedWebView.Listener() - { - final LoadingFragment fragment = new LoadingFragment(); - - @Override - public void onPageStarted(String url, Bitmap favicon) - { - fragment.show(); - } - - @Override - public void onPageFinished(String url) - { - fragment.dismiss(); - } - - @Override - public void onPageError(int errorCode, String description, String failingUrl) - { - - } - - @Override - public void onDownloadRequested(String url, String filename, String mimeType, long contentLength, String contentDisposition, String userAgent) - { - startDownload(url, filename); - } - - @Override - public void onExternalPageRequest(String url) - { - Intent intent = new Intent(ACTION_VIEW, Uri.parse(url)); - startActivity(intent); - } - }); - } - - public void startDownload(String url, String filename) - { - String name = StringUtil.decodeUtf8(filename); - filename = StringUtil.forFilesystem(name); - - if (!filename.endsWith(FILE_EXTENSION)) - { - ToastLogger.showText("Failed to start download, invalid file extension.", true); - return; - } - - mCurrentFilename = FilenameUtils.removeExtension(name); - - File directory = mActivity.getExternalFilesDir(DIRECTORY_DOWNLOADS); - File file = new File(directory, filename + FILE_EXTENSION); - - Downloader downloader = new Downloader(file, url); - - mFragment = new DownloadingFragment(); - mFragment.setDownloader(downloader, () -> { - - mFragment.getText().setVisibility(View.VISIBLE); - mFragment.getText().setText(R.string.chimu_connecting); - mFragment.getButton().setVisibility(View.VISIBLE); - mFragment.getButton().setText(R.string.chimu_cancel); - - downloader.setObserver(ChimuWebView.this); - downloader.download(); - - mFragment.getButton().setOnClickListener(v -> downloader.cancel()); - }); - mFragment.show(); - } - - //----------------------------------------------------------------------------------------------------------------// - - @Override - public void dismiss() - { - mWebView.destroy(); - super.dismiss(); - } - - //----------------------------------------------------------------------------------------------------------------// - - @Override - public void onDownloadStart(Downloader downloader) - { - mActivity.runOnUiThread(() -> mFragment.getText().setText(StringTable.format(R.string.chimu_downloading, mCurrentFilename))); - } - - @Override - public void onDownloadEnd(Downloader downloader) - { - mActivity.runOnUiThread(() -> { - mFragment.getProgressBar().setVisibility(View.GONE); - mFragment.getProgressBar().setIndeterminate(true); - mFragment.getProgressBar().setVisibility(View.VISIBLE); - - mFragment.getText().setText(StringTable.format(R.string.chimu_importing, mCurrentFilename)); - mFragment.getButton().setVisibility(View.GONE); - }); - - File file = downloader.getFile(); - - try (ZipFile zip = new ZipFile(file)) - { - if (!zip.isValidZipFile()) - { - mActivity.runOnUiThread(mFragment::dismiss); - ToastLogger.showText("Import failed, invalid ZIP file.", true); - return; - } - - if (!FileUtils.extractZip(file.getPath(), Config.getBeatmapPath())) - { - mActivity.runOnUiThread(mFragment::dismiss); - ToastLogger.showText("Import failed, unable to extract ZIP file.", true); - return; - } - - LibraryManager.INSTANCE.updateLibrary(true); - } - catch (IOException e) - { - ToastLogger.showText("Import failed: " + e.getMessage(), true); - } - mActivity.runOnUiThread(mFragment::dismiss); - - if (Multiplayer.isConnected()) - RoomScene.INSTANCE.onRoomBeatmapChange(Multiplayer.room.getBeatmap()); - } - - @Override - public void onDownloadCancel(Downloader downloader) - { - ToastLogger.showText("Download canceled.", true); - mActivity.runOnUiThread(mFragment::dismiss); - } - - @Override - public void onDownloadUpdate(Downloader downloader) - { - String info = String.format("\n%.3f kb/s (%d%%)", downloader.getSpeed(SizeMeasure.MBPS), (int) downloader.getProgress()); - - mActivity.runOnUiThread(() -> { - mFragment.getText().setText(StringTable.format(R.string.chimu_downloading, mCurrentFilename) + info); - mFragment.getProgressBar().setIndeterminate(false); - mFragment.getProgressBar().setProgress((int) downloader.getProgress()); - }); - } - - @Override - public void onDownloadFail(Downloader downloader) - { - mActivity.runOnUiThread(mFragment::dismiss); - - if (downloader.getException() != null) - { - ToastLogger.showText("Download failed: " + downloader.getException().getMessage(), true); - return; - } - ToastLogger.showText("Download failed.", true); - } -} diff --git a/src/com/reco1l/legacy/ui/ChimuWebView.kt b/src/com/reco1l/legacy/ui/ChimuWebView.kt new file mode 100644 index 000000000..dcd8240e8 --- /dev/null +++ b/src/com/reco1l/legacy/ui/ChimuWebView.kt @@ -0,0 +1,185 @@ +package com.reco1l.legacy.ui + +import android.content.Intent +import android.content.Intent.ACTION_VIEW +import android.graphics.Bitmap +import android.net.Uri +import android.os.Environment.DIRECTORY_DOWNLOADS +import android.view.View +import com.edlplan.ui.fragment.LoadingFragment +import com.edlplan.ui.fragment.WebViewFragment +import com.reco1l.framework.net.IDownloaderObserver +import im.delight.android.webview.AdvancedWebView +import ru.nsu.ccfit.zuev.osu.GlobalManager +import ru.nsu.ccfit.zuev.osuplus.R + +import com.reco1l.framework.extensions.decodeUtf8 +import com.reco1l.framework.extensions.forFilesystem +import com.reco1l.framework.net.Downloader +import com.reco1l.framework.net.SizeMeasure +import com.reco1l.legacy.Multiplayer +import com.reco1l.legacy.ui.multiplayer.RoomScene +import net.lingala.zip4j.ZipFile +import org.apache.commons.io.FilenameUtils +import ru.nsu.ccfit.zuev.osu.Config +import ru.nsu.ccfit.zuev.osu.LibraryManager +import ru.nsu.ccfit.zuev.osu.ToastLogger +import ru.nsu.ccfit.zuev.osu.helper.FileUtils +import ru.nsu.ccfit.zuev.osu.helper.StringTable +import java.io.IOException + +object ChimuWebView : WebViewFragment(), IDownloaderObserver { + private val MIRROR: Uri = Uri.parse("https://chimu.moe/en/beatmaps?mode=0") + const val FILE_EXTENSION = ".osz" + + private lateinit var mFragment: DownloadingFragment + private lateinit var mWebView: AdvancedWebView + private lateinit var mCurrentFilename: String + + private val mActivity = GlobalManager.getInstance().mainActivity + + init { + super.setURL(MIRROR.toString()) + } + + override val layoutID: Int + get() = R.layout.fragment_chimu + + override fun onLoadView() { + super.onLoadView() + mWebView = findViewById(R.id.web)!! + mWebView.addPermittedHostname(MIRROR.host) + mWebView.setListener(mActivity, + object : AdvancedWebView.Listener { + val fragment = LoadingFragment() + + override fun onPageStarted(url: String?, favicon: Bitmap?) = fragment.show() + + override fun onPageFinished(url: String?) = fragment.dismiss() + + override fun onPageError( + errorCode: Int, + description: String?, + failingUrl: String? + ) { + } + + override fun onDownloadRequested( + url: String?, + suggestedFilename: String?, + mimeType: String?, + contentLength: Long, + contentDisposition: String?, + userAgent: String? + ) { + startDownload(url!!, suggestedFilename!!) + } + + override fun onExternalPageRequest(url: String?) = + startActivity(Intent(ACTION_VIEW, Uri.parse(url))) + } + ) + } + + fun startDownload(url: String, suggestedFilename: String) { + val name = suggestedFilename.decodeUtf8() + val filename = name.forFilesystem() + + if (!filename.endsWith(FILE_EXTENSION)) { + ToastLogger.showText("Failed to start download. Invalid file extension", true) + return + } + + mCurrentFilename = FilenameUtils.removeExtension(filename) + + val directory = mActivity.getExternalFilesDir(DIRECTORY_DOWNLOADS) + val file = directory?.resolve(filename + FILE_EXTENSION)!! + + val downloader = Downloader(file, url) + + mFragment = DownloadingFragment() + mFragment.setDownloader(downloader) { + mFragment.text.visibility = View.VISIBLE + mFragment.text.text = R.string.chimu_connecting.toString() + mFragment.button.visibility = View.VISIBLE + mFragment.button.text = R.string.chimu_cancel.toString() + + downloader.observer = this@ChimuWebView + downloader.download() + + mFragment.button.setOnClickListener { + downloader.cancel() + } + } + mFragment.show() + } + + override fun dismiss() { + mWebView.destroy() + super.dismiss() + } + + override fun onDownloadStart(downloader: Downloader) { + mActivity.runOnUiThread { + mFragment.text.text = StringTable.format(R.string.chimu_downloading, mCurrentFilename) + } + } + + override fun onDownloadEnd(downloader: Downloader) { + mActivity.runOnUiThread { + mFragment.progressBar.visibility = View.GONE + mFragment.progressBar.isIndeterminate = true + mFragment.progressBar.visibility = View.VISIBLE + + mFragment.text.text = StringTable.format(R.string.chimu_importing, mCurrentFilename) + mFragment.button.visibility = View.GONE + } + + val file = downloader.file + + try { + ZipFile(file).use { + if (!it.isValidZipFile) { + mActivity.runOnUiThread(mFragment::dismiss) + ToastLogger.showText("Import failed, invalid ZIP file.", true) + return + } + + if (!FileUtils.extractZip(file.path, Config.getBeatmapPath())) { + mActivity.runOnUiThread(mFragment::dismiss) + ToastLogger.showText("Import failed, failed to extract ZIP file.", true) + return + } + + LibraryManager.INSTANCE.updateLibrary(true) + } + } catch (e: IOException) { + ToastLogger.showText("Import failed:" + e.message, true) + } + + mActivity.runOnUiThread(mFragment::dismiss) + + if (Multiplayer.isConnected) + RoomScene.onRoomBeatmapChange(Multiplayer.room!!.beatmap) + } + + override fun onDownloadCancel(downloader: Downloader) { + ToastLogger.showText("Download canceled.", true) + mActivity.runOnUiThread(mFragment::dismiss) + } + + override fun onDownloadUpdate(downloader: Downloader) { + val info = String.format("\n%.3f kb/s (%d%%)", downloader.getSpeed(SizeMeasure.MBPS), downloader.progress.toInt()) + + mActivity.runOnUiThread { + mFragment.text.text = StringTable.format(R.string.chimu_downloading, mCurrentFilename) + info + mFragment.progressBar.isIndeterminate = false + mFragment.progressBar.progress = downloader.progress.toInt() + } + } + + override fun onDownloadFail(downloader: Downloader) { + mActivity.runOnUiThread(mFragment::dismiss) + ToastLogger.showText("Download failed. " + downloader.exception?.message, true) + } +} \ No newline at end of file diff --git a/src/com/reco1l/legacy/ui/DownloadingFragment.java b/src/com/reco1l/legacy/ui/DownloadingFragment.java deleted file mode 100644 index d044da15a..000000000 --- a/src/com/reco1l/legacy/ui/DownloadingFragment.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.reco1l.legacy.ui; - -import android.text.TextUtils; -import android.view.View; -import android.widget.Button; -import android.widget.ProgressBar; -import android.widget.TextView; -import com.edlplan.ui.fragment.LoadingFragment; -import com.google.android.material.progressindicator.CircularProgressIndicator; -import com.reco1l.framework.net.Downloader; -import ru.nsu.ccfit.zuev.osuplus.R; - -public class DownloadingFragment extends LoadingFragment -{ - - private Downloader mDownloader; - private Runnable mAwaitCall; - - private Button mButton; - private TextView mText; - private CircularProgressIndicator mProgressBar; - - //----------------------------------------------------------------------------------------------------------------// - - public void setDownloader(Downloader downloader, Runnable await) - { - mAwaitCall = await; - mDownloader = downloader; - } - - //----------------------------------------------------------------------------------------------------------------// - - @Override - protected int getLayoutID() - { - return R.layout.fragment_downloading; - } - - //----------------------------------------------------------------------------------------------------------------// - - @Override - protected void onLoadView() - { - super.onLoadView(); - - mText = findViewById(R.id.text); - mButton = findViewById(R.id.button); - mProgressBar = findViewById(R.id.progress); - - mAwaitCall.run(); - } - - //----------------------------------------------------------------------------------------------------------------// - - @Override - public void callDismissOnBackPress() - { - if (mDownloader.isDownloading()) - { - mDownloader.cancel(); - return; - } - super.callDismissOnBackPress(); - } - - //----------------------------------------------------------------------------------------------------------------// - - public ProgressBar getProgressBar() - { - return mProgressBar; - } - - public Button getButton() - { - return mButton; - } - - public TextView getText() - { - return mText; - } - - public void setText(String text) - { - mText.setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE); - mText.setText(text); - } -} \ No newline at end of file diff --git a/src/com/reco1l/legacy/ui/DownloadingFragment.kt b/src/com/reco1l/legacy/ui/DownloadingFragment.kt new file mode 100644 index 000000000..a72b348bf --- /dev/null +++ b/src/com/reco1l/legacy/ui/DownloadingFragment.kt @@ -0,0 +1,59 @@ +package com.reco1l.legacy.ui + +import android.text.TextUtils +import android.view.View +import android.widget.Button +import android.widget.TextView +import com.edlplan.ui.fragment.LoadingFragment +import com.google.android.material.progressindicator.CircularProgressIndicator +import com.reco1l.framework.net.Downloader +import ru.nsu.ccfit.zuev.osuplus.R + +class DownloadingFragment : LoadingFragment() { + private lateinit var mDownloader: Downloader + private lateinit var mAwaitCall: Runnable + private lateinit var mButton: Button + private lateinit var mText: TextView + private lateinit var mProgressBar: CircularProgressIndicator + + fun setDownloader(downloader: Downloader, awaitCall: Runnable) { + mAwaitCall = awaitCall + mDownloader = downloader + } + + override val layoutID: Int + get() = R.layout.fragment_downloading + + override fun onLoadView() { + super.onLoadView() + + mText = findViewById(R.id.text)!! + mButton = findViewById(R.id.button)!! + mProgressBar = findViewById(R.id.progress)!! + + mAwaitCall.run() + } + + override fun callDismissOnBackPress() { + if (mDownloader.isDownloading) { + mDownloader.cancel() + return + } + + super.callDismissOnBackPress() + } + + val progressBar: CircularProgressIndicator + get() = mProgressBar + + val button: Button + get() = mButton + + val text: TextView + get() = mText + + fun setText(text: String) { + mText.visibility = if (TextUtils.isEmpty(text)) View.GONE else View.VISIBLE + mText.text = text + } +} \ No newline at end of file diff --git a/src/com/reco1l/legacy/ui/MainMenu.kt b/src/com/reco1l/legacy/ui/MainMenu.kt index 53702898b..55df59fc4 100644 --- a/src/com/reco1l/legacy/ui/MainMenu.kt +++ b/src/com/reco1l/legacy/ui/MainMenu.kt @@ -78,7 +78,7 @@ class MainMenu(val main: MainScene) getGlobal().songService.isGaming = false getGlobal().engine.scene = main.scene - ChimuWebView.INSTANCE.show() + ChimuWebView.show() } else { main.musicControl(MusicOption.PLAY) diff --git a/src/com/reco1l/legacy/ui/entity/BeatmapButton.kt b/src/com/reco1l/legacy/ui/entity/BeatmapButton.kt index 2727add46..3ce9e2e89 100644 --- a/src/com/reco1l/legacy/ui/entity/BeatmapButton.kt +++ b/src/com/reco1l/legacy/ui/entity/BeatmapButton.kt @@ -5,8 +5,9 @@ import com.reco1l.api.ibancho.RoomAPI import com.reco1l.api.ibancho.data.PlayerStatus.READY import com.reco1l.api.ibancho.data.RoomBeatmap import com.reco1l.framework.extensions.orAsyncCatch -import com.reco1l.legacy.ui.ChimuWebView.FILE_EXTENSION +import com.reco1l.legacy.ui.ChimuWebView as chimuFragment import com.reco1l.legacy.Multiplayer +import com.reco1l.legacy.ui.ChimuWebView.FILE_EXTENSION import com.reco1l.legacy.ui.multiplayer.RoomScene import org.anddev.andengine.entity.sprite.Sprite import org.anddev.andengine.entity.text.ChangeableText @@ -16,7 +17,6 @@ import ru.nsu.ccfit.zuev.osu.RGBColor import ru.nsu.ccfit.zuev.osu.ToastLogger import ru.nsu.ccfit.zuev.osu.menu.MenuItemTrack import ru.nsu.ccfit.zuev.skins.OsuSkin -import com.reco1l.legacy.ui.ChimuWebView.INSTANCE as chimuFragment import ru.nsu.ccfit.zuev.osu.GlobalManager.getInstance as getGlobal import ru.nsu.ccfit.zuev.osu.LibraryManager.INSTANCE as libraryManager import ru.nsu.ccfit.zuev.osu.ResourceManager.getInstance as getResources