From 0f3b9ff4d6ea496f95d2d191ca758265d66671fb Mon Sep 17 00:00:00 2001 From: Akash Yadav Date: Sun, 2 Jan 2022 21:03:19 +0530 Subject: [PATCH] Move view options to bottom sheet --- .idea/misc.xml | 7 +- app/src/main/AndroidManifest.xml | 128 +++--- .../com/itsaky/androidide/EditorActivity.java | 374 ++++-------------- .../adapters/EditorBottomSheetTabAdapter.java | 118 ++++++ .../fragments/BuildOutputFragment.java | 58 +++ .../fragments/DiagnosticsListFragment.java | 83 ++++ .../androidide/fragments/IDELogFragment.java | 21 + .../androidide/fragments/LogViewFragment.java | 64 +++ .../fragments/NonEditableEditorFragment.java | 72 ++++ .../fragments/SearchResultFragment.java | 81 ++++ .../androidide/fragments/sheets/LogSheet.java | 87 ---- .../androidide/lsp/IDELanguageClientImpl.java | 4 +- .../androidide/services/IDELogService.java | 38 ++ .../utils/EditorBottomSheetBehavior.java | 68 ++++ app/src/main/res/layout/activity_download.xml | 2 +- app/src/main/res/layout/activity_editor.xml | 345 +--------------- .../layout/fragment_non_editable_editor.xml | 22 ++ .../res/layout/layout_diagnostic_info.xml | 6 +- .../res/layout/layout_editor_bottom_sheet.xml | 75 ++++ app/src/main/res/values/strings.xml | 5 +- 20 files changed, 873 insertions(+), 785 deletions(-) create mode 100644 app/src/main/java/com/itsaky/androidide/adapters/EditorBottomSheetTabAdapter.java create mode 100644 app/src/main/java/com/itsaky/androidide/fragments/BuildOutputFragment.java create mode 100644 app/src/main/java/com/itsaky/androidide/fragments/DiagnosticsListFragment.java create mode 100644 app/src/main/java/com/itsaky/androidide/fragments/IDELogFragment.java create mode 100644 app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.java create mode 100644 app/src/main/java/com/itsaky/androidide/fragments/NonEditableEditorFragment.java create mode 100644 app/src/main/java/com/itsaky/androidide/fragments/SearchResultFragment.java delete mode 100755 app/src/main/java/com/itsaky/androidide/fragments/sheets/LogSheet.java create mode 100644 app/src/main/java/com/itsaky/androidide/services/IDELogService.java create mode 100644 app/src/main/java/com/itsaky/androidide/utils/EditorBottomSheetBehavior.java create mode 100644 app/src/main/res/layout/fragment_non_editable_editor.xml create mode 100644 app/src/main/res/layout/layout_editor_bottom_sheet.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 4fa9ac7c9..301599295 100755 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -10,8 +10,13 @@ - + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 69b3f5506..9bd4da35f 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,89 +1,91 @@ - - - - - - - - + + + + + + + + tools:ignore="UnusedAttribute,MediaCapabilities"> + + + - - - + - - - - + + - - - - + + - - + - - - - - - - - - - - - - - + android:windowSoftInputMode="adjustResize"> + + + + + + + + + + + + + + + + - + + \ No newline at end of file diff --git a/app/src/main/java/com/itsaky/androidide/EditorActivity.java b/app/src/main/java/com/itsaky/androidide/EditorActivity.java index 10ee3df3e..0b39aeedf 100755 --- a/app/src/main/java/com/itsaky/androidide/EditorActivity.java +++ b/app/src/main/java/com/itsaky/androidide/EditorActivity.java @@ -44,8 +44,6 @@ import androidx.appcompat.view.menu.MenuBuilder; import androidx.core.content.ContextCompat; import androidx.core.view.GravityCompat; import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import androidx.transition.Slide; import androidx.transition.TransitionManager; @@ -54,20 +52,24 @@ import com.blankj.utilcode.util.IntentUtils; import com.blankj.utilcode.util.KeyboardUtils; import com.blankj.utilcode.util.SizeUtils; import com.blankj.utilcode.util.ThreadUtils; +import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.navigation.NavigationView; import com.google.android.material.tabs.TabLayout; -import com.google.android.material.transition.MaterialContainerTransform; +import com.google.android.material.tabs.TabLayoutMediator; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.itsaky.androidide.adapters.DiagnosticsAdapter; +import com.itsaky.androidide.adapters.EditorBottomSheetTabAdapter; import com.itsaky.androidide.adapters.EditorPagerAdapter; +import com.itsaky.androidide.adapters.SearchListAdapter; import com.itsaky.androidide.app.StudioActivity; import com.itsaky.androidide.databinding.ActivityEditorBinding; import com.itsaky.androidide.databinding.LayoutDiagnosticInfoBinding; import com.itsaky.androidide.databinding.LayoutSearchProjectBinding; import com.itsaky.androidide.fragments.EditorFragment; import com.itsaky.androidide.fragments.FileTreeFragment; +import com.itsaky.androidide.fragments.SearchResultFragment; import com.itsaky.androidide.fragments.sheets.OptionsListFragment; import com.itsaky.androidide.fragments.sheets.ProgressSheet; import com.itsaky.androidide.fragments.sheets.TextSheetFragment; @@ -76,38 +78,39 @@ import com.itsaky.androidide.handlers.FileOptionsHandler; import com.itsaky.androidide.handlers.IDEHandler; import com.itsaky.androidide.interfaces.DiagnosticClickListener; import com.itsaky.androidide.interfaces.EditorActivityProvider; -import com.itsaky.androidide.language.logs.LogLanguageImpl; +import com.itsaky.androidide.lsp.IDELanguageClientImpl; import com.itsaky.androidide.lsp.LSP; import com.itsaky.androidide.lsp.LSPProvider; import com.itsaky.androidide.managers.PreferenceManager; -import com.itsaky.androidide.project.AndroidProject; import com.itsaky.androidide.models.DiagnosticGroup; import com.itsaky.androidide.models.LogLine; import com.itsaky.androidide.models.SaveResult; import com.itsaky.androidide.models.SearchResult; import com.itsaky.androidide.models.SheetOption; +import com.itsaky.androidide.project.AndroidProject; import com.itsaky.androidide.project.IDEProject; import com.itsaky.androidide.services.LogReceiver; import com.itsaky.androidide.services.builder.IDEService; import com.itsaky.androidide.shell.ShellServer; -import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE; import com.itsaky.androidide.tasks.TaskExecutor; import com.itsaky.androidide.utils.DialogUtils; -import com.itsaky.inflater.ILayoutInflater; +import com.itsaky.androidide.utils.EditorBottomSheetBehavior; import com.itsaky.androidide.utils.LSPUtils; import com.itsaky.androidide.utils.Logger; import com.itsaky.androidide.utils.RecursiveFileSearcher; import com.itsaky.androidide.utils.Symbols; -import com.itsaky.androidide.utils.TransformUtils; -import com.itsaky.androidide.utils.TypefaceUtils; import com.itsaky.androidide.views.MaterialBanner; import com.itsaky.androidide.views.SymbolInputView; +import com.itsaky.inflater.ILayoutInflater; import com.itsaky.lsp.services.IDELanguageServer; import com.itsaky.toaster.Toaster; import com.unnamed.b.atv.model.TreeNode; -import io.github.rosemoe.editor.langs.EmptyLanguage; -import io.github.rosemoe.editor.widget.CodeEditor; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DidChangeConfigurationParams; +import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.Position; +import org.jetbrains.annotations.Contract; import java.io.File; import java.util.ArrayList; @@ -119,17 +122,10 @@ import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; +import io.github.rosemoe.editor.widget.CodeEditor; import me.piruin.quickaction.ActionItem; import me.piruin.quickaction.QuickAction; -import org.eclipse.lsp4j.Diagnostic; -import org.eclipse.lsp4j.DidChangeConfigurationParams; -import org.eclipse.lsp4j.InitializeResult; -import org.eclipse.lsp4j.Position; -import org.jetbrains.annotations.Contract; - -import com.itsaky.androidide.lsp.IDELanguageClientImpl; - public class EditorActivity extends StudioActivity implements FileTreeFragment.FileActionListener, TabLayout.OnTabSelectedListener, NavigationView.OnNavigationItemSelectedListener, @@ -142,14 +138,11 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F private ActivityEditorBinding mBinding; private LayoutDiagnosticInfoBinding mDiagnosticInfoBinding; private EditorPagerAdapter mPagerAdapter; + private EditorBottomSheetTabAdapter bottomSheetTabAdapter; private FileTreeFragment mFileTreeFragment; private EditorFragment mCurrentFragment; public static File mCurrentFile; private TreeNode mLastHeld; - private CodeEditor buildView; - private CodeEditor logView; - private RecyclerView diagnosticList; - private RecyclerView searchResultList; private SymbolInputView symbolInput; private AndroidProject mProject; @@ -158,14 +151,15 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F private BuildServiceHandler mBuildServiceHandler; private FileOptionsHandler mFileOptionsHandler; - private LogLanguageImpl mLogLanguageImpl; - private QuickAction mTabCloseAction; private TextSheetFragment mDaemonStatusFragment; private OptionsListFragment mFileOptionsFragment; private ProgressSheet mSearchingProgress; private AlertDialog mFindInProjectDialog; + @SuppressWarnings("rawtypes") + private EditorBottomSheetBehavior mEditorBottomSheet; + private static final String TAG_FILE_OPTIONS_FRAGMENT = "file_options_fragment"; private static final org.eclipse.lsp4j.Range Range_ofZero = new org.eclipse.lsp4j.Range (new Position (0, 0), new Position (0, 0)); @@ -198,7 +192,6 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F R.id.menuEditor_lintRelease }; - @Override protected View bindLayout () { mBinding = ActivityEditorBinding.inflate (getLayoutInflater ()); @@ -222,13 +215,38 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F loadFragment (mFileTreeFragment); symbolInput = new SymbolInputView (this); - mBinding.inputContainer.addView (symbolInput, 0, new ViewGroup.LayoutParams (-1, -2)); + mBinding.bottomSheet.textContainer.addView (symbolInput, 0, new ViewGroup.LayoutParams (-1, -2)); mBinding.editorViewPager.setOffscreenPageLimit (9); mBinding.editorViewPager.setAdapter (mPagerAdapter); mBinding.tabs.setupWithViewPager (mBinding.editorViewPager); mBinding.tabs.addOnTabSelectedListener (this); - mBinding.fabView.setOnClickListener (v -> showViewOptions ()); + + bottomSheetTabAdapter = new EditorBottomSheetTabAdapter (this); + mBinding.bottomSheet.pager.setAdapter (bottomSheetTabAdapter); + + final var mediator = new TabLayoutMediator (mBinding.bottomSheet.tabs, + mBinding.bottomSheet.pager, + true, + true, + (tab, position) -> tab.setText (bottomSheetTabAdapter.getTitle (position))); + mediator.attach (); + mBinding.bottomSheet.pager.setUserInputEnabled (false); + + //noinspection rawtypes + mEditorBottomSheet = (EditorBottomSheetBehavior) EditorBottomSheetBehavior.from (mBinding.bottomSheet.getRoot ()); + mEditorBottomSheet.setBinding (mBinding.bottomSheet); + mEditorBottomSheet.addBottomSheetCallback (new BottomSheetBehavior.BottomSheetCallback () { + @Override + public void onStateChanged (@NonNull View bottomSheet, int newState) { + mBinding.bottomSheet.textContainer.setVisibility (newState == BottomSheetBehavior.STATE_EXPANDED ? View.INVISIBLE : View.VISIBLE); + } + + @Override + public void onSlide (@NonNull View bottomSheet, float slideOffset) { + mBinding.bottomSheet.textContainer.setAlpha (1f - slideOffset); + } + }); createQuickActions (); @@ -256,18 +274,10 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F mBinding.getRoot ().closeDrawer (GravityCompat.START); } else if (getDaemonStatusFragment ().isShowing ()) { getDaemonStatusFragment ().dismiss (); - } else if (mBinding.buildContainer.getVisibility () == View.VISIBLE) { - hideBuildResult (); - } else if (mBinding.logContainer.getVisibility () == View.VISIBLE) { - hideLogResult (); - } else if (mBinding.viewOptionsCard.getVisibility () == View.VISIBLE) { - hideViewOptions (); - } else if (mBinding.diagContainer.getVisibility () == View.VISIBLE) { - hideDiagnostics (); - } else if (mBinding.searchResultsContainer.getVisibility () == View.VISIBLE) { - hideSearchResults (); } else if (mFileOptionsFragment != null && mFileOptionsFragment.isShowing ()) { mFileOptionsFragment.dismiss (); + } else if (mEditorBottomSheet.getState () == BottomSheetBehavior.STATE_EXPANDED) { + mEditorBottomSheet.setState (BottomSheetBehavior.STATE_COLLAPSED); } else { confirmProjectClose (); } @@ -492,17 +502,14 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F } public void handleSearchResults (Map> results) { - getSearchResultList ().setAdapter (new com.itsaky.androidide.adapters.SearchListAdapter (results, file -> { + setSearchResultAdapter (new com.itsaky.androidide.adapters.SearchListAdapter (results, file -> { openFile (file); - hideSearchResults (); hideViewOptions (); }, match -> { openFileAndSelect (match.file, match); - hideSearchResults (); hideViewOptions (); })); - mBinding.transformScrim.setVisibility (View.VISIBLE); - mBinding.fabView.setVisibility (View.GONE); + showSearchResults (); if (mSearchingProgress != null && mSearchingProgress.isShowing ()) { @@ -511,8 +518,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F } public void appendApkLog (LogLine line) { - getLogLanguage ().addLine (line); - appendLogOut (line.toString ()); + bottomSheetTabAdapter.getLogFragment ().appendLog (line); } public void setIDEProject (IDEProject project) { @@ -520,31 +526,10 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F } public void appendBuildOut (final String str) { - runOnUiThread (() -> { - String strFinal = str.endsWith ("\n") ? str : str.concat ("\n"); - getBuildView (true).getText ().append (strFinal); - }); - } - - public void appendLogOut (final String str) { - runOnUiThread (() -> { - String strFinal = str.endsWith ("\n") ? str : str.concat ("\n"); - getLogView (true).getText ().append (strFinal); - }); - } - - public void showFiles () { - if (mBinding.viewOptionsCard.getVisibility () == View.VISIBLE) { - hideViewOptions (); - } - - mBinding.getRoot ().openDrawer (GravityCompat.END, true); + bottomSheetTabAdapter.getBuildOutputFragment ().appendOutput (str); } public void showDaemonStatus () { - if (mBinding.viewOptionsCard.getVisibility () == View.VISIBLE) { - hideViewOptions (); - } ShellServer shell = getApp ().newShell (t -> getDaemonStatusFragment ().append (t.toString ())); shell.bgAppend (String.format ("echo '%s'", getString (R.string.msg_getting_daemom_status))); shell.bgAppend (String.format ("cd '%s' && sh gradlew --status", mProject.getProjectPath ())); @@ -553,107 +538,37 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F } } - public void hideToolbarAndTabs () { - mBinding.editorAppBarLayout.setVisibility (View.INVISIBLE); - } - - public void showToolbarAndTabs () { - mBinding.editorAppBarLayout.setVisibility (View.VISIBLE); - } - - public void showViewOptions () { - try { - if (mCurrentFragment != null && mCurrentFragment.getEditor () != null) { - mCurrentFragment.getEditor ().hideAutoCompleteWindow (); - mCurrentFragment.getEditor ().hideDiagnosticWindow (); - } - - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.fabView, mBinding.viewOptionsCard)); - mBinding.viewOptionsCard.setVisibility (View.VISIBLE); - mBinding.transformScrim.setVisibility (View.VISIBLE); - mBinding.fabView.setVisibility (View.GONE); - } catch (Throwable e) { - LOG.error ("Failed to show view options", e); + public void hideViewOptions () { + if (mEditorBottomSheet.getState () != BottomSheetBehavior.STATE_COLLAPSED) { + mEditorBottomSheet.setState (BottomSheetBehavior.STATE_COLLAPSED); } } - public void hideViewOptions () { - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.viewOptionsCard, mBinding.fabView)); - mBinding.viewOptionsCard.setVisibility (View.GONE); - mBinding.transformScrim.setVisibility (View.GONE); - mBinding.fabView.setVisibility (View.VISIBLE); - } - - public void showBuildResult () { - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.viewBuildOut, mBinding.buildContainer)); - mBinding.buildContainer.setVisibility (View.VISIBLE); - mBinding.viewOptionsCard.setVisibility (View.GONE); - hideToolbarAndTabs (); - } - - public void hideBuildResult () { - showToolbarAndTabs (); - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.buildContainer, mBinding.viewBuildOut)); - mBinding.buildContainer.setVisibility (View.GONE); - mBinding.viewOptionsCard.setVisibility (View.VISIBLE); - } - - public void showLogResult () { - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.viewLogs, mBinding.logContainer)); - mBinding.logContainer.setVisibility (View.VISIBLE); - mBinding.viewOptionsCard.setVisibility (View.GONE); - hideToolbarAndTabs (); - } - - public void hideLogResult () { - showToolbarAndTabs (); - - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.logContainer, mBinding.viewLogs)); - mBinding.logContainer.setVisibility (View.GONE); - mBinding.viewOptionsCard.setVisibility (View.VISIBLE); - } - - public void showDiagnostics () { - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.viewDiags, mBinding.diagContainer)); - mBinding.diagContainer.setVisibility (View.VISIBLE); - mBinding.viewOptionsCard.setVisibility (View.GONE); - hideToolbarAndTabs (); - } - - public void hideDiagnostics () { - showToolbarAndTabs (); - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.diagContainer, mBinding.viewDiags)); - mBinding.diagContainer.setVisibility (View.GONE); - mBinding.viewOptionsCard.setVisibility (View.VISIBLE); - } - public void showSearchResults () { - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.viewSearchResults, mBinding.searchResultsContainer)); - mBinding.searchResultsContainer.setVisibility (View.VISIBLE); - mBinding.viewOptionsCard.setVisibility (View.GONE); - hideToolbarAndTabs (); - } - - public void hideSearchResults () { - showToolbarAndTabs (); - TransitionManager.beginDelayedTransition (mBinding.getRoot (), createContainerTransformFor (mBinding.searchResultsContainer, mBinding.viewSearchResults)); - mBinding.searchResultsContainer.setVisibility (View.GONE); - mBinding.viewOptionsCard.setVisibility (View.VISIBLE); + if (mEditorBottomSheet.getState () != BottomSheetBehavior.STATE_EXPANDED) { + mEditorBottomSheet.setState (BottomSheetBehavior.STATE_EXPANDED); + } + + final int index = bottomSheetTabAdapter.findIndexOfFragmentByClass (SearchResultFragment.class); + if (index >= 0 && index < mBinding.bottomSheet.tabs.getTabCount ()) { + final var tab = mBinding.bottomSheet.tabs.getTabAt (index); + if (tab != null) { + tab.select (); + } + } } public void handleDiagnosticsResultVisibility (boolean errorVisible) { - mBinding.diagEmptyView.setVisibility (errorVisible ? View.VISIBLE : View.GONE); - getDiagnosticsList ().setVisibility (errorVisible ? View.GONE : View.VISIBLE); + bottomSheetTabAdapter.getDiagnosticsFragment ().handleResultVisibility (errorVisible); } public void handleSearchResultVisibility (boolean errorVisible) { - mBinding.searchEmptyView.setVisibility (errorVisible ? View.VISIBLE : View.GONE); - getSearchResultList ().setVisibility (errorVisible ? View.GONE : View.VISIBLE); + bottomSheetTabAdapter.getSearchResultFragment ().handleResultVisibility (errorVisible); } public void setStatus (final CharSequence text) { try { - runOnUiThread (() -> mBinding.editorStatusText.setText (text)); + runOnUiThread (() -> mBinding.bottomSheet.statusText.setText (text)); } catch (Throwable th) { LOG.error ("Failed to update status text", th); } @@ -682,7 +597,6 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F @Override public void onDiagnosticClick (File file, @NonNull Diagnostic diagnostic) { openFileAndSelect (file, diagnostic.getRange ()); - hideDiagnostics (); hideViewOptions (); } @@ -843,85 +757,12 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F return mDaemonStatusFragment == null ? mDaemonStatusFragment = new TextSheetFragment ().setTextSelectable (true).setTitleText (R.string.gradle_daemon_status) : mDaemonStatusFragment; } - public CodeEditor getBuildView () { - return getBuildView (false); + public void setDiagnosticsAdapter (@NonNull final DiagnosticsAdapter adapter) { + bottomSheetTabAdapter.getDiagnosticsFragment ().setAdapter (adapter); } - public CodeEditor getBuildView (boolean setup) { - CodeEditor edit = buildView == null ? createBuildView () : buildView; - if (setup && edit.getParent () == null) { - setupContainers (); - } - return edit; - } - - public CodeEditor createBuildView () { - buildView = new CodeEditor (this); - buildView.setEditable (false); - buildView.setDividerWidth (0); - buildView.setEditorLanguage (new EmptyLanguage ()); - buildView.setOverScrollEnabled (false); - buildView.setTextActionMode (CodeEditor.TextActionMode.ACTION_MODE); - buildView.setWordwrap (false); - buildView.setUndoEnabled (false); - buildView.setTypefaceLineNumber (TypefaceUtils.jetbrainsMono ()); - buildView.setTypefaceText (TypefaceUtils.jetbrainsMono ()); - buildView.setTextSize (12); - buildView.setColorScheme (new SchemeAndroidIDE ()); - return buildView; - } - - public CodeEditor getLogView () { - return getLogView (false); - } - - public CodeEditor getLogView (boolean setup) { - CodeEditor edit = logView == null ? createLogView () : logView; - if (setup && edit.getParent () == null) { - setupContainers (); - } - return edit; - } - - public CodeEditor createLogView () { - logView = new CodeEditor (this); - logView.setEditable (false); - logView.setDividerWidth (0); - logView.setEditorLanguage (getLogLanguage ()); - logView.setOverScrollEnabled (false); - logView.setTextActionMode (CodeEditor.TextActionMode.ACTION_MODE); - logView.setWordwrap (false); - logView.setUndoEnabled (false); - logView.setTypefaceLineNumber (TypefaceUtils.jetbrainsMono ()); - logView.setTypefaceText (TypefaceUtils.jetbrainsMono ()); - logView.setTextSize (12); - buildView.setColorScheme (new SchemeAndroidIDE ()); - return logView; - } - - public RecyclerView getDiagnosticsList () { - return diagnosticList == null ? createDiagnosticsList () : diagnosticList; - } - - public RecyclerView createDiagnosticsList () { - diagnosticList = new RecyclerView (this); - diagnosticList.setLayoutManager (new LinearLayoutManager (this)); - diagnosticList.setAdapter (new DiagnosticsAdapter (new ArrayList<> (), this)); - return diagnosticList; - } - - public RecyclerView getSearchResultList () { - return searchResultList == null ? createSearchResultList () : searchResultList; - } - - public RecyclerView createSearchResultList () { - searchResultList = new RecyclerView (this); - searchResultList.setLayoutManager (new LinearLayoutManager (this)); - return searchResultList; - } - - public LogLanguageImpl getLogLanguage () { - return mLogLanguageImpl == null ? mLogLanguageImpl = new LogLanguageImpl () : mLogLanguageImpl; + public void setSearchResultAdapter (@NonNull final SearchListAdapter adapter) { + bottomSheetTabAdapter.getSearchResultFragment ().setAdapter (adapter); } @Override @@ -1173,67 +1014,10 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F } private void setupContainers () { - removeFromParent (getBuildView ()); - removeFromParent (getLogView ()); - removeFromParent (getDiagnosticsList ()); - removeFromParent (getSearchResultList ()); - - mBinding.buildOutcontainer.addView (getBuildView (), new ViewGroup.LayoutParams (-1, -1)); - mBinding.buildContainer.setVisibility (View.GONE); - mBinding.buildOutToolbar.setNavigationOnClickListener (v -> hideBuildResult ()); - mBinding.buildOutToolbar.setOnClickListener (v -> hideBuildResult ()); - - mBinding.buildOutToolbar.getMenu ().clear (); - getMenuInflater ().inflate (R.menu.menu_build_output, mBinding.buildOutToolbar.getMenu ()); - mBinding.buildOutToolbar.setOnMenuItemClickListener (item -> { - if (item.getItemId () == R.id.buildOut_clear) { - getBuildView ().setText (""); - setStatus (""); - return true; - } - return false; - }); - - mBinding.logOutcontainer.addView (getLogView (), new ViewGroup.LayoutParams (-1, -1)); - mBinding.logContainer.setVisibility (View.GONE); - mBinding.logOutToolbar.setNavigationOnClickListener (v -> hideLogResult ()); - mBinding.logOutToolbar.setOnClickListener (v -> hideLogResult ()); - - mBinding.diagListContainer.addView (getDiagnosticsList (), new ViewGroup.LayoutParams (-1, -1)); - mBinding.diagContainer.setVisibility (View.GONE); - mBinding.diagToolbar.setNavigationOnClickListener (v -> hideDiagnostics ()); - mBinding.diagToolbar.setOnClickListener (v -> hideDiagnostics ()); - - mBinding.searchResultsListContainer.addView (getSearchResultList (), new ViewGroup.LayoutParams (-1, -1)); - mBinding.searchResultsContainer.setVisibility (View.GONE); - mBinding.searchResultsToolbar.setNavigationOnClickListener (v -> hideSearchResults ()); - mBinding.searchResultsToolbar.setOnClickListener (v -> hideSearchResults ()); - - mBinding.viewOptionsCard.setVisibility (View.GONE); - mBinding.transformScrim.setVisibility (View.GONE); - - mBinding.transformScrim.setOnClickListener (v -> hideViewOptions ()); - mBinding.viewBuildOut.setOnClickListener (v -> showBuildResult ()); - mBinding.viewDiags.setOnClickListener (v -> showDiagnostics ()); - mBinding.viewSearchResults.setOnClickListener (v -> showSearchResults ()); - mBinding.viewLogs.setOnClickListener (v -> showLogResult ()); - mBinding.viewFiles.setOnClickListener (v -> showFiles ()); - mBinding.viewDaemonStatus.setOnClickListener (v -> showDaemonStatus ()); - handleDiagnosticsResultVisibility (true); handleSearchResultVisibility (true); } - @NonNull - private MaterialContainerTransform createContainerTransformFor (View start, View end) { - return createContainerTransformFor (start, end, mBinding.realContainer); - } - - @NonNull - private MaterialContainerTransform createContainerTransformFor (View start, View end, View drawingView) { - return TransformUtils.createContainerTransformFor (start, end, drawingView); - } - private void startServices () { if (!IDELanguageClientImpl.isInitialized ()) { @@ -1249,22 +1033,18 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F getBuildServiceHandler ().assembleDebug (false); } - private void removeFromParent (@NonNull View v) { - if (v.getParent () != null && v.getParent () instanceof ViewGroup) { - ((ViewGroup) v.getParent ()).removeView (v); - } - } - private void onSoftInputChanged () { invalidateOptionsMenu (); if (KeyboardUtils.isSoftInputVisible (this)) { TransitionManager.beginDelayedTransition (mBinding.getRoot (), new Slide (Gravity.TOP)); symbolInput.setVisibility (View.VISIBLE); - mBinding.fabView.hide (); + mBinding.bottomSheet.statusText.setVisibility (View.GONE); + mBinding.bottomSheet.swipeHint.setVisibility (View.GONE); } else { TransitionManager.beginDelayedTransition (mBinding.getRoot (), new Slide (Gravity.BOTTOM)); symbolInput.setVisibility (View.GONE); - mBinding.fabView.show (); + mBinding.bottomSheet.statusText.setVisibility (View.VISIBLE); + mBinding.bottomSheet.swipeHint.setVisibility (View.VISIBLE); } } diff --git a/app/src/main/java/com/itsaky/androidide/adapters/EditorBottomSheetTabAdapter.java b/app/src/main/java/com/itsaky/androidide/adapters/EditorBottomSheetTabAdapter.java new file mode 100644 index 000000000..cb70ec05a --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/adapters/EditorBottomSheetTabAdapter.java @@ -0,0 +1,118 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.adapters; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.viewpager2.adapter.FragmentStateAdapter; + +import com.itsaky.androidide.R; +import com.itsaky.androidide.fragments.BuildOutputFragment; +import com.itsaky.androidide.fragments.DiagnosticsListFragment; +import com.itsaky.androidide.fragments.IDELogFragment; +import com.itsaky.androidide.fragments.LogViewFragment; +import com.itsaky.androidide.fragments.SearchResultFragment; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class EditorBottomSheetTabAdapter extends FragmentStateAdapter { + + private final List fragments; + + public EditorBottomSheetTabAdapter (@NonNull FragmentActivity fragmentActivity) { + super (fragmentActivity); + + this.fragments = new ArrayList<> (); + this.fragments.add (new Tab (fragmentActivity.getString (R.string.build_output), new BuildOutputFragment ())); + this.fragments.add (new Tab (fragmentActivity.getString (R.string.app_logs), new LogViewFragment ())); + this.fragments.add (new Tab (fragmentActivity.getString (R.string.ide_logs), new IDELogFragment ())); + this.fragments.add (new Tab (fragmentActivity.getString (R.string.view_diags), new DiagnosticsListFragment ())); + this.fragments.add (new Tab (fragmentActivity.getString (R.string.view_search_results), new SearchResultFragment ())); + } + + @NonNull + @Override + public Fragment createFragment (int position) { + return this.fragments.get (position).fragment; + } + + @Override + public int getItemCount () { + return fragments.size (); + } + + public String getTitle (int position) { + return fragments.get (position).title; + } + + @NonNull + public BuildOutputFragment getBuildOutputFragment () { + return Objects.requireNonNull (findFragmentByClass (BuildOutputFragment.class)); + } + + @NonNull + public LogViewFragment getLogFragment () { + return Objects.requireNonNull (findFragmentByClass (LogViewFragment.class)); + } + + @NonNull + public DiagnosticsListFragment getDiagnosticsFragment () { + return Objects.requireNonNull (findFragmentByClass (DiagnosticsListFragment.class)); + } + + @NonNull + public SearchResultFragment getSearchResultFragment () { + return Objects.requireNonNull (findFragmentByClass (SearchResultFragment.class)); + } + + @Nullable + private T findFragmentByClass (Class clazz) { + for (final var tab : this.fragments) { + if (tab.fragment.getClass () == clazz) { + return (T) tab.fragment; + } + } + return null; + } + + public int findIndexOfFragmentByClass (Class tClass) { + for (int i = 0; i < this.fragments.size (); i++) { + final var tab = this.fragments.get (i); + if (tab.fragment.getClass () == tClass) { + return i; + } + } + + return -1; + } + + static class Tab { + + public Tab (String title, Fragment fragment) { + this.title = title; + this.fragment = fragment; + } + + String title; + Fragment fragment; + } +} diff --git a/app/src/main/java/com/itsaky/androidide/fragments/BuildOutputFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/BuildOutputFragment.java new file mode 100644 index 000000000..f65b891c9 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/fragments/BuildOutputFragment.java @@ -0,0 +1,58 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.fragments; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.blankj.utilcode.util.ThreadUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class BuildOutputFragment extends NonEditableEditorFragment { + + private final List unsavedLines = new ArrayList<> (); + + @Override + public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated (view, savedInstanceState); + + if (!unsavedLines.isEmpty ()) { + for (String line : unsavedLines) { + Objects.requireNonNull (getEditor ()).getText ().append (line.trim () + "\n"); + } + unsavedLines.clear (); + } + } + + public void appendOutput (String output) { + if (getEditor () == null) { + unsavedLines.add (output); + return; + } + ThreadUtils.runOnUiThread (() -> { + final var message = output == null || output.endsWith ("\n") ? output : output + "\n"; + getEditor ().getText ().append (message); + }); + } +} diff --git a/app/src/main/java/com/itsaky/androidide/fragments/DiagnosticsListFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/DiagnosticsListFragment.java new file mode 100644 index 000000000..2081c7841 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/fragments/DiagnosticsListFragment.java @@ -0,0 +1,83 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.fragments; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.itsaky.androidide.adapters.DiagnosticsAdapter; +import com.itsaky.androidide.views.EmptyView; + +import java.util.ArrayList; + +public class DiagnosticsListFragment extends Fragment { + + private RecyclerView list; + private EmptyView emptyView; + + private DiagnosticsAdapter unsavedAdapter; + + @Nullable + @Override + public View onCreateView (@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, @Nullable Bundle savedInstanceState) { + final var container = new LinearLayout (inflater.getContext ()); + container.setOrientation (LinearLayout.VERTICAL); + container.setLayoutParams (new ViewGroup.LayoutParams (-1, -1)); + + this.list = new RecyclerView (inflater.getContext ()); + this.emptyView = new EmptyView (inflater.getContext ()); + + container.addView (list, new LinearLayout.LayoutParams (-1, -1)); + container.addView (emptyView, new LinearLayout.LayoutParams (-1, -1)); + + return container; + } + + @Override + public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated (view, savedInstanceState); + + list.setLayoutManager (new LinearLayoutManager (list.getContext ())); + list.setAdapter (unsavedAdapter != null ? unsavedAdapter : new DiagnosticsAdapter (new ArrayList<> (), null)); + unsavedAdapter = null; + } + + public void setAdapter (@NonNull DiagnosticsAdapter adapter) { + if (list != null) { + list.setAdapter (adapter); + } else { + unsavedAdapter = adapter; + } + } + + public void handleResultVisibility (boolean error) { + if (emptyView != null && list != null) { + emptyView.setVisibility (error ? View.VISIBLE : View.GONE); + list.setVisibility (error ? View.GONE : View.VISIBLE); + } + } +} diff --git a/app/src/main/java/com/itsaky/androidide/fragments/IDELogFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/IDELogFragment.java new file mode 100644 index 000000000..8231d2b31 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/fragments/IDELogFragment.java @@ -0,0 +1,21 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.fragments; + +public class IDELogFragment extends LogViewFragment { +} diff --git a/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.java new file mode 100644 index 000000000..825a38675 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.java @@ -0,0 +1,64 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.fragments; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.blankj.utilcode.util.ThreadUtils; +import com.itsaky.androidide.language.logs.LogLanguageImpl; +import com.itsaky.androidide.models.LogLine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class LogViewFragment extends NonEditableEditorFragment { + + private final LogLanguageImpl language = new LogLanguageImpl (); + private final List unsavedLines = new ArrayList<> (); + + @Override + public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated (view, savedInstanceState); + Objects.requireNonNull (getEditor ()).setEditorLanguage (language); + + if (!unsavedLines.isEmpty ()) { + for (var line : unsavedLines) { + language.addLine (line); + getEditor ().getText ().append (line.toString ().trim () + "\n"); + } + unsavedLines.clear (); + } + } + + public void appendLog (LogLine line) { + if (getEditor () == null) { + unsavedLines.add (line); + return; + } + + this.language.addLine (line); + final var lineString = line.toString (); + final var msg = lineString.endsWith ("\n") ? lineString : lineString + "\n"; + ThreadUtils.runOnUiThread (() -> getEditor ().getText ().append (msg)); + } +} diff --git a/app/src/main/java/com/itsaky/androidide/fragments/NonEditableEditorFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/NonEditableEditorFragment.java new file mode 100644 index 000000000..ec8c78435 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/fragments/NonEditableEditorFragment.java @@ -0,0 +1,72 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.fragments; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.itsaky.androidide.databinding.FragmentNonEditableEditorBinding; +import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE; +import com.itsaky.androidide.utils.TypefaceUtils; + +import io.github.rosemoe.editor.langs.EmptyLanguage; +import io.github.rosemoe.editor.widget.CodeEditor; + +public abstract class NonEditableEditorFragment extends Fragment { + + private FragmentNonEditableEditorBinding binding; + + @Nullable + @Override + public View onCreateView (@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + this.binding = FragmentNonEditableEditorBinding.inflate (inflater, container, false); + return binding.getRoot (); + } + + @Override + public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated (view, savedInstanceState); + + final var editor = binding.getRoot (); + editor.setEditable (false); + editor.setDividerWidth (0); + editor.setEditorLanguage (new EmptyLanguage ()); + editor.setOverScrollEnabled (false); + editor.setTextActionMode (CodeEditor.TextActionMode.ACTION_MODE); + editor.setWordwrap (false); + editor.setUndoEnabled (false); + editor.setTypefaceLineNumber (TypefaceUtils.jetbrainsMono ()); + editor.setTypefaceText (TypefaceUtils.jetbrainsMono ()); + editor.setTextSize (12); + editor.setColorScheme (new SchemeAndroidIDE ()); + } + + @Nullable + public CodeEditor getEditor () { + if (binding == null) { + return null; + } + return binding.editor; + } +} diff --git a/app/src/main/java/com/itsaky/androidide/fragments/SearchResultFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/SearchResultFragment.java new file mode 100644 index 000000000..ac1ce194b --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/fragments/SearchResultFragment.java @@ -0,0 +1,81 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.fragments; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.itsaky.androidide.adapters.SearchListAdapter; +import com.itsaky.androidide.views.EmptyView; + +public class SearchResultFragment extends Fragment { + + private RecyclerView list; + private EmptyView emptyView; + + private SearchListAdapter unsavedAdapter; + + @Nullable + @Override + public View onCreateView (@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, @Nullable Bundle savedInstanceState) { + final var container = new LinearLayout (inflater.getContext ()); + container.setOrientation (LinearLayout.VERTICAL); + container.setLayoutParams (new ViewGroup.LayoutParams (-1, -1)); + + this.list = new RecyclerView (inflater.getContext ()); + this.emptyView = new EmptyView (inflater.getContext ()); + + container.addView (list, new LinearLayout.LayoutParams (-1, -1)); + container.addView (emptyView, new LinearLayout.LayoutParams (-1, -1)); + + return container; + } + + @Override + public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated (view, savedInstanceState); + + list.setLayoutManager (new LinearLayoutManager (list.getContext ())); + list.setAdapter (unsavedAdapter != null ? unsavedAdapter : new SearchListAdapter (null, null, null)); + unsavedAdapter = null; + } + + public void setAdapter (@NonNull final SearchListAdapter adapter) { + if (list == null) { + unsavedAdapter = adapter; + return; + } + this.list.setAdapter (adapter); + } + + public void handleResultVisibility (boolean error) { + if (emptyView != null && list != null) { + emptyView.setVisibility (error ? View.VISIBLE : View.GONE); + list.setVisibility (error ? View.GONE : View.VISIBLE); + } + } +} diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/LogSheet.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/LogSheet.java deleted file mode 100755 index 7f0199663..000000000 --- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/LogSheet.java +++ /dev/null @@ -1,87 +0,0 @@ -/************************************************************************************ - * 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 - * (at your option) any later version. - * - * AndroidIDE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with AndroidIDE. If not, see . - * -**************************************************************************************/ - - -package com.itsaky.androidide.fragments.sheets; - -import android.graphics.Typeface; -import android.util.TypedValue; -import android.view.ViewGroup; -import android.widget.HorizontalScrollView; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; -import com.blankj.utilcode.util.ThrowableUtils; -import com.itsaky.androidide.R; -import com.itsaky.androidide.models.LogLine; -import android.annotation.SuppressLint; - -public class LogSheet extends BaseBottomSheetFragment { - - private ScrollView verticalScroll; - private LinearLayout mContainer; - - @Override - protected void bind(LinearLayout container) { - mContainer = new LinearLayout(getContext()); - mContainer.setOrientation(LinearLayout.VERTICAL); - - verticalScroll = new ScrollView(getContext()); - verticalScroll.setFillViewport(true); - - HorizontalScrollView scroll = new HorizontalScrollView(getContext()); - scroll.setFillViewport(true); - - container.removeAllViews(); - verticalScroll.removeAllViews(); - mContainer.removeAllViews(); - scroll.removeAllViews(); - - container.addView(verticalScroll); - verticalScroll.addView(scroll, new ScrollView.LayoutParams(-1, -1)); - scroll.addView(mContainer, new HorizontalScrollView.LayoutParams(-1, -1)); - } - - @Override - protected String getTitle() { - return getString(R.string.logs); - } - - public void addLine(LogLine line) { - if(line != null) { - try { - mContainer.addView(createLogTextView(line), new ViewGroup.LayoutParams(-1, -2)); - verticalScroll.scrollTo(0, mContainer.getChildAt(mContainer.getChildCount() - 1).getBottom()); - } catch (Throwable th) {} - } - } - - @SuppressLint("SetTextI18n") - protected TextView createLogTextView(LogLine line) { - TextView text = new TextView(getContext()); - text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); - text.setTextColor(line.getColor(getContext())); - text.setText(line + ""); - text.setSingleLine(true); - text.setMaxLines(1); - text.setTypeface(Typeface.MONOSPACE); - return text; - } -} diff --git a/app/src/main/java/com/itsaky/androidide/lsp/IDELanguageClientImpl.java b/app/src/main/java/com/itsaky/androidide/lsp/IDELanguageClientImpl.java index 53c0bbb26..457100e35 100755 --- a/app/src/main/java/com/itsaky/androidide/lsp/IDELanguageClientImpl.java +++ b/app/src/main/java/com/itsaky/androidide/lsp/IDELanguageClientImpl.java @@ -359,7 +359,7 @@ public class IDELanguageClientImpl implements IDELanguageClient { if(!file.exists() || !file.isFile()) return; diagnostics.put(file, params.getDiagnostics()); - activity().getDiagnosticsList().setAdapter(newDiagnosticsAdapter()); + activity().setDiagnosticsAdapter(newDiagnosticsAdapter()); EditorFragment editor = null; if(activity().getPagerAdapter() != null && (editor = activity().getPagerAdapter().findEditorByFile(file)) != null) { @@ -382,7 +382,7 @@ public class IDELanguageClientImpl implements IDELanguageClient { if(error) { - activity().getSearchResultList().setAdapter(new SearchListAdapter(null, null, null)); + activity().setSearchResultAdapter (new SearchListAdapter(null, null, null)); return; } diff --git a/app/src/main/java/com/itsaky/androidide/services/IDELogService.java b/app/src/main/java/com/itsaky/androidide/services/IDELogService.java new file mode 100644 index 000000000..a4aae68d8 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/services/IDELogService.java @@ -0,0 +1,38 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.services; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +public class IDELogService extends Service { + + public IDELogService () { + } + + @Override + public void onCreate () { + super.onCreate (); + } + + @Override + public IBinder onBind (Intent intent) { + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/itsaky/androidide/utils/EditorBottomSheetBehavior.java b/app/src/main/java/com/itsaky/androidide/utils/EditorBottomSheetBehavior.java new file mode 100644 index 000000000..2067958d0 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/utils/EditorBottomSheetBehavior.java @@ -0,0 +1,68 @@ +/* + * 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 + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.utils; + +import android.content.Context; +import android.graphics.Rect; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; + +import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.itsaky.androidide.databinding.LayoutEditorBottomSheetBinding; + +public class EditorBottomSheetBehavior extends BottomSheetBehavior { + + private LayoutEditorBottomSheetBinding binding; + + public EditorBottomSheetBehavior (Context context, AttributeSet attributeSet) { + super(context, attributeSet); + + setSaveFlags (SAVE_ALL); + } + + public void setBinding (LayoutEditorBottomSheetBinding binding) { + this.binding = binding; + } + + @Override + public boolean onInterceptTouchEvent (@NonNull CoordinatorLayout parent, @NonNull V child, @NonNull MotionEvent event) { + if (binding != null) { + final var rect = getPagerRect (); + if (rect.contains (event.getX (), event.getY ())) { + return false; + } + } + + return super.onInterceptTouchEvent (parent, child, event); + } + + @NonNull + private RectF getPagerRect () { + final var rect = new RectF (); + rect.left = binding.pager.getX (); + rect.top = binding.pager.getY (); + rect.right = rect.left + binding.pager.getWidth (); + rect.bottom = rect.top + binding.pager.getHeight (); + return rect; + } +} diff --git a/app/src/main/res/layout/activity_download.xml b/app/src/main/res/layout/activity_download.xml index c13c57226..a77a3bd34 100755 --- a/app/src/main/res/layout/activity_download.xml +++ b/app/src/main/res/layout/activity_download.xml @@ -57,7 +57,7 @@ diff --git a/app/src/main/res/layout/activity_editor.xml b/app/src/main/res/layout/activity_editor.xml index a2ee7b88e..e08d8fe00 100755 --- a/app/src/main/res/layout/activity_editor.xml +++ b/app/src/main/res/layout/activity_editor.xml @@ -8,24 +8,22 @@ android:id="@+id/editor_drawerLayout" android:animateLayoutChanges="true"> - - + + app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior"> - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_diagnostic_info.xml b/app/src/main/res/layout/layout_diagnostic_info.xml index e535c2023..744d49f31 100755 --- a/app/src/main/res/layout/layout_diagnostic_info.xml +++ b/app/src/main/res/layout/layout_diagnostic_info.xml @@ -1,11 +1,9 @@ - + android:textIsSelectable="true" /> diff --git a/app/src/main/res/layout/layout_editor_bottom_sheet.xml b/app/src/main/res/layout/layout_editor_bottom_sheet.xml new file mode 100644 index 000000000..aa47429a7 --- /dev/null +++ b/app/src/main/res/layout/layout_editor_bottom_sheet.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + \ 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 bafc8e7f5..2f7073d94 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,9 +26,9 @@ Discussions on Telegram I have nothing to show you… Terminal - @android:string/ok Reset - Logs + App Logs + IDE Logs Splash image Cancel Get started @@ -339,5 +339,6 @@ Code generation failed Failed to generate XML code. Would you like to exit anyway? UI Designer returned invalid result + Swipe up for build output, logs and more.