RustAssistant/app/src/main/java/com/coldmint/rust/pro/EditActivity.kt

1420 lines
65 KiB
Kotlin
Raw Normal View History

2022-04-04 14:03:10 +00:00
package com.coldmint.rust.pro
import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
2022-08-19 06:51:28 +00:00
import android.graphics.drawable.Drawable
2022-04-04 14:03:10 +00:00
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.provider.MediaStore
import android.view.*
import android.widget.PopupMenu
import android.widget.Toast
2022-08-22 07:32:10 +00:00
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
2022-04-04 14:03:10 +00:00
import androidx.core.view.GravityCompat
import androidx.core.view.isVisible
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.WhichButton
import com.afollestad.materialdialogs.actions.setActionButtonEnabled
2022-04-24 14:20:26 +00:00
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
2022-04-04 14:03:10 +00:00
import com.afollestad.materialdialogs.input.getInputField
import com.afollestad.materialdialogs.input.input
2022-08-19 06:51:28 +00:00
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
2022-04-04 14:03:10 +00:00
import com.coldmint.rust.core.ModClass
import com.coldmint.rust.core.database.code.CodeDataBase
import com.coldmint.rust.core.database.file.FileDataBase
import com.coldmint.rust.core.tool.AppOperator
2022-04-28 10:30:45 +00:00
import com.coldmint.rust.core.tool.DebugHelper
2022-04-04 14:03:10 +00:00
import com.coldmint.rust.core.tool.FileOperator
2022-04-28 10:30:45 +00:00
import com.coldmint.rust.core.web.ServerConfiguration
2022-04-04 14:03:10 +00:00
import com.coldmint.rust.pro.adapters.FileAdapter
import com.coldmint.rust.pro.base.BaseActivity
import com.coldmint.rust.pro.databinding.ActivityEditBinding
import com.coldmint.rust.pro.databinding.EditStartBinding
import com.coldmint.rust.pro.edit.CodeToolAdapter
import com.coldmint.rust.pro.edit.RustCompletionAdapter
import com.coldmint.rust.pro.edit.RustLanguage
import com.coldmint.rust.pro.interfaces.BookmarkListener
import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.CompletionItemConverter
import com.coldmint.rust.pro.tool.GlobalMethod
import com.coldmint.rust.pro.viewmodel.EditStartViewModel
import com.coldmint.rust.pro.viewmodel.EditViewModel
2022-07-04 14:39:28 +00:00
import com.google.android.material.dialog.MaterialAlertDialogBuilder
2022-04-04 14:03:10 +00:00
import com.google.android.material.snackbar.Snackbar
2022-08-17 01:25:20 +00:00
import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
2022-08-19 06:51:28 +00:00
import jp.wasabeef.glide.transformations.BlurTransformation
2022-04-04 14:03:10 +00:00
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
class EditActivity : BaseActivity<ActivityEditBinding>() {
private val viewModel by lazy {
ViewModelProvider(this).get(EditViewModel::class.java)
}
2022-08-22 07:32:10 +00:00
private lateinit var turretCoordinateResults: ActivityResultLauncher<Intent>
2022-04-04 14:03:10 +00:00
private lateinit var rustLanguage: RustLanguage
private var fileAdapter: FileAdapter? = null
//是第一次启动嘛
var isFirst = true
/**
* 编辑器左侧视图
*/
private val editStartBinding: EditStartBinding by lazy {
EditStartBinding.bind(viewBinding.root)
}
/**
* 编辑器左侧视图模型
*/
private val editStartViewModel: EditStartViewModel by lazy {
ViewModelProvider(this).get(EditStartViewModel::class.java)
}
2022-08-26 13:51:15 +00:00
// /**
// * 编辑器右侧视图模型
// */
// private val editEndViewModel: EditEndViewModel by lazy {
// ViewModelProvider(this).get(EditEndViewModel::class.java)
// }
2022-04-04 14:03:10 +00:00
2022-08-26 13:51:15 +00:00
// /**
// * 编辑器右侧视图
// */
// private val editEndBinding: EditEndBinding by lazy {
// EditEndBinding.bind(viewBinding.root)
// }
2022-04-04 14:03:10 +00:00
2022-07-04 14:39:28 +00:00
fun showRenewalTip() {
val debugKey = "续费提示"
2022-08-14 02:43:53 +00:00
val account = AppSettings.getValue(AppSettings.Setting.Account, "")
val time = AppSettings.getValue(AppSettings.Setting.ExpirationTime, 0.toLong())
2022-04-28 10:30:45 +00:00
if (time == 0.toLong() || account.isBlank()) {
2022-07-04 14:39:28 +00:00
DebugHelper.printLog(debugKey, "没有账号或续费信息,关闭界面。")
Toast.makeText(this, "请先登录", Toast.LENGTH_SHORT).show()
finish()
2022-04-28 10:30:45 +00:00
} else {
val stringTime = ServerConfiguration.toStringTime(time)
if (stringTime == ServerConfiguration.ForeverTime) {
2022-07-04 14:39:28 +00:00
DebugHelper.printLog(debugKey, "永久用户无需处理续费提示。")
2022-04-28 10:30:45 +00:00
} else {
2022-07-04 14:39:28 +00:00
val difference = time - System.currentTimeMillis()
if (difference < 0) {
//已经过期
DebugHelper.printLog(debugKey, "此用户的助手已经过期。")
MaterialAlertDialogBuilder(this).setTitle(R.string.activation_app)
.setMessage(
R.string.activation_app_tip
).setPositiveButton(R.string.activate) { i, i2 ->
finish()
val intent = Intent(this, ActivateActivity::class.java)
startActivity(intent)
}.setNegativeButton(R.string.dialog_cancel) { i, i2 ->
finish()
}.setCancelable(false).show()
} else if (difference < 604800000) {
//如果在7天内到期
val day = difference / 86400000 + 1
DebugHelper.printLog(
debugKey,
"显示续费提醒(" + difference + "/86400000)" + day + "天。"
)
MaterialAlertDialogBuilder(this).setTitle(R.string.renewal_tip_title)
.setMessage(
String.format(
getString(R.string.renewal_tip_msg),
account,
day
)
).setPositiveButton(R.string.renewal) { i, i2 ->
val intent = Intent(this, ActivateActivity::class.java)
startActivity(intent)
}.setNegativeButton(R.string.dialog_cancel) { i, i2 ->
}.setCancelable(false).show()
} else {
DebugHelper.printLog(debugKey, "还剩余7天以上无需提示。")
2022-04-28 10:30:45 +00:00
}
}
}
}
2022-04-04 14:03:10 +00:00
/**
* 加载主要的观察者
*/
fun loadMainObserve() {
viewModel.needSaveLiveData.observe(this) {
if (it) {
MaterialDialog(this).show {
title(R.string.edit_function).message(R.string.text_changed)
.positiveButton(R.string.edit_function) {
viewModel.saveAllFile(
viewBinding.tabLayout.selectedTabPosition,
viewBinding.codeEditor.text.toString()
) {
viewModel.needCheckAutoSave = false
finish()
}
}.negativeButton(R.string.dialog_cancel)
.neutralButton(R.string.not_save_exit).neutralButton {
MaterialDialog(this@EditActivity).show {
title(R.string.not_save_exit).message(R.string.not_save_exit_tip)
.negativeButton(R.string.dialog_cancel)
.positiveButton(R.string.dialog_ok) {
viewModel.needCheckAutoSave = false
finish()
}.cancelable(false)
}
}.cancelable(false)
}
}
}
viewModel.englishModeLiveData.observe(this) {
rustLanguage.setEnglish(it)
}
2022-08-17 01:25:20 +00:00
// viewBinding.codeEditor.setItemListener { i, completionItem ->
// viewModel.executorService.submit {
// val extrasData = completionItem.extrasData
// if (extrasData != null) {
// val listData = extrasData.getString("list")
// if (listData != null) {
// val lineParser = LineParser(listData)
// lineParser.symbol = ","
// val list = ArrayList<CompletionItem>()
// lineParser.analyse { lineNum, lineData, isEnd ->
// val temCodeInfo =
// CodeDataBase.getInstance(this).getCodeDao().findCodeByCode(lineData)
// if (temCodeInfo == null) {
//
// } else {
2022-08-19 06:51:28 +00:00
// val CompletionItemConverter = CompletionItemConverter.instance
// CompletionItemConverter.init(this)
2022-08-17 01:25:20 +00:00
// list.add(
2022-08-19 06:51:28 +00:00
// CompletionItemConverter.codeInfoToCompletionItem(
2022-08-17 01:25:20 +00:00
// temCodeInfo
// )
// )
// }
// true
// }
// if (list.isNotEmpty()) {
// runOnUiThread {
// viewBinding.codeEditor.createEditorAutoCompleteList(list)
// }
// }
// }
// }
// }
// true
// }
2022-04-04 14:03:10 +00:00
viewModel.openedSourceFileListLiveData.observe(this) {
viewBinding.tabLayout.removeAllTabs()
2022-08-26 13:51:15 +00:00
viewBinding.tabLayout.isVisible = true
2022-04-04 14:03:10 +00:00
it.forEach {
val openedSourceFile = it
val tab = viewBinding.tabLayout.newTab()
tab.text = if (openedSourceFile.isNeedSave()) {
String.format(
getString(R.string.need_save),
openedSourceFile.file.name
)
} else {
openedSourceFile.file.name
}
tab.view.setOnClickListener { view ->
val path = it.file.absolutePath
if (viewModel.getNowOpenFilePath() != path) {
//更新Tab文本
val selectedTabPosition = viewBinding.tabLayout.selectedTabPosition
val oldTab = viewBinding.tabLayout.getTabAt(selectedTabPosition)
val oldOpenedSourceFile =
viewModel.openedSourceFileListLiveData.getOpenedSourceFile(
selectedTabPosition
)
val isChanged = oldOpenedSourceFile
.isChanged(viewBinding.codeEditor.text.toString())
if (isChanged) {
oldTab?.text = String.format(
getString(R.string.need_save),
oldOpenedSourceFile.file.name
)
}
viewModel.setNowOpenFilePath(path)
viewModel.codeLiveData.value = openedSourceFile.getEditText()
}
}
tab.view.setOnLongClickListener {
val popupMenu = PopupMenu(this@EditActivity, it)
popupMenu.menu.add(R.string.open_directory_of_file)
if (viewModel.openedSourceFileListLiveData.value.size > 1) {
popupMenu.menu.add(R.string.close)
}
popupMenu.setOnMenuItemClickListener {
when (it.title.toString()) {
getString(R.string.close) -> {
if (openedSourceFile.isNeedSave()) {
MaterialDialog(this).show {
title(R.string.edit_function).message(
R.string.text_changed
).positiveButton(R.string.edit_function).positiveButton {
viewModel.saveOneFile(openedSourceFile)
viewModel.closeFile(openedSourceFile)
}
.negativeButton(R.string.dialog_cancel).negativeButton {
viewModel.closeFile(openedSourceFile)
}
}
} else {
viewModel.closeFile(openedSourceFile)
}
}
getString(R.string.open_directory_of_file) -> {
editStartViewModel.loadPathLiveData.value =
FileOperator.getSuperDirectory(openedSourceFile.file)
viewBinding.editDrawerlayout.openDrawer(GravityCompat.START)
}
}
false
}
popupMenu.show()
true
}
viewBinding.tabLayout.addTab(tab)
if (openedSourceFile.file.absolutePath == viewModel.getNowOpenFilePath()) {
viewBinding.tabLayout.selectTab(tab)
viewModel.codeLiveData.value = openedSourceFile.getEditText()
}
}
}
viewModel.codeLiveData.observe(this) {
2022-08-17 01:25:20 +00:00
// rustLanguage.autoCompleteProvider.setSourceFolder(
// FileOperator.getSuperDirectory(
// viewModel.getNowOpenFilePath()
// )
// )
2022-04-04 14:03:10 +00:00
//初始化加载路径数据(仅在第一次有效)
editStartViewModel.initLoadPathLiveData(viewModel.getNowOpenFilePath())
viewBinding.myProgressBar.isVisible = false
viewBinding.codeEditor.isVisible = true
viewBinding.codeEditor.setText(it)
}
viewModel.loadingLiveData.observe(
this
) {
if (it) {
viewBinding.myProgressBar.isVisible = true
viewBinding.codeEditor.isVisible = false
} else {
viewBinding.myProgressBar.isVisible = false
viewBinding.codeEditor.isVisible = true
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
when (requestCode) {
//在找不到资源选择文件
1 -> {
val path = data?.getStringExtra("File") ?: return
val file = File(path)
val targetFile = viewModel.targetFile
if (targetFile != null) {
val targetType = FileOperator.getFileType(targetFile)
val nowType = FileOperator.getFileType(file)
if (targetType == nowType) {
val copyResult = FileOperator.copyFile(file, targetFile)
if (!copyResult) {
Snackbar.make(
viewBinding.recyclerview,
getText(R.string.copy_file_error),
Snackbar.LENGTH_SHORT
).show()
} else {
viewModel.addFileInDataBase(targetFile)
}
} else {
Snackbar.make(
viewBinding.recyclerview,
getText(R.string.bad_file_type),
Snackbar.LENGTH_SHORT
).show()
}
}
}
2 -> {
//新建源文件
val path = data?.getStringExtra("File") ?: return
val file = File(path)
viewModel.openFile(path)
viewModel.addFileInDataBase(file)
editStartViewModel.loadPathLiveData.value = FileOperator.getSuperDirectory(file)
}
3, 4 -> {
//左侧选择文件(4为相册选择)
val path = if (requestCode == 3) {
data?.getStringExtra("File")
} else {
FileOperator.parsePicturePath(this, data)
}
if (path == null) {
return
}
val file = File(path)
val copyFile = File(editStartViewModel.loadPathLiveData.value + "/" + file.name)
val copyResult =
FileOperator.copyFile(file, copyFile)
if (!copyResult) {
Snackbar.make(
viewBinding.recyclerview,
getText(R.string.copy_file_error),
Snackbar.LENGTH_SHORT
).show()
} else {
viewModel.addFileInDataBase(copyFile)
editStartViewModel.reloadList()
}
}
}
}
}
/**
* 初始化侧滑视图
*/
private fun initDrawerLayout() {
viewBinding.editDrawerlayout.addDrawerListener(object : DrawerLayout.DrawerListener {
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}
override fun onDrawerOpened(drawerView: View) {
}
override fun onDrawerClosed(drawerView: View) {
viewBinding.editDrawerlayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
}
override fun onDrawerStateChanged(newState: Int) {
}
})
}
2022-08-26 13:51:15 +00:00
// /**
// * 加载右侧观察者
// */
// fun loadEndObserve() {
// editEndViewModel.loadStateLiveData.observe(this) {
// editEndBinding.imageview.isVisible = it
// editEndBinding.textview.isVisible = it
// editEndBinding.logView.isVisible = !it
// }
//
// editEndViewModel.analysisResultLiveData.observe(this) {
// val adapter = CompileLogAdapter(this, it.toMutableList())
// editEndBinding.logView.adapter = adapter
// }
// }
//
// /**
// * 初始化右侧视图
// */
// fun initEndView() {
// editEndBinding.logView.layoutManager = LinearLayoutManager(this)
// }
2022-04-04 14:03:10 +00:00
//当用户切换到其他应用界面时
override fun onPause() {
if (viewModel.needCheckAutoSave) {
2022-08-14 02:43:53 +00:00
val need = AppSettings.getValue(AppSettings.Setting.AutoSave, true)
2022-04-04 14:03:10 +00:00
if (need) {
viewModel.saveAllFile(
viewBinding.tabLayout.selectedTabPosition,
2022-08-10 09:27:38 +00:00
viewBinding.codeEditor.text.toString()
) {
Toast.makeText(this, R.string.auto_save_toast, Toast.LENGTH_SHORT).show()
}
2022-04-04 14:03:10 +00:00
}
}
super.onPause()
}
override fun onResume() {
super.onResume()
if (isFirst) {
isFirst = false
} else {
viewModel.needCheckAutoSave = true
}
}
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
if (canUseView) {
setReturnButton()
loadStartObserve()
2022-08-26 13:51:15 +00:00
// loadEndObserve()
2022-04-04 14:03:10 +00:00
initDrawerLayout()
initCodeToolbar()
2022-08-17 01:25:20 +00:00
initCodeEditor()
2022-04-04 14:03:10 +00:00
initStartView()
2022-08-26 13:51:15 +00:00
// initEndView()
2022-07-04 14:39:28 +00:00
showRenewalTip()
2022-08-19 06:51:28 +00:00
loadCustomStyle()
2022-08-22 07:32:10 +00:00
turretCoordinateResults =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
viewModel.reloadCode()
}
2022-04-04 14:03:10 +00:00
} else {
2022-08-22 07:32:10 +00:00
title = getString(R.string.mod_action1)
2022-04-04 14:03:10 +00:00
val thisIntent = intent
val bundle = thisIntent.getBundleExtra("data")
if (bundle == null) {
showError("请传入bundle")
return
}
val path = bundle.getString("path")
if (path == null) {
showError("请传入路径")
return
}
val modPath = bundle.getString("modPath")
if (modPath == null) {
showError("请传入模组路径")
return
}
viewModel.modClass = ModClass(File(modPath))
loadMainObserve()
viewModel.loadData()
viewModel.openFile(path)
}
}
private fun initStartView() {
editStartBinding.fileList.layoutManager = LinearLayoutManager(this)
editStartBinding.fab.setOnClickListener {
val popupMenu = PopupMenu(this@EditActivity, editStartBinding.fab)
if (fileAdapter != null) {
val selectPath = fileAdapter!!.selectPath
if (selectPath != null) {
if (fileAdapter!!.isCopyFile && !viewModel.processFiles) {
popupMenu.menu.add(R.string.copy_to_this)
} else {
popupMenu.menu.add(R.string.cut_to_this)
}
}
}
popupMenu.menu.add(R.string.create_unit)
popupMenu.menu.add(R.string.create_folder)
popupMenu.menu.add(R.string.select_file)
popupMenu.menu.add(R.string.select_the_image_in_the_album)
popupMenu.setOnMenuItemClickListener { item ->
val title = item.title
val handler = Handler(Looper.getMainLooper())
when (title) {
getText(R.string.create_unit) -> {
viewModel.needCheckAutoSave = false
val intent = Intent(this@EditActivity, CreateUnitActivity::class.java)
val bundle = Bundle()
bundle.putString("modPath", viewModel.modClass?.modFile?.absolutePath)
bundle.putString("createPath", editStartViewModel.loadPathLiveData.value)
intent.putExtra("data", bundle)
startActivityForResult(intent, 2)
}
getString(R.string.select_the_image_in_the_album) -> {
this.startActivityForResult(
Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
), 4
)
}
getText(R.string.select_file) -> {
viewModel.needCheckAutoSave = false
val bundle = Bundle()
val intent = Intent(this@EditActivity, FileManagerActivity::class.java)
bundle.putString("type", "selectFile")
//bundle.putString("path", modClass.getModFile().getAbsolutePath());
intent.putExtra("data", bundle)
startActivityForResult(intent, 3)
}
getText(R.string.create_folder) -> {
MaterialDialog(this).show {
title(R.string.create_folder)
input(maxLength = 255, waitForPositiveButton = false) { dialog, text ->
if (text.length in 1..255) {
dialog.setActionButtonEnabled(WhichButton.POSITIVE, true)
}
}.positiveButton(R.string.dialog_ok, null) { dialog ->
val string = dialog.getInputField().text.toString()
if (!string.isEmpty()) {
val file =
File(editStartViewModel.loadPathLiveData.value + "/" + string)
if (file.exists()) {
Toast.makeText(
this@EditActivity,
R.string.folder_error,
Toast.LENGTH_SHORT
).show()
} else {
file.mkdirs()
editStartViewModel.reloadList()
}
}
}.negativeButton(R.string.dialog_close)
}
}
getText(R.string.copy_to_this) -> {
viewModel.executorService.submit {
viewModel.processFiles = true
val selectPath = fileAdapter?.selectPath ?: return@submit
val nowPath = editStartViewModel.loadPathLiveData.value
val oldFile = File(selectPath)
val newFile = File(nowPath + "/" + oldFile.name)
if (FileOperator.copyFiles(oldFile, newFile)) {
handler.post {
fileAdapter?.cleanSelectPath()
viewModel.processFiles = false
editStartViewModel.reloadList()
}
} else {
handler.post {
Toast.makeText(
this@EditActivity,
getText(R.string.copy_failed),
Toast.LENGTH_SHORT
).show()
viewModel.processFiles = false
}
}
}
}
getText(R.string.cut_to_this) -> {
viewModel.executorService.submit {
viewModel.processFiles = true
val selectPath = fileAdapter?.selectPath ?: return@submit
val nowPath = editStartViewModel.loadPathLiveData.value
val oldFile = File(selectPath)
val newFile = File(nowPath + "/" + oldFile.name)
if (FileOperator.removeFiles(oldFile, newFile)) {
handler.post {
fileAdapter?.cleanSelectPath()
editStartViewModel.reloadList()
viewModel.processFiles = false
}
} else {
handler.post {
Toast.makeText(
this@EditActivity,
getText(R.string.cut_failed),
Toast.LENGTH_SHORT
).show()
viewModel.processFiles = false
}
}
}
}
}
false
}
popupMenu.show()
}
}
/**
* 加载左侧观察者
*/
private fun loadStartObserve() {
//加载状态改变
editStartViewModel.loadStatusLiveData.observe(this) {
editStartBinding.fab.isVisible = it
editStartBinding.unableOpenView.isVisible = !it
editStartBinding.fileList.isVisible = it
}
//文件列表加载的路径改变
editStartViewModel.loadPathLiveData.observe(this) {
editStartViewModel.loadList(it)
}
//文件列表的数据改变
editStartViewModel.fileListLiveData.observe(this) {
val finalFileAdapter: FileAdapter =
if (fileAdapter == null) {
fileAdapter = FileAdapter(this, it)
fileAdapter!!
} else {
fileAdapter?.setNewDataList(it)
fileAdapter!!
}
finalFileAdapter.setItemEvent { i, fileItemBinding, viewHolder, file ->
fileItemBinding.contentView.setOnClickListener {
if (file == null) {
editStartViewModel.loadPathLiveData.value = FileOperator.getSuperDirectory(
editStartViewModel.loadPathLiveData.value ?: ""
)
} else {
if (file.isDirectory) {
editStartViewModel.loadPathLiveData.value = file.absolutePath
} else {
viewModel.openFile(file.absolutePath)
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.START)
}
}
}
fileItemBinding.more.setOnClickListener {
if (file == null) {
return@setOnClickListener
}
val popupMenu = PopupMenu(this@EditActivity, it)
val cutBoardMenu = popupMenu.menu.addSubMenu(R.string.cut_board_operation)
val fileMenu = popupMenu.menu.addSubMenu(R.string.file_operation)
2022-08-10 09:27:38 +00:00
val bookmarksMenu = popupMenu.menu.addSubMenu(R.string.mine_bookmarks)
2022-04-04 14:03:10 +00:00
cutBoardMenu.add(R.string.copy_file_name)
cutBoardMenu.add(R.string.copy_file_path)
cutBoardMenu.add(R.string.copy_file_absolutely_path)
fileMenu.add(R.string.copy)
fileMenu.add(R.string.cut_off)
2022-08-10 09:27:38 +00:00
fileMenu.add(R.string.rename)
2022-04-04 14:03:10 +00:00
fileMenu.add(R.string.del_mod)
val bookmarkManager = editStartViewModel.bookmarkManager
if (bookmarkManager.contains(file)) {
bookmarksMenu.add(R.string.remove_bookmark)
} else {
bookmarksMenu.add(R.string.add_bookmark)
}
bookmarksMenu.add(R.string.bookmark_manager)
val bookmarkContent: SubMenu? =
if (bookmarkManager.size > 0) {
bookmarksMenu.addSubMenu(R.string.jump_a_bookmark)
} else {
null
}
//哈希表映射(名称,路径)
val bookmarkMap = HashMap<String, String?>()
bookmarkManager.fromList(object : BookmarkListener {
override fun find(path: String, name: String) {
bookmarkMap[name] = path
bookmarkContent!!.add(name)
}
})
popupMenu.setOnMenuItemClickListener(PopupMenu.OnMenuItemClickListener { item ->
val title = item.title
if (title == getText(R.string.copy_file_name)) {
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.START)
val name = file.name
GlobalMethod.copyText(
this@EditActivity,
name,
viewBinding.recyclerview
)
} else if (title == getText(R.string.copy_file_path)) {
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.START)
val path = file.absolutePath
GlobalMethod.copyText(
this@EditActivity,
path,
viewBinding.recyclerview
)
} else if (title == getText(R.string.copy_file_absolutely_path)) {
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.START)
if (viewModel.modClass == null) {
Snackbar.make(
viewBinding.recyclerview,
getText(R.string.copy_file_absolutely_path_error),
Snackbar.LENGTH_SHORT
).show()
return@OnMenuItemClickListener true
}
var relative =
FileOperator.getRelativePath(
file,
viewModel.modClass!!.modFile
)
if (relative == null || relative.isEmpty()) {
Snackbar.make(
viewBinding.recyclerview,
getText(R.string.copy_file_absolutely_path_error),
Snackbar.LENGTH_SHORT
).show()
} else {
relative = "ROOT:" + relative.substring(1)
GlobalMethod.copyText(
this@EditActivity,
relative,
viewBinding.recyclerview
)
}
} else if (title == getText(R.string.del_mod)) {
val absolutePath = file.absolutePath
var canDel = true
if (viewModel.openedSourceFileListLiveData.value.isNotEmpty()) {
for (openedFile in viewModel.openedSourceFileListLiveData.value) {
val path = openedFile.file.absolutePath
if (path.startsWith(absolutePath)) {
canDel = false
}
}
}
if (!canDel) {
Snackbar.make(
viewBinding.recyclerview,
R.string.unable_del,
Snackbar.LENGTH_SHORT
).show()
return@OnMenuItemClickListener false
}
if (FileOperator.delete_files(file)) {
viewModel.removeFileInDataBase(file)
editStartViewModel.reloadList()
}
} else if (title == getText(R.string.copy)) {
fileAdapter?.setSelectPath(file.absolutePath, true)
} else if (title == getText(R.string.cut_off)) {
val absolutePath = file.absolutePath
var canCut = true
if (viewModel.openedSourceFileListLiveData.value.isNotEmpty()) {
for (openedFile in viewModel.openedSourceFileListLiveData.value) {
val path = openedFile.file.absolutePath
if (path.startsWith(absolutePath)) {
canCut = false
}
}
}
if (!canCut) {
Snackbar.make(
viewBinding.recyclerview,
R.string.unable_cut,
Snackbar.LENGTH_SHORT
).show()
return@OnMenuItemClickListener false
}
fileAdapter?.setSelectPath(file.absolutePath, false)
2022-08-10 09:27:38 +00:00
} else if (title == getText(R.string.rename)) {
2022-04-04 14:03:10 +00:00
val absolutePath = file.absolutePath
var canRename = true
if (viewModel.openedSourceFileListLiveData.value.isNotEmpty()) {
for (openedFile in viewModel.openedSourceFileListLiveData.value) {
val path = openedFile.file.absolutePath
if (path.startsWith(absolutePath)) {
canRename = false
}
}
}
if (!canRename) {
Snackbar.make(
viewBinding.recyclerview,
R.string.unable_rename,
Snackbar.LENGTH_SHORT
).show()
return@OnMenuItemClickListener false
}
val oldName = file.name
MaterialDialog(this@EditActivity).show {
2022-08-10 09:27:38 +00:00
title(R.string.rename)
2022-04-04 14:03:10 +00:00
input(
maxLength = 255,
waitForPositiveButton = false, prefill = oldName
) { dialog, text ->
if (text.length in 1..255) {
dialog.setActionButtonEnabled(
WhichButton.POSITIVE,
true
)
}
}.positiveButton(R.string.dialog_ok, null) { dialog ->
val newName = dialog.getInputField().text.toString()
if (newName != oldName) {
val reNameFile =
File(editStartViewModel.loadPathLiveData.value + "/" + newName)
file.renameTo(reNameFile)
editStartViewModel.reloadList()
}
}.negativeButton(R.string.dialog_close)
}
} else if (title == getString(R.string.remove_bookmark)) {
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.START)
val removeBookmark =
bookmarkManager.removeBookmark(file.absolutePath)
if (removeBookmark) {
Snackbar.make(
viewBinding.recyclerview,
R.string.remove_bookmark_success,
Snackbar.LENGTH_SHORT
).setAction(R.string.symbol10) {
bookmarkManager.addBookmark(
file.absolutePath,
FileOperator.getPrefixName(file)
)
viewBinding.editDrawerlayout.openDrawer(GravityCompat.START)
}.show()
} else {
Snackbar.make(
viewBinding.recyclerview,
R.string.remove_bookmark_fail,
Snackbar.LENGTH_SHORT
).show()
}
} else if (title == getString(R.string.add_bookmark)) {
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.START)
val addBookmark = bookmarkManager.addBookmark(
file.absolutePath,
FileOperator.getPrefixName(file)
)
if (addBookmark) {
Snackbar.make(
viewBinding.recyclerview,
R.string.add_bookmark_success,
Snackbar.LENGTH_SHORT
).show()
} else {
Snackbar.make(
viewBinding.recyclerview,
R.string.add_bookmark_fail,
Snackbar.LENGTH_SHORT
).show()
}
} else if (title == getString(R.string.bookmark_manager)) {
bookmarkManager.save()
viewModel.needCheckAutoSave = false
startActivity(
Intent(
this@EditActivity,
BookmarkManagerActivity::class.java
)
)
} else {
if (bookmarkMap.containsKey(title)) {
val newFile = File(bookmarkMap[title])
if (newFile.exists()) {
if (newFile.isDirectory) {
editStartViewModel.loadList(newFile.absolutePath)
} else {
viewModel.openFile(newFile.absolutePath)
}
} else {
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.START)
Snackbar.make(
viewBinding.recyclerview,
R.string.bookmark_jump_failed,
Snackbar.LENGTH_SHORT
).show()
}
}
}
false
})
popupMenu.show()
}
}
editStartBinding.fileList.adapter = fileAdapter
}
}
/**
* 初始化代码工具栏
*/
fun initCodeToolbar() {
val items = ArrayList<String>()
items.add(getString(R.string.symbol1))
items.add(getString(R.string.symbol9))
items.add(getString(R.string.code_tip))
items.add(getString(R.string.code_table))
// items.add(getString(R.string.code_language_on))
items.add(getString(R.string.symbol11))
2022-08-14 02:43:53 +00:00
val customSymbol = AppSettings.getValue(
2022-04-04 14:03:10 +00:00
AppSettings.Setting.CustomSymbol,
"[],:='*_$%@#{}()"
)
val chars = customSymbol.toCharArray()
if (chars.isNotEmpty()) {
for (c in chars) {
items.add(c.toString())
}
}
val codeToolAdapter = CodeToolAdapter(this, items)
codeToolAdapter.setItemEvent { i, codeToolItemBinding, viewHolder, item ->
codeToolItemBinding.root.setOnClickListener {
if (item == getString(R.string.symbol11)) {
2022-08-19 06:51:28 +00:00
GlobalMethod.showColorPickerDialog(this) {
viewBinding.codeEditor.insertText(it, it.length)
}
2022-04-04 14:03:10 +00:00
} else if (item == getString(R.string.code_table)) {
viewModel.needCheckAutoSave = false
startActivity(Intent(this@EditActivity, CodeTableActivity::class.java))
} else if (item == getString(R.string.symbol1)) {
//关闭手势滑动
viewBinding.editDrawerlayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
openDrawer(GravityCompat.START)
} else if (item == getString(R.string.symbol9)) {
if (!viewBinding.codeEditor.formatCodeAsync()) {
Snackbar.make(
viewBinding.codeEditor,
R.string.format_failed,
Snackbar.LENGTH_SHORT
).show()
}
} else if (item == getString(R.string.code_tip)) {
2022-08-17 01:25:20 +00:00
// viewModel.executorService.submit {
// try {
// val list = ArrayList<CompletionItem>()
// //如果不包含:搜索键
// val lineNumber = viewBinding.codeEditor.selectedLineNumber
// val navigationList =
// viewBinding.codeEditor.textAnalyzeResult.navigation
// var section: String? = null
// if (navigationList != null && navigationList.isNotEmpty()) {
// for (navigation in navigationList) {
// if (navigation.line > lineNumber) {
// break
// } else {
// section = navigation.label
// }
// }
// }
// //如果不在任何节内
// if (section == null) {
// runOnUiThread {
// runOnUiThread {
// Snackbar.make(
// viewBinding.recyclerview,
// this.getString(R.string.code_tip_error1),
// Snackbar.LENGTH_SHORT
// ).show()
// }
// }
// return@submit
// }
// val trueSection =
// rustLanguage.autoCompleteProvider.getSectionType(section)
// val codeDataBase = CodeDataBase.getInstance(this)
// val lineData =
// viewBinding.codeEditor.text.getLine(lineNumber).toString()
// if (lineData.startsWith('[') && lineData.endsWith(']')) {
// runOnUiThread {
// Snackbar.make(
// viewBinding.recyclerview,
// R.string.code_tip_error2,
// Snackbar.LENGTH_SHORT
// ).show()
// }
// return@submit
// }
// val offset = lineData.indexOf(':')
// if (offset > -1) {
// //如果包含:
// runOnUiThread {
// Snackbar.make(
// viewBinding.recyclerview,
// this.getString(R.string.can_not_tip_value),
// Snackbar.LENGTH_SHORT
// ).show()
// }
// return@submit
// } else {
// val codeInfoList = if (lineData.isBlank()) {
// codeDataBase.getCodeDao().findCodeBySection(trueSection)
// } else {
// val number = AppSettings.getValue(
// AppSettings.Setting.IdentifiersPromptNumber,
// 40
// )
// codeDataBase.getCodeDao()
// .findCodeByKeyFromSection(lineData, trueSection, number)
// }
// if (codeInfoList != null && codeInfoList.isNotEmpty()) {
2022-08-19 06:51:28 +00:00
// val CompletionItemConverter =
2022-08-17 01:25:20 +00:00
// CompletionItemConverter.instance.init(this)
// codeInfoList.forEach {
// list.add(
2022-08-19 06:51:28 +00:00
// CompletionItemConverter.codeInfoToCompletionItem(
2022-08-17 01:25:20 +00:00
// it
// )
// )
// }
// } else {
// runOnUiThread {
// Snackbar.make(
// viewBinding.recyclerview,
// String.format(
// this.getString(R.string.code_tip_error3),
// SourceFile.getSectionType(section)
// ),
// Snackbar.LENGTH_SHORT
// ).show()
// }
// }
// }
// runOnUiThread {
// viewBinding.codeEditor.createEditorAutoCompleteList(list)
// }
// } catch (e: Exception) {
// e.printStackTrace()
// }
//
// }
2022-04-04 14:03:10 +00:00
} else {
try {
2022-08-17 01:25:20 +00:00
viewBinding.codeEditor.insertText(item, item.length)
2022-04-04 14:03:10 +00:00
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
val linearLayoutManager = LinearLayoutManager(this)
linearLayoutManager.orientation = RecyclerView.HORIZONTAL
viewBinding.recyclerview.isVisible = true
viewBinding.recyclerview.layoutManager = linearLayoutManager
viewBinding.recyclerview.adapter = codeToolAdapter
}
//初始化编辑器
fun initCodeEditor() {
//CodEditor初始化
viewBinding.codeEditor.isWordwrap = true
2022-08-14 02:43:53 +00:00
val useFont = AppSettings.getValue(AppSettings.Setting.UseJetBrainsMonoFont, true)
2022-04-04 14:03:10 +00:00
if (useFont) {
viewBinding.codeEditor.typefaceText = Typeface.createFromAsset(
assets,
"JetBrainsMono-Regular.ttf"
)
}
2022-08-19 06:51:28 +00:00
rustLanguage = RustLanguage()
2022-04-04 14:03:10 +00:00
rustLanguage.setCodeDataBase(CodeDataBase.getInstance(this))
rustLanguage.setFileDataBase(
FileDataBase.getInstance(
this,
viewModel.modClass!!.modName
)
)
rustLanguage.setCodeEditor(viewBinding.codeEditor)
2022-08-19 06:51:28 +00:00
viewBinding.codeEditor.setAutoCompletionItemAdapter(RustCompletionAdapter())
viewBinding.codeEditor.isVerticalScrollBarEnabled = false
val path = viewModel.modClass?.modFile?.absolutePath ?: ""
CompletionItemConverter.configurationFileConversion(
path,
"ROOT",
path
)
viewBinding.codeEditor.setEditorLanguage(rustLanguage)
}
/**
* 加载自动
*/
fun loadCustomStyle() {
val key = "加载自定义编辑框样式"
2022-04-04 14:03:10 +00:00
val editorColorScheme = EditorColorScheme()
2022-08-19 06:51:28 +00:00
val codeEditBackGroundEnable =
AppSettings.getValue(AppSettings.Setting.CodeEditBackGroundEnable, false)
val backgroundColor =
if (codeEditBackGroundEnable) {
DebugHelper.printLog(key, "启用背景图像,设置背景为透明。")
Color.TRANSPARENT
} else {
DebugHelper.printLog(key, "未启用背景图像,设置背景为窗口颜色。")
GlobalMethod.getThemeColor(this, android.R.attr.windowBackground)
}
2022-08-26 13:51:15 +00:00
val darkMode = AppSettings.getValue(AppSettings.Setting.NightMode, false)
if (darkMode) {
//代码(可识别的关键字)
editorColorScheme.setColor(
EditorColorScheme.KEYWORD,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.KeywordColorDark, ""))
)
//默认文本
editorColorScheme.setColor(
EditorColorScheme.TEXT_NORMAL,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.TextColorDark, ""))
)
//注释
editorColorScheme.setColor(
EditorColorScheme.COMMENT,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.AnnotationColorDark, ""))
)
//节
editorColorScheme.setColor(
EditorColorScheme.FUNCTION_NAME,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.SectionColorDark, ""))
)
} else {
//代码(可识别的关键字)
editorColorScheme.setColor(
EditorColorScheme.KEYWORD,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.KeywordColor, ""))
)
//默认文本
editorColorScheme.setColor(
EditorColorScheme.TEXT_NORMAL,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.TextColor, ""))
)
//注释
editorColorScheme.setColor(
EditorColorScheme.COMMENT,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.AnnotationColor, ""))
)
//节
editorColorScheme.setColor(
EditorColorScheme.FUNCTION_NAME,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.SectionColor, ""))
)
}
2022-08-17 01:25:20 +00:00
editorColorScheme.setColor(
EditorColorScheme.WHOLE_BACKGROUND,
backgroundColor
)
editorColorScheme.setColor(
EditorColorScheme.LINE_NUMBER_BACKGROUND,
backgroundColor
)
2022-08-19 06:51:28 +00:00
editorColorScheme.setColor(EditorColorScheme.COMPLETION_WND_BACKGROUND, backgroundColor)
if (codeEditBackGroundEnable) {
//设置自定义背景图
Glide.with(this)
.load(AppSettings.getValue(AppSettings.Setting.CodeEditBackGroundPath, "")).apply(
RequestOptions.bitmapTransform(
BlurTransformation(
AppSettings.getValue(
AppSettings.Setting.BlurTransformationValue,
1
)
)
)
).into(object : CustomTarget<Drawable>() {
override fun onResourceReady(
resource: Drawable,
transition: Transition<in Drawable>?
) {
window.setBackgroundDrawable(resource)
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
2022-04-04 14:03:10 +00:00
2022-08-19 06:51:28 +00:00
}
viewBinding.codeEditor.colorScheme = editorColorScheme
2022-04-04 14:03:10 +00:00
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.menu_editer, menu)
return true
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_DOWN) {
if (viewModel.checkFilesIfNeedSave(
viewBinding.tabLayout.selectedTabPosition,
viewBinding.codeEditor.text.toString()
)
) {
return true
}
}
return super.onKeyDown(keyCode, event)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
editStartViewModel.bookmarkManager.save()
if (viewModel.checkFilesIfNeedSave(
viewBinding.tabLayout.selectedTabPosition,
viewBinding.codeEditor.text.toString()
)
) {
return true
}
}
R.id.turret_design -> {
2022-08-22 07:32:10 +00:00
val needSave = viewModel.checkOneFileIfNeedSave(
viewBinding.tabLayout.selectedTabPosition,
viewBinding.codeEditor.text.toString()
)
if (needSave) {
Snackbar.make(viewBinding.codeEditor, R.string.save_tip, Snackbar.LENGTH_SHORT)
.show()
} else {
val goIntent = Intent(this, TurretDesignActivity::class.java)
val modPath = viewModel.modClass!!.modFile.absolutePath
val filePath = viewModel.getNowOpenFilePath()
goIntent.putExtra("modPath", modPath)
goIntent.putExtra("filePath", filePath)
turretCoordinateResults.launch(goIntent)
}
2022-04-04 14:03:10 +00:00
}
2022-04-24 14:20:26 +00:00
R.id.display_source_code -> {
val file = File(viewModel.getNowOpenFilePath())
val code = FileOperator.readFile(file)
MaterialDialog(this, BottomSheet()).show {
title(text = file.name).message(text = code).negativeButton(R.string.dialog_ok)
2022-04-28 10:30:45 +00:00
.cancelable(false)
2022-04-24 14:20:26 +00:00
}
}
2022-04-04 14:03:10 +00:00
R.id.clear_code_cache -> {
Snackbar.make(
viewBinding.recyclerview,
getString(R.string.clean_up_code_cache_complete),
Snackbar.LENGTH_SHORT
).show()
}
R.id.open_game_test -> {
2022-08-14 02:43:53 +00:00
val packName = AppSettings.getValue(
2022-04-04 14:03:10 +00:00
AppSettings.Setting.GamePackage,
GlobalMethod.DEFAULT_GAME_PACKAGE
)
if (AppOperator.isAppInstalled(this@EditActivity, packName)) {
AppOperator.openApp(this@EditActivity, packName)
} else {
Snackbar.make(
viewBinding.recyclerview,
R.string.no_game_installed,
Snackbar.LENGTH_SHORT
).show()
}
}
R.id.code_navigation -> {
2022-08-17 01:25:20 +00:00
// viewModel.executorService.submit {
// val labels = viewBinding.codeEditor.textAnalyzeResult.navigation
// if (labels == null || labels.size == 0) {
// runOnUiThread {
// Snackbar.make(
// viewBinding.recyclerview,
// R.string.not_find_code_navigation,
// Snackbar.LENGTH_SHORT
// ).show()
// }
// } else {
// val items = ArrayList<CharSequence>()
// var i = 0
// while (i < labels.size) {
// items.add(labels[i].label)
// i++
// }
// val tip = String.format(getString(R.string.navigation_tip), items.size)
// runOnUiThread {
// MaterialDialog(this).show {
// title(R.string.code_navigation).positiveButton(R.string.dialog_cancel)
// .message(text = tip)
// .listItems(
// items = items,
// waitForPositiveButton = false,
// selection = object : ItemListener {
// override fun invoke(
// dialog: MaterialDialog,
// offset: Int,
// text: CharSequence
// ) {
// viewBinding.codeEditor.jumpToLine(
// labels[offset].line
// )
// viewBinding.codeEditor.moveSelectionEnd()
// dialog.dismiss()
// }
//
// })
// }
// }
// }
// }
2022-04-04 14:03:10 +00:00
}
R.id.save_text -> {
val openedSourceFile =
viewModel.openedSourceFileListLiveData.getOpenedSourceFile(viewBinding.tabLayout.selectedTabPosition)
val needSave =
openedSourceFile.isChanged(viewBinding.codeEditor.text.toString())
if (needSave) {
2022-08-26 13:51:15 +00:00
viewModel.compilerFile(openedSourceFile) {
viewModel.openedSourceFileListLiveData.getOpenedSourceFile(
viewBinding.tabLayout.selectedTabPosition
).save(it)
}
2022-04-04 14:03:10 +00:00
}
2022-08-26 13:51:15 +00:00
Snackbar.make(
viewBinding.recyclerview,
R.string.save_complete2,
Snackbar.LENGTH_SHORT
).show()
2022-04-04 14:03:10 +00:00
}
R.id.show_line_number -> {
viewBinding.codeEditor.isLineNumberEnabled =
!viewBinding.codeEditor.isLineNumberEnabled
item.isChecked = viewBinding.codeEditor.isLineNumberEnabled
}
R.id.word_wrap -> {
viewBinding.codeEditor.isWordwrap = !viewBinding.codeEditor.isWordwrap
item.isChecked = viewBinding.codeEditor.isWordwrap
}
R.id.convertToTemplate -> {
viewModel.needCheckAutoSave = false
val intent = Intent(this@EditActivity, TemplateMakerActivity::class.java)
2022-08-26 13:51:15 +00:00
val file = File(viewModel.getNowOpenFilePath())
intent.putExtra(
2022-04-04 14:03:10 +00:00
"path",
2022-08-26 13:51:15 +00:00
viewModel.getNowOpenFilePath()
)
intent.putExtra(
"name",
FileOperator.getPrefixName(file)
2022-04-04 14:03:10 +00:00
)
startActivity(intent)
}
R.id.text_undo -> {
viewBinding.codeEditor.undo()
}
R.id.text_redo -> {
viewBinding.codeEditor.redo()
}
R.id.search_view -> {
viewBinding.codeEditor.searcher.stopSearch()
viewBinding.codeEditor.beginSearchMode()
}
}
return super.onOptionsItemSelected(item)
}
/**
* 打开侧滑
*/
fun openDrawer(gravity: Int) {
viewBinding.editDrawerlayout.openDrawer(gravity)
viewBinding.codeEditor.hideAutoCompleteWindow()
viewBinding.codeEditor.hideSoftInput()
}
2022-08-14 02:43:53 +00:00
override fun getViewBindingObject(layoutInflater: LayoutInflater): ActivityEditBinding {
2022-04-04 14:03:10 +00:00
return ActivityEditBinding.inflate(layoutInflater)
}
}