From 3b925708210dd2c98ebf65d2935e223f2188016f Mon Sep 17 00:00:00 2001 From: Akash Yadav Date: Thu, 27 Jan 2022 09:05:10 +0530 Subject: [PATCH] Made the 'Auto save files' an EXPERIMENTAL feature and disabled by default Can be enabled from preferences --- .idea/misc.xml | 1 + .../main/assets/data/common/gradle-plugin.zip | Bin 37243 -> 37239 bytes .../com/itsaky/androidide/EditorActivity.java | 115 ++++++++++++------ .../preferences/EditorPreferences.java | 78 +++++++----- .../com/itsaky/androidide/utils/Symbols.java | 14 ++- .../androidide/viewmodel/EditorViewModel.java | 9 ++ .../androidide/views/CodeEditorView.java | 8 ++ app/src/main/res/values/strings.xml | 4 + .../managers/PreferenceManager.java | 1 + 9 files changed, 161 insertions(+), 69 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index c7b0a3074..3ff66db25 100755 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -12,6 +12,7 @@ + diff --git a/app/src/main/assets/data/common/gradle-plugin.zip b/app/src/main/assets/data/common/gradle-plugin.zip index 6e8589236b80a35a079ce391ee53eedb71d7ca13..572dc40f7bf8d6cfef4e492bc9dec45385da6fe3 100644 GIT binary patch delta 2139 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 diff --git a/app/src/main/java/com/itsaky/androidide/EditorActivity.java b/app/src/main/java/com/itsaky/androidide/EditorActivity.java index 2674950d4..2bd9c7f8e 100755 --- a/app/src/main/java/com/itsaky/androidide/EditorActivity.java +++ b/app/src/main/java/com/itsaky/androidide/EditorActivity.java @@ -28,6 +28,7 @@ import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.text.TextUtils; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; @@ -110,7 +111,6 @@ import com.itsaky.androidide.views.CodeEditorView; import com.itsaky.androidide.views.MaterialBanner; import com.itsaky.androidide.views.SymbolInputView; import com.itsaky.inflater.ILayoutInflater; -import com.itsaky.inflater.values.ValuesTable; import com.itsaky.inflater.values.ValuesTableFactory; import com.itsaky.lsp.java.models.JavaServerConfiguration; import com.itsaky.lsp.models.DiagnosticItem; @@ -122,7 +122,6 @@ import com.unnamed.b.atv.model.TreeNode; import org.jetbrains.annotations.Contract; import java.io.File; -import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; @@ -133,6 +132,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -827,7 +827,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F public void saveResult (int index, SaveResult result) { if (index >= 0 && index < mViewModel.getOpenedFileCount ()) { var frag = getEditorAtIndex (index); - if (frag == null) { + if (frag == null || frag.getFile () == null) { return; } @@ -941,8 +941,13 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F var opened = mViewModel.getOpenedFile (index); LOG.info ("Closing file:", opened); final var editor = getEditorAtIndex (index); + + if (editor != null && editor.isModified ()) { + notifyFilesUnsaved (Collections.singletonList (editor), () -> closeFile (index)); + return; + } + if (editor != null && editor.getEditor () != null) { - editor.save (); editor.getEditor ().close (); } else { LOG.error ("Cannot save file before close. Editor instance is null"); @@ -964,40 +969,80 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F public void closeAll () { final var count = mViewModel.getOpenedFileCount (); + final var unsavedFiles = mViewModel.getOpenedFiles () + .stream () + .map (this::getEditorForFile) + .filter (editor -> editor != null && editor.isModified ()) + .collect (Collectors.toList ()); - // Save and close all files one by one - for (int i = 0; i < count; i++) { - final var editor = getEditorAtIndex (i); - if (editor != null && editor.getEditor () != null) { - editor.save (); - editor.getEditor ().close (); - } else { - LOG.error ("Unable to save file at index:", i); + if (unsavedFiles.isEmpty ()) { + // Files were already saved, close all files one by one + for (int i = 0; i < count; i++) { + final var editor = getEditorAtIndex (i); + if (editor != null && editor.getEditor () != null) { + editor.getEditor ().close (); + } else { + LOG.error ("Unable to close file at index:", i); + } } + + mViewModel.removeAllFiles (); + mBinding.tabs.removeAllTabs (); + mBinding.tabs.requestLayout (); + mBinding.editorContainer.removeAllViews (); + + invalidateOptionsMenu (); + } else { + // There are unsaved files + notifyFilesUnsaved (unsavedFiles, this::closeAll); } - - mViewModel.removeAllFiles (); - mBinding.tabs.removeAllTabs (); - mBinding.tabs.requestLayout (); - mBinding.editorContainer.removeAllViews (); - - invalidateOptionsMenu (); + } + + private void notifyFilesUnsaved (List unsavedEditors, Runnable invokeAfter) { + final var builder = DialogUtils.newYesNoDialog (this, + getString (R.string.title_files_unsaved), // title + getString (R.string.msg_files_unsaved, TextUtils.join ("\n", unsavedEditors)), // message + (dialog, which) -> { // 'yes' click + dialog.dismiss (); + saveAll (true); + invokeAfter.run (); + }, + (dialog, which) -> { // 'no' click + dialog.dismiss (); + // Mark all the files as saved, then try to close them all + for (var editor : unsavedEditors) { + editor.markAsSaved (); + } + + invokeAfter.run (); + }); + builder.show (); } public void closeOthers () { - final var file = mViewModel.getCurrentFile (); - for (int i = 0; i < mViewModel.getOpenedFileCount (); i++) { - final var editor = getEditorAtIndex (i); - - // Index of files changes as we keep close files - // So we compare the files instead of index - if (editor != null) { - if (!file.equals (editor.getFile ())) { - closeFile (i); + final var unsavedFiles = mViewModel.getOpenedFiles () + .stream () + .map (this::getEditorForFile) + .filter (editor -> editor != null && editor.isModified ()) + .collect (Collectors.toList ()); + + if (unsavedFiles.isEmpty ()) { + final var file = mViewModel.getCurrentFile (); + for (int i = 0; i < mViewModel.getOpenedFileCount (); i++) { + final var editor = getEditorAtIndex (i); + + // Index of files changes as we keep close files + // So we compare the files instead of index + if (editor != null) { + if (!file.equals (editor.getFile ())) { + closeFile (i); + } + } else { + LOG.error ("Unable to save file at index:", i); } - } else { - LOG.error ("Unable to save file at index:", i); } + } else { + notifyFilesUnsaved (unsavedFiles, this::closeOthers); } } @@ -1019,7 +1064,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F public CodeEditorView getEditorForFile (@NonNull final File file) { for (int i = 0; i < mViewModel.getOpenedFileCount (); i++) { final CodeEditorView editor = (CodeEditorView) mBinding.editorContainer.getChildAt (i); - if (editor.getFile ().equals (file)) { + if (file.equals (editor.getFile ())) { return editor; } } @@ -1157,7 +1202,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F private void previewLayout () { try { - if (getCurrentEditor () == null) { + if (getCurrentEditor () == null || getCurrentEditor ().getFile () == null) { LOG.error ("No file is opened. Cannot preview layout."); return; } @@ -1498,14 +1543,16 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F mTabCloseAction.setOnActionItemClickListener ((item) -> { final int id = item.getActionId (); - saveAll (); + if (getApp ().getPrefManager ().getBoolean (PreferenceManager.KEY_EDITOR_AUTO_SAVE, false)) { + saveAll (); + } + if (id == ACTION_ID_CLOSE) { closeFile (mBinding.tabs.getSelectedTabPosition ()); } if (id == ACTION_ID_OTHERS) { closeOthers (); - closeOthers (); } if (id == ACTION_ID_ALL) { diff --git a/app/src/main/java/com/itsaky/androidide/fragments/preferences/EditorPreferences.java b/app/src/main/java/com/itsaky/androidide/fragments/preferences/EditorPreferences.java index bbc4176ee..666fc3c6d 100755 --- a/app/src/main/java/com/itsaky/androidide/fragments/preferences/EditorPreferences.java +++ b/app/src/main/java/com/itsaky/androidide/fragments/preferences/EditorPreferences.java @@ -19,6 +19,8 @@ package com.itsaky.androidide.fragments.preferences; import android.os.Bundle; import android.view.LayoutInflater; + +import androidx.annotation.NonNull; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.SwitchPreference; @@ -33,12 +35,15 @@ import com.itsaky.androidide.utils.DialogUtils; import static com.itsaky.androidide.managers.PreferenceManager.*; import static com.itsaky.androidide.models.PrefBasedJavaServerSettings.*; -public class EditorPreferences extends BasePreferenceFragment implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener { +public class EditorPreferences extends BasePreferenceFragment { @Override public void onCreatePreferences(Bundle p1, String p2) { super.onCreatePreferences(p1, p2); - if(getContext() == null) return; + + if(getContext() == null) { + return; + } final var screen = getPreferenceScreen(); final var commonCategory = new PreferenceCategory (getContext ()); @@ -48,6 +53,7 @@ public class EditorPreferences extends BasePreferenceFragment implements Prefere final var nonPrintable = new Preference(getContext()); final var tabSize = new Preference(getContext()); final var drawHex = new SwitchPreference(getContext()); + final var autoSave = new SwitchPreference (getContext ()); final var javaMatchLower = new SwitchPreference (getContext ()); @@ -74,6 +80,11 @@ public class EditorPreferences extends BasePreferenceFragment implements Prefere drawHex.setTitle(R.string.idepref_editor_drawhexcolors_title); drawHex.setSummary(R.string.idepref_editor_drawhexcolors_summary); + autoSave.setIcon (R.drawable.ic_save); + autoSave.setKey (KEY_EDITOR_AUTO_SAVE); + autoSave.setTitle (getString(R.string.idepref_editor_autoSave_title)); + autoSave.setSummary (getString(R.string.idepref_editor_autoSave_summary)); + javaMatchLower.setKey (KEY_JAVA_PREF_MATCH_LOWER); javaMatchLower.setIcon (R.drawable.ic_text_lower); javaMatchLower.setTitle (getString(R.string.idepref_java_matchLower_title)); @@ -84,46 +95,55 @@ public class EditorPreferences extends BasePreferenceFragment implements Prefere commonCategory.addPreference(nonPrintable); commonCategory.addPreference(tabSize); commonCategory.addPreference(drawHex); + commonCategory.addPreference (autoSave); javaCategory.setTitle (getString(R.string.idepref_editor_category_java)); javaCategory.addPreference (javaMatchLower); setPreferenceScreen(screen); - fontSize.setOnPreferenceClickListener(this); - nonPrintable.setOnPreferenceClickListener(this); - tabSize.setOnPreferenceClickListener(this); - drawHex.setOnPreferenceChangeListener(this); - javaMatchLower.setOnPreferenceChangeListener (this); + fontSize.setOnPreferenceClickListener(this::onPreferenceClick); + nonPrintable.setOnPreferenceClickListener(this::onPreferenceClick); + tabSize.setOnPreferenceClickListener(this::onPreferenceClick); + drawHex.setOnPreferenceChangeListener(this::onPreferenceChange); + autoSave.setOnPreferenceChangeListener (this::onPreferenceChange); + javaMatchLower.setOnPreferenceChangeListener (this::onPreferenceChange); drawHex.setChecked(getPrefManager().getBoolean(KEY_EDITOR_DRAW_HEX, true)); + autoSave.setChecked (getPrefManager ().getBoolean (KEY_EDITOR_AUTO_SAVE, false)); javaMatchLower.setChecked (getPrefManager ().getBoolean (KEY_JAVA_PREF_MATCH_LOWER, false)); } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { + + public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { final boolean value = (boolean) newValue; - if(preference.getKey().equals(KEY_EDITOR_DRAW_HEX)) { - getPrefManager().putBoolean(KEY_EDITOR_DRAW_HEX, value); - ConstantsBridge.EDITOR_PREF_DRAW_HEX_CHANGED = true; - } else if (preference.getKey ().equals (KEY_JAVA_PREF_MATCH_LOWER)) { - getPrefManager ().putBoolean (KEY_JAVA_PREF_MATCH_LOWER, value); - final var javaServer = StudioApp.getInstance ().getJavaLanguageServer (); - javaServer.applySettings (PrefBasedJavaServerSettings.getInstance ()); + + switch (preference.getKey ()) { + case KEY_EDITOR_DRAW_HEX: + ConstantsBridge.EDITOR_PREF_DRAW_HEX_CHANGED = true; + break; + case KEY_JAVA_PREF_MATCH_LOWER: + final var javaServer = StudioApp.getInstance ().getJavaLanguageServer (); + javaServer.applySettings (PrefBasedJavaServerSettings.getInstance ()); + break; } + + getPrefManager ().putBoolean (preference.getKey (), value); return true; } - - @Override - public boolean onPreferenceClick(Preference preference) { + + public boolean onPreferenceClick(@NonNull Preference preference) { final String key = preference.getKey(); - if(key.equals(KEY_EDITOR_FONT_SIZE)) { - showTextSizeDialog(); - } else if(key.equals(KEY_EDITOR_PRINTABLE_CHARS)) { - showPrintableCharsDialog(); - } else if(key.equals(KEY_EDITOR_TAB_SIZE)) { - showTabSizeDialog(); - } + switch (key) { + case KEY_EDITOR_FONT_SIZE: + showTextSizeDialog (); + break; + case KEY_EDITOR_PRINTABLE_CHARS: + showPrintableCharsDialog (); + break; + case KEY_EDITOR_TAB_SIZE: + showTabSizeDialog (); + break; + } return true; } @@ -170,9 +190,7 @@ public class EditorPreferences extends BasePreferenceFragment implements Prefere float s = binding.slider.getValue(); changeTextSize(binding, s); }); - builder.setNeutralButton(R.string.reset, (p1, p2) -> { - changeTextSize(binding, 14); - }); + builder.setNeutralButton(R.string.reset, (p1, p2) -> changeTextSize(binding, 14)); builder.setCancelable(false); builder.show(); } diff --git a/app/src/main/java/com/itsaky/androidide/utils/Symbols.java b/app/src/main/java/com/itsaky/androidide/utils/Symbols.java index 60dcbb2a6..77a549269 100755 --- a/app/src/main/java/com/itsaky/androidide/utils/Symbols.java +++ b/app/src/main/java/com/itsaky/androidide/utils/Symbols.java @@ -1,8 +1,6 @@ -/************************************************************************************ +/* * This file is part of AndroidIDE. * - * - * * AndroidIDE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,18 +14,24 @@ * You should have received a copy of the GNU General Public License * along with AndroidIDE. If not, see . * -**************************************************************************************/ + */ package com.itsaky.androidide.utils; +import androidx.annotation.Nullable; + import com.itsaky.androidide.app.StudioApp; import com.itsaky.androidide.views.SymbolInputView.Symbol; import java.io.File; public class Symbols { - public static Symbol[] forFile(File file) { + public static Symbol[] forFile(@Nullable File file) { + if (file == null) { + return new Symbol[0]; + } + if (file.isFile()) { if (file.getName().endsWith(".java") || file.getName().endsWith(".gradle")) diff --git a/app/src/main/java/com/itsaky/androidide/viewmodel/EditorViewModel.java b/app/src/main/java/com/itsaky/androidide/viewmodel/EditorViewModel.java index ef415c630..59664d119 100644 --- a/app/src/main/java/com/itsaky/androidide/viewmodel/EditorViewModel.java +++ b/app/src/main/java/com/itsaky/androidide/viewmodel/EditorViewModel.java @@ -125,6 +125,15 @@ public class EditorViewModel extends ViewModel { return Objects.requireNonNull (mFiles.getValue ()).size (); } + /** + * Get the list of currently opened files. + * @return The list of opened files. + */ + @NonNull + public List getOpenedFiles () { + return mFiles.getValue () == null ? new ArrayList<> () : mFiles.getValue (); + } + /** * Add an observer to the list of opened files. * @param lifecycleOwner The lifecycle owner. diff --git a/app/src/main/java/com/itsaky/androidide/views/CodeEditorView.java b/app/src/main/java/com/itsaky/androidide/views/CodeEditorView.java index 3f17f61e1..edd74837e 100644 --- a/app/src/main/java/com/itsaky/androidide/views/CodeEditorView.java +++ b/app/src/main/java/com/itsaky/androidide/views/CodeEditorView.java @@ -374,4 +374,12 @@ public class CodeEditorView extends FrameLayout { ValuesTableFactory.syncWithFile (getFile ()); } } + + /** + * Mark this files as saved. Even if it not saved. + */ + public void markAsSaved () { + isModified = false; + notifySaved (); + } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 62daf1b8a..c029c2761 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -359,5 +359,9 @@ If enabled, then typing a lower case or upper case letters will suggest class names as well as scope members. Common Java + Unsaved files + Some files are not saved. Would you like to save them before closing? Unsaved files are:\n%s + Save before closing files + Save files before closing them. This is an EXPERIMENTAL feature. You are expected to save the files yourself. diff --git a/common/src/main/java/com/itsaky/androidide/managers/PreferenceManager.java b/common/src/main/java/com/itsaky/androidide/managers/PreferenceManager.java index de7b68703..027e349b0 100755 --- a/common/src/main/java/com/itsaky/androidide/managers/PreferenceManager.java +++ b/common/src/main/java/com/itsaky/androidide/managers/PreferenceManager.java @@ -42,6 +42,7 @@ public class PreferenceManager { public static final String KEY_EDITOR_FONT_SIZE = "idepref_editor_fontSize"; public static final String KEY_EDITOR_PRINTABLE_CHARS = "idepref_editor_nonPrintableFlags"; public static final String KEY_EDITOR_TAB_SIZE = "idepref_editor_tabSize"; + public static final String KEY_EDITOR_AUTO_SAVE = "idepref_editor_autoSave"; public static final String KEY_GRADLE_CMD_STACK_TRACE = "idepref_gradleCmd_stacktrace"; public static final String KEY_GRADLE_CMD_DEBUG = "idepref_gradleCmd_debug";