diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/adapter/EditorAdapter.kt b/app/src/main/kotlin/org/cosmicide/rewrite/adapter/EditorAdapter.kt index 0036daa3..09551427 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/adapter/EditorAdapter.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/adapter/EditorAdapter.kt @@ -51,7 +51,11 @@ class EditorAdapter(val fragment: Fragment, val fileViewModel: FileViewModel) : } override fun createFragment(position: Int): Fragment { - val fragment = CodeEditorFragment(fileViewModel.files.value!![position]) + val fragment = CodeEditorFragment().apply { + arguments = Bundle().apply { + putSerializable("file", fileViewModel.files.value!![position]) + } + } fragments.add(fragment) return fragment } @@ -74,11 +78,12 @@ class EditorAdapter(val fragment: Fragment, val fileViewModel: FileViewModel) : fragments.forEach { it.save() } } - class CodeEditorFragment(val file: File) : Fragment() { + class CodeEditorFragment : Fragment() { private lateinit var eventReceiver: SubscriptionReceipt private lateinit var binding: EditorFragmentBinding lateinit var editor: IdeEditor + val file by lazy { requireArguments().getSerializable("file") as File } override fun onCreateView( inflater: LayoutInflater, diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/EditorFragment.kt b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/EditorFragment.kt index 4d4462c3..9d5837d4 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/EditorFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/EditorFragment.kt @@ -19,6 +19,7 @@ import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.bottomsheet.BottomSheetDialog +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator @@ -31,6 +32,7 @@ import kotlinx.coroutines.launch import org.cosmic.ide.dependency.resolver.getArtifact import org.cosmicide.project.Language import org.cosmicide.project.Project +import org.cosmicide.rewrite.FileProvider.openFileWithExternalApp import org.cosmicide.rewrite.R import org.cosmicide.rewrite.adapter.EditorAdapter import org.cosmicide.rewrite.adapter.NavAdapter @@ -38,22 +40,21 @@ import org.cosmicide.rewrite.common.BaseBindingFragment import org.cosmicide.rewrite.databinding.FragmentEditorBinding import org.cosmicide.rewrite.databinding.NavigationElementsBinding import org.cosmicide.rewrite.databinding.NewDependencyBinding +import org.cosmicide.rewrite.databinding.TreeviewContextActionDialogItemBinding import org.cosmicide.rewrite.editor.formatter.GoogleJavaFormat import org.cosmicide.rewrite.editor.formatter.ktfmtFormatter import org.cosmicide.rewrite.model.FileViewModel -import org.cosmicide.rewrite.treeview.FileSet import org.cosmicide.rewrite.util.FileFactoryProvider import org.cosmicide.rewrite.util.FileIndex import org.cosmicide.rewrite.util.ProjectHandler import org.jetbrains.kotlin.psi.KtFile import java.io.File -class EditorFragment( - private val project: Project -) : BaseBindingFragment() { +class EditorFragment : BaseBindingFragment() { private lateinit var fileIndex: FileIndex private val fileViewModel by activityViewModels() private lateinit var editorAdapter: EditorAdapter + private val project by lazy { requireArguments().getSerializable("project") as Project } override fun getViewBinding() = FragmentEditorBinding.inflate(layoutInflater) @@ -97,34 +98,31 @@ class EditorFragment( } } - requireActivity().onBackPressedDispatcher.addCallback( - object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - binding.apply { - val fragment = - parentFragmentManager.findFragmentById(R.id.fragment_container) - if (fragment !is EditorFragment) { - parentFragmentManager.popBackStack() - return - } - if (drawer.isOpen) { - drawer.close() - } else { - editorAdapter.saveAll() + requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + binding.apply { + val fragment = parentFragmentManager.findFragmentById(R.id.fragment_container) + if (fragment !is EditorFragment) { + parentFragmentManager.popBackStack() + return + } + if (drawer.isOpen) { + drawer.close() + } else { + editorAdapter.saveAll() - fileIndex.putFiles( - binding.pager.currentItem, - fileViewModel.files.value!! - ) + fileIndex.putFiles( + binding.pager.currentItem, fileViewModel.files.value!! + ) - fileViewModel.removeAll() - fileViewModel.files.removeObservers(viewLifecycleOwner) + fileViewModel.removeAll() + fileViewModel.files.removeObservers(viewLifecycleOwner) - parentFragmentManager.popBackStack() - } + parentFragmentManager.popBackStack() } } - }) + } + }) TabLayoutMediator(binding.tabLayout, binding.pager, true, true) { tab, position -> tab.text = fileViewModel.files.value!![position].name @@ -170,7 +168,7 @@ class EditorFragment( } override fun onItemLongClick(v: View, position: Int) { - showMenu(v, R.menu.treeview_menu, position) + showTreeViewMenu(v, nodes.get(position).value) } }) } @@ -337,11 +335,11 @@ class EditorFragment( } } - val psiFile = - if (language == Language.Kotlin) - FileFactoryProvider.getKtPsiFile(editor.file.name, editor.editor.text.toString()) - else - FileFactoryProvider.getPsiJavaFile(editor.file.name, editor.editor.text.toString()) + val psiFile = if (language == Language.Kotlin) FileFactoryProvider.getKtPsiFile( + editor.file.name, + editor.editor.text.toString() + ) + else FileFactoryProvider.getPsiJavaFile(editor.file.name, editor.editor.text.toString()) val classes = psiFile.classes if (classes.isEmpty() && language == Language.Java) { @@ -452,23 +450,6 @@ class EditorFragment( }.commit() } - private fun traverseDirectory(dir: File): Set { - val set = mutableSetOf() - val files = dir.listFiles() ?: return set - for (file in files) { - when { - file.isFile -> set.add(FileSet(file)) - file.isDirectory -> { - val tempSet = mutableSetOf().apply { - addAll(traverseDirectory(file)) - } - set.add(FileSet(file, tempSet)) - } - } - } - return set - } - private fun showMenu(v: View, @MenuRes menuRes: Int, position: Int) { val popup = PopupMenu(requireContext(), v) popup.menuInflater.inflate(menuRes, popup.menu) @@ -477,15 +458,118 @@ class EditorFragment( when (it.itemId) { R.id.close_tab -> { fileViewModel.removeFile(position) + } R.id.close_all_tab -> fileViewModel.removeAll() - R.id.close_left_tab -> fileViewModel.removeLeft(position) - R.id.close_right_tab -> fileViewModel.removeRight(position) + R.id.close_left_tab -> fileViewModel.removeLeft(position - 1) + R.id.close_right_tab -> fileViewModel.removeRight(position - 1) R.id.close_other_tab -> fileViewModel.removeOthers(fileViewModel.currentFile!!) } true } popup.show() } + + private fun showTreeViewMenu(v: View, file: File) { + val popup = PopupMenu(v.context, v) + popup.menuInflater.inflate(R.menu.treeview_menu, popup.menu) + + if (file.isDirectory) { + popup.menu.removeItem(R.id.open_external) + } else { + popup.menu.removeItem(R.id.create_kotlin_class) + popup.menu.removeItem(R.id.create_java_class) + popup.menu.removeItem(R.id.create_folder) + } + + popup.setOnMenuItemClickListener { + when (it.itemId) { + R.id.create_kotlin_class -> { + val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) + binding.textInputLayout.suffixText = ".kt" + MaterialAlertDialogBuilder(v.context).setTitle("Create kotlin class") + .setView(binding.root).setPositiveButton("Create") { _, _ -> + var name = binding.edittext.text.toString() + name = name.replace("\\.", "") + file.resolve("$name.kt").createNewFile() + initTreeView() + }.setNegativeButton("Cancel") { dialog, _ -> + dialog.dismiss() + }.show() + } + + R.id.create_java_class -> { + val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) + binding.textInputLayout.suffixText = ".java" + MaterialAlertDialogBuilder(v.context).setTitle("Create java class") + .setView(binding.root).setPositiveButton("Create") { _, _ -> + var name = binding.edittext.text.toString() + name = name.replace("\\.", "") + file.resolve("$name.java").createNewFile() + initTreeView() + }.setNegativeButton("Cancel") { dialog, _ -> + dialog.dismiss() + }.show() + } + + R.id.create_folder -> { + val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) + MaterialAlertDialogBuilder(v.context).setTitle("Create folder") + .setView(binding.root).setPositiveButton("Create") { _, _ -> + var name = binding.edittext.text.toString() + name = name.replace("\\.", "") + file.resolve(name).mkdirs() + initTreeView() + }.setNegativeButton("Cancel") { dialog, _ -> + dialog.dismiss() + }.show() + } + + R.id.create_file -> { + val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) + MaterialAlertDialogBuilder(v.context).setTitle("Create file") + .setView(binding.root).setPositiveButton("Create") { _, _ -> + var name = binding.edittext.text.toString() + name = name.replace("\\.", "") + file.resolve(name).createNewFile() + initTreeView() + }.setNegativeButton("Cancel") { dialog, _ -> + dialog.dismiss() + }.show() + } + + R.id.rename -> { + val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) + binding.edittext.setText(file.name) + MaterialAlertDialogBuilder(v.context).setTitle("Rename").setView(binding.root) + .setPositiveButton("Create") { _, _ -> + var name = binding.edittext.text.toString() + name = name.replace("\\.", "") + file.renameTo(file.parentFile!!.resolve(name)) + initTreeView() + }.setNegativeButton("Cancel") { dialog, _ -> + dialog.dismiss() + }.show() + } + + R.id.delete -> { + MaterialAlertDialogBuilder(v.context).setTitle("Delete") + .setMessage("Are you sure you want to delete this file") + .setPositiveButton("Create") { _, _ -> + file.deleteRecursively() + initTreeView() + }.setNegativeButton("Cancel") { dialog, _ -> + dialog.dismiss() + }.show() + } + + R.id.open_external -> { + openFileWithExternalApp(v.context, file) + } + } + true + } + popup.show() + } } diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/InstallResourcesFragment.kt b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/InstallResourcesFragment.kt index 1d1b521e..34a8af7a 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/InstallResourcesFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/InstallResourcesFragment.kt @@ -7,11 +7,13 @@ package org.cosmicide.rewrite.fragment +import android.annotation.SuppressLint import android.os.Bundle import android.view.View import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.cosmicide.rewrite.R import org.cosmicide.rewrite.common.BaseBindingFragment import org.cosmicide.rewrite.databinding.InstallResourcesFragmentBinding @@ -24,20 +26,25 @@ class InstallResourcesFragment : BaseBindingFragment() { private fun navigateToEditorFragment(project: Project) { parentFragmentManager.beginTransaction().apply { - add(R.id.fragment_container, EditorFragment(project)) + add(R.id.fragment_container, EditorFragment().apply { + arguments = Bundle().apply { + putSerializable("project", project) + } + }) addToBackStack(null) setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_FADE) }.commit() diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/ProjectFragment.kt b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/ProjectFragment.kt index d5de9057..ee9c06d1 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/ProjectFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/ProjectFragment.kt @@ -316,7 +316,11 @@ class ProjectFragment : BaseBindingFragment(), private fun navigateToEditorFragment(project: Project) { parentFragmentManager.beginTransaction().apply { - add(R.id.fragment_container, EditorFragment(project)) + add(R.id.fragment_container, EditorFragment().apply { + arguments = Bundle().apply { + putSerializable("project", project) + } + }) addToBackStack(null) setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_FADE) }.commit() diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/ProjectOutputFragment.kt b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/ProjectOutputFragment.kt index 508da725..383ee058 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/ProjectOutputFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/ProjectOutputFragment.kt @@ -99,10 +99,11 @@ class ProjectOutputFragment : BaseBindingFragment() binding.infoEditor.setText("classes.jar not found") return } - JarFile(jar).use { - val mainClass = it.entries().asSequence().firstOrNull { entry -> - entry.name == "Main.class" - } + JarFile(jar).use { file -> + val sequence = file.entries().asSequence() + val mainClass = sequence.firstOrNull { entry -> + entry.name.endsWith("Main.class") + } ?: sequence.firstOrNull() if (mainClass == null) { binding.infoEditor.setText("No entrypoint Main class found") return @@ -212,6 +213,7 @@ class ProjectOutputFragment : BaseBindingFragment() } private fun initVM() { + println("[VM] Initializing...") val time = System.currentTimeMillis() catchVMException { @@ -224,10 +226,11 @@ class ProjectOutputFragment : BaseBindingFragment() // init VM ssvm.initVM() - // add test JAR + // add classpath JAR FileUtil.classpathDir.walk().filter { it.extension == "jar" }.forEach { ssvm.addURL(it) } + // add libs project.libDir.walk().filter { it.extension == "jar" }.forEach { ssvm.addURL(it) } @@ -240,7 +243,9 @@ class ProjectOutputFragment : BaseBindingFragment() private fun invoke(className: String) { catchVMException { + println("[VM] Invoking $className") ssvm.invokeMainMethod(className) + println("[VM] VM exited") } } diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/settings/AboutSettings.kt b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/settings/AboutSettings.kt index eb021e15..2fef6eb3 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/fragment/settings/AboutSettings.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/fragment/settings/AboutSettings.kt @@ -16,11 +16,20 @@ import android.os.Build import android.provider.Settings import android.widget.Toast import androidx.fragment.app.FragmentActivity +import androidx.fragment.app.FragmentTransaction +import androidx.lifecycle.lifecycleScope import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import de.Maxr1998.modernpreferences.PreferenceScreen import de.Maxr1998.modernpreferences.helpers.onClick import de.Maxr1998.modernpreferences.helpers.pref +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.cosmicide.rewrite.BuildConfig +import org.cosmicide.rewrite.R +import org.cosmicide.rewrite.fragment.InstallResourcesFragment +import org.cosmicide.rewrite.util.FileUtil +import org.cosmicide.rewrite.util.ResourceUtil class AboutSettings(private val activity: FragmentActivity) : SettingsProvider { override fun provideSettings(builder: PreferenceScreen.Builder) { @@ -92,6 +101,25 @@ class AboutSettings(private val activity: FragmentActivity) : SettingsProvider { } } + pref("clear_cache") { + title = "Clear cache" + onClick { + activity.lifecycleScope.launch(Dispatchers.IO) { + ResourceUtil.resources.forEach { + FileUtil.dataDir.resolve(it).delete() + } + withContext(Dispatchers.Main) { + Toast.makeText(activity, "Cache cleared", Toast.LENGTH_LONG).show() + activity.supportFragmentManager.beginTransaction().apply { + add(R.id.fragment_container, InstallResourcesFragment()) + setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) + }.commit() + } + } + true + } + } + pref("force_crash") { title = "Force crash" onClick { diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/model/FileViewModel.kt b/app/src/main/kotlin/org/cosmicide/rewrite/model/FileViewModel.kt index 9f43a409..83180336 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/model/FileViewModel.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/model/FileViewModel.kt @@ -54,12 +54,15 @@ class FileViewModel : ViewModel() { * Removes the given file from the list of files. */ fun removeFile(pos: Int) { - files.value = files.value?.toMutableList()?.apply { removeAt(pos + 1) } + files.value = files.value!!.toMutableList().apply { removeAt(pos) } - if (files.value!!.isEmpty()) { - setCurrentPosition(-1) - } else { - setCurrentPosition(pos - 1) + if (currentPosition.value == pos) { + if (files.value!!.isEmpty()) { + setCurrentPosition(-1) + } + } + if (currentPosition.value!! > pos) { + setCurrentPosition(currentPosition.value!! - 1) } } diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/treeview/FileTreeNodeGenerator.kt b/app/src/main/kotlin/org/cosmicide/rewrite/treeview/FileTreeNodeGenerator.kt deleted file mode 100644 index f741c3e2..00000000 --- a/app/src/main/kotlin/org/cosmicide/rewrite/treeview/FileTreeNodeGenerator.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of Cosmic IDE. - * Cosmic IDE is a 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. - * Cosmic IDE 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 Foobar. If not, see . - */ - -package org.cosmicide.rewrite.treeview - -import android.util.Log -import io.github.dingyi222666.view.treeview.AbstractTree -import io.github.dingyi222666.view.treeview.Tree -import io.github.dingyi222666.view.treeview.TreeNode -import io.github.dingyi222666.view.treeview.TreeNodeGenerator -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.io.File - -class FileTreeNodeGenerator(private val rootItem: FileSet) : TreeNodeGenerator { - - override fun createNode( - parentNode: TreeNode, - currentData: FileSet, - tree: AbstractTree - ): TreeNode { - return TreeNode( - data = currentData, - depth = parentNode.depth + 1, - name = currentData.file.name, - id = tree.generateId(), - hasChild = currentData.file.isDirectory, - isChild = currentData.file.isDirectory, - expand = false - ) - } - - override suspend fun fetchNodeChildData(targetNode: TreeNode): Set = - withContext(Dispatchers.IO) { - val set = mutableSetOf() - val files = targetNode.requireData().file.listFiles() ?: return@withContext set - Log.d("Refreshing Data", targetNode.requireData().file.name) - for (file in files) { - when { - file.isFile -> set.add(FileSet(file)) - file.isDirectory -> { - set.add(FileSet(file, subDir = traverseDirectory(file).toMutableSet())) - } - } - } - return@withContext set - } - - override fun createRootNode(): TreeNode { - return TreeNode( - data = rootItem, - depth = 0, - name = rootItem.file.name, - id = Tree.ROOT_NODE_ID, - hasChild = true, - isChild = false - ) - } - - private fun traverseDirectory(dir: File): Set { - val set = mutableSetOf() - val files = dir.listFiles() ?: return set - for (file in files) { - when { - file.isFile -> set.add(FileSet(file)) - file.isDirectory -> { - val tempSet = mutableSetOf().apply { - addAll(traverseDirectory(file)) - } - set.add(FileSet(file, tempSet)) - } - } - } - return set - } -} - -data class FileSet(val file: File, val subDir: MutableSet = mutableSetOf()) \ No newline at end of file diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/treeview/ViewBinder.kt b/app/src/main/kotlin/org/cosmicide/rewrite/treeview/ViewBinder.kt deleted file mode 100644 index bc48222d..00000000 --- a/app/src/main/kotlin/org/cosmicide/rewrite/treeview/ViewBinder.kt +++ /dev/null @@ -1,264 +0,0 @@ -/* - * This file is part of Cosmic IDE. - * Cosmic IDE is a 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. - * Cosmic IDE 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 Foobar. If not, see . - */ - -package org.cosmicide.rewrite.treeview - -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.Space -import androidx.annotation.MenuRes -import androidx.appcompat.widget.PopupMenu -import androidx.core.view.updateLayoutParams -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import io.github.dingyi222666.view.treeview.TreeNode -import io.github.dingyi222666.view.treeview.TreeNodeEventListener -import io.github.dingyi222666.view.treeview.TreeView -import io.github.dingyi222666.view.treeview.TreeViewBinder -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import org.cosmicide.rewrite.FileProvider.openFileWithExternalApp -import org.cosmicide.rewrite.R -import org.cosmicide.rewrite.databinding.TreeviewContextActionDialogItemBinding -import org.cosmicide.rewrite.databinding.TreeviewItemDirBinding -import org.cosmicide.rewrite.databinding.TreeviewItemFileBinding -import org.cosmicide.rewrite.extension.getDip -import org.cosmicide.rewrite.model.FileViewModel -import java.io.File - -class ViewBinder( - private val lifeScope: CoroutineScope, - private val layoutInflater: LayoutInflater, - private val fileViewModel: FileViewModel, - private val treeView: TreeView -) : TreeViewBinder(), TreeNodeEventListener { - private lateinit var dirBinding: TreeviewItemDirBinding - private lateinit var fileBinding: TreeviewItemFileBinding - - override fun createView(parent: ViewGroup, viewType: Int): View { - return when (viewType) { - ViewType.DIRECTORY.ordinal -> { - dirBinding = TreeviewItemDirBinding.inflate(layoutInflater, parent, false) - dirBinding.root - } - - ViewType.FILE.ordinal -> { - fileBinding = TreeviewItemFileBinding.inflate(layoutInflater, parent, false) - fileBinding.root - } - - else -> throw IllegalArgumentException("Invalid view type: $viewType") - } - } - - override fun getItemViewType(node: TreeNode): Int { - return if (node.isChild) ViewType.DIRECTORY.ordinal else ViewType.FILE.ordinal - } - - override fun bindView( - holder: TreeView.ViewHolder, - node: TreeNode, - listener: TreeNodeEventListener - ) { - with(holder.itemView.findViewById(R.id.space)) { - updateLayoutParams { - width = node.depth * context.getDip(22f).toInt() - } - } - - when { - node.isChild -> { - dirBinding.textView.text = node.data!!.file.name - applyDir(node) - } - - else -> applyFile(node) - } - } - - private fun applyFile(node: TreeNode) { - fileBinding.textView.text = node.name.toString() - } - - private fun applyDir(node: TreeNode) { - val rotation = if (node.expand) 90f else 0f - dirBinding.imageView.animate() - .rotation(rotation) - .setDuration(200) - .start() - } - - override fun onLongClick(node: TreeNode, holder: TreeView.ViewHolder): Boolean { - showMenu( - holder.itemView.findViewById(R.id.textView), - R.menu.treeview_menu, - node.data!!.file, - node - ) - return false - } - - override fun onClick(node: TreeNode, holder: TreeView.ViewHolder) { - when { - node.isChild -> applyDir(node) - else -> fileViewModel.addFile(node.data!!.file) - } - } - - override fun onToggle(node: TreeNode, isExpand: Boolean, holder: TreeView.ViewHolder) { - applyDir(node) - } - - private fun showMenu(v: View, @MenuRes menuRes: Int, file: File, node: TreeNode) { - val popup = PopupMenu(v.context, v) - popup.menuInflater.inflate(menuRes, popup.menu) - - if (node.isChild) { - popup.menu.removeItem(R.id.open_external) - } else { - popup.menu.removeItem(R.id.create_kotlin_class) - popup.menu.removeItem(R.id.create_java_class) - popup.menu.removeItem(R.id.create_folder) - } - - popup.setOnMenuItemClickListener { - val parentNode = treeView.tree.getParentNode(node) - when (it.itemId) { - R.id.create_kotlin_class -> { - val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) - binding.textInputLayout.suffixText = ".kt" - MaterialAlertDialogBuilder(v.context) - .setTitle("Create kotlin class") - .setView(binding.root) - .setPositiveButton("Create") { _, _ -> - file.absolutePath - val name = binding.edittext.text.toString() - file.resolve("$name.kt").createNewFile() - lifeScope.launch { - treeView.refresh(node = parentNode) - } - } - .setNegativeButton("Cancel") { dialog, _ -> - dialog.dismiss() - } - .show() - } - - R.id.create_java_class -> { - val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) - binding.textInputLayout.suffixText = ".java" - MaterialAlertDialogBuilder(v.context) - .setTitle("Create java class") - .setView(binding.root) - .setPositiveButton("Create") { _, _ -> - file.absolutePath - var name = binding.edittext.text.toString() - name = name.replace("\\.", "") - file.resolve("$name.java").createNewFile() - lifeScope.launch { - Log.d("ViewBinder", "Refresh treeview") - treeView.refresh(node = parentNode) - } - } - .setNegativeButton("Cancel") { dialog, _ -> - dialog.dismiss() - } - .show() - } - - R.id.create_folder -> { - val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) - MaterialAlertDialogBuilder(v.context) - .setTitle("Create folder") - .setView(binding.root) - .setPositiveButton("Create") { _, _ -> - var name = binding.edittext.text.toString() - name = name.replace("\\.", "") - file.resolve(name).mkdirs() - lifeScope.launch { - Log.d("ViewBinder", "Refresh treeview") - treeView.refresh() - } - } - .setNegativeButton("Cancel") { dialog, _ -> - dialog.dismiss() - } - .show() - } - - R.id.create_file -> { - val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) - MaterialAlertDialogBuilder(v.context) - .setTitle("Create file") - .setView(binding.root) - .setPositiveButton("Create") { _, _ -> - var name = binding.edittext.text.toString() - name = name.replace("\\.", "") - file.resolve(name).createNewFile() - lifeScope.launch { - treeView.refresh() - } - } - .setNegativeButton("Cancel") { dialog, _ -> - dialog.dismiss() - } - .show() - - } - - R.id.rename -> { - val binding = TreeviewContextActionDialogItemBinding.inflate(layoutInflater) - binding.edittext.setText(file.name) - MaterialAlertDialogBuilder(v.context) - .setTitle("Rename") - .setView(binding.root) - .setPositiveButton("Create") { _, _ -> - var name = binding.edittext.text.toString() - name = name.replace("\\.", "") - file.renameTo(file.parentFile!!.resolve(name)) - lifeScope.launch { - Log.d("ViewBinder", "Refresh treeview") - treeView.refresh(node = parentNode) - } - } - .setNegativeButton("Cancel") { dialog, _ -> - dialog.dismiss() - } - .show() - } - - R.id.delete -> { - MaterialAlertDialogBuilder(v.context) - .setTitle("Delete") - .setMessage("Are you sure you want to delete this file") - .setPositiveButton("Create") { _, _ -> - file.deleteRecursively() - lifeScope.launch { - Log.d("ViewBinder", "Refresh treeview") - treeView.refresh(node = parentNode) - } - } - .setNegativeButton("Cancel") { dialog, _ -> - dialog.dismiss() - } - .show() - } - - R.id.open_external -> { - openFileWithExternalApp(v.context, file) - } - } - true - } - popup.show() - } -} - -enum class ViewType { - DIRECTORY, FILE -} \ No newline at end of file diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/util/DownloadUtil.kt b/app/src/main/kotlin/org/cosmicide/rewrite/util/DownloadUtil.kt index 6a190194..08581775 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/util/DownloadUtil.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/util/DownloadUtil.kt @@ -19,7 +19,6 @@ class Download(val url: String, val callback: (percent: Int) -> Unit) { fun start(file: File) { val connection = URL(url).openConnection() as HttpURLConnection - connection.setRequestProperty("Accept-Encoding", "gzip") connection.requestMethod = "GET" totalBytes = connection.contentLengthLong diff --git a/app/src/main/kotlin/org/cosmicide/rewrite/util/ResourceUtil.kt b/app/src/main/kotlin/org/cosmicide/rewrite/util/ResourceUtil.kt index 3bb3b507..0af20ef0 100644 --- a/app/src/main/kotlin/org/cosmicide/rewrite/util/ResourceUtil.kt +++ b/app/src/main/kotlin/org/cosmicide/rewrite/util/ResourceUtil.kt @@ -16,7 +16,7 @@ package org.cosmicide.rewrite.util object ResourceUtil { - private val resources = arrayOf("classpath/android.jar", "rt.jar", "index.json") + val resources = arrayOf("classpath/android.jar", "rt.jar", "index.json") fun missingResources(): List { val missing = mutableListOf() diff --git a/app/src/main/res/layout/install_resources_fragment.xml b/app/src/main/res/layout/install_resources_fragment.xml index ebc833cf..1dd9481e 100644 --- a/app/src/main/res/layout/install_resources_fragment.xml +++ b/app/src/main/res/layout/install_resources_fragment.xml @@ -5,59 +5,66 @@ ~ You should have received a copy of the GNU General Public License along with Foobar. If not, see . --> - + android:background="?colorSurface"> - - - + android:orientation="vertical"> - + - + - + + - + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/title.txt b/fastlane/metadata/android/en-US/title.txt new file mode 100644 index 00000000..ead59ea2 --- /dev/null +++ b/fastlane/metadata/android/en-US/title.txt @@ -0,0 +1 @@ +Cosmic IDE \ No newline at end of file diff --git a/feature/java-completion/src/main/java/org/cosmicide/completion/java/parser/CompletionProvider.kt b/feature/java-completion/src/main/java/org/cosmicide/completion/java/parser/CompletionProvider.kt index 41ec4d68..6b9e0c03 100644 --- a/feature/java-completion/src/main/java/org/cosmicide/completion/java/parser/CompletionProvider.kt +++ b/feature/java-completion/src/main/java/org/cosmicide/completion/java/parser/CompletionProvider.kt @@ -72,8 +72,10 @@ class CompletionProvider { val environment = JavaCoreProjectEnvironment({ logger.info("JavaCoreProjectEnvironment disposed") }, JavaCoreApplicationEnvironment { logger.info("JavaCoreApplicationEnvironment disposed") }) - val symbolCacher = SymbolCacher(FileUtil.classpathDir.resolve("android.jar")).apply { - loadClassesFromJar() + val symbolCacher by lazy { + SymbolCacher(FileUtil.classpathDir.resolve("android.jar")).apply { + loadClassesFromJar() + } } val fileFactory by lazy { diff --git a/feature/project/src/main/java/org/cosmicide/project/Language.kt b/feature/project/src/main/java/org/cosmicide/project/Language.kt index f690c88a..ce9142f6 100644 --- a/feature/project/src/main/java/org/cosmicide/project/Language.kt +++ b/feature/project/src/main/java/org/cosmicide/project/Language.kt @@ -9,13 +9,14 @@ package org.cosmicide.project import org.cosmicide.project.templates.javaClass import org.cosmicide.project.templates.kotlinClass +import java.io.Serializable /** * A sealed class representing a programming language. * * @property extension the file extension associated with the language */ -sealed class Language(val extension: String) : java.io.Serializable { +sealed class Language(val extension: String) : Serializable { /** * Generates the content of a class file for the language. diff --git a/feature/project/src/main/java/org/cosmicide/project/Project.kt b/feature/project/src/main/java/org/cosmicide/project/Project.kt index ba07587d..10ba38cb 100644 --- a/feature/project/src/main/java/org/cosmicide/project/Project.kt +++ b/feature/project/src/main/java/org/cosmicide/project/Project.kt @@ -8,6 +8,7 @@ package org.cosmicide.project import java.io.File +import java.io.Serializable /** * Represents a project. @@ -18,7 +19,7 @@ import java.io.File data class Project( val root: File, val language: Language -) { +) : Serializable { /** * The name of the project, derived from the root directory.