diff --git a/app/src/main/java/dev/aldi/sayuti/editor/manage/LibraryDownloaderDialogFragment.java b/app/src/main/java/dev/aldi/sayuti/editor/manage/LibraryDownloaderDialogFragment.java index a239f50a27..2a0855e812 100644 --- a/app/src/main/java/dev/aldi/sayuti/editor/manage/LibraryDownloaderDialogFragment.java +++ b/app/src/main/java/dev/aldi/sayuti/editor/manage/LibraryDownloaderDialogFragment.java @@ -11,8 +11,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.fragment.app.DialogFragment; +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.gson.Gson; @@ -32,85 +32,81 @@ import pro.sketchware.utility.FileUtil; import pro.sketchware.utility.SketchwareUtil; -public class LibraryDownloaderDialogFragment extends DialogFragment { +public class LibraryDownloaderDialogFragment extends BottomSheetDialogFragment { private LibraryDownloaderDialogBinding binding; - private final Gson gson = new Gson(); - private boolean notAssociatedWithProject = false; - private String dependencyName; - private BuildSettings buildSettings; - private String local_lib_file = ""; - private LibraryDownloaderListener listener; - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - binding = LibraryDownloaderDialogBinding.inflate(getLayoutInflater()); - initVariables(); + private Gson gson = new Gson(); + private BuildSettings buildSettings; - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity()); - builder.setView(binding.getRoot()); + private boolean notAssociatedWithProject; + private String dependencyName; + private String localLibFile; + private OnLibraryDownloadedTask onLibraryDownloadedTask; - return builder.create(); + public interface OnLibraryDownloadedTask { + void invoke(); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + binding = LibraryDownloaderDialogBinding.inflate(inflater, container, false); return binding.getRoot(); } - public void setListener(LibraryDownloaderListener listener) { - this.listener = listener; - } - - public interface LibraryDownloaderListener { - void onTaskCompleted(); - } + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - private void initVariables() { if (getArguments() == null) return; notAssociatedWithProject = getArguments().getBoolean("notAssociatedWithProject", false); buildSettings = (BuildSettings) getArguments().getSerializable("buildSettings"); - local_lib_file = getArguments().getString("local_lib_file"); + localLibFile = getArguments().getString("localLibFile"); + + binding.btnCancel.setOnClickListener(v -> dismiss()); + binding.btnDownload.setOnClickListener(v -> initDownloadFlow()); } - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - binding.downloadButton.setOnClickListener(v1 -> initDownloadFlow()); + public void setOnLibraryDownloadedTask(OnLibraryDownloadedTask onLibraryDownloadedTask) { + this.onLibraryDownloadedTask = onLibraryDownloadedTask; } private void initDownloadFlow() { - dependencyName = Objects.requireNonNull(binding.dependencyInput.getText()).toString(); - if (dependencyName.isEmpty()) { - SketchwareUtil.toastError("Please enter a dependency"); + dependencyName = binding.dependencyInput.getText().toString(); + if (dependencyName == null || dependencyName.isEmpty()) { + binding.dependencyInputLayout.setError("Please enter a dependency"); + binding.dependencyInputLayout.setErrorEnabled(true); return; } + var parts = dependencyName.split(":"); if (parts.length != 3) { - SketchwareUtil.toastError("Invalid dependency format"); + binding.dependencyInputLayout.setError("Invalid dependency format"); + binding.dependencyInputLayout.setErrorEnabled(true); return; } - binding.downloadStatusTxt.setText("Looking for dependency..."); + binding.dependencyInfo.setText("Looking for dependency..."); + binding.dependencyInputLayout.setErrorEnabled(false); setDownloadState(true); var group = parts[0]; var artifact = parts[1]; var version = parts[2]; - var resolver = new DependencyResolver(group, artifact, version, binding.skipSubDependenciesCheckBox.isChecked(), buildSettings); + var resolver = new DependencyResolver(group, artifact, version, binding.cbSkipSubdependencies.isChecked(), buildSettings); var handler = new Handler(Looper.getMainLooper()); class SetTextRunnable implements Runnable { - private final String message; + private final String text; - SetTextRunnable(String message) { - this.message = message; + SetTextRunnable(String text) { + this.text = text; } @Override public void run() { - binding.downloadStatusTxt.setText(message); + binding.dependencyInfo.setText(text); } } @@ -209,16 +205,16 @@ public void onTaskCompleted(@NonNull List dependencies) { SketchwareUtil.toast("Library downloaded successfully"); if (!notAssociatedWithProject) { new SetTextRunnable("Adding dependencies to project...").run(); - var fileContent = FileUtil.readFile(local_lib_file); + var fileContent = FileUtil.readFile(localLibFile); var enabledLibs = gson.fromJson(fileContent, Helper.TYPE_MAP_LIST); enabledLibs.addAll(dependencies.stream() .map(name -> ManageLocalLibraryActivity.createLibraryMap(name, dependencyName)) .collect(Collectors.toList())); - FileUtil.writeFile(local_lib_file, gson.toJson(enabledLibs)); + FileUtil.writeFile(localLibFile, gson.toJson(enabledLibs)); } if (getActivity() == null) return; dismiss(); - if (listener != null) listener.onTaskCompleted(); + if (onLibraryDownloadedTask != null) onLibraryDownloadedTask.invoke(); }); } }); @@ -226,12 +222,10 @@ public void onTaskCompleted(@NonNull List dependencies) { } private void setDownloadState(boolean downloading) { - binding.downloadButton.setEnabled(!downloading); + binding.btnCancel.setVisibility(downloading ? View.GONE : View.VISIBLE); + binding.btnDownload.setEnabled(!downloading); binding.dependencyInput.setEnabled(!downloading); - binding.downloadButton.setText(downloading ? "Downloading..." : "Download"); - binding.downloadProgressCardView.setVisibility(downloading ? View.VISIBLE : View.GONE); - binding.hintText.setVisibility(downloading ? View.GONE : View.VISIBLE); - binding.skipSubDependenciesCheckBox.setVisibility(downloading ? View.GONE : View.VISIBLE); + binding.cbSkipSubdependencies.setEnabled(!downloading); setCancelable(!downloading); } } diff --git a/app/src/main/java/dev/aldi/sayuti/editor/manage/ManageLocalLibraryActivity.java b/app/src/main/java/dev/aldi/sayuti/editor/manage/ManageLocalLibraryActivity.java index 8af85fa4b1..76522bbfc8 100644 --- a/app/src/main/java/dev/aldi/sayuti/editor/manage/ManageLocalLibraryActivity.java +++ b/app/src/main/java/dev/aldi/sayuti/editor/manage/ManageLocalLibraryActivity.java @@ -32,7 +32,6 @@ import mod.hey.studios.util.Helper; import mod.jbk.util.AddMarginOnApplyWindowInsetsListener; -import pro.sketchware.R; import pro.sketchware.databinding.ManageLocallibrariesBinding; import pro.sketchware.databinding.ViewItemLocalLibBinding; import pro.sketchware.databinding.ViewItemLocalLibSearchBinding; @@ -96,7 +95,7 @@ protected void onCreate(Bundle savedInstanceState) { LibraryDownloaderDialogFragment fragment = new LibraryDownloaderDialogFragment(); fragment.setArguments(bundle); - fragment.setListener(this::loadLibraries); + fragment.setOnLibraryDownloadedTask(this::loadLibraries); fragment.show(getSupportFragmentManager(), "library_downloader_dialog"); }); @@ -211,7 +210,7 @@ public void onBindViewHolder(ViewHolder holder, final int position) { var binding = holder.binding; final File libraryFile = libraryFiles.get(position); - final String librarySize = FileUtil.formatFileSize(libraryFile.length()); + final String librarySize = FileUtil.formatFileSize(FileUtil.getFileSize(libraryFile)); binding.libraryName.setText(libraryFile.getName()); binding.librarySize.setText(librarySize); binding.libraryName.setSelected(true); @@ -317,7 +316,7 @@ public void onBindViewHolder(ViewHolder holder, final int position) { var binding = holder.binding; final File libraryFile = filteredLibraryFiles.get(position); - final String librarySize = FileUtil.formatFileSize(libraryFile.length()); + final String librarySize = FileUtil.formatFileSize(FileUtil.getFileSize(libraryFile)); binding.libraryName.setText(libraryFile.getName()); binding.librarySize.setText(librarySize); binding.libraryName.setSelected(true); diff --git a/app/src/main/java/pro/sketchware/utility/FileUtil.java b/app/src/main/java/pro/sketchware/utility/FileUtil.java index ec24b2b4ac..a754665cff 100644 --- a/app/src/main/java/pro/sketchware/utility/FileUtil.java +++ b/app/src/main/java/pro/sketchware/utility/FileUtil.java @@ -54,34 +54,56 @@ @SuppressWarnings("unused") public class FileUtil { + public static long getFileSize(File file) { + if (file == null || !file.exists()) { + return 0; + } + + if (!file.isDirectory()) { + return file.length(); + } + + List dirs = new LinkedList<>(); + dirs.add(file); + + long result = 0; + while (!dirs.isEmpty()) { + File dir = dirs.remove(0); + if (!dir.exists()) + continue; + File[] listFiles = dir.listFiles(); + if (listFiles == null || listFiles.length == 0) + continue; + for (File child : listFiles) { + if (child.isDirectory()) { + dirs.add(child); + } else { + result += child.length(); + } + } + } + + return result; + } + public static String formatFileSize(long size) { return formatFileSize(size, false); } public static String formatFileSize(long size, boolean removeZero) { - if (size < 1024) { - return String.format("%d B", size); - } else if (size < 1024 * 1024) { - float value = size / 1024.0f; - if (removeZero && (value - (int) value) * 10 == 0) { - return String.format("%d KB", (int) value); - } else { - return String.format("%.1f KB", value); - } - } else if (size < 1024 * 1024 * 1024) { - float value = size / 1024.0f / 1024.0f; - if (removeZero && (value - (int) value) * 10 == 0) { - return String.format("%d MB", (int) value); - } else { - return String.format("%.1f MB", value); - } + String[] units = {"B", "KiB", "MiB", "GiB"}; + float value = size; + int unitIndex = 0; + + while (value >= 1024 && unitIndex < units.length - 1) { + value /= 1024; + unitIndex++; + } + + if (removeZero && (value - (int) value) * 10 == 0) { + return String.format("%d %s", (int) value, units[unitIndex]); } else { - float value = size / 1024.0f / 1024.0f / 1024.0f; - if (removeZero && (value - (int) value) * 10 == 0) { - return String.format("%d GB", (int) value); - } else { - return String.format("%.1f GB", value); - } + return String.format("%.1f %s", value, units[unitIndex]); } } diff --git a/app/src/main/res/layout/library_downloader_dialog.xml b/app/src/main/res/layout/library_downloader_dialog.xml index b26cd6f49e..f98e4f4b9d 100644 --- a/app/src/main/res/layout/library_downloader_dialog.xml +++ b/app/src/main/res/layout/library_downloader_dialog.xml @@ -1,31 +1,34 @@ + android:orientation="vertical"> + + + android:layout_marginEnd="20dp" + android:layout_marginStart="20dp" + android:text="Download a dependency" + android:textAppearance="?attr/textAppearanceTitleLarge" /> + android:hint="Enter a dependency" + android:importantForAutofill="noExcludeDescendants" + app:placeholderText="@string/local_library_manager_dependency_example"> - - - - - - - - - - - + android:layout_marginBottom="16dp" + android:layout_marginHorizontal="20dp" + android:layout_marginTop="12dp" + android:orientation="horizontal"> + +