Move view options to bottom sheet

This commit is contained in:
Akash Yadav
2022-01-02 21:03:19 +05:30
parent 8f0eee1f95
commit 0f3b9ff4d6
20 changed files with 873 additions and 785 deletions
+6 -1
View File
@@ -10,8 +10,13 @@
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_relative_layout.xml" value="0.175" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_about.xml" value="0.2" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_designer.xml" value="0.264" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_editor.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_download.xml" value="0.1188034188034188" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_editor.xml" value="0.264" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/fragment_non_editable_editor.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_about_items.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_diagnostic_info.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_editor_bottom_sheet.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/layout_symbol_item.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/menu/menu_editor.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/menu/menu_editor_nav.xml" value="0.20512820512820512" />
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/common/src/main/res/layout/layout_color_picker.xml" value="0.264" />
+65 -63
View File
@@ -1,89 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.itsaky.androidide">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
tools:ignore="UnusedAttribute,MediaCapabilities"
android:name=".app.StudioApp"
android:allowBackup="false"
android:allowNativeHeapPointerTagging="false"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:allowBackup="false"
android:largeHeap="true"
android:allowNativeHeapPointerTagging="false"
android:hardwareAccelerated="true">
tools:ignore="UnusedAttribute,MediaCapabilities">
<service
android:name=".services.IDELogService"
android:enabled="true"
android:exported="true"></service>
<activity
android:name=".SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|uiMode">
</activity>
<activity
android:configChanges="orientation|screenSize|uiMode"></activity>
<activity
android:name=".DesignerActivity"
android:configChanges="orientation|screenSize|uiMode"
android:windowSoftInputMode="adjustResize">
</activity>
<activity
android:name=".DownloadActivity"
android:configChanges="orientation|screenSize|uiMode">
</activity>
<activity
android:windowSoftInputMode="adjustResize"></activity>
<activity
android:name=".DownloadActivity"
android:configChanges="orientation|screenSize|uiMode"></activity>
<activity
android:name=".EditorActivity"
android:configChanges="orientation|screenSize|uiMode"
android:windowSoftInputMode="adjustResize">
</activity>
<activity
android:name=".PreferencesActivity"
android:configChanges="orientation|screenSize">
</activity>
<activity
android:configChanges="orientation|screenSize|uiMode"
android:windowSoftInputMode="adjustResize"></activity>
<activity
android:name=".PreferencesActivity"
android:configChanges="orientation|screenSize"></activity>
<activity
android:name=".AboutActivity"
android:configChanges="orientation|screenSize|uiMode">
</activity>
<activity
android:configChanges="orientation|screenSize|uiMode"></activity>
<activity
android:name=".TerminalActivity"
android:configChanges="orientation|screenSize|uiMode"
android:windowSoftInputMode="adjustResize">
</activity>
<service
android:name=".services.MessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<receiver
android:name="com.itsaky.androidide.services.LogReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.itsaky.androidide.logs.APPEND_LOG" />
</intent-filter>
</receiver>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_launcher" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/secondaryColor" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/cms_channel_id_devs" />
android:windowSoftInputMode="adjustResize"></activity>
<service
android:name=".services.MessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<receiver
android:name=".services.LogReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.itsaky.androidide.logs.APPEND_LOG" />
</intent-filter>
</receiver>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_launcher" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/secondaryColor" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/cms_channel_id_devs" />
</application>
</manifest>
</manifest>
@@ -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<File, List<SearchResult>> 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);
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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<Tab> 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 extends Fragment> T findFragmentByClass (Class<T> clazz) {
for (final var tab : this.fragments) {
if (tab.fragment.getClass () == clazz) {
return (T) tab.fragment;
}
}
return null;
}
public <T extends Fragment> int findIndexOfFragmentByClass (Class<T> 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;
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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<String> 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);
});
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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);
}
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.fragments;
public class IDELogFragment extends LogViewFragment {
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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<LogLine> 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));
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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;
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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);
}
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*
**************************************************************************************/
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;
}
}
@@ -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;
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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;
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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<V extends View> extends BottomSheetBehavior<V> {
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;
}
}
@@ -57,7 +57,7 @@
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/androidstringok"
android:text="@android:string/ok"
android:id="@+id/dismiss"
android:textColor="@color/primaryTextColor"
app:backgroundTint="@color/secondaryColor"/>
+17 -328
View File
@@ -8,24 +8,22 @@
android:id="@+id/editor_drawerLayout"
android:animateLayoutChanges="true">
<androidx.constraintlayout.widget.ConstraintLayout
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/realContainer">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="8dp"
android:id="@+id/editor_appBarLayout"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior">
<com.google.android.material.appbar.MaterialToolbar
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="@color/primaryDarkColor"
android:elevation="10dp"
android:id="@+id/editor_toolbar"/>
<com.google.android.material.progressindicator.LinearProgressIndicator
@@ -56,313 +54,20 @@
app:tabGravity="fill"/>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/fragContainer"
app:layout_constraintTop_toBottomOf="@id/editor_appBarLayout"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.itsaky.androidide.views.NonSwipableViewPager
android:id="@+id/editor_viewPager"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1.0"
android:background="@color/content_background"/>
<com.itsaky.androidide.views.NonSwipableViewPager
android:id="@+id/editor_viewPager"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1.0"
android:background="@color/content_background"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/>
<LinearLayout
android:id="@+id/input_container"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/editor_statusText"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:gravity="center"
android:textSize="14sp"
android:background="@android:color/black"
android:textColor="@color/primaryTextColor"
android:singleLine="true"/>
<include
android:id="@+id/bottom_sheet"
layout="@layout/layout_editor_bottom_sheet"/>
</LinearLayout>
</LinearLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/transformScrim"
android:background="@color/transform_scrim"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.card.MaterialCardView
android:id="@+id/viewOptionsCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="24dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:cardElevation="8dp"
app:cardCornerRadius="8dp"
app:cardBackgroundColor="@color/primaryLightColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:id="@+id/view_buildOut"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="start|center_vertical"
android:insetTop="0dp"
android:insetBottom="0dp"
android:text="@string/build_output"
android:layout_marginBottom="1dp"
android:textColor="@color/primaryTextColor"
app:iconTint="@color/primaryIconColor"
app:cornerRadius="0dp"
app:icon="@drawable/ic_build_output"
app:backgroundTint="@color/primaryColor"
app:rippleColor="@color/rippleHighlightColor_light"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:id="@+id/view_diags"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="start|center_vertical"
android:insetTop="0dp"
android:insetBottom="0dp"
android:text="@string/view_diags"
android:layout_marginBottom="1dp"
android:textColor="@color/primaryTextColor"
app:iconTint="@color/primaryIconColor"
app:cornerRadius="0dp"
app:icon="@drawable/ic_diagnostics"
app:backgroundTint="@color/primaryColor"
app:rippleColor="@color/rippleHighlightColor_light"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:id="@+id/view_search_results"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="start|center_vertical"
android:insetTop="0dp"
android:insetBottom="0dp"
android:text="@string/view_search_results"
android:layout_marginBottom="1dp"
android:textColor="@color/primaryTextColor"
app:iconTint="@color/primaryIconColor"
app:cornerRadius="0dp"
app:icon="@drawable/ic_search"
app:backgroundTint="@color/primaryColor"
app:rippleColor="@color/rippleHighlightColor_light"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:id="@+id/view_logs"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="start|center_vertical"
android:insetTop="0dp"
android:insetBottom="0dp"
android:text="@string/logs"
android:layout_marginBottom="1dp"
android:textColor="@color/primaryTextColor"
app:iconTint="@color/primaryIconColor"
app:cornerRadius="0dp"
app:icon="@drawable/ic_log"
app:backgroundTint="@color/primaryColor"
app:rippleColor="@color/rippleHighlightColor_light"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:id="@+id/view_files"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="start|center_vertical"
android:insetTop="0dp"
android:insetBottom="0dp"
android:text="@string/show_files"
android:layout_marginBottom="1dp"
android:textColor="@color/primaryTextColor"
app:iconTint="@color/primaryIconColor"
app:cornerRadius="0dp"
app:icon="@drawable/ic_folder"
app:backgroundTint="@color/primaryColor"
app:rippleColor="@color/rippleHighlightColor_light"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:id="@+id/view_daemonStatus"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="start|center_vertical"
android:insetTop="0dp"
android:insetBottom="0dp"
android:text="@string/gradle_daemon_status"
android:textColor="@color/primaryTextColor"
app:iconTint="@color/primaryIconColor"
app:cornerRadius="0dp"
app:icon="@drawable/ic_info"
app:backgroundTint="@color/primaryColor"
app:rippleColor="@color/rippleHighlightColor_light"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:orientation="vertical"
android:id="@+id/buildContainer"
android:visibility="gone"
android:background="@color/primaryDarkColor"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:layout_height="56dp"
android:layout_width="match_parent"
android:id="@+id/buildOutToolbar"
android:elevation="8dp"
android:background="@color/primaryDarkColor"
app:title="@string/build_output"
app:navigationIcon="@drawable/ic_chevron_down"
app:navigationIconTint="@color/primaryIconColor"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/buildOutcontainer"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/logContainer"
android:visibility="gone"
android:background="@color/primaryDarkColor"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:layout_height="56dp"
android:layout_width="match_parent"
android:id="@+id/logOutToolbar"
android:elevation="8dp"
android:background="@color/primaryDarkColor"
app:title="@string/logs"
app:navigationIcon="@drawable/ic_chevron_down"
app:navigationIconTint="@color/primaryIconColor"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/logOutcontainer"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:id="@+id/diagContainer"
android:visibility="gone"
android:background="@color/primaryDarkColor"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:layout_height="56dp"
android:layout_width="match_parent"
android:id="@+id/diagToolbar"
android:elevation="8dp"
android:background="@color/primaryDarkColor"
app:title="@string/view_diags"
app:navigationIcon="@drawable/ic_chevron_down"
app:navigationIconTint="@color/primaryIconColor"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/diagListContainer">
<com.itsaky.androidide.views.EmptyView
android:id="@+id/diagEmptyView"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:id="@+id/searchResultsContainer"
android:visibility="gone"
android:background="@color/primaryDarkColor"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:layout_height="56dp"
android:layout_width="match_parent"
android:id="@+id/searchResultsToolbar"
android:elevation="8dp"
android:background="@color/primaryDarkColor"
app:title="@string/view_search_results"
app:navigationIcon="@drawable/ic_chevron_down"
app:navigationIconTint="@color/primaryIconColor"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/searchResultsListContainer">
<com.itsaky.androidide.views.EmptyView
android:id="@+id/searchEmptyView"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
</LinearLayout>
<TextView
<TextView
android:id="@+id/symbolText"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
@@ -382,23 +87,7 @@
android:id="@+id/diagnosticInfo"
layout="@layout/layout_diagnostic_info"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="24dp"
android:visibility="visible"
app:backgroundTint="@color/secondaryColor"
app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/ic_view"
app:tint="@color/primaryTextColor"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/startNav"
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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 <https://www.gnu.org/licenses/>.
-->
<io.github.rosemoe.editor.widget.CodeEditor
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/editor"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/msg"
android:padding="8dp"
android:textColor="@color/primaryTextColor"
android:textSize="11sp"
android:textIsSelectable="true"/>
android:textIsSelectable="true" />
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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 <https://www.gnu.org/licenses/>.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:elevation="8dp"
app:behavior_hideable="false"
app:behavior_peekHeight="40dp"
app:layout_behavior="com.itsaky.androidide.utils.EditorBottomSheetBehavior">
<LinearLayout
android:id="@+id/text_container"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="vertical"
android:background="@android:color/black">
<TextView
android:id="@+id/statusText"
android:layout_height="20dp"
android:layout_width="match_parent"
android:gravity="center"
android:textSize="14sp"
android:textColor="@color/primaryTextColor"
android:singleLine="true" />
<TextView
android:id="@+id/swipe_hint"
android:layout_width="match_parent"
android:layout_height="18dp"
android:text="@string/msg_swipe_up"
android:gravity="center"
android:textColor="@color/secondaryTextColor"
android:textSize="11sp"/>
</LinearLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="36dp"
android:background="@android:color/black"
app:tabIndicatorColor="@color/secondaryColor"
app:tabIndicatorGravity="stretch"
app:tabIndicatorHeight="36dp"
app:tabTextAppearance="@style/AppTheme.TabLayout.Title"
app:tabSelectedTextColor="@color/primaryTextColor"
app:tabMode="scrollable"
app:tabGravity="fill"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/content_background" />
</LinearLayout>
+3 -2
View File
@@ -26,9 +26,9 @@
<string name="discussions_on_telegram">Discussions on Telegram</string>
<string name="msg_empty_view">I have nothing to show you&#8230;</string>
<string name="btn_terminal">Terminal</string>
<string name="androidstringok">@android:string/ok</string>
<string name="reset">Reset</string>
<string name="logs">Logs</string>
<string name="app_logs">App Logs</string>
<string name="ide_logs">IDE Logs</string>
<string name="label_splash_image">Splash image</string>
<string name="cancel">Cancel</string>
<string name="get_started">Get started</string>
@@ -339,5 +339,6 @@
<string name="title_code_generation_failed">Code generation failed</string>
<string name="msg_code_generation_failed">Failed to generate XML code. Would you like to exit anyway?</string>
<string name="msg_invalid_designer_result">UI Designer returned invalid result</string>
<string name="msg_swipe_up">Swipe up for build output, logs and more.</string>
</resources>