diff --git a/app/src/main/assets/data/common/tooling-api-all.jar b/app/src/main/assets/data/common/tooling-api-all.jar index 77f5294457..6fa1c8591f 100644 Binary files a/app/src/main/assets/data/common/tooling-api-all.jar and b/app/src/main/assets/data/common/tooling-api-all.jar differ diff --git a/app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt index 13a1dd18e8..25133a9f0c 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt @@ -251,9 +251,6 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler { log.info("Opening file at index:", position, "file: ", file) val editor = CodeEditorView(this, file, selection!!) - editor.editor.subscribeEvent(ContentChangeEvent::class.java) { event, _ -> - onEditorContentChanged(event) - } editor.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) binding.editorContainer.addView(editor) @@ -365,11 +362,9 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler { } } - private fun onEditorContentChanged(event: ContentChangeEvent) { - if (event.action != ContentChangeEvent.ACTION_SET_NEW_TEXT) { - viewModel.setFilesModified(true) - invalidateOptionsMenu() - } + private fun onEditorContentChanged() { + viewModel.setFilesModified(true) + invalidateOptionsMenu() } override fun areFilesModified(): Boolean { @@ -542,6 +537,9 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler { @Subscribe(threadMode = ThreadMode.MAIN) fun onDocumentChange(event: DocumentChangeEvent) { + // update content modification status + onEditorContentChanged() + val index = findIndexOfEditorByFile(event.file.toFile()) if (index == -1) { return diff --git a/app/src/main/java/com/itsaky/androidide/ui/editor/CodeEditorView.java b/app/src/main/java/com/itsaky/androidide/ui/editor/CodeEditorView.java index 61f224ddb0..5e99caef60 100644 --- a/app/src/main/java/com/itsaky/androidide/ui/editor/CodeEditorView.java +++ b/app/src/main/java/com/itsaky/androidide/ui/editor/CodeEditorView.java @@ -118,6 +118,12 @@ public CodeEditorView( final var editor = getEditor(); editor.post(() -> { editor.setText(contents, createEditorArgs()); + + // editor.setText(...) sets the modified flag to true + // but in this case, file is read from disk and hence the contents are not modified at all + // so the flag must be changed to unmodified + // TODO: Find a better way to check content modification status + editor.markUnmodified(); postRead(); selection.validate(); diff --git a/app/src/main/res/xml/ide_file_provider_paths.xml b/app/src/main/res/xml/ide_file_provider_paths.xml index ee86c813ba..7ee76a55e4 100644 --- a/app/src/main/res/xml/ide_file_provider_paths.xml +++ b/app/src/main/res/xml/ide_file_provider_paths.xml @@ -14,12 +14,11 @@ ~ You should have received a copy of the GNU General Public License ~ along with AndroidIDE. If not, see . --> - - - - \ No newline at end of file + + + + + + + diff --git a/changelogs/v2.4.1-beta.md b/changelogs/v2.4.1-beta.md new file mode 100644 index 0000000000..15592ded13 --- /dev/null +++ b/changelogs/v2.4.1-beta.md @@ -0,0 +1,10 @@ +# AndroidIDE v2.4.1-beta + +## Important notes + +- The terminal packages have been moved to `packages.androidide.com/apt/termux-main`. + +## Fixes + +- Project initialization fails if the project contains a `java-library` module. +- Classes from the same package are imported when selecting a class completion item (#869). \ No newline at end of file diff --git a/editor/src/main/java/com/itsaky/androidide/editor/ui/EditorActionsMenu.kt b/editor/src/main/java/com/itsaky/androidide/editor/ui/EditorActionsMenu.kt index 463798ffbd..bfa6fae5ec 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/ui/EditorActionsMenu.kt +++ b/editor/src/main/java/com/itsaky/androidide/editor/ui/EditorActionsMenu.kt @@ -83,6 +83,11 @@ open class EditorActionsMenu constructor(val editor: IDEEditor) : private var mLastScroll: Long = 0 private var mLastPosition: Int = 0 + private val contentHeight by lazy { + // approximated size is around 56dp + SizeUtils.dp2px(56f) + } + private val menu: MenuBuilder = MenuBuilder(editor.context) protected open var location = ActionItem.Location.EDITOR_TEXT_ACTIONS @@ -226,6 +231,8 @@ open class EditorActionsMenu constructor(val editor: IDEEditor) : private fun selectTop(rect: RectF): Int { val rowHeight = editor.rowHeight + // when the window is being shown for the first time, the height is 0 + val height = if (this.height == 0) contentHeight else this.height return if (rect.top - rowHeight * 3 / 2f > height) { (rect.top - rowHeight * 3 / 2 - height).toInt() } else { @@ -325,7 +332,7 @@ open class EditorActionsMenu constructor(val editor: IDEEditor) : override fun show() { - if (editor.searcher.searching) { + if (editor.searcher.isSearching) { // Do not show if user is searching text return } diff --git a/editor/src/main/java/com/itsaky/androidide/editor/ui/EditorSearchLayout.kt b/editor/src/main/java/com/itsaky/androidide/editor/ui/EditorSearchLayout.kt index 5f9060989e..f3974c54f2 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/ui/EditorSearchLayout.kt +++ b/editor/src/main/java/com/itsaky/androidide/editor/ui/EditorSearchLayout.kt @@ -28,8 +28,8 @@ import android.view.inputmethod.EditorInfo import android.widget.FrameLayout import android.widget.PopupMenu import com.itsaky.androidide.editor.databinding.LayoutFindInFileBinding -import com.itsaky.androidide.resources.R import com.itsaky.androidide.editor.ui.ReplaceAction.doReplace +import com.itsaky.androidide.resources.R import com.itsaky.androidide.utils.SingleTextWatcher import io.github.rosemoe.sora.widget.EditorSearcher.SearchOptions import java.util.regex.Pattern @@ -47,6 +47,8 @@ class EditorSearchLayout(context: Context, val editor: IDEEditor) : FrameLayout( private val findInFileBinding: LayoutFindInFileBinding private val optionsMenu: PopupMenu + private var isSearching = false + init { findInFileBinding = LayoutFindInFileBinding.inflate(LayoutInflater.from(context)) findInFileBinding.prev.setOnClickListener(::onSearchActionClick) @@ -113,6 +115,7 @@ class EditorSearchLayout(context: Context, val editor: IDEEditor) : FrameLayout( findInFileBinding.searchInput.removeTextChangedListener(this.searchInputTextWatcher) findInFileBinding.root.visibility = GONE this.searchInputTextWatcher = null + this.editor.searcher.onClose() } if (!searcher.hasQuery()) { return diff --git a/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java b/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java index c440bed593..1988be6395 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java +++ b/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java @@ -722,10 +722,7 @@ public void ensureWindowsDismissed() { * @param event The content change event. */ private void handleContentChange(ContentChangeEvent event, Unsubscribe unsubscribe) { - if (event.getAction() != ContentChangeEvent.ACTION_SET_NEW_TEXT) { - isModified = true; - } - + isModified = true; if (getFile() == null) { return; } diff --git a/editor/src/main/java/io/github/rosemoe/sora/widget/IDEEditorSearcher.kt b/editor/src/main/java/io/github/rosemoe/sora/widget/IDEEditorSearcher.kt index 41732085aa..6f4914c5e7 100644 --- a/editor/src/main/java/io/github/rosemoe/sora/widget/IDEEditorSearcher.kt +++ b/editor/src/main/java/io/github/rosemoe/sora/widget/IDEEditorSearcher.kt @@ -15,8 +15,6 @@ * along with AndroidIDE. If not, see . */ -@file:Suppress("DEPRECATION") - package io.github.rosemoe.sora.widget import com.itsaky.androidide.editor.ui.IDEEditor @@ -29,7 +27,7 @@ import com.itsaky.androidide.editor.ui.IDEEditor */ open class IDEEditorSearcher(editor: IDEEditor) : EditorSearcher(editor) { - var searching = false + var isSearching = false private set protected fun getEditor(): CodeEditor { @@ -67,11 +65,15 @@ open class IDEEditorSearcher(editor: IDEEditor) : EditorSearcher(editor) { } override fun stopSearch() { - searching = false + isSearching = false super.stopSearch() } + fun onClose() { + isSearching = false + } + private fun markSearching() { - searching = true + isSearching = true } } diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/fragments/AttrValueEditorFragment.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/fragments/AttrValueEditorFragment.kt index fdbf11a384..a59116a24f 100644 --- a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/fragments/AttrValueEditorFragment.kt +++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/fragments/AttrValueEditorFragment.kt @@ -76,7 +76,7 @@ class AttrValueEditorFragment : Fragment() { val header = this.header ?: return val view = this.viewModel.view ?: return val attr = this.viewModel.selectedAttr ?: return - + val ns = attr.namespace?.prefix?.let { "${it}:" } ?: "" header.name.text = "${ns}${attr.name}" header.desc.text = attr.namespace?.uri ?: "" @@ -90,10 +90,15 @@ class AttrValueEditorFragment : Fragment() { ) textView.dropDownVerticalOffset = -binding.root.height textView.showDropDown() - + val value = binding.attrValue.text.toString() attr.value = value - view.applyAttribute(attr.copyAttr(value = value)) + try { + view.applyAttribute(attr.copyAttr(value = value)) + } catch (e: Exception) { + // When the user is editing the attribute value, it is always invalid and cannot be + // resolved. Exceptions may be thrown while parsing the value which should be ignored + } } textView.setText(attr.value)