This commit is contained in:
coldmint 2022-08-17 09:25:20 +08:00
parent 23a43c98f5
commit 24d9faba32
73 changed files with 2504 additions and 1476 deletions

Binary file not shown.

View File

@ -88,12 +88,12 @@ dependencies {
// TinyPinyin核心包80KB // TinyPinyin核心包80KB
implementation 'com.github.promeg:tinypinyin:2.0.3' implementation 'com.github.promeg:tinypinyin:2.0.3'
implementation 'io.github.youth5201314:banner:2.2.2' implementation 'io.github.youth5201314:banner:2.2.2'
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.core:core-ktx:1.8.0'
implementation 'com.github.deano2390:MaterialShowcaseView:1.3.4' implementation 'com.github.deano2390:MaterialShowcaseView:1.3.4'
implementation 'com.google.code.gson:gson:2.8.9' implementation 'com.google.code.gson:gson:2.9.1'
implementation 'com.github.yalantis:ucrop:2.2.6-native' implementation 'com.github.yalantis:ucrop:2.2.6-native'
implementation 'com.kongzue.stacklabel:stacklabelview:1.1.9' implementation 'com.kongzue.stacklabel:stacklabelview:1.1.9'
implementation files('libs/editor_0.8.aar') implementation 'io.github.Rosemoe.sora-editor:editor:0.16.5'
implementation project(path: ':assistantCoreLibrary') implementation project(path: ':assistantCoreLibrary')
implementation project(path: ':turretsDragView') implementation project(path: ':turretsDragView')
implementation project(path: ':dialog') implementation project(path: ':dialog')

Binary file not shown.

View File

@ -261,8 +261,8 @@
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
android:name=".EditActivity" android:name=".EditActivity"
android:configChanges="orientation"
android:exported="true" android:exported="true"
android:windowSoftInputMode="adjustResize"
android:label="@string/mod_action1" android:label="@string/mod_action1"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity

View File

@ -122,6 +122,7 @@ class CreateModActivity : BaseActivity<ActivityCreateModBinding>() {
val fileWriter = FileWriter(mod_directory.absolutePath + "/mod-info.txt") val fileWriter = FileWriter(mod_directory.absolutePath + "/mod-info.txt")
fileWriter.write(stringBuilder.toString()) fileWriter.write(stringBuilder.toString())
fileWriter.close() fileWriter.close()
setResult(RESULT_OK)
finish() finish()
} catch (e: IOException) { } catch (e: IOException) {
e.printStackTrace() e.printStackTrace()

View File

@ -5,6 +5,7 @@ import android.os.Bundle
import android.content.Intent import android.content.Intent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.* import android.widget.*
import androidx.activity.result.contract.ActivityResultContracts
import com.coldmint.rust.pro.adapters.CreateUnitPageAdapter import com.coldmint.rust.pro.adapters.CreateUnitPageAdapter
import com.coldmint.rust.pro.databinding.ActivityCreateUnitBinding import com.coldmint.rust.pro.databinding.ActivityCreateUnitBinding
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
@ -38,42 +39,28 @@ class CreateUnitActivity : BaseActivity<ActivityCreateUnitBinding>() {
}.attach() }.attach()
val root = bundle.getString("modPath") val root = bundle.getString("modPath")
createUnitPageAdapter.setRootPath(root) createUnitPageAdapter.setRootPath(root)
val set = createUnitPageAdapter.setCreatePath(bundle.getString("createPath", root)) createUnitPageAdapter.setCreatePath(bundle.getString("createPath", root))
// if (!set) { // registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
// //如果没有设置成功当fragment没有附加到activity // val resultCode = it.resultCode
// viewBinding.toolbar.postDelayed({ // when (requestCode) {
// createUnitPageAdapter.setCreatePath(bundle.getString("createPath", root)) // 1 -> if (resultCode == RESULT_OK) {
// }, 50) // val directents = data!!.getStringExtra("Directents")
// if (directents != null) {
// createUnitPageAdapter.setCreatePath(directents)
// }
// }
// 2 -> if (resultCode == RESULT_OK) {
// val path = data!!.getStringExtra("File")
// val intent = Intent()
// intent.putExtra("File", path)
// setResult(RESULT_OK, intent)
// finish()
// }
// }
// } // }
// loadlist()
} }
} }
// fun getmCreatePath(): String {
// return mCreatePath
// }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
1 -> if (resultCode == RESULT_OK) {
val directents = data!!.getStringExtra("Directents")
if (directents != null) {
createUnitPageAdapter.setCreatePath(directents)
}
}
2 -> if (resultCode == RESULT_OK) {
val path = data!!.getStringExtra("File")
val intent = Intent()
intent.putExtra("File", path)
setResult(RESULT_OK, intent)
finish()
}
}
}
override fun getViewBindingObject(layoutInflater: LayoutInflater): ActivityCreateUnitBinding { override fun getViewBindingObject(layoutInflater: LayoutInflater): ActivityCreateUnitBinding {
return ActivityCreateUnitBinding.inflate(layoutInflater) return ActivityCreateUnitBinding.inflate(layoutInflater)

View File

@ -3,7 +3,10 @@ package com.coldmint.rust.pro
import android.content.Intent import android.content.Intent
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.coldmint.rust.pro.adapters.GuideAdapter import com.coldmint.rust.pro.adapters.GuideAdapter
@ -13,11 +16,22 @@ import com.coldmint.rust.pro.databinding.ActivityCreationWizardBinding
import com.coldmint.rust.pro.tool.AppSettings import com.coldmint.rust.pro.tool.AppSettings
class CreationWizardActivity : BaseActivity<ActivityCreationWizardBinding>() { class CreationWizardActivity : BaseActivity<ActivityCreationWizardBinding>() {
lateinit var createMod: ActivityResultLauncher<Intent>
//创建向导类型(模组,模板包) //创建向导类型(模组,模板包)
lateinit var type: String lateinit var type: String
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) { override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
setReturnButton() setReturnButton()
title = getString(R.string.creation_assistant) title = getString(R.string.creation_assistant)
createMod = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) {
finish()
Log.d("创建单位", "收到了数据,关闭界面。")
} else {
Log.d("创建单位", "没有收到数据。")
}
}
val temType = intent.getStringExtra("type") val temType = intent.getStringExtra("type")
if (temType.isNullOrBlank()) { if (temType.isNullOrBlank()) {
showToast("请传入类型") showToast("请传入类型")
@ -74,7 +88,7 @@ class CreationWizardActivity : BaseActivity<ActivityCreationWizardBinding>() {
val fileBundle = Bundle() val fileBundle = Bundle()
fileBundle.putString("type", "selectFile") fileBundle.putString("type", "selectFile")
startIntent.putExtra("data", fileBundle) startIntent.putExtra("data", fileBundle)
startActivity(startIntent ) startActivity(startIntent)
} }
} }
} }
@ -118,15 +132,14 @@ class CreationWizardActivity : BaseActivity<ActivityCreationWizardBinding>() {
val adapter = GuideAdapter(this, dataList) val adapter = GuideAdapter(this, dataList)
adapter.setItemEvent { i, itemGuideBinding, viewHolder, guideData -> adapter.setItemEvent { i, itemGuideBinding, viewHolder, guideData ->
itemGuideBinding.root.setOnClickListener { itemGuideBinding.root.setOnClickListener {
finish()
when (guideData.titleRes) { when (guideData.titleRes) {
R.string.create_mod_lable -> { R.string.create_mod_lable -> {
startActivity( val startActivity =
Intent( Intent(
this, this,
CreateModActivity::class.java CreateModActivity::class.java
) )
) createMod.launch(startActivity)
} }
R.string.import_mod -> { R.string.import_mod -> {
val startIntent = val startIntent =
@ -135,6 +148,7 @@ class CreationWizardActivity : BaseActivity<ActivityCreationWizardBinding>() {
fileBundle.putString("type", "selectFile") fileBundle.putString("type", "selectFile")
startIntent.putExtra("data", fileBundle) startIntent.putExtra("data", fileBundle)
startActivity(startIntent) startActivity(startIntent)
finish()
} }
R.string.import_mod_from_package_directory -> { R.string.import_mod_from_package_directory -> {
val startIntent = val startIntent =
@ -149,9 +163,11 @@ class CreationWizardActivity : BaseActivity<ActivityCreationWizardBinding>() {
fileBundle.putString("rootpath", packDirectory) fileBundle.putString("rootpath", packDirectory)
startIntent.putExtra("data", fileBundle) startIntent.putExtra("data", fileBundle)
startActivity(startIntent) startActivity(startIntent)
finish()
} }
R.string.import_mod_from_recycle_bin -> { R.string.import_mod_from_recycle_bin -> {
startActivity(Intent(this, RecyclingStationActivity::class.java)) startActivity(Intent(this, RecyclingStationActivity::class.java))
finish()
} }
} }
} }

View File

@ -60,10 +60,10 @@ import com.flask.colorpicker.ColorPickerView
import com.flask.colorpicker.builder.ColorPickerDialogBuilder import com.flask.colorpicker.builder.ColorPickerDialogBuilder
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import io.github.rosemoe.sora.data.CompletionItem import io.github.rosemoe.sora.lang.completion.CompletionItem
import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
import java.io.File import java.io.File
import java.util.* import java.util.*
import io.github.rosemoe.sora.widget.EditorColorScheme
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -75,9 +75,6 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
private lateinit var rustLanguage: RustLanguage private lateinit var rustLanguage: RustLanguage
private var fileAdapter: FileAdapter? = null private var fileAdapter: FileAdapter? = null
val symbolChannel by lazy {
viewBinding.codeEditor.createNewSymbolChannel()
}
//是第一次启动嘛 //是第一次启动嘛
var isFirst = true var isFirst = true
@ -199,41 +196,41 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
rustLanguage.setEnglish(it) rustLanguage.setEnglish(it)
} }
viewBinding.codeEditor.setItemListener { i, completionItem -> // viewBinding.codeEditor.setItemListener { i, completionItem ->
viewModel.executorService.submit { // viewModel.executorService.submit {
val extrasData = completionItem.extrasData // val extrasData = completionItem.extrasData
if (extrasData != null) { // if (extrasData != null) {
val listData = extrasData.getString("list") // val listData = extrasData.getString("list")
if (listData != null) { // if (listData != null) {
val lineParser = LineParser(listData) // val lineParser = LineParser(listData)
lineParser.symbol = "," // lineParser.symbol = ","
val list = ArrayList<CompletionItem>() // val list = ArrayList<CompletionItem>()
lineParser.analyse { lineNum, lineData, isEnd -> // lineParser.analyse { lineNum, lineData, isEnd ->
val temCodeInfo = // val temCodeInfo =
CodeDataBase.getInstance(this).getCodeDao().findCodeByCode(lineData) // CodeDataBase.getInstance(this).getCodeDao().findCodeByCode(lineData)
if (temCodeInfo == null) { // if (temCodeInfo == null) {
//
} else { // } else {
val completionItemConverter = CompletionItemConverter.instance // val completionItemConverter = CompletionItemConverter.instance
completionItemConverter.init(this) // completionItemConverter.init(this)
list.add( // list.add(
completionItemConverter.codeInfoToCompletionItem( // completionItemConverter.codeInfoToCompletionItem(
temCodeInfo // temCodeInfo
) // )
) // )
} // }
true // true
} // }
if (list.isNotEmpty()) { // if (list.isNotEmpty()) {
runOnUiThread { // runOnUiThread {
viewBinding.codeEditor.createEditorAutoCompleteList(list) // viewBinding.codeEditor.createEditorAutoCompleteList(list)
} // }
} // }
} // }
} // }
} // }
true // true
} // }
viewModel.openedSourceFileListLiveData.observe(this) { viewModel.openedSourceFileListLiveData.observe(this) {
viewBinding.tabLayout.removeAllTabs() viewBinding.tabLayout.removeAllTabs()
it.forEach { it.forEach {
@ -314,11 +311,11 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
} }
viewModel.codeLiveData.observe(this) { viewModel.codeLiveData.observe(this) {
rustLanguage.autoCompleteProvider.setSourceFolder( // rustLanguage.autoCompleteProvider.setSourceFolder(
FileOperator.getSuperDirectory( // FileOperator.getSuperDirectory(
viewModel.getNowOpenFilePath() // viewModel.getNowOpenFilePath()
) // )
) // )
//初始化加载路径数据(仅在第一次有效) //初始化加载路径数据(仅在第一次有效)
editStartViewModel.initLoadPathLiveData(viewModel.getNowOpenFilePath()) editStartViewModel.initLoadPathLiveData(viewModel.getNowOpenFilePath())
viewBinding.myProgressBar.isVisible = false viewBinding.myProgressBar.isVisible = false
@ -480,8 +477,8 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
loadStartObserve() loadStartObserve()
loadEndObserve() loadEndObserve()
initDrawerLayout() initDrawerLayout()
initCodeEditor()
initCodeToolbar() initCodeToolbar()
initCodeEditor()
initStartView() initStartView()
initEndView() initEndView()
showRenewalTip() showRenewalTip()
@ -979,7 +976,7 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
builder.append(viewModel.convertDigital(r)) builder.append(viewModel.convertDigital(r))
builder.append(viewModel.convertDigital(g)) builder.append(viewModel.convertDigital(g))
builder.append(viewModel.convertDigital(b)) builder.append(viewModel.convertDigital(b))
symbolChannel.insertSymbol(builder.toString(), builder.length) viewBinding.codeEditor.insertText(builder.toString(), builder.length)
} }
.setNegativeButton(R.string.dialog_cancel) { dialog, which -> } .setNegativeButton(R.string.dialog_cancel) { dialog, which -> }
.build() .build()
@ -1000,107 +997,107 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
).show() ).show()
} }
} else if (item == getString(R.string.code_tip)) { } else if (item == getString(R.string.code_tip)) {
viewModel.executorService.submit { // viewModel.executorService.submit {
try { // try {
val list = ArrayList<CompletionItem>() // val list = ArrayList<CompletionItem>()
//如果不包含:搜索键 // //如果不包含:搜索键
val lineNumber = viewBinding.codeEditor.selectedLineNumber // val lineNumber = viewBinding.codeEditor.selectedLineNumber
val navigationList = // val navigationList =
viewBinding.codeEditor.textAnalyzeResult.navigation // viewBinding.codeEditor.textAnalyzeResult.navigation
var section: String? = null // var section: String? = null
if (navigationList != null && navigationList.isNotEmpty()) { // if (navigationList != null && navigationList.isNotEmpty()) {
for (navigation in navigationList) { // for (navigation in navigationList) {
if (navigation.line > lineNumber) { // if (navigation.line > lineNumber) {
break // break
} else { // } else {
section = navigation.label // section = navigation.label
} // }
} // }
} // }
//如果不在任何节内 // //如果不在任何节内
if (section == null) { // if (section == null) {
runOnUiThread { // runOnUiThread {
runOnUiThread { // runOnUiThread {
Snackbar.make( // Snackbar.make(
viewBinding.recyclerview, // viewBinding.recyclerview,
this.getString(R.string.code_tip_error1), // this.getString(R.string.code_tip_error1),
Snackbar.LENGTH_SHORT // Snackbar.LENGTH_SHORT
).show() // ).show()
} // }
} // }
return@submit // return@submit
} // }
val trueSection = // val trueSection =
rustLanguage.autoCompleteProvider.getSectionType(section) // rustLanguage.autoCompleteProvider.getSectionType(section)
val codeDataBase = CodeDataBase.getInstance(this) // val codeDataBase = CodeDataBase.getInstance(this)
val lineData = // val lineData =
viewBinding.codeEditor.text.getLine(lineNumber).toString() // viewBinding.codeEditor.text.getLine(lineNumber).toString()
if (lineData.startsWith('[') && lineData.endsWith(']')) { // if (lineData.startsWith('[') && lineData.endsWith(']')) {
runOnUiThread { // runOnUiThread {
Snackbar.make( // Snackbar.make(
viewBinding.recyclerview, // viewBinding.recyclerview,
R.string.code_tip_error2, // R.string.code_tip_error2,
Snackbar.LENGTH_SHORT // Snackbar.LENGTH_SHORT
).show() // ).show()
} // }
return@submit // return@submit
} // }
val index = lineData.indexOf(':') // val offset = lineData.indexOf(':')
if (index > -1) { // if (offset > -1) {
//如果包含: // //如果包含:
runOnUiThread { // runOnUiThread {
Snackbar.make( // Snackbar.make(
viewBinding.recyclerview, // viewBinding.recyclerview,
this.getString(R.string.can_not_tip_value), // this.getString(R.string.can_not_tip_value),
Snackbar.LENGTH_SHORT // Snackbar.LENGTH_SHORT
).show() // ).show()
} // }
return@submit // return@submit
} else { // } else {
val codeInfoList = if (lineData.isBlank()) { // val codeInfoList = if (lineData.isBlank()) {
codeDataBase.getCodeDao().findCodeBySection(trueSection) // codeDataBase.getCodeDao().findCodeBySection(trueSection)
} else { // } else {
val number = AppSettings.getValue( // val number = AppSettings.getValue(
AppSettings.Setting.IdentifiersPromptNumber, // AppSettings.Setting.IdentifiersPromptNumber,
40 // 40
) // )
codeDataBase.getCodeDao() // codeDataBase.getCodeDao()
.findCodeByKeyFromSection(lineData, trueSection, number) // .findCodeByKeyFromSection(lineData, trueSection, number)
} // }
if (codeInfoList != null && codeInfoList.isNotEmpty()) { // if (codeInfoList != null && codeInfoList.isNotEmpty()) {
val completionItemConverter = // val completionItemConverter =
CompletionItemConverter.instance.init(this) // CompletionItemConverter.instance.init(this)
codeInfoList.forEach { // codeInfoList.forEach {
list.add( // list.add(
completionItemConverter.codeInfoToCompletionItem( // completionItemConverter.codeInfoToCompletionItem(
it // it
) // )
) // )
} // }
} else { // } else {
runOnUiThread { // runOnUiThread {
Snackbar.make( // Snackbar.make(
viewBinding.recyclerview, // viewBinding.recyclerview,
String.format( // String.format(
this.getString(R.string.code_tip_error3), // this.getString(R.string.code_tip_error3),
SourceFile.getSectionType(section) // SourceFile.getSectionType(section)
), // ),
Snackbar.LENGTH_SHORT // Snackbar.LENGTH_SHORT
).show() // ).show()
} // }
} // }
} // }
runOnUiThread { // runOnUiThread {
viewBinding.codeEditor.createEditorAutoCompleteList(list) // viewBinding.codeEditor.createEditorAutoCompleteList(list)
} // }
} catch (e: Exception) { // } catch (e: Exception) {
e.printStackTrace() // e.printStackTrace()
} // }
//
} // }
} else { } else {
try { try {
symbolChannel.insertSymbol(item, item.length) viewBinding.codeEditor.insertText(item, item.length)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
@ -1139,53 +1136,41 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
rustLanguage.setCodeEditor(viewBinding.codeEditor) rustLanguage.setCodeEditor(viewBinding.codeEditor)
val night = AppSettings.getValue(AppSettings.Setting.NightMode, false) val night = AppSettings.getValue(AppSettings.Setting.NightMode, false)
val editorColorScheme = EditorColorScheme() val editorColorScheme = EditorColorScheme()
if (night) { val backgroundColor = GlobalMethod.getThemeColor(this, android.R.attr.windowBackground)
//代码(可识别的关键字) //代码(可识别的关键字)
editorColorScheme.setColor(EditorColorScheme.KEYWORD, Color.rgb(178, 119, 49)) editorColorScheme.setColor(
//默认文本 EditorColorScheme.KEYWORD,
editorColorScheme.setColor(EditorColorScheme.TEXT_NORMAL, Color.rgb(169, 183, 198)) GlobalMethod.getThemeColor(this, android.R.attr.colorSecondary)
//注释 )
editorColorScheme.setColor(EditorColorScheme.COMMENT, Color.rgb(128, 128, 128)) //默认文本
//节 editorColorScheme.setColor(EditorColorScheme.TEXT_NORMAL, Color.rgb(169, 183, 198))
editorColorScheme.setColor( //注释
EditorColorScheme.FUNCTION_NAME, editorColorScheme.setColor(
Color.rgb(152, 118, 170) EditorColorScheme.COMMENT,
) GlobalMethod.getThemeColor(this, android.R.attr.textColorTertiary)
//错误 )
editorColorScheme.setColor( //节
EditorColorScheme.WHOLE_BACKGROUND, editorColorScheme.setColor(
Color.rgb(60, 63, 65) EditorColorScheme.FUNCTION_NAME,
) GlobalMethod.getColorPrimary(this)
editorColorScheme.setColor( )
EditorColorScheme.LINE_NUMBER_BACKGROUND, editorColorScheme.setColor(
Color.rgb(60, 63, 65) EditorColorScheme.WHOLE_BACKGROUND,
) backgroundColor
} else { )
//代码(可识别的关键字) editorColorScheme.setColor(
editorColorScheme.setColor(EditorColorScheme.KEYWORD, Color.rgb(42, 92, 170)) EditorColorScheme.LINE_NUMBER_BACKGROUND,
//默认文本 backgroundColor
editorColorScheme.setColor(EditorColorScheme.TEXT_NORMAL, Color.BLACK) )
//注释
editorColorScheme.setColor(EditorColorScheme.COMMENT, Color.rgb(128, 128, 128))
//节
editorColorScheme.setColor(EditorColorScheme.FUNCTION_NAME, Color.rgb(170, 33, 22))
editorColorScheme.setColor(
EditorColorScheme.WHOLE_BACKGROUND,
Color.rgb(240, 240, 243)
)
//变量名
editorColorScheme.setColor(EditorColorScheme.LITERAL, Color.rgb(153, 50, 204))
}
viewBinding.codeEditor.colorScheme = editorColorScheme viewBinding.codeEditor.colorScheme = editorColorScheme
viewBinding.codeEditor.setAutoCompletionItemAdapter(RustCompletionAdapter()) viewBinding.codeEditor.setAutoCompletionItemAdapter(RustCompletionAdapter())
viewBinding.codeEditor.isVerticalScrollBarEnabled = false viewBinding.codeEditor.isVerticalScrollBarEnabled = false
val path = viewModel.modClass?.modFile?.absolutePath ?: "" val path = viewModel.modClass?.modFile?.absolutePath ?: ""
rustLanguage.autoCompleteProvider.setConfigurationFileConversion( // rustLanguage.autoCompleteProvider.setConfigurationFileConversion(
path, // path,
"ROOT", // "ROOT",
path // path
) // )
viewBinding.codeEditor.setEditorLanguage(rustLanguage) viewBinding.codeEditor.setEditorLanguage(rustLanguage)
} }
@ -1262,49 +1247,49 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
} }
} }
R.id.code_navigation -> { R.id.code_navigation -> {
viewModel.executorService.submit { // viewModel.executorService.submit {
val labels = viewBinding.codeEditor.textAnalyzeResult.navigation // val labels = viewBinding.codeEditor.textAnalyzeResult.navigation
if (labels == null || labels.size == 0) { // if (labels == null || labels.size == 0) {
runOnUiThread { // runOnUiThread {
Snackbar.make( // Snackbar.make(
viewBinding.recyclerview, // viewBinding.recyclerview,
R.string.not_find_code_navigation, // R.string.not_find_code_navigation,
Snackbar.LENGTH_SHORT // Snackbar.LENGTH_SHORT
).show() // ).show()
} // }
} else { // } else {
val items = ArrayList<CharSequence>() // val items = ArrayList<CharSequence>()
var i = 0 // var i = 0
while (i < labels.size) { // while (i < labels.size) {
items.add(labels[i].label) // items.add(labels[i].label)
i++ // i++
} // }
val tip = String.format(getString(R.string.navigation_tip), items.size) // val tip = String.format(getString(R.string.navigation_tip), items.size)
runOnUiThread { // runOnUiThread {
MaterialDialog(this).show { // MaterialDialog(this).show {
title(R.string.code_navigation).positiveButton(R.string.dialog_cancel) // title(R.string.code_navigation).positiveButton(R.string.dialog_cancel)
.message(text = tip) // .message(text = tip)
.listItems( // .listItems(
items = items, // items = items,
waitForPositiveButton = false, // waitForPositiveButton = false,
selection = object : ItemListener { // selection = object : ItemListener {
override fun invoke( // override fun invoke(
dialog: MaterialDialog, // dialog: MaterialDialog,
index: Int, // offset: Int,
text: CharSequence // text: CharSequence
) { // ) {
viewBinding.codeEditor.jumpToLine( // viewBinding.codeEditor.jumpToLine(
labels[index].line // labels[offset].line
) // )
viewBinding.codeEditor.moveSelectionEnd() // viewBinding.codeEditor.moveSelectionEnd()
dialog.dismiss() // dialog.dismiss()
} // }
//
}) // })
} // }
} // }
} // }
} // }
} }
R.id.save_text -> { R.id.save_text -> {
val openedSourceFile = val openedSourceFile =
@ -1534,24 +1519,24 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.END) viewBinding.editDrawerlayout.closeDrawer(GravityCompat.END)
} }
addAdditionalName -> { addAdditionalName -> {
val labels = // val labels =
viewBinding.codeEditor.textAnalyzeResult.navigation // viewBinding.codeEditor.textAnalyzeResult.navigation
var num = 1 // var num = 1
labels.forEach { // labels.forEach {
val type = SourceFile.getSectionType( // val type = SourceFile.getSectionType(
it.label.substring( // it.label.substring(
1, // 1,
it.label.length - 1 // it.label.length - 1
) // )
) // )
if (type == sectionName) { // if (type == sectionName) {
num++ // num++
} // }
} // }
val name = "_" + num.toString() // val name = "_" + num.toString()
viewBinding.codeEditor.setSelection(lineNum, columnNum) // viewBinding.codeEditor.setSelection(lineNum, columnNum)
symbolChannel.insertSymbol(name, name.length) // viewBinding.codeEditor.insertText(name, name.length)
viewBinding.editDrawerlayout.closeDrawer(GravityCompat.END) // viewBinding.editDrawerlayout.closeDrawer(GravityCompat.END)
} }
} }
false false

View File

@ -142,7 +142,7 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
// ) // )
// ) // )
// MaterialDialog(this).title(R.string.open_type) // MaterialDialog(this).title(R.string.open_type)
// .listItems(items = openList) { dialog, index, text -> // .listItems(items = openList) { dialog, offset, text ->
// when (text) { // when (text) {
// getString(R.string.edit_template) -> { // getString(R.string.edit_template) -> {
// editTemplate(file) // editTemplate(file)

View File

@ -59,23 +59,22 @@ class LibraryActivity : BaseActivity<ActivityLibraryBinding>() {
"Apache License 2.0" "Apache License 2.0"
) )
) )
// libInfoArrayList.add(
// LibInfo(
// "Kongzue StackLabel",
// "空祖家的堆叠标签以下碎念一开始起名字“StackLabel”没想太多结果被人吐槽Stack是整齐堆叠的意思...........好吧这是我的锅不过现在要改也来不及了,好用就行了...吧?",
// "https://github.com/kongzue/StackLabel",
// "Apache License 2.0"
// )
// )
libInfoArrayList.add( libInfoArrayList.add(
LibInfo( LibInfo(
"Kongzue StackLabel", "sora-editor",
"空祖家的堆叠标签以下碎念一开始起名字“StackLabel”没想太多结果被人吐槽Stack是整齐堆叠的意思...........好吧这是我的锅不过现在要改也来不及了,好用就行了...吧?", "A cool code editor library on Android with syntax-highlighting and auto-completion. (aka CodeEditor)",
"https://github.com/kongzue/StackLabel", "https://github.com/Rosemoe/sora-editor",
"Apache License 2.0" "LGPL 2.1"
) )
) )
val libInfo = LibInfo(
"sora-editor",
"A cool code editor library on Android with syntax-highlighting and auto-completion. (aka CodeEditor)",
"https://github.com/Rosemoe/sora-editor",
"LGPL 2.1"
)
libInfo.tip =
"铁锈助手使用sora-editor的魔改版本。\n\n由ColdMint魔改自Rose的sora-editor编辑框。\n\n在原基础上新增功能:\n-列表控制api用于实现连锁提示\n-自定义列表适配器(用于适配视图)\n\n目前修改版本为0.8由ColdMint维护。\n\n于2022-1-25日同步主项目。"
libInfoArrayList.add(libInfo)
libInfoArrayList.add( libInfoArrayList.add(
LibInfo( LibInfo(
"ColorPicker", "ColorPicker",

View File

@ -5,6 +5,8 @@ import com.coldmint.rust.pro.base.BaseActivity
import org.json.JSONObject import org.json.JSONObject
import android.os.Bundle import android.os.Bundle
import android.content.Intent import android.content.Intent
import android.text.Editable
import android.text.TextWatcher
import android.util.Log import android.util.Log
import com.coldmint.rust.pro.tool.AppSettings import com.coldmint.rust.pro.tool.AppSettings
import org.json.JSONException import org.json.JSONException
@ -28,14 +30,20 @@ import com.coldmint.rust.core.dataBean.IntroducingDataBean
import com.coldmint.rust.core.dataBean.ListParserDataBean import com.coldmint.rust.core.dataBean.ListParserDataBean
import com.coldmint.rust.core.dataBean.template.LocalTemplateFile import com.coldmint.rust.core.dataBean.template.LocalTemplateFile
import com.coldmint.rust.core.dataBean.template.TemplatePackage import com.coldmint.rust.core.dataBean.template.TemplatePackage
import com.coldmint.rust.core.dataBean.template.WebTemplateData
import com.coldmint.rust.core.interfaces.ApiCallBack
import com.coldmint.rust.core.interfaces.TemplateParser import com.coldmint.rust.core.interfaces.TemplateParser
import com.coldmint.rust.core.templateParser.InputParser import com.coldmint.rust.core.templateParser.InputParser
import com.coldmint.rust.core.templateParser.IntroducingParser import com.coldmint.rust.core.templateParser.IntroducingParser
import com.coldmint.rust.core.templateParser.ListParser import com.coldmint.rust.core.templateParser.ListParser
import com.coldmint.rust.core.tool.FileOperator import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.core.web.TemplatePhp
import com.coldmint.rust.pro.databinding.ActivityTemplateParserBinding import com.coldmint.rust.pro.databinding.ActivityTemplateParserBinding
import com.coldmint.rust.pro.tool.UnitAutoCompleteHelper import com.coldmint.rust.pro.tool.UnitAutoCompleteHelper
import com.coldmint.rust.pro.viewmodel.TemplateParserViewModel import com.coldmint.rust.pro.viewmodel.TemplateParserViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.dialog.MaterialDialogs
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import com.google.gson.Gson import com.google.gson.Gson
import java.io.File import java.io.File
@ -68,9 +76,8 @@ class TemplateParserActivity : BaseActivity<ActivityTemplateParserBinding>() {
if (code.isBlank()) { if (code.isBlank()) {
code = getString(R.string.not_found_data2) code = getString(R.string.not_found_data2)
} }
CoreDialog(this).setTitle(viewModel.getTemplateName(language)).setMessage(code) MaterialAlertDialogBuilder(this).setTitle(viewModel.getTemplateName(language))
.setPositiveButton(R.string.dialog_ok) { .setMessage(code).setPositiveButton(R.string.dialog_ok) { i, i2 ->
}.show() }.show()
} }
} }
@ -79,8 +86,51 @@ class TemplateParserActivity : BaseActivity<ActivityTemplateParserBinding>() {
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) { override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
if (canUseView) { if (canUseView) {
setReturnButton() setReturnButton()
val unitAutoCompleteHelper = UnitAutoCompleteHelper(this)
unitAutoCompleteHelper.onBindAutoCompleteTextView(viewBinding.fileNameInputView)
viewBinding.fileNameInputView.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun afterTextChanged(p0: Editable?) {
val text = p0.toString()
if (text.isBlank()) {
viewBinding.fileNameInputLayout.error = getString(R.string.file_name_error)
} else {
viewBinding.fileNameInputLayout.isErrorEnabled = false
}
}
})
viewBinding.fab.setOnClickListener {
val name = viewBinding.fileNameInputView.text.toString()
if (name.isNotBlank()) {
val build = viewModel.buildFile(this, name)
if (build) {
setResult(RESULT_OK)
finish()
} else {
Snackbar.make(
viewBinding.fab,
R.string.create_unit_failed,
Snackbar.LENGTH_SHORT
).show()
}
}
}
val createDirectory = intent.getStringExtra("createDirectory")
if (createDirectory == null) {
Toast.makeText(this, "没有设置创建目录", Toast.LENGTH_SHORT).show()
finish()
return
}
viewModel.setCreateDirectory(createDirectory)
val link = intent.getStringExtra("link") val link = intent.getStringExtra("link")
if (link == null) { if (link == null) {
Toast.makeText(this, "请设置链接", Toast.LENGTH_SHORT).show() Toast.makeText(this, "请设置链接", Toast.LENGTH_SHORT).show()
@ -99,8 +149,42 @@ class TemplateParserActivity : BaseActivity<ActivityTemplateParserBinding>() {
viewBinding.nestedScrollView.isVisible = true viewBinding.nestedScrollView.isVisible = true
title = viewModel.getTemplateName(language) title = viewModel.getTemplateName(language)
} else { } else {
Log.d("模板解析器", "加载网络模板$link")
TemplatePhp.instance.getTemplate(link, object : ApiCallBack<WebTemplateData> {
override fun onResponse(t: WebTemplateData) {
if (t.code == ServerConfiguration.Success_Code) {
viewModel.setTemplate(t.data)
val templateParserList =
viewModel.getTemplateParserList(this@TemplateParserActivity)
templateParserList.forEach {
viewBinding.base.addView(it.contextView)
}
viewBinding.linearLayout.isVisible = false
viewBinding.nestedScrollView.isVisible = true
title = viewModel.getTemplateName(language)
} else {
Toast.makeText(
this@TemplateParserActivity,
t.message,
Toast.LENGTH_SHORT
).show()
finish()
}
}
override fun onFailure(e: Exception) {
e.printStackTrace()
Toast.makeText(
this@TemplateParserActivity,
R.string.network_error,
Toast.LENGTH_SHORT
).show()
finish()
}
})
} }
} }
} }

View File

@ -184,7 +184,8 @@ class UserHomePageActivity : BaseActivity<ActivityUserHomePageBinding>() {
viewBinding.loginTimeView.text = String.format( viewBinding.loginTimeView.text = String.format(
getString(R.string.user_info), getString(R.string.user_info),
spaceInfoData.data.loginTime, spaceInfoData.data.loginTime,
spaceInfoData.data.account spaceInfoData.data.account,
spaceInfoData.data.location
) )
viewBinding.fab.isVisible = true viewBinding.fab.isVisible = true

View File

@ -451,7 +451,7 @@ class ModActionAdapter(
if (string.isNotEmpty() && string != oldname) { if (string.isNotEmpty() && string != oldname) {
val newFile = File(FileOperator.getSuperDirectory(mod_file) + "/" + string) val newFile = File(FileOperator.getSuperDirectory(mod_file) + "/" + string)
mod_file.renameTo(newFile) mod_file.renameTo(newFile)
mModFragment.loadMods() mModFragment.loadModList()
} }
true true
}.setNegativeButton(R.string.dialog_cancel) { }.setNegativeButton(R.string.dialog_cancel) {
@ -728,7 +728,7 @@ class ModActionAdapter(
if (ok) { if (ok) {
handler.post { handler.post {
materialDialog.dismiss() materialDialog.dismiss()
mModFragment.loadMods() mModFragment.loadModList()
Snackbar.make( Snackbar.make(
(mModFragment.view)!!, (mModFragment.view)!!,
R.string.repair_complete, R.string.repair_complete,
@ -764,7 +764,7 @@ class ModActionAdapter(
) )
handler.post { handler.post {
materialDialog.dismiss() materialDialog.dismiss()
mModFragment.loadMods() mModFragment.loadModList()
if (needShowSnackbar) { if (needShowSnackbar) {
Snackbar.make( Snackbar.make(
(mModFragment.view)!!, (mModFragment.view)!!,
@ -889,7 +889,7 @@ class ModActionAdapter(
repairThread.setModpath(unzip_path.absolutePath) repairThread.setModpath(unzip_path.absolutePath)
repairThread.start() repairThread.start()
} }
mModFragment.loadMods() mModFragment.loadModList()
} }
} else { } else {
handler.post { handler.post {

View File

@ -11,16 +11,17 @@ import com.bumptech.glide.Glide
import android.os.Build import android.os.Build
import com.coldmint.rust.pro.base.BaseAdapter import com.coldmint.rust.pro.base.BaseAdapter
import com.coldmint.rust.pro.databinding.ModListItemBinding import com.coldmint.rust.pro.databinding.ModListItemBinding
import me.zhanghai.android.fastscroll.PopupTextProvider
/*模组适配器 /*模组适配器
* 此适配器只能使用于ModFragment成员变量按需传递 * 此适配器只能使用于ModFragment成员变量按需传递
* */ * */
class ModAdapter(context: Context, dataList: MutableList<ModClass>) : class ModAdapter(context: Context, dataList: MutableList<ModClass>) :
BaseAdapter<ModListItemBinding, ModClass>(context, dataList) { BaseAdapter<ModListItemBinding, ModClass>(context, dataList), PopupTextProvider {
init { init {
dataList.sortBy { dataList.sortBy {
it.modName getInitial(it.modName)
} }
} }
@ -71,4 +72,9 @@ class ModAdapter(context: Context, dataList: MutableList<ModClass>) :
viewBinding.modUpTime.text = data.lastModificationTime viewBinding.modUpTime.text = data.lastModificationTime
viewBinding.modNameView.text = data.modName viewBinding.modNameView.text = data.modName
} }
override fun getPopupText(position: Int): String {
val s = dataList[position].modName
return getInitial(s).toString()
}
} }

View File

@ -13,8 +13,12 @@ import android.graphics.BitmapFactory
import android.content.Intent import android.content.Intent
import com.coldmint.rust.pro.TemplateParserActivity import com.coldmint.rust.pro.TemplateParserActivity
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.coldmint.rust.core.LocalTemplatePackage import com.coldmint.rust.core.LocalTemplatePackage
import com.coldmint.rust.core.dataBean.template.Template import com.coldmint.rust.core.dataBean.template.Template
@ -28,7 +32,8 @@ class TemplateAdapter(
private val context: Context, private val context: Context,
private val mGroup: List<TemplatePackage>, private val mGroup: List<TemplatePackage>,
private val mItemList: List<List<Template>>, private val mItemList: List<List<Template>>,
mEnvironmentLanguage: String mEnvironmentLanguage: String,
private val startTemplateParserActivity: ActivityResultLauncher<Intent>
) : BaseExpandableListAdapter() { ) : BaseExpandableListAdapter() {
private val layoutInflater: LayoutInflater = LayoutInflater.from(context) private val layoutInflater: LayoutInflater = LayoutInflater.from(context)
private val mEnvironmentLanguage: String private val mEnvironmentLanguage: String
@ -117,7 +122,9 @@ class TemplateAdapter(
val intent = Intent(context, TemplateParserActivity::class.java) val intent = Intent(context, TemplateParserActivity::class.java)
intent.putExtra("link", templateClass.getLink()) intent.putExtra("link", templateClass.getLink())
intent.putExtra("isLocal", templateClass.isLocal()) intent.putExtra("isLocal", templateClass.isLocal())
context.startActivity(intent) intent.putExtra("createDirectory", createPath)
startTemplateParserActivity.launch(intent)
} }
return templateItemBinding.root return templateItemBinding.root
} }

View File

@ -340,14 +340,14 @@ class TemplateListAdapter(
// holder.templateListItemBinding.delButton.setBackgroundColor(R.color.blue_200) // holder.templateListItemBinding.delButton.setBackgroundColor(R.color.blue_200)
// holder.templateListItemBinding.delButton.setText(R.string.del_moding) // holder.templateListItemBinding.delButton.setText(R.string.del_moding)
// } // }
// val index = mFiles.indexOf(templateClass.directest) // val offset = mFiles.indexOf(templateClass.directest)
// mFiles.removeAt(index) // mFiles.removeAt(offset)
// FileOperator.delete_files(templateClass.directest) // FileOperator.delete_files(templateClass.directest)
// mfragment.requireActivity().runOnUiThread { // mfragment.requireActivity().runOnUiThread {
// if (mFiles.size == 0) { // if (mFiles.size == 0) {
// mfragment.load_list(mRootPath, true) // mfragment.load_list(mRootPath, true)
// } else { // } else {
// notifyItemRemoved(index) // notifyItemRemoved(offset)
// } // }
// } // }
// }.start() // }.start()

View File

@ -3,7 +3,7 @@ package com.coldmint.rust.pro.adapters
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import com.coldmint.rust.core.dataBean.webTemplate.WebTemplatePackageListData import com.coldmint.rust.core.dataBean.WebTemplatePackageListData
import com.coldmint.rust.pro.R import com.coldmint.rust.pro.R
import com.coldmint.rust.pro.base.BaseAdapter import com.coldmint.rust.pro.base.BaseAdapter
import com.coldmint.rust.pro.databinding.ItemWebTemplateBinding import com.coldmint.rust.pro.databinding.ItemWebTemplateBinding

View File

@ -9,22 +9,19 @@ import com.coldmint.rust.core.interfaces.EnglishMode
import com.coldmint.rust.core.tool.LineParser import com.coldmint.rust.core.tool.LineParser
import com.coldmint.rust.core.tool.LocalVariableName import com.coldmint.rust.core.tool.LocalVariableName
import com.coldmint.rust.pro.R import com.coldmint.rust.pro.R
import io.github.rosemoe.sora.data.NavigationItem import io.github.rosemoe.sora.lang.styling.Span
import io.github.rosemoe.sora.data.Span import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
import io.github.rosemoe.sora.interfaces.CodeAnalyzer
import io.github.rosemoe.sora.text.TextAnalyzeResult
import io.github.rosemoe.sora.text.TextAnalyzer
import io.github.rosemoe.sora.widget.EditorColorScheme
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.collections.HashSet import kotlin.collections.HashSet
import kotlin.text.StringBuilder import kotlin.text.StringBuilder
class RustAnalyzer() : CodeAnalyzer,EnglishMode { @Deprecated("已过时")
private val labels: ArrayList<NavigationItem> by lazy { class RustAnalyzer() : EnglishMode {
ArrayList() // private val labels: ArrayList<NavigationItem> by lazy {
} // ArrayList()
// }
companion object { companion object {
/** /**
@ -57,292 +54,292 @@ class RustAnalyzer() : CodeAnalyzer,EnglishMode {
* @param colors TextAnalyzeResult * @param colors TextAnalyzeResult
* @param delegate Delegate * @param delegate Delegate
*/ */
override fun analyze( // override fun analyze(
content: CharSequence, // content: CharSequence,
colors: TextAnalyzeResult, // colors: TextAnalyzeResult,
delegate: TextAnalyzer.AnalyzeThread.Delegate // delegate: TextAnalyzer.AnalyzeThread.Delegate
) { // ) {
//添加换行符作为结束符 // //添加换行符作为结束符
val str = content.toString() + "\n" // val str = content.toString() + "\n"
if (str.isBlank() || codeDataBase == null) { // if (str.isBlank() || codeDataBase == null) {
return // return
} // }
val lineParser = LineParser() // val lineParser = LineParser()
lineParser.parserSymbol = true // lineParser.parserSymbol = true
lineParser.symbol = "_" // lineParser.symbol = "_"
colors.addNormalIfNull() // colors.addNormalIfNull()
if (delegate.shouldAnalyze()) { // if (delegate.shouldAnalyze()) {
labels.clear() // labels.clear()
localVariableNameList.clear() // localVariableNameList.clear()
var codeBlockType: CompileConfiguration.CodeBlockType = // var codeBlockType: CompileConfiguration.CodeBlockType =
CompileConfiguration.CodeBlockType.Key // CompileConfiguration.CodeBlockType.Key
var lineNum = 0 // var lineNum = 0
val keyBuilder = StringBuilder() // val keyBuilder = StringBuilder()
val valueBuilder = StringBuilder() // val valueBuilder = StringBuilder()
var column = 0 // var column = 0
var startIndex = -1 // var startIndex = -1
//是否执行二次渲染,用于判断值是否合法 // //是否执行二次渲染,用于判断值是否合法
var lineRendering = true // var lineRendering = true
var lastSection: String? = null // var lastSection: String? = null
val stringTokenizer = StringTokenizer(str, CodeCompiler2.split, true) // val stringTokenizer = StringTokenizer(str, CodeCompiler2.split, true)
while (stringTokenizer.hasMoreTokens()) { // while (stringTokenizer.hasMoreTokens()) {
val code = stringTokenizer.nextToken() // val code = stringTokenizer.nextToken()
when (code) { // when (code) {
"\n" -> { // "\n" -> {
if (codeBlockType != CompileConfiguration.CodeBlockType.Note && codeBlockType != CompileConfiguration.CodeBlockType.Section && lineRendering) { // if (codeBlockType != CompileConfiguration.CodeBlockType.Note && codeBlockType != CompileConfiguration.CodeBlockType.Section && lineRendering) {
renderLineContent( // renderLineContent(
startIndex, // startIndex,
lastSection, // lastSection,
colors, // colors,
lineNum, // lineNum,
keyBuilder, // keyBuilder,
valueBuilder // valueBuilder
) // )
} // }
lineNum++ // lineNum++
column = 0 // column = 0
lineRendering = true // lineRendering = true
startIndex = -1 // startIndex = -1
codeBlockType = CompileConfiguration.CodeBlockType.Key // codeBlockType = CompileConfiguration.CodeBlockType.Key
keyBuilder.clear() // keyBuilder.clear()
valueBuilder.clear() // valueBuilder.clear()
} // }
" ", ",", "/" -> if (codeBlockType != CompileConfiguration.CodeBlockType.Note) { // " ", ",", "/" -> if (codeBlockType != CompileConfiguration.CodeBlockType.Note) {
if (codeBlockType == CompileConfiguration.CodeBlockType.Value) { // if (codeBlockType == CompileConfiguration.CodeBlockType.Value) {
valueBuilder.append(code) // valueBuilder.append(code)
} // }
column += code.length // column += code.length
} // }
":" -> { // ":" -> {
if (lastSection != null && codeBlockType != CompileConfiguration.CodeBlockType.Note) { // if (lastSection != null && codeBlockType != CompileConfiguration.CodeBlockType.Note) {
codeBlockType = CompileConfiguration.CodeBlockType.Value // codeBlockType = CompileConfiguration.CodeBlockType.Value
colors.addIfNeeded(lineNum, column, EditorColorScheme.TEXT_NORMAL) // colors.addIfNeeded(lineNum, column, EditorColorScheme.TEXT_NORMAL)
column += code.length // column += code.length
} // }
} // }
"\r" -> { // "\r" -> {
} // }
"(", ")", "=", "%", "." -> if (codeBlockType != CompileConfiguration.CodeBlockType.Note) { // "(", ")", "=", "%", "." -> if (codeBlockType != CompileConfiguration.CodeBlockType.Note) {
if (codeBlockType == CompileConfiguration.CodeBlockType.Value || codeBlockType == CompileConfiguration.CodeBlockType.VariableName) { // if (codeBlockType == CompileConfiguration.CodeBlockType.Value || codeBlockType == CompileConfiguration.CodeBlockType.VariableName) {
valueBuilder.append(code) // valueBuilder.append(code)
} // }
column += code.length // column += code.length
} // }
"}" -> { // "}" -> {
if (codeBlockType != CompileConfiguration.CodeBlockType.Note) { // if (codeBlockType != CompileConfiguration.CodeBlockType.Note) {
if (codeBlockType == CompileConfiguration.CodeBlockType.VariableName) { // if (codeBlockType == CompileConfiguration.CodeBlockType.VariableName) {
colors.addIfNeeded( // colors.addIfNeeded(
lineNum, // lineNum,
column, // column,
EditorColorScheme.TEXT_NORMAL // EditorColorScheme.TEXT_NORMAL
) // )
codeBlockType = CompileConfiguration.CodeBlockType.Value // codeBlockType = CompileConfiguration.CodeBlockType.Value
valueBuilder.append(code) // valueBuilder.append(code)
} // }
column += code.length // column += code.length
} // }
} // }
"{" -> { // "{" -> {
if (codeBlockType != CompileConfiguration.CodeBlockType.Note) { // if (codeBlockType != CompileConfiguration.CodeBlockType.Note) {
if (codeBlockType == CompileConfiguration.CodeBlockType.Value) { // if (codeBlockType == CompileConfiguration.CodeBlockType.Value) {
lineRendering = false // lineRendering = false
codeBlockType = CompileConfiguration.CodeBlockType.VariableName // codeBlockType = CompileConfiguration.CodeBlockType.VariableName
valueBuilder.append(code) // valueBuilder.append(code)
} // }
column += code.length // column += code.length
} // }
} // }
else -> if (codeBlockType != CompileConfiguration.CodeBlockType.Note) { // else -> if (codeBlockType != CompileConfiguration.CodeBlockType.Note) {
if (codeBlockType == CompileConfiguration.CodeBlockType.VariableName) { // if (codeBlockType == CompileConfiguration.CodeBlockType.VariableName) {
val symbol = "." // val symbol = "."
val symbolIndex = code.indexOf(symbol) // val symbolIndex = code.indexOf(symbol)
if (symbolIndex > -1) { // if (symbolIndex > -1) {
//渲染 ${节.键} 的格式 // //渲染 ${节.键} 的格式
val sectionSpan = // val sectionSpan =
Span.obtain(column, EditorColorScheme.FUNCTION_NAME) // Span.obtain(column, EditorColorScheme.FUNCTION_NAME)
colors.add( // colors.add(
lineNum, // lineNum,
sectionSpan // sectionSpan
) // )
val symbolSpan = // val symbolSpan =
Span.obtain( // Span.obtain(
column + symbolIndex, // column + symbolIndex,
EditorColorScheme.TEXT_NORMAL // EditorColorScheme.TEXT_NORMAL
) // )
colors.add( // colors.add(
lineNum, // lineNum,
symbolSpan // symbolSpan
) // )
val keySpan = Span.obtain( // val keySpan = Span.obtain(
column + symbolIndex + symbol.length, // column + symbolIndex + symbol.length,
EditorColorScheme.KEYWORD // EditorColorScheme.KEYWORD
) // )
colors.add(lineNum, keySpan) // colors.add(lineNum, keySpan)
//
// } else {
// //渲染 ${变量名} 的个格式
// localVariableNameList.add(LocalVariableName(code, lineNum))
// val span = Span.obtain(column, EditorColorScheme.LITERAL)
// colors.add(
// lineNum,
// span
// )
// }
// } else {
// //不是变量名的话
// if (code.startsWith("#")) {
// codeBlockType = CompileConfiguration.CodeBlockType.Note
// colors.addIfNeeded(lineNum, column, EditorColorScheme.COMMENT)
// } else if (code.startsWith("[") && code.endsWith("]")) {
// codeBlockType = CompileConfiguration.CodeBlockType.Section
// lastSection = code
// labels.add(
// NavigationItem(
// lineNum,
// code.substring(1, code.length - 1)
// )
// )
// val span = Span.obtain(0, EditorColorScheme.FUNCTION_NAME)
// colors.add(
// lineNum,
// span
// )
// } else {
// if (lastSection != null) {
// //当代码属于某个节时渲染
// if (codeBlockType == CompileConfiguration.CodeBlockType.Key) {
// keyBuilder.append(code)
// if (hasCode(code)) {
// colors.addIfNeeded(
// lineNum,
// column,
// EditorColorScheme.KEYWORD
// )
// val trueCode = getCode(code)
// if (trueCode == "@define" || trueCode == "@global") {
// codeBlockType =
// CompileConfiguration.CodeBlockType.VariableName
// }
// } else {
// if (code.contains("_")) {
// val parser = LineParser(code)
// parser.symbol = "_"
// parser.parserSymbol = true
// //局部渲染偏移
// var offset = 0
// parser.analyse { temLineNum, lineData, isEnd ->
// if (lineData == parser.symbol) {
// //是符号,添加符号跨度
// colors.addIfNeeded(
// lineNum, column + offset,
// EditorColorScheme.TEXT_NORMAL
// )
// } else {
// if (hasCode(lineData)) {
// colors.addIfNeeded(
// lineNum,
// column + offset,
// EditorColorScheme.KEYWORD
// )
// } else {
// colors.addIfNeeded(
// lineNum, column + offset,
// EditorColorScheme.TEXT_NORMAL
// )
// }
// }
// offset += lineData.length
// true
// }
// } else {
// val span =
// Span.obtain(
// column,
// EditorColorScheme.TEXT_NORMAL
// )
// colors.add(
// lineNum,
// span
// )
// }
// }
// } else {
// if (startIndex == -1) {
// startIndex = column
// }
// valueBuilder.append(getCode(code))
// }
// }
// }
// }
// column += code.length
// }
// }
// }
// colors.navigation = labels
// colors.determine(lineNum)
// }
// }
} else { // /**
//渲染 ${变量名} 的个格式 // * 渲染行内容
localVariableNameList.add(LocalVariableName(code, lineNum)) // * @param startIndex Int 冒号的起初位置
val span = Span.obtain(column, EditorColorScheme.LITERAL) // * @param lastSection String? 最后的节
colors.add( // * @param colors TextAnalyzeResult 颜色渲染
lineNum, // * @param lineNum Int 行号
span // * @param keyBuilder StringBuilder
) // * @param valueBuilder StringBuilder
} // */
} else { // private fun renderLineContent(
//不是变量名的话 // startIndex: Int,
if (code.startsWith("#")) { // lastSection: String?,
codeBlockType = CompileConfiguration.CodeBlockType.Note // colors: TextAnalyzeResult,
colors.addIfNeeded(lineNum, column, EditorColorScheme.COMMENT) // lineNum: Int,
} else if (code.startsWith("[") && code.endsWith("]")) { // keyBuilder: StringBuilder,
codeBlockType = CompileConfiguration.CodeBlockType.Section // valueBuilder: StringBuilder
lastSection = code // ) {
labels.add( // //不在任何节内
NavigationItem( // if (lastSection == null) {
lineNum, // val valueErrorSpan =
code.substring(1, code.length - 1) // Span.obtain(
) // 0,
) // EditorColorScheme.FUNCTION_NAME
val span = Span.obtain(0, EditorColorScheme.FUNCTION_NAME) // )
colors.add( // valueErrorSpan.problemFlags = Span.FLAG_ERROR
lineNum, // colors.add(lineNum, valueErrorSpan)
span // return
) // }
} else { // if (startIndex > -1) {
if (lastSection != null) { // //值是否合法
//当代码属于某个节时渲染 // if (isValid(
if (codeBlockType == CompileConfiguration.CodeBlockType.Key) { // keyBuilder.toString(),
keyBuilder.append(code) // valueBuilder.toString().trim()
if (hasCode(code)) { // )
colors.addIfNeeded( // ) {
lineNum, // if (hasCode(valueBuilder.toString().trim(), true)) {
column, // colors.addIfNeeded(
EditorColorScheme.KEYWORD // lineNum,
) // startIndex,
val trueCode = getCode(code) // EditorColorScheme.KEYWORD
if (trueCode == "@define" || trueCode == "@global") { // )
codeBlockType = // } else {
CompileConfiguration.CodeBlockType.VariableName // colors.addIfNeeded(
} // lineNum,
} else { // startIndex,
if (code.contains("_")) { // EditorColorScheme.TEXT_NORMAL
val parser = LineParser(code) // )
parser.symbol = "_" // }
parser.parserSymbol = true // } else {
//局部渲染偏移 // val valueErrorSpan =
var offset = 0 // Span.obtain(
parser.analyse { temLineNum, lineData, isEnd -> // startIndex,
if (lineData == parser.symbol) { // EditorColorScheme.FUNCTION_NAME
//是符号,添加符号跨度 // )
colors.addIfNeeded( // valueErrorSpan.problemFlags = Span.FLAG_ERROR
lineNum, column + offset, // colors.add(lineNum, valueErrorSpan)
EditorColorScheme.TEXT_NORMAL // }
) // }
} else { // }
if (hasCode(lineData)) {
colors.addIfNeeded(
lineNum,
column + offset,
EditorColorScheme.KEYWORD
)
} else {
colors.addIfNeeded(
lineNum, column + offset,
EditorColorScheme.TEXT_NORMAL
)
}
}
offset += lineData.length
true
}
} else {
val span =
Span.obtain(
column,
EditorColorScheme.TEXT_NORMAL
)
colors.add(
lineNum,
span
)
}
}
} else {
if (startIndex == -1) {
startIndex = column
}
valueBuilder.append(getCode(code))
}
}
}
}
column += code.length
}
}
}
colors.navigation = labels
colors.determine(lineNum)
}
}
/**
* 渲染行内容
* @param startIndex Int 冒号的起初位置
* @param lastSection String? 最后的节
* @param colors TextAnalyzeResult 颜色渲染
* @param lineNum Int 行号
* @param keyBuilder StringBuilder
* @param valueBuilder StringBuilder
*/
private fun renderLineContent(
startIndex: Int,
lastSection: String?,
colors: TextAnalyzeResult,
lineNum: Int,
keyBuilder: StringBuilder,
valueBuilder: StringBuilder
) {
//不在任何节内
if (lastSection == null) {
val valueErrorSpan =
Span.obtain(
0,
EditorColorScheme.FUNCTION_NAME
)
valueErrorSpan.problemFlags = Span.FLAG_ERROR
colors.add(lineNum, valueErrorSpan)
return
}
if (startIndex > -1) {
//值是否合法
if (isValid(
keyBuilder.toString(),
valueBuilder.toString().trim()
)
) {
if (hasCode(valueBuilder.toString().trim(), true)) {
colors.addIfNeeded(
lineNum,
startIndex,
EditorColorScheme.KEYWORD
)
} else {
colors.addIfNeeded(
lineNum,
startIndex,
EditorColorScheme.TEXT_NORMAL
)
}
} else {
val valueErrorSpan =
Span.obtain(
startIndex,
EditorColorScheme.FUNCTION_NAME
)
valueErrorSpan.problemFlags = Span.FLAG_ERROR
colors.add(lineNum, valueErrorSpan)
}
}
}
/** /**

View File

@ -0,0 +1,433 @@
package com.coldmint.rust.pro.edit
import android.content.Context
import android.util.Log
import com.coldmint.rust.core.CodeCompiler2
import com.coldmint.rust.core.SourceFile
import com.coldmint.rust.core.database.code.CodeDataBase
import com.coldmint.rust.core.database.code.SectionInfo
import com.coldmint.rust.core.database.file.FileDataBase
import com.coldmint.rust.core.interfaces.EnglishMode
import com.coldmint.rust.core.tool.DebugHelper
import com.coldmint.rust.core.tool.LineParser
import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.CompletionItemConverter
import io.github.rosemoe.sora.lang.completion.CompletionItem
import io.github.rosemoe.sora.lang.completion.CompletionPublisher
import io.github.rosemoe.sora.widget.CodeEditor
import java.util.ArrayList
import java.util.concurrent.Executors
/**
* @author Cold Mint
* @date 2022/1/25 17:32
*/
class RustAutoComplete(val context: Context) : EnglishMode {
private val debugKey = "自动完成器"
private var codeDataBase: CodeDataBase? = null
private val executorService = Executors.newCachedThreadPool()
private var fileDataBase: FileDataBase? = null
private var codeEditor: CodeEditor? = null
private var sectionNameMap: HashMap<String, String> = HashMap()
private val lineParser by lazy {
val tem = LineParser()
tem.symbol = ","
tem
}
private val identifiersPromptNumber: Int by lazy {
AppSettings.getValue(AppSettings.Setting.IdentifiersPromptNumber, 40)
}
//类型转换器
private val completionItemConverter: CompletionItemConverter by lazy {
CompletionItemConverter.instance.init(context)
}
companion object {
var keyWord = ""
}
/**
* 是否为英文模式
*/
private var isEnglishMode = false
/**
* 设置源文件目录
* @param sourceFolder String
*/
fun setSourceFolder(sourceFolder: String) {
DebugHelper.printLog(debugKey, "已设置源文件目录" + sourceFolder, "设置源文件目录")
completionItemConverter.setSourceFilePath(sourceFolder)
}
/**
* 设置文件转换器配置
* @param sourceFilePath String
* @param rootCodeName String
* @param modFolder String
*/
fun setConfigurationFileConversion(
sourceFilePath: String,
rootCodeName: String,
modFolder: String
) {
completionItemConverter.configurationFileConversion(sourceFilePath, rootCodeName, modFolder)
}
/**
*设置文件数据库
* @param fileDataBase FileDataBase?
*/
fun setFileDataBase(fileDataBase: FileDataBase?) {
this.fileDataBase = fileDataBase
}
fun setCodeDataBase(codeDataBase: CodeDataBase) {
this.codeDataBase = codeDataBase
}
/**
* 设置代码编辑器
* @param codeEditor CodeEditor?
*/
fun setCodeEditor(codeEditor: CodeEditor?) {
this.codeEditor = codeEditor
}
/**
* 获取节类型(永远返回英文)
* @param section String
* @return String
*/
fun getSectionType(section: String): String {
if (sectionNameMap.containsKey(section)) {
return sectionNameMap[section] ?: SourceFile.getSectionType(section)
}
val result = if (isEnglishMode) {
SourceFile.getSectionType(section)
} else {
val sectionInfo = codeDataBase!!.getSectionDao()
.findSectionInfoByTranslate(SourceFile.getSectionType(section))
sectionInfo?.code ?: SourceFile.getSectionType(section)
}
sectionNameMap[section] = result
return result
}
/**
* 请求自动完成
* @param prefix String?
* @param completionPublisher CompletionPublisher
* @param line Int
* @param column Int
*/
fun requireAutoComplete(
prefix: String?,
completionPublisher: CompletionPublisher,
line: Int,
column: Int
) {
if (codeEditor == null) {
throw NullPointerException("未绑定编辑框")
}
if (fileDataBase == null) {
throw NullPointerException("未绑定文件数据库")
}
if (codeDataBase == null) {
throw NullPointerException("未绑定代码数据库")
}
if (prefix == null) {
return
}
keyWord = prefix
val temCodeEditor: CodeEditor = codeEditor!!
val lineData = temCodeEditor.text.getLineString(line)
if (lineData.startsWith('[')) {
//搜索节
val name = lineData.subSequence(1, lineData.length).toString()
val list = if (isEnglishMode) {
codeDataBase!!.getSectionDao()
.searchSectionInfoByCode(name, limitNum = identifiersPromptNumber)
} else {
codeDataBase!!.getSectionDao()
.searchSectionInfoByTranslate(name, limitNum = identifiersPromptNumber)
}
list?.forEach {
completionPublisher.addItem(completionItemConverter.sectionInfoToCompletionItem(it))
}
} else {
val key = ":"
val keyIndex = lineData.lastIndexOf(key)
if (keyIndex > -1) {
//检查是否可响应变量
val start = "\${"
val end = "}"
val startIndex = lineData.lastIndexOf(start)
if (startIndex > -1) {
val endIndex = lineData.lastIndexOf(end)
if (endIndex < startIndex) {
//如果}的位置小于${的位置,说明没有闭合
val keyWord =
lineData.subSequence(startIndex + start.length, lineData.length)
.toString()
val previousText =
lineData.subSequence(keyIndex + key.length, startIndex).toString()
if (keyWord.isNotBlank()) {
RustAnalyzer.localVariableNameList.forEach {
if (it.name.contains(keyWord)) {
completionPublisher.addItem(
completionItemConverter.localVariableNameToCompletionItem(
it, previousText
)
)
}
}
} else {
RustAnalyzer.localVariableNameList.forEach {
completionPublisher.addItem(
completionItemConverter.localVariableNameToCompletionItem(
it, previousText
)
)
}
}
RustAutoComplete.keyWord = keyWord
return
}
}
// val value =
// lineData.subSequence(keyIndex + key.length, lineData.length).toString().trim()
// Log.d("值", value)
//搜索值
// frontIndex 前面冒号的位置
val frontIndex = lineData.lastIndexOf(key, keyIndex - key.length)
val keyValue = if (frontIndex > -1) {
lineData.subSequence(frontIndex + key.length, keyIndex)
} else {
lineData.subSequence(0, keyIndex)
}
val codeInfo =
if (isEnglishMode) {
codeDataBase!!.getCodeDao().findCodeByCode(keyValue.toString())
} else {
codeDataBase!!.getCodeDao().findCodeByTranslate(keyValue.toString())
}
DebugHelper.printLog(
debugKey,
"值[" + keyValue + "]英文模式[" + isEnglishMode + "]代码信息[" + codeInfo + "]关键字[" + prefix + "]",
"值检查"
)
if (codeInfo != null) {
val typeInfo = completionItemConverter.getValueType(codeInfo.type)
//获取代码的关联列表
if (typeInfo != null && typeInfo.list.isNotBlank()) {
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]自动提示列表[" + typeInfo.list + "]", "关联提示"
)
lineParser.text = typeInfo.list
lineParser.analyse { lineNum, lineData, isEnd ->
//分析关联提示项目
val temCodeInfo =
codeDataBase!!.getCodeDao().findCodeByCode(lineData)
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]是代码[" + (temCodeInfo != null) + "]",
"关联提示列表分析"
)
if (temCodeInfo == null) {
if (lineData.startsWith("@file(") && lineData.endsWith(")")) {
val fileType = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
)
val fileInfo = fileDataBase!!.getFileInfoDao()
.searchFileInfoByNameAndType(
prefix,
fileType.toString(),
identifiersPromptNumber
)
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]搜索了[" + fileType + "]类型的文件,返回了[" + (fileInfo?.size
?: -1) + "]个结果",
"关联提示列表分析"
)
if (fileInfo != null && fileInfo.isNotEmpty()) {
for (fileTable in fileInfo) {
completionPublisher.addItem(
completionItemConverter.fileTableToCompletionItem(
fileTable
)
)
}
}
} else if (lineData.startsWith("@customType(") && lineData.endsWith(
")"
)
) {
//用户自动值类型提示
val customType = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
fileDataBase!!.getValueDao()
.searchValueByKey(
prefix,
customType,
identifiersPromptNumber
)
?.forEach {
completionPublisher.addItem(
completionItemConverter.valueTableToCompletionItem(
it
)
)
}
} else if (lineData.startsWith("@type(") && lineData.endsWith(")")) {
val type = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
val list = if (isEnglishMode
) {
codeDataBase!!.getCodeDao().findCodeByCodeInType(
prefix,
type,
identifiersPromptNumber
)
} else {
codeDataBase!!.getCodeDao().findCodeByTranslateInType(
prefix,
type,
identifiersPromptNumber
)
}
DebugHelper.printLog(
debugKey,
"关联了值类型[" + type + "]获取[" + (list?.size ?: -1) + "]个结果",
"值类型引用"
)
if (!list.isNullOrEmpty()) {
list.forEach {
completionPublisher.addItem(
completionItemConverter.codeInfoToCompletionItem(
it
)
)
}
}
} else if (lineData.startsWith("@section") && lineData.endsWith(
")"
)
) {
val section = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
// codeEditor!!.textAnalyzeResult.navigation.forEach {
// if (section == getSectionType(it.label)) {
// result.add(
// completionItemConverter.navigationItemToCompletionItem(
// it
// )
// )
// }
// }
} else {
//无法分析的关联项目
// result.add(
// CompletionItem(
// lineData,
// String.format(
// completionItemConverter.associatedTip,
// codeInfo.translate
// )
// )
// )
}
} else {
val show = if (isEnglishMode) {
temCodeInfo.code.contains(prefix)
} else {
temCodeInfo.translate.contains(prefix)
}
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]是否包含" + prefix + "关键字[" + show + "]",
"关联提示列表分析"
)
if (show) {
completionPublisher.addItem(
completionItemConverter.codeInfoToCompletionItem(
temCodeInfo
)
)
}
}
true
}
}
}
} else {
//如果不包含:搜索键
// val navigationList = temCodeEditor.textAnalyzeResult.navigation
// var section: String? = null
// if (navigationList != null && navigationList.isNotEmpty()) {
// for (navigation in navigationList) {
// if (navigation.line > line) {
// break
// } else {
// section = navigation.label
// }
// }
// }
// //如果不在任何节内
// if (section == null) {
// return@submit
// }
// val trueSection = getSectionType(section)
// val list = if (isEnglishMode) {
// codeDataBase!!.getCodeDao().findCodeByEnglishCodeKeyFromSection(
// prefix,
// trueSection,
// identifiersPromptNumber
// )
// } else {
// codeDataBase!!.getCodeDao()
// .findCodeByKeyFromSection(prefix, trueSection, identifiersPromptNumber)
// }
// if (list != null && list.isNotEmpty()) {
// list.forEach {
// result.add(
// completionItemConverter.codeInfoToCompletionItem(it)
// )
// }
// }
}
}
}
override fun isEnglishMode(): Boolean {
return isEnglishMode
}
override fun setEnglish(englishMode: Boolean) {
this.isEnglishMode = englishMode
completionItemConverter.setEnglish(englishMode)
}
}

View File

@ -1,439 +0,0 @@
package com.coldmint.rust.pro.edit
import android.content.Context
import android.util.Log
import com.coldmint.rust.core.CodeCompiler2
import com.coldmint.rust.core.SourceFile
import com.coldmint.rust.core.database.code.CodeDataBase
import com.coldmint.rust.core.database.code.SectionInfo
import com.coldmint.rust.core.database.file.FileDataBase
import com.coldmint.rust.core.interfaces.EnglishMode
import com.coldmint.rust.core.tool.DebugHelper
import com.coldmint.rust.core.tool.LineParser
import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.CompletionItemConverter
import io.github.rosemoe.sora.data.CompletionItem
import io.github.rosemoe.sora.interfaces.AutoCompleteProvider
import io.github.rosemoe.sora.text.TextAnalyzeResult
import io.github.rosemoe.sora.widget.CodeEditor
import java.util.ArrayList
import java.util.concurrent.Executors
/**
* @author Cold Mint
* @date 2022/1/25 17:32
*/
class RustAutoComplete2(val context: Context) : AutoCompleteProvider, EnglishMode {
private val result: ArrayList<CompletionItem> by lazy {
ArrayList()
}
private val debugKey = "自动完成器"
private var codeDataBase: CodeDataBase? = null
private val executorService = Executors.newCachedThreadPool()
private var fileDataBase: FileDataBase? = null
private var codeEditor: CodeEditor? = null
private var sectionNameMap: HashMap<String, String> = HashMap()
private val lineParser by lazy {
val tem = LineParser()
tem.symbol = ","
tem
}
private val identifiersPromptNumber: Int by lazy {
AppSettings.getValue(AppSettings.Setting.IdentifiersPromptNumber, 40)
}
//类型转换器
private val completionItemConverter: CompletionItemConverter by lazy {
CompletionItemConverter.instance.init(context)
}
companion object {
var keyWord = ""
}
/**
* 是否为英文模式
*/
private var isEnglishMode = false
/**
* 设置源文件目录
* @param sourceFolder String
*/
fun setSourceFolder(sourceFolder: String) {
DebugHelper.printLog(debugKey, "已设置源文件目录" + sourceFolder, "设置源文件目录")
completionItemConverter.setSourceFilePath(sourceFolder)
}
/**
* 设置文件转换器配置
* @param sourceFilePath String
* @param rootCodeName String
* @param modFolder String
*/
fun setConfigurationFileConversion(
sourceFilePath: String,
rootCodeName: String,
modFolder: String
) {
completionItemConverter.configurationFileConversion(sourceFilePath, rootCodeName, modFolder)
}
/**
*设置文件数据库
* @param fileDataBase FileDataBase?
*/
fun setFileDataBase(fileDataBase: FileDataBase?) {
this.fileDataBase = fileDataBase
}
fun setCodeDataBase(codeDataBase: CodeDataBase) {
this.codeDataBase = codeDataBase
}
/**
* 设置代码编辑器
* @param codeEditor CodeEditor?
*/
fun setCodeEditor(codeEditor: CodeEditor?) {
this.codeEditor = codeEditor
}
/**
* 获取节类型(永远返回英文)
* @param section String
* @return String
*/
fun getSectionType(section: String): String {
if (sectionNameMap.containsKey(section)) {
return sectionNameMap[section] ?: SourceFile.getSectionType(section)
}
val result = if (isEnglishMode) {
SourceFile.getSectionType(section)
} else {
val sectionInfo = codeDataBase!!.getSectionDao()
.findSectionInfoByTranslate(SourceFile.getSectionType(section))
sectionInfo?.code ?: SourceFile.getSectionType(section)
}
sectionNameMap[section] = result
return result
}
override fun getAutoCompleteItems(
prefix: String?,
analyzeResult: TextAnalyzeResult?,
line: Int,
column: Int
): MutableList<CompletionItem> {
if (codeEditor == null) {
throw NullPointerException("未绑定编辑框")
return ArrayList<CompletionItem>()
}
if (fileDataBase == null) {
throw NullPointerException("未绑定文件数据库")
return ArrayList<CompletionItem>()
}
if (codeDataBase == null) {
throw NullPointerException("未绑定代码数据库")
return ArrayList<CompletionItem>()
}
if (prefix == null) {
return ArrayList<CompletionItem>()
}
keyWord = prefix
val future = executorService.submit {
result.clear()
val temCodeEditor: CodeEditor = codeEditor!!
val lineData = temCodeEditor.text.getLineString(line)
if (lineData.startsWith('[')) {
//搜索节
val name = lineData.subSequence(1, lineData.length).toString()
val list = if (isEnglishMode) {
codeDataBase!!.getSectionDao()
.searchSectionInfoByCode(name, limitNum = identifiersPromptNumber)
} else {
codeDataBase!!.getSectionDao()
.searchSectionInfoByTranslate(name, limitNum = identifiersPromptNumber)
}
list?.forEach {
result.add(completionItemConverter.sectionInfoToCompletionItem(it))
}
} else {
val key = ":"
val keyIndex = lineData.lastIndexOf(key)
if (keyIndex > -1) {
//检查是否可响应变量
val start = "\${"
val end = "}"
val startIndex = lineData.lastIndexOf(start)
if (startIndex > -1) {
val endIndex = lineData.lastIndexOf(end)
if (endIndex < startIndex) {
//如果}的位置小于${的位置,说明没有闭合
val keyWord =
lineData.subSequence(startIndex + start.length, lineData.length)
.toString()
val previousText =
lineData.subSequence(keyIndex + key.length, startIndex).toString()
if (keyWord.isNotBlank()) {
RustAnalyzer.localVariableNameList.forEach {
if (it.name.contains(keyWord)) {
result.add(
completionItemConverter.localVariableNameToCompletionItem(
it, previousText
)
)
}
}
} else {
RustAnalyzer.localVariableNameList.forEach {
result.add(
completionItemConverter.localVariableNameToCompletionItem(
it, previousText
)
)
}
}
RustAutoComplete2.keyWord = keyWord
return@submit
}
}
// val value =
// lineData.subSequence(keyIndex + key.length, lineData.length).toString().trim()
// Log.d("值", value)
//搜索值
// frontIndex 前面冒号的位置
val frontIndex = lineData.lastIndexOf(key, keyIndex - key.length)
val keyValue = if (frontIndex > -1) {
lineData.subSequence(frontIndex + key.length, keyIndex)
} else {
lineData.subSequence(0, keyIndex)
}
val codeInfo =
if (isEnglishMode) {
codeDataBase!!.getCodeDao().findCodeByCode(keyValue.toString())
} else {
codeDataBase!!.getCodeDao().findCodeByTranslate(keyValue.toString())
}
DebugHelper.printLog(
debugKey,
"值[" + keyValue + "]英文模式[" + isEnglishMode + "]代码信息[" + codeInfo + "]关键字[" + prefix + "]",
"值检查"
)
if (codeInfo != null) {
val typeInfo = completionItemConverter.getValueType(codeInfo.type)
//获取代码的关联列表
if (typeInfo != null && typeInfo.list.isNotBlank()) {
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]自动提示列表[" + typeInfo.list + "]", "关联提示"
)
lineParser.text = typeInfo.list
lineParser.analyse { lineNum, lineData, isEnd ->
//分析关联提示项目
val temCodeInfo =
codeDataBase!!.getCodeDao().findCodeByCode(lineData)
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]是代码[" + (temCodeInfo != null) + "]",
"关联提示列表分析"
)
if (temCodeInfo == null) {
if (lineData.startsWith("@file(") && lineData.endsWith(")")) {
val fileType = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
)
val fileInfo = fileDataBase!!.getFileInfoDao()
.searchFileInfoByNameAndType(
prefix,
fileType.toString(),
identifiersPromptNumber
)
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]搜索了[" + fileType + "]类型的文件,返回了[" + (fileInfo?.size
?: -1) + "]个结果",
"关联提示列表分析"
)
if (fileInfo != null && fileInfo.isNotEmpty()) {
for (fileTable in fileInfo) {
result.add(
completionItemConverter.fileTableToCompletionItem(
fileTable
)
)
}
}
} else if (lineData.startsWith("@customType(") && lineData.endsWith(
")"
)
) {
//用户自动值类型提示
val customType = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
fileDataBase!!.getValueDao()
.searchValueByKey(
prefix,
customType,
identifiersPromptNumber
)
?.forEach {
result.add(
completionItemConverter.valueTableToCompletionItem(
it
)
)
}
} else if (lineData.startsWith("@type(") && lineData.endsWith(")")) {
val type = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
val list = if (isEnglishMode
) {
codeDataBase!!.getCodeDao().findCodeByCodeInType(
prefix,
type,
identifiersPromptNumber
)
} else {
codeDataBase!!.getCodeDao().findCodeByTranslateInType(
prefix,
type,
identifiersPromptNumber
)
}
DebugHelper.printLog(
debugKey,
"关联了值类型[" + type + "]获取[" + (list?.size ?: -1) + "]个结果",
"值类型引用"
)
if (!list.isNullOrEmpty()) {
list.forEach {
result.add(
completionItemConverter.codeInfoToCompletionItem(
it
)
)
}
}
} else if (lineData.startsWith("@section") && lineData.endsWith(
")"
)
) {
val section = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
codeEditor!!.textAnalyzeResult.navigation.forEach {
if (section == getSectionType(it.label)) {
result.add(
completionItemConverter.navigationItemToCompletionItem(
it
)
)
}
}
} else {
//无法分析的关联项目
result.add(
CompletionItem(
lineData,
String.format(
completionItemConverter.associatedTip,
codeInfo.translate
)
)
)
}
} else {
val show = if (isEnglishMode) {
temCodeInfo.code.contains(prefix)
} else {
temCodeInfo.translate.contains(prefix)
}
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]是否包含" + prefix + "关键字[" + show + "]",
"关联提示列表分析"
)
if (show) {
result.add(
completionItemConverter.codeInfoToCompletionItem(
temCodeInfo
)
)
}
}
true
}
}
}
} else {
//如果不包含:搜索键
val navigationList = temCodeEditor.textAnalyzeResult.navigation
var section: String? = null
if (navigationList != null && navigationList.isNotEmpty()) {
for (navigation in navigationList) {
if (navigation.line > line) {
break
} else {
section = navigation.label
}
}
}
//如果不在任何节内
if (section == null) {
return@submit
}
val trueSection = getSectionType(section)
val list = if (isEnglishMode) {
codeDataBase!!.getCodeDao().findCodeByEnglishCodeKeyFromSection(
prefix,
trueSection,
identifiersPromptNumber
)
} else {
codeDataBase!!.getCodeDao()
.findCodeByKeyFromSection(prefix, trueSection, identifiersPromptNumber)
}
if (list != null && list.isNotEmpty()) {
list.forEach {
result.add(
completionItemConverter.codeInfoToCompletionItem(it)
)
}
}
}
}
}
return if (future.get() == null) {
result
} else {
ArrayList<CompletionItem>()
}
}
override fun isEnglishMode(): Boolean {
return isEnglishMode
}
override fun setEnglish(englishMode: Boolean) {
this.isEnglishMode = englishMode
completionItemConverter.setEnglish(englishMode)
}
}

View File

@ -0,0 +1,16 @@
package com.coldmint.rust.pro.edit
import com.coldmint.rust.core.dataBean.CompileConfiguration
/**
* Rust代码标记
* @property offset Int
* @property codeBlockType CodeBlockType
*/
class RustCodeToken(
var offset: Int = 0,
var codeBlockType: CompileConfiguration.CodeBlockType = CompileConfiguration.CodeBlockType.Note
) {
}

View File

@ -1,29 +1,30 @@
package com.coldmint.rust.pro.edit package com.coldmint.rust.pro.edit
import android.content.DialogInterface
import android.graphics.Color import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import android.view.ViewGroup import android.view.ViewGroup
import android.view.LayoutInflater import android.view.LayoutInflater
import com.coldmint.rust.pro.R
import android.widget.TextView
import android.graphics.drawable.Drawable
import android.text.SpannableString
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.Spanned import android.text.Spanned
import android.text.style.StyleSpan import android.text.style.StyleSpan
import android.view.View import android.view.View
import android.widget.ImageView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import android.util.TypedValue import android.util.TypedValue
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.coldmint.rust.pro.databinding.EditItemBinding import com.coldmint.rust.pro.databinding.EditItemBinding
import com.coldmint.rust.pro.tool.GlobalMethod import com.coldmint.rust.pro.tool.GlobalMethod
import io.github.rosemoe.sora.widget.EditorCompletionAdapter import io.github.rosemoe.sora.widget.component.EditorCompletionAdapter
import java.util.* import java.util.*
/**
* Rust完成适配器
* @property layoutInflater (LayoutInflater..LayoutInflater?)
* @property spannableStringBuilder SpannableStringBuilder
* @property colorSpan ForegroundColorSpan
* @property bold StyleSpan
*/
class RustCompletionAdapter : EditorCompletionAdapter() { class RustCompletionAdapter : EditorCompletionAdapter() {
private val layoutInflater by lazy { private val layoutInflater by lazy {
LayoutInflater.from(context) LayoutInflater.from(context)
@ -39,20 +40,20 @@ class RustCompletionAdapter : EditorCompletionAdapter() {
isCurrentCursorPosition: Boolean isCurrentCursorPosition: Boolean
): View { ): View {
val editItem = EditItemBinding.inflate(layoutInflater, parent, false) val editItem = EditItemBinding.inflate(layoutInflater, parent, false)
val completionItem = getItem(position) val completionItem = getItem(position) as RustCompletionItem
spannableStringBuilder.clear() spannableStringBuilder.clear()
val label = completionItem.label val label = completionItem.label.toString()
spannableStringBuilder.append(label) spannableStringBuilder.append(label)
//节补丁 //节补丁
if (RustAutoComplete2.keyWord.startsWith('[') && RustAutoComplete2.keyWord.length > 1) { if (RustAutoComplete.keyWord.startsWith('[') && RustAutoComplete.keyWord.length > 1) {
RustAutoComplete2.keyWord = RustAutoComplete.keyWord =
RustAutoComplete2.keyWord.subSequence(1, RustAutoComplete2.keyWord.length) RustAutoComplete.keyWord.subSequence(1, RustAutoComplete.keyWord.length)
.toString() .toString()
} }
val start = label.lowercase(Locale.getDefault()) val start = label.lowercase(Locale.getDefault())
.indexOf(RustAutoComplete2.keyWord.lowercase(Locale.getDefault())) .indexOf(RustAutoComplete.keyWord.lowercase(Locale.getDefault()))
if (start > -1) { if (start > -1) {
val end = start + RustAutoComplete2.keyWord.length val end = start + RustAutoComplete.keyWord.length
spannableStringBuilder.setSpan( spannableStringBuilder.setSpan(
colorSpan, colorSpan,
start, start,
@ -63,8 +64,8 @@ class RustCompletionAdapter : EditorCompletionAdapter() {
} }
editItem.titleView.text = spannableStringBuilder editItem.titleView.text = spannableStringBuilder
editItem.contentView.text = completionItem.desc editItem.contentView.text = completionItem.desc
if (completionItem.extrasData != null && completionItem.extrasData.containsKey("sub")) { if (completionItem.subtitle != null) {
editItem.subTitleView.text = completionItem.extrasData.getString("sub") editItem.subTitleView.text = completionItem.subtitle
} else { } else {
editItem.subTitleView.isVisible = false editItem.subTitleView.isVisible = false
} }

View File

@ -0,0 +1,54 @@
package com.coldmint.rust.pro.edit
import android.graphics.drawable.Drawable
import io.github.rosemoe.sora.lang.completion.CompletionItem
import io.github.rosemoe.sora.text.Content
import io.github.rosemoe.sora.widget.CodeEditor
/**
* Rust完成器对象
* @property label String
* @constructor
*/
class RustCompletionItem(var title: String) : CompletionItem(title) {
init {
label = title
}
constructor(title: String, commit: String, subtitle: String) : this(commit) {
this.title = title
this.label = commit
this.subtitle = subtitle
}
constructor(title: String, subtitle: String, icon: Drawable?) : this(title) {
this.title = title
this.label = title
this.subtitle = subtitle
}
constructor(title: String, commit: String, sub: String, icon: Drawable?) : this(commit) {
this.title = title
this.label = commit
this.subtitle = sub
this.icon = icon
}
var cursorOffset: Int = 0
var subtitle: String? = null
/**
* 执行完成
* @param p0 CodeEditor
* @param p1 Content
* @param p2 Int
* @param p3 Int
*/
override fun performCompletion(p0: CodeEditor?, p1: Content?, p2: Int, p3: Int) {
}
}

View File

@ -0,0 +1,27 @@
package com.coldmint.rust.pro.edit
import io.github.rosemoe.sora.lang.format.Formatter
import io.github.rosemoe.sora.text.Content
import io.github.rosemoe.sora.text.TextRange
class RustFormatter : Formatter {
override fun format(p0: Content, p1: TextRange) {
}
override fun formatRegion(p0: Content, p1: TextRange, p2: TextRange) {
}
override fun setReceiver(p0: Formatter.FormatResultReceiver?) {
}
override fun isRunning(): Boolean {
return false
}
override fun destroy() {
}
}

View File

@ -0,0 +1,133 @@
package com.coldmint.rust.pro.edit
import com.coldmint.rust.core.dataBean.CompileConfiguration
import io.github.rosemoe.sora.lang.analysis.AsyncIncrementalAnalyzeManager
import io.github.rosemoe.sora.lang.analysis.IncrementalAnalyzeManager
import io.github.rosemoe.sora.lang.styling.CodeBlock
import io.github.rosemoe.sora.lang.styling.Span
import io.github.rosemoe.sora.lang.styling.TextStyle
import io.github.rosemoe.sora.text.Content
import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
/**
* Rust增量分析器
*/
class RustIncrementalAnalyzeManager :
AsyncIncrementalAnalyzeManager<Int, RustCodeToken>() {
override fun getInitialState(): Int {
//获取初始状态
return 0
}
override fun stateEquals(state: Int?, another: Int?): Boolean {
return true
}
override fun tokenizeLine(
line: CharSequence?,
state: Int?,
lineIndex: Int
): IncrementalAnalyzeManager.LineTokenizeResult<Int, RustCodeToken> {
if (line.isNullOrBlank()) {
return IncrementalAnalyzeManager.LineTokenizeResult(0, null)
}
val tokens = ArrayList<RustCodeToken>()
if (line.startsWith("#")) {
//是注释
tokens.add(RustCodeToken())
return IncrementalAnalyzeManager.LineTokenizeResult(0, tokens)
}
val index = line.lastIndexOf(':')
if (index > 0) {
//是代码
tokens.add(RustCodeToken(0, CompileConfiguration.CodeBlockType.Key))
tokens.add(RustCodeToken(index, CompileConfiguration.CodeBlockType.Symbol))
tokens.add(RustCodeToken(index + 1, CompileConfiguration.CodeBlockType.Value))
return IncrementalAnalyzeManager.LineTokenizeResult(0, tokens)
}
if (line.startsWith('[') && line.endsWith(']')) {
//是节
tokens.add(RustCodeToken(0, CompileConfiguration.CodeBlockType.Section))
return IncrementalAnalyzeManager.LineTokenizeResult(0, tokens)
}
tokens.add(RustCodeToken())
return IncrementalAnalyzeManager.LineTokenizeResult(0, tokens)
}
override fun generateSpansForLine(tokens: IncrementalAnalyzeManager.LineTokenizeResult<Int, RustCodeToken>?): MutableList<Span> {
val spans = ArrayList<Span>()
val tokenList = tokens?.tokens
if (tokenList == null || tokenList.isEmpty()) {
spans.add(
Span.obtain(
0,
TextStyle.makeStyle(EditorColorScheme.COMMENT)
)
)
return spans
}
tokenList.forEach {
when (it.codeBlockType) {
CompileConfiguration.CodeBlockType.Section -> {
spans.add(
Span.obtain(
it.offset,
TextStyle.makeStyle(
EditorColorScheme.FUNCTION_NAME,
0,
true,
false,
false
)
)
)
}
CompileConfiguration.CodeBlockType.Value -> {
spans.add(
Span.obtain(
it.offset,
TextStyle.makeStyle(EditorColorScheme.COMMENT)
)
)
}
CompileConfiguration.CodeBlockType.Symbol -> {
spans.add(
Span.obtain(
it.offset,
TextStyle.makeStyle(EditorColorScheme.COMMENT)
)
)
}
CompileConfiguration.CodeBlockType.Key -> {
spans.add(
Span.obtain(
it.offset,
TextStyle.makeStyle(EditorColorScheme.KEYWORD)
)
)
}
else -> {
spans.add(
Span.obtain(
it.offset,
TextStyle.makeStyle(EditorColorScheme.COMMENT)
)
)
}
}
}
return spans
}
override fun computeBlocks(
text: Content?,
delegate: CodeBlockAnalyzeDelegate?
): MutableList<CodeBlock> {
return ArrayList<CodeBlock>()
}
}

View File

@ -2,29 +2,42 @@ package com.coldmint.rust.pro.edit
import android.content.Context import android.content.Context
import android.util.Log import android.os.Bundle
import com.coldmint.rust.core.CodeCompiler2
import com.coldmint.rust.core.dataBean.dataset.CodeDataBean
import com.coldmint.rust.core.database.code.CodeDataBase import com.coldmint.rust.core.database.code.CodeDataBase
import com.coldmint.rust.core.database.file.FileDataBase import com.coldmint.rust.core.database.file.FileDataBase
import com.coldmint.rust.core.interfaces.EnglishMode import com.coldmint.rust.core.interfaces.EnglishMode
import com.coldmint.rust.core.tool.DebugHelper
import io.github.rosemoe.sora.data.CompletionItem import io.github.rosemoe.sora.lang.Language
import io.github.rosemoe.sora.interfaces.AutoCompleteProvider import io.github.rosemoe.sora.lang.analysis.AnalyzeManager
import io.github.rosemoe.sora.interfaces.CodeAnalyzer import io.github.rosemoe.sora.lang.completion.CompletionPublisher
import io.github.rosemoe.sora.interfaces.EditorLanguage import io.github.rosemoe.sora.lang.completion.IdentifierAutoComplete
import io.github.rosemoe.sora.interfaces.NewlineHandler import io.github.rosemoe.sora.lang.format.Formatter
import io.github.rosemoe.sora.lang.smartEnter.NewlineHandleResult
import io.github.rosemoe.sora.lang.smartEnter.NewlineHandler
import io.github.rosemoe.sora.text.CharPosition
import io.github.rosemoe.sora.text.Content
import io.github.rosemoe.sora.text.ContentReference
import io.github.rosemoe.sora.text.TextRange
import io.github.rosemoe.sora.widget.CodeEditor import io.github.rosemoe.sora.widget.CodeEditor
import io.github.rosemoe.sora.widget.SymbolPairMatch import io.github.rosemoe.sora.widget.SymbolPairMatch
class RustLanguage( class RustLanguage(
private val context: Context, private val context: Context,
) : EditorLanguage, EnglishMode { ) : Language, EnglishMode {
private val mRustAnalyzer: RustAnalyzer by lazy { private val mRustAnalyzer: RustAnalyzer by lazy {
RustAnalyzer() RustAnalyzer()
} }
private val autoComplete: RustAutoComplete2 = RustAutoComplete2(context)
private val autoComplete by lazy {
RustAutoComplete(context)
}
// private val autoComplete: RustAutoComplete = RustAutoComplete(context)
private var isEnglishMode = false private var isEnglishMode = false
private val rustAnalyzeManager by lazy {
RustIncrementalAnalyzeManager()
}
/** /**
* 设置代码数据库 * 设置代码数据库
@ -32,7 +45,7 @@ class RustLanguage(
*/ */
fun setCodeDataBase(codeDataBase: CodeDataBase) { fun setCodeDataBase(codeDataBase: CodeDataBase) {
mRustAnalyzer.setCodeDataBase(codeDataBase) mRustAnalyzer.setCodeDataBase(codeDataBase)
autoComplete.setCodeDataBase(codeDataBase) // autoComplete.setCodeDataBase(codeDataBase)
} }
/** /**
@ -40,61 +53,83 @@ class RustLanguage(
* @param codeEditor * @param codeEditor
*/ */
fun setCodeEditor(codeEditor: CodeEditor?) { fun setCodeEditor(codeEditor: CodeEditor?) {
autoComplete.setCodeEditor(codeEditor) // autoComplete.setCodeEditor(codeEditor)
} }
fun setFileDataBase(fileDataBase: FileDataBase) { fun setFileDataBase(fileDataBase: FileDataBase) {
autoComplete.setFileDataBase(fileDataBase) // autoComplete.setFileDataBase(fileDataBase)
} }
//语法分析器 //语法分析器
override fun getAnalyzer(): CodeAnalyzer { // override fun getAnalyzer(): CodeAnalyzer {
return mRustAnalyzer // return mRustAnalyzer
} // }
//自动完成器 //自动完成器
override fun getAutoCompleteProvider(): RustAutoComplete2 { // override fun getAutoCompleteProvider(): RustAutoComplete {
return autoComplete // return autoComplete
// }
// /**
// * 是否为自动完成字符
// *
// * @param ch 字符
// * @return 逻辑值
// */
// override fun isAutoCompleteChar(ch: Char): Boolean {
// return when (ch) {
// ':', '.', '_', ' ', ',' -> false
// else -> true
// }
// }
override fun getAnalyzeManager(): AnalyzeManager {
return rustAnalyzeManager
} }
override fun getInterruptionLevel(): Int {
/** return Language.INTERRUPTION_LEVEL_STRONG
* 是否为自动完成字符
*
* @param ch 字符
* @return 逻辑值
*/
override fun isAutoCompleteChar(ch: Char): Boolean {
return when (ch) {
':', '.', '_', ' ', ',' -> false
else -> true
}
} }
//获取分割进度 override fun requireAutoComplete(
override fun getIndentAdvance(content: String): Int { p0: ContentReference,
p1: CharPosition,
p2: CompletionPublisher,
p3: Bundle
) {
val line = p0.getLine(p1.getLine())
p2.addItem(RustCompletionItem("121221"))
p2.updateList()
// autoComplete.requireAutoComplete(line,p2,p1.getLine(),p1.getColumn())
}
override fun getIndentAdvance(p0: ContentReference, p1: Int, p2: Int): Int {
return 0 return 0
} }
//用标签 //用标签
override fun useTab(): Boolean { override fun useTab(): Boolean {
return false return true
} }
//格式化 override fun getFormatter(): Formatter {
override fun format(text: CharSequence): CharSequence { return RustFormatter()
return CodeCompiler2.format(text.toString())
} }
//符号配对之间的匹配 override fun getSymbolPairs(): SymbolPairMatch {
override fun getSymbolPairs(): SymbolPairMatch? { return SymbolPairMatch()
}
override fun getNewlineHandlers(): Array<NewlineHandler>? {
//行处理程序,按下回车时
return null return null
} }
//获取新线的处理程序
override fun getNewlineHandlers(): Array<NewlineHandler> { override fun destroy() {
return arrayOf()
} }
override fun isEnglishMode(): Boolean { override fun isEnglishMode(): Boolean {
@ -103,7 +138,7 @@ class RustLanguage(
override fun setEnglish(englishMode: Boolean) { override fun setEnglish(englishMode: Boolean) {
mRustAnalyzer.setEnglish(englishMode) mRustAnalyzer.setEnglish(englishMode)
autoComplete.setEnglish(englishMode) // autoComplete.setEnglish(englishMode)
isEnglishMode = englishMode isEnglishMode = englishMode
} }

View File

@ -1,19 +1,25 @@
package com.coldmint.rust.pro.fragments package com.coldmint.rust.pro.fragments
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ExpandableListView import android.widget.ExpandableListView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.coldmint.dialog.CoreDialog import com.coldmint.dialog.CoreDialog
import com.coldmint.rust.core.LocalTemplatePackage import com.coldmint.rust.core.LocalTemplatePackage
import com.coldmint.rust.core.dataBean.template.LocalTemplateFile import com.coldmint.rust.core.dataBean.template.LocalTemplateFile
import com.coldmint.rust.core.dataBean.template.Template import com.coldmint.rust.core.dataBean.template.Template
import com.coldmint.rust.core.dataBean.template.TemplatePackage
import com.coldmint.rust.core.tool.FileOperator import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.pro.FileManagerActivity import com.coldmint.rust.pro.FileManagerActivity
import com.coldmint.rust.pro.R import com.coldmint.rust.pro.R
@ -35,8 +41,10 @@ class InstalledTemplateFragment : BaseFragment<FragmentInstalledTemplateBinding>
InstalledTemplateViewModel() InstalledTemplateViewModel()
} }
private lateinit var startTemplateParserActivity: ActivityResultLauncher<Intent>
var mTemplateAdapter: TemplateAdapter? = null
private lateinit var mTemplateAdapter: TemplateAdapter
/** /**
@ -69,19 +77,32 @@ class InstalledTemplateFragment : BaseFragment<FragmentInstalledTemplateBinding>
//这里做关于父项的相关操作...... //这里做关于父项的相关操作......
val numView = view.findViewById<TextView>(R.id.template_num) val numView = view.findViewById<TextView>(R.id.template_num)
val templateClass = val templateClass =
mTemplateAdapter!!.getGroup(groupPosition) as LocalTemplatePackage mTemplateAdapter.getGroup(groupPosition) as TemplatePackage
CoreDialog(requireContext()).setTitle(R.string.template_info) CoreDialog(requireContext()).setTitle(R.string.template_info)
.setMessage( .setMessage(
templateClass.getInfo()?.description templateClass.getDescription()
?: requireContext().getString(R.string.describe) ).setCancelable(false).setPositiveButton(
).setCancelable(false).setPositiveButton(R.string.delete_title) { if (templateClass.isLocal()) {
R.string.delete_title
} else {
R.string.de_subscription
}
) {
numView.setText(R.string.del_moding) numView.setText(R.string.del_moding)
val handler = Handler(Looper.getMainLooper()) templateClass.delete(
val scope = CoroutineScope(Job()) AppSettings.getValue(
scope.launch { AppSettings.Setting.Token,
FileOperator.delete_files(templateClass.directest) ""
handler.post { )
) {
if (it) {
viewModel.loadTemplate(requireContext()) viewModel.loadTemplate(requireContext())
} else {
Toast.makeText(
requireContext(),
R.string.delete_error,
Toast.LENGTH_SHORT
).show()
} }
} }
}.setNegativeButton(R.string.dialog_cancel) { }.setNegativeButton(R.string.dialog_cancel) {
@ -92,11 +113,25 @@ class InstalledTemplateFragment : BaseFragment<FragmentInstalledTemplateBinding>
} }
true true
} }
viewBinding.swipeRefreshLayout.setOnRefreshListener {
viewModel.loadTemplate(requireContext())
viewBinding.swipeRefreshLayout.isRefreshing = false
}
} }
override fun whenViewCreated(inflater: LayoutInflater, savedInstanceState: Bundle?) { override fun whenViewCreated(inflater: LayoutInflater, savedInstanceState: Bundle?) {
initAction() initAction()
startTemplateParserActivity =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
Log.d("启动模板解析器", "收到成功回调,关闭界面。")
requireActivity().finish()
} else {
Log.w("启动模板解析器", "未收到有效回调。")
}
}
viewModel.createPathLiveData.observe(this) { viewModel.createPathLiveData.observe(this) {
var relativePath = FileOperator.getRelativePath( var relativePath = FileOperator.getRelativePath(
it, it,
@ -112,16 +147,24 @@ class InstalledTemplateFragment : BaseFragment<FragmentInstalledTemplateBinding>
(requireContext().getText(R.string.unit_path) as String), (requireContext().getText(R.string.unit_path) as String),
relativePath relativePath
) )
mTemplateAdapter?.setCreatePath(it) if (this::mTemplateAdapter.isInitialized) {
mTemplateAdapter.setCreatePath(it)
Log.d("创建目录观察者", "模板适配器设置目录为${it}")
} else {
Log.e("创建目录观察者", "模板适配器没有设置目录。")
}
} }
viewModel.setLoadCallBack { viewModel.setLoadCallBack {
mTemplateAdapter = TemplateAdapter( mTemplateAdapter = TemplateAdapter(
requireContext(), requireContext(),
viewModel.getGroupData(), viewModel.getGroupData(),
viewModel.getItemData(), viewModel.getItemData(),
viewModel.environmentLanguage viewModel.environmentLanguage, startTemplateParserActivity
) )
viewBinding.expandableList.setAdapter(mTemplateAdapter!!) viewBinding.expandableList.setAdapter(mTemplateAdapter)
val path = viewModel.createPathLiveData.value.toString()
mTemplateAdapter.setCreatePath(path)
Log.d("创建目录观察者", "模板适配器设置目录为${path}")
} }
viewModel.loadTemplate(requireContext()) viewModel.loadTemplate(requireContext())
} }

View File

@ -27,17 +27,25 @@ import com.coldmint.rust.pro.databinding.ModFragmentBinding
import com.coldmint.rust.pro.databinding.ModListItemBinding import com.coldmint.rust.pro.databinding.ModListItemBinding
import com.coldmint.rust.pro.tool.AppSettings import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.GlobalMethod import com.coldmint.rust.pro.tool.GlobalMethod
import com.coldmint.rust.pro.viewmodel.ModViewModel
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.dialog.MaterialDialogs import com.google.android.material.dialog.MaterialDialogs
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import me.zhanghai.android.fastscroll.FastScrollScrollView
import me.zhanghai.android.fastscroll.FastScrollerBuilder
import java.io.File import java.io.File
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.concurrent.thread import kotlin.concurrent.thread
class ModFragment : BaseFragment<ModFragmentBinding>() { class ModFragment : BaseFragment<ModFragmentBinding>() {
val viewModel: ModViewModel by lazy {
ModViewModel()
}
lateinit var modAdapter: ModAdapter lateinit var modAdapter: ModAdapter
val needRecycling by lazy { val needRecycling by lazy {
if (GlobalMethod.isActive) { if (GlobalMethod.isActive) {
@ -49,88 +57,6 @@ class ModFragment : BaseFragment<ModFragmentBinding>() {
false false
} }
} }
val executorService = Executors.newSingleThreadExecutor()
//初始化视图
fun loadMods() {
val useProgressBar = !this::modAdapter.isInitialized || modAdapter.itemCount == 0
val handler = Handler(Looper.getMainLooper())
thread {
if (useProgressBar) {
handler.post {
viewBinding.progressBar.isVisible = true
viewBinding.modError.isVisible = false
viewBinding.modErrorIcon.isVisible = false
viewBinding.modList.isVisible = false
}
}
val mod_directory = File(AppSettings.getValue(AppSettings.Setting.ModFolder, ""))
if (!mod_directory.exists()) {
mod_directory.mkdirs()
}
val files = mod_directory.listFiles()
val thisContent = requireContext()
if (files != null && files.isNotEmpty()) {
val data = ArrayList<ModClass>()
for (t in files) {
if (ModClass.isMod(t)) {
data.add(ModClass(t))
}
}
if (data.isEmpty()) {
handler.post {
showNotFindMod()
}
return@thread
}
if (useProgressBar) {
modAdapter = ModAdapter(thisContent, data)
} else {
modAdapter.setNewDataList(data)
}
modAdapter.setItemChangeEvent { changeType, i, modClass, i2 ->
if (i2 == 0) {
handler.post { loadMods() }
}
}
// modAdapter.
modAdapter.setItemEvent { i, modListItemBinding, viewHolder, modClass ->
modListItemBinding.root.setOnClickListener {
onClickItemWork(modListItemBinding, modClass)
}
modListItemBinding.root.setOnLongClickListener {
modAdapter.showDeleteItemDialog(
modClass.modName,
viewHolder.adapterPosition,
onClickPositiveButton = { d, b ->
delFile(handler, modClass, viewHolder.adapterPosition)
false
})
false
}
}
if (useProgressBar) {
handler.postDelayed({
viewBinding.modList.isVisible = true
viewBinding.modError.isVisible = false
viewBinding.modErrorIcon.isVisible = false
viewBinding.progressBar.isVisible = false
viewBinding.modList.adapter = modAdapter
}, MainActivity.hideViewDelay)
} else {
handler.post {
modAdapter.notifyDataSetChanged()
viewBinding.modList.adapter = modAdapter
}
}
} else {
handler.post {
showNotFindMod()
}
}
}
}
/** /**
* 删除文件 * 删除文件
@ -142,7 +68,8 @@ class ModFragment : BaseFragment<ModFragmentBinding>() {
modClass: ModClass, modClass: ModClass,
index: Int? = null index: Int? = null
) { ) {
executorService.submit { val scope = CoroutineScope(Job())
scope.run {
val targetFile = modClass.modFile val targetFile = modClass.modFile
val errorFolder = val errorFolder =
File(AppSettings.dataRootDirectory + "/modErrorReport/" + modClass.modName) File(AppSettings.dataRootDirectory + "/modErrorReport/" + modClass.modName)
@ -249,9 +176,64 @@ class ModFragment : BaseFragment<ModFragmentBinding>() {
} }
} }
/**
* 加载模组列表
*/
fun loadModList() {
val scope = CoroutineScope(Job())
val handler = Handler(Looper.getMainLooper())
scope.run {
val dataList = viewModel.loadMod()
handler.post {
viewBinding.progressBar.isVisible = true
viewBinding.modErrorIcon.isVisible = false
viewBinding.modError.isVisible = false
viewBinding.swipeRefreshLayout.isVisible = false
}
if (dataList == null) {
handler.post {
viewBinding.modError.setText(R.string.not_find_mod)
viewBinding.modError.isVisible = true
viewBinding.modErrorIcon.isVisible = true
viewBinding.swipeRefreshLayout.isVisible = false
viewBinding.progressBar.isVisible = false
}
} else {
handler.post {
viewBinding.swipeRefreshLayout.isVisible = true
viewBinding.progressBar.isVisible = false
viewBinding.modErrorIcon.isVisible = false
viewBinding.modError.isVisible = false
modAdapter = ModAdapter(requireContext(), dataList)
FastScrollerBuilder(viewBinding.modList).useMd2Style()
.setPopupTextProvider(modAdapter).build()
modAdapter.setItemEvent { i, modListItemBinding, viewHolder, modClass ->
modListItemBinding.root.setOnClickListener {
onClickItemWork(modListItemBinding, modClass)
}
modListItemBinding.root.setOnLongClickListener {
modAdapter.showDeleteItemDialog(
modClass.modName,
viewHolder.adapterPosition,
onClickPositiveButton = { d, b ->
delFile(handler, modClass, viewHolder.adapterPosition)
false
})
false
}
}
viewBinding.modList.adapter = modAdapter
}
}
}
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
loadMods() loadModList()
} }
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
@ -346,16 +328,16 @@ class ModFragment : BaseFragment<ModFragmentBinding>() {
bottomSheetDialog.show() bottomSheetDialog.show()
} }
/** // /**
* 显示没有找到模组 // * 显示没有找到模组
*/ // */
fun showNotFindMod() { // fun showNotFindMod() {
viewBinding.modError.setText(R.string.not_find_mod) // viewBinding.modError.setText(R.string.not_find_mod)
viewBinding.modError.isVisible = true // viewBinding.modError.isVisible = true
viewBinding.modErrorIcon.isVisible = true // viewBinding.modErrorIcon.isVisible = true
viewBinding.modList.isVisible = false // viewBinding.modList.isVisible = false
viewBinding.progressBar.isVisible = false // viewBinding.progressBar.isVisible = false
} // }
override fun getViewBindingObject(layoutInflater: LayoutInflater): ModFragmentBinding { override fun getViewBindingObject(layoutInflater: LayoutInflater): ModFragmentBinding {
return ModFragmentBinding.inflate(layoutInflater) return ModFragmentBinding.inflate(layoutInflater)
@ -369,5 +351,10 @@ class ModFragment : BaseFragment<ModFragmentBinding>() {
DividerItemDecoration.VERTICAL DividerItemDecoration.VERTICAL
) )
) )
viewBinding.swipeRefreshLayout.setOnRefreshListener {
loadModList()
viewBinding.swipeRefreshLayout.isRefreshing = false
}
viewModel.loadMod()
} }
} }

View File

@ -2,12 +2,17 @@ package com.coldmint.rust.pro.fragments
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.coldmint.rust.core.dataBean.webTemplate.WebTemplatePackageListData import com.coldmint.dialog.CoreDialog
import com.coldmint.rust.core.dataBean.ApiResponse
import com.coldmint.rust.core.dataBean.WebTemplatePackageListData
import com.coldmint.rust.core.interfaces.ApiCallBack import com.coldmint.rust.core.interfaces.ApiCallBack
import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.core.web.TemplatePhp import com.coldmint.rust.core.web.TemplatePhp
import com.coldmint.rust.pro.R
import com.coldmint.rust.pro.adapters.WebTemplateAdapter import com.coldmint.rust.pro.adapters.WebTemplateAdapter
import com.coldmint.rust.pro.base.BaseFragment import com.coldmint.rust.pro.base.BaseFragment
import com.coldmint.rust.pro.databinding.FragmentTemplateCommunityBinding import com.coldmint.rust.pro.databinding.FragmentTemplateCommunityBinding
@ -45,6 +50,75 @@ class TemplateCommunityFragment : BaseFragment<FragmentTemplateCommunityBinding>
viewBinding.loadView.isVisible = false viewBinding.loadView.isVisible = false
viewBinding.errorLayout.isVisible = false viewBinding.errorLayout.isVisible = false
val adapter = WebTemplateAdapter(requireContext(), t.data) val adapter = WebTemplateAdapter(requireContext(), t.data)
adapter.setItemEvent { i, itemWebTemplateBinding, viewHolder, data ->
itemWebTemplateBinding.button.setOnClickListener {
var subscribe = data.subscribe
if (subscribe) {
CoreDialog(requireContext()).setTitle(R.string.de_subscription)
.setMessage(
String.format(
getString(R.string.de_subscription_msg),
data.name
)
).setPositiveButton(R.string.dialog_ok) {
//退订
TemplatePhp.instance.deleteSubscription(token, data.id,
object : ApiCallBack<ApiResponse> {
override fun onResponse(t: ApiResponse) {
if (t.code == ServerConfiguration.Success_Code) {
itemWebTemplateBinding.button.setText(R.string.subscription)
data.subscribe = false
} else {
Toast.makeText(
requireContext(),
t.message,
Toast.LENGTH_SHORT
).show()
}
}
override fun onFailure(e: Exception) {
e.printStackTrace()
Toast.makeText(
requireContext(),
R.string.network_error,
Toast.LENGTH_SHORT
).show()
}
})
}.setNegativeButton(R.string.dialog_cancel) {
}.setCancelable(false).show()
} else {
TemplatePhp.instance.subscription(token, data.id,
object : ApiCallBack<ApiResponse> {
override fun onResponse(t: ApiResponse) {
if (t.code == ServerConfiguration.Success_Code) {
itemWebTemplateBinding.button.setText(R.string.de_subscription)
data.subscribe = true
} else {
Toast.makeText(
requireContext(),
t.message,
Toast.LENGTH_SHORT
).show()
}
}
override fun onFailure(e: Exception) {
e.printStackTrace()
Toast.makeText(
requireContext(),
R.string.network_error,
Toast.LENGTH_SHORT
).show()
}
})
}
}
}
viewBinding.recyclerView.adapter = adapter viewBinding.recyclerView.adapter = adapter
FastScrollerBuilder(viewBinding.recyclerView).useMd2Style() FastScrollerBuilder(viewBinding.recyclerView).useMd2Style()
.setPopupTextProvider(adapter).build() .setPopupTextProvider(adapter).build()

View File

@ -14,8 +14,7 @@ import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.core.tool.LocalVariableName import com.coldmint.rust.core.tool.LocalVariableName
import com.coldmint.rust.core.web.Dynamic import com.coldmint.rust.core.web.Dynamic
import com.coldmint.rust.pro.R import com.coldmint.rust.pro.R
import io.github.rosemoe.sora.data.CompletionItem import com.coldmint.rust.pro.edit.RustCompletionItem
import io.github.rosemoe.sora.data.NavigationItem
import java.io.File import java.io.File
import java.lang.StringBuilder import java.lang.StringBuilder
@ -129,9 +128,9 @@ class CompletionItemConverter private constructor() : EnglishMode {
/** /**
* 节信息转换为自动完成对象 * 节信息转换为自动完成对象
* @param sectionInfo SectionInfo * @param sectionInfo SectionInfo
* @return CompletionItem * @return RustCompletionItem
*/ */
fun sectionInfoToCompletionItem(sectionInfo: SectionInfo): CompletionItem { fun sectionInfoToCompletionItem(sectionInfo: SectionInfo): RustCompletionItem {
if (!isInitComplete) { if (!isInitComplete) {
NullPointerException("没有初始化。") NullPointerException("没有初始化。")
} }
@ -147,14 +146,14 @@ class CompletionItemConverter private constructor() : EnglishMode {
"[" + sectionInfo.translate + end "[" + sectionInfo.translate + end
} }
val completionItem = if (isEnglishMode) { val completionItem = if (isEnglishMode) {
CompletionItem( RustCompletionItem(
sectionInfo.code, sectionInfo.code,
commit, commit,
section, section,
boxDrawable boxDrawable
) )
} else { } else {
CompletionItem( RustCompletionItem(
sectionInfo.translate, sectionInfo.translate,
commit, commit,
section, section,
@ -173,18 +172,18 @@ class CompletionItemConverter private constructor() : EnglishMode {
* 本地变量转自动完成对象 * 本地变量转自动完成对象
* @param localVariableName LocalVariableName * @param localVariableName LocalVariableName
* @param previousText String? 之前的内容(冒号后面的值) * @param previousText String? 之前的内容(冒号后面的值)
* @return CompletionItem * @return RustCompletionItem
*/ */
fun localVariableNameToCompletionItem( fun localVariableNameToCompletionItem(
localVariableName: LocalVariableName, localVariableName: LocalVariableName,
previousText: String? = null previousText: String? = null
): CompletionItem { ): RustCompletionItem {
val commit = if (previousText == null) { val commit = if (previousText == null) {
"\${" + localVariableName.name + "}" "\${" + localVariableName.name + "}"
} else { } else {
previousText + "\${" + localVariableName.name + "}" previousText + "\${" + localVariableName.name + "}"
} }
return CompletionItem( return RustCompletionItem(
localVariableName.name, localVariableName.name,
commit, commit,
variableName, boxDrawable variableName, boxDrawable
@ -194,21 +193,21 @@ class CompletionItemConverter private constructor() : EnglishMode {
/** /**
* 转换代码信息到自动完成对象 * 转换代码信息到自动完成对象
* @param codeInfo CodeInfo * @param codeInfo CodeInfo
* @return CompletionItem * @return RustCompletionItem
*/ */
fun codeInfoToCompletionItem(codeInfo: CodeInfo): CompletionItem { fun codeInfoToCompletionItem(codeInfo: CodeInfo): RustCompletionItem {
if (!isInitComplete) { if (!isInitComplete) {
NullPointerException("没有初始化。") NullPointerException("没有初始化。")
} }
val typeInfo = getValueType(codeInfo.type) val typeInfo = getValueType(codeInfo.type)
val completionItem = if (isEnglishMode) { val completionItem = if (isEnglishMode) {
CompletionItem( RustCompletionItem(
codeInfo.code, codeInfo.code,
codeInfo.code + typeInfo?.external, codeInfo.code + typeInfo?.external,
codeInfo.description, boxDrawable codeInfo.description, boxDrawable
) )
} else { } else {
CompletionItem( RustCompletionItem(
codeInfo.translate, codeInfo.translate,
codeInfo.translate + typeInfo?.external, codeInfo.translate + typeInfo?.external,
codeInfo.description, boxDrawable codeInfo.description, boxDrawable
@ -218,7 +217,7 @@ class CompletionItemConverter private constructor() : EnglishMode {
if (typeList != null && typeList.isNotBlank()) { if (typeList != null && typeList.isNotBlank()) {
val bundle = Bundle() val bundle = Bundle()
bundle.putString("list", typeList) bundle.putString("list", typeList)
completionItem.extrasData = bundle // completionItem.extrasData = bundle
} }
val offset = typeInfo?.offset val offset = typeInfo?.offset
if (offset != null && offset.isNotBlank()) { if (offset != null && offset.isNotBlank()) {
@ -260,7 +259,7 @@ class CompletionItemConverter private constructor() : EnglishMode {
* @param valueTable ValueTable * @param valueTable ValueTable
* @return CompletionItem * @return CompletionItem
*/ */
fun valueTableToCompletionItem(valueTable: ValueTable): CompletionItem { fun valueTableToCompletionItem(valueTable: ValueTable): RustCompletionItem {
if (isInitComplete) { if (isInitComplete) {
NullPointerException("没有初始化。") NullPointerException("没有初始化。")
} }
@ -278,7 +277,7 @@ class CompletionItemConverter private constructor() : EnglishMode {
} }
} }
} }
return CompletionItem(valueTable.keyWord, desc, boxDrawable) return RustCompletionItem(valueTable.keyWord, desc, boxDrawable)
} }
/** /**
@ -286,23 +285,23 @@ class CompletionItemConverter private constructor() : EnglishMode {
* @param navigationItem NavigationItem * @param navigationItem NavigationItem
* @return CompletionItem * @return CompletionItem
*/ */
fun navigationItemToCompletionItem(navigationItem: NavigationItem): CompletionItem { // fun navigationItemToCompletionItem(navigationItem: NavigationItem): RustCompletionItem {
val name = SourceFile.getAbsoluteSectionName(navigationItem.label) // val name = SourceFile.getAbsoluteSectionName(navigationItem.label)
val type = SourceFile.getSectionType(navigationItem.label) // val type = SourceFile.getSectionType(navigationItem.label)
return CompletionItem( // return RustCompletionItem(
name, // name,
name, // name,
type, // type,
boxDrawable // boxDrawable
) // )
} // }
/** /**
* 文件信息转自动完成对象 * 文件信息转自动完成对象
* @param fileTable FileTable * @param fileTable FileTable
* @return CompletionItem * @return CompletionItem
*/ */
fun fileTableToCompletionItem(fileTable: FileTable): CompletionItem { fun fileTableToCompletionItem(fileTable: FileTable): RustCompletionItem {
if (!isInitComplete) { if (!isInitComplete) {
NullPointerException("没有初始化。") NullPointerException("没有初始化。")
} }
@ -335,7 +334,7 @@ class CompletionItemConverter private constructor() : EnglishMode {
} }
} }
val completionItem = val completionItem =
CompletionItem( RustCompletionItem(
fileTable.fileName, fileTable.fileName,
stringBuilder.toString(), stringBuilder.toString(),
fileTable.type, drawable fileTable.type, drawable
@ -353,7 +352,7 @@ class CompletionItemConverter private constructor() : EnglishMode {
if (rootCodeName == null) { if (rootCodeName == null) {
throw NullPointerException("未设置Root名称") throw NullPointerException("未设置Root名称")
} }
return CompletionItem( return RustCompletionItem(
fileTable.fileName, fileTable.fileName,
fileTable.fileName, fileTable.fileName,
fileTable.type, fileDrawable fileTable.type, fileDrawable

View File

@ -4,12 +4,16 @@ import android.content.Context
import android.util.Log import android.util.Log
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.coldmint.rust.core.LocalTemplatePackage import com.coldmint.rust.core.LocalTemplatePackage
import com.coldmint.rust.core.dataBean.SubscriptionData
import com.coldmint.rust.core.dataBean.template.LocalTemplateFile import com.coldmint.rust.core.dataBean.template.LocalTemplateFile
import com.coldmint.rust.core.dataBean.template.Template import com.coldmint.rust.core.dataBean.template.Template
import com.coldmint.rust.core.dataBean.template.TemplatePackage import com.coldmint.rust.core.dataBean.template.TemplatePackage
import com.coldmint.rust.core.interfaces.ApiCallBack
import com.coldmint.rust.core.interfaces.FileFinderListener import com.coldmint.rust.core.interfaces.FileFinderListener
import com.coldmint.rust.core.tool.FileFinder2 import com.coldmint.rust.core.tool.FileFinder2
import com.coldmint.rust.core.tool.FileOperator import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.core.web.TemplatePhp
import com.coldmint.rust.pro.base.BaseViewModel import com.coldmint.rust.pro.base.BaseViewModel
import com.coldmint.rust.pro.tool.AppSettings import com.coldmint.rust.pro.tool.AppSettings
import org.json.JSONException import org.json.JSONException
@ -80,8 +84,36 @@ class InstalledTemplateViewModel : BaseViewModel() {
fun loadTemplate(context: Context) { fun loadTemplate(context: Context) {
groupList.clear() groupList.clear()
itemList.clear() itemList.clear()
loadLocalTemplate(context) val token = AppSettings.getValue(AppSettings.Setting.Token,"")
loadCallBack?.invoke() TemplatePhp.instance.getSubscriptionDataList(token,object :ApiCallBack<SubscriptionData>{
override fun onResponse(t: SubscriptionData) {
if (t.code == ServerConfiguration.Success_Code){
Log.d("加载网络订阅模板", "正在处理。")
t.data.forEach {
groupList.add(it)
val temList = ArrayList<Template>()
itemList.add(temList)
it.templateList.forEach {
temList.add(it)
}
}
loadLocalTemplate(context)
loadCallBack?.invoke()
}else{
Log.w("加载网络订阅模板", t.message)
loadLocalTemplate(context)
loadCallBack?.invoke()
}
}
override fun onFailure(e: Exception) {
e.printStackTrace()
Log.e("加载网络订阅模板", e.toString())
loadLocalTemplate(context)
loadCallBack?.invoke()
}
})
} }
/** /**
@ -134,7 +166,7 @@ class InstalledTemplateViewModel : BaseViewModel() {
Log.d("加载本地模板", "已成功分配" + file.absolutePath) Log.d("加载本地模板", "已成功分配" + file.absolutePath)
} }
} else { } else {
Log.e("加载本地模板", "无法分配" + file.absolutePath) Log.w("加载本地模板", "无法分配" + file.absolutePath)
} }
return true return true
} }

View File

@ -0,0 +1,58 @@
package com.coldmint.rust.pro.viewmodel
import android.os.Environment
import android.util.Log
import com.coldmint.rust.core.ModClass
import com.coldmint.rust.pro.base.BaseViewModel
import com.coldmint.rust.pro.tool.AppSettings
import java.io.File
/**
* 模组ViewModel
*/
class ModViewModel : BaseViewModel() {
/**
* 加载模组
*/
fun loadMod(): ArrayList<ModClass>? {
val key = "加载模组列表"
val modFolder = File(
AppSettings.getValue(
AppSettings.Setting.ModFolder,
Environment.getExternalStorageDirectory().absolutePath + "/rustedWarfare/units/"
)
)
if (modFolder.exists()) {
if (!modFolder.isDirectory) {
Log.e(key, "模组文件夹${modFolder},不是文件夹。")
return null
}
val fileList = modFolder.listFiles()
if (fileList.isNullOrEmpty()) {
Log.e(key, "模组文件夹${modFolder},为空。")
return null
}
val arrayList = ArrayList<ModClass>()
fileList.forEach {
val isMod = ModClass.isMod(it)
if (isMod) {
arrayList.add(ModClass(it))
Log.d(key, "已添加${it.absolutePath}")
} else {
Log.e(key, "${it.absolutePath} 不是模组。")
}
}
return if (arrayList.isEmpty()){
return null
}else{
arrayList
}
} else {
Log.e(key, "模组文件夹${modFolder}不存在。")
return null
}
}
}

View File

@ -3,6 +3,7 @@ package com.coldmint.rust.pro.viewmodel
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.coldmint.rust.core.SourceFile
import com.coldmint.rust.core.dataBean.InputParserDataBean import com.coldmint.rust.core.dataBean.InputParserDataBean
import com.coldmint.rust.core.dataBean.IntroducingDataBean import com.coldmint.rust.core.dataBean.IntroducingDataBean
import com.coldmint.rust.core.dataBean.ListParserDataBean import com.coldmint.rust.core.dataBean.ListParserDataBean
@ -11,16 +12,24 @@ import com.coldmint.rust.core.interfaces.TemplateParser
import com.coldmint.rust.core.templateParser.InputParser import com.coldmint.rust.core.templateParser.InputParser
import com.coldmint.rust.core.templateParser.IntroducingParser import com.coldmint.rust.core.templateParser.IntroducingParser
import com.coldmint.rust.core.templateParser.ListParser import com.coldmint.rust.core.templateParser.ListParser
import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.pro.base.BaseViewModel import com.coldmint.rust.pro.base.BaseViewModel
import com.coldmint.rust.pro.tool.AppSettings
import com.google.gson.Gson import com.google.gson.Gson
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import java.io.File
class TemplateParserViewModel : BaseViewModel() { class TemplateParserViewModel : BaseViewModel() {
//json数据 //json数据
private var jsonData: JSONObject? = null private var jsonData: JSONObject? = null
private var template: Template? = null private var template: Template? = null
private lateinit var arrayList :ArrayList<TemplateParser>
//创建目录
private var createDirectory: String? = null
/** /**
* 设置模板数据 * 设置模板数据
@ -32,6 +41,15 @@ class TemplateParserViewModel : BaseViewModel() {
} }
/**
* 设置创建目录
* @param path String
*/
fun setCreateDirectory(path: String) {
createDirectory = path
}
/** /**
* 获取源代码 * 获取源代码
* @return String * @return String
@ -51,14 +69,105 @@ class TemplateParserViewModel : BaseViewModel() {
} }
/**
* 构建文件
* @param context Context
* @param fileName String
* @return Boolean
*/
fun buildFile(context: Context, fileName: String): Boolean {
if (createDirectory == null) {
Log.e("构建文件", "没有设置创建目录。")
return false
}
val index = fileName.lastIndexOf('.')
val independentFolder = AppSettings.getValue(AppSettings.Setting.IndependentFolder, true)
val createPath = if (independentFolder) {
val folderName =
if (index > -1) {
fileName.substring(0 until index)
} else {
fileName
}
"$createDirectory/$folderName"
} else {
createDirectory
}
Log.d("构建文件", "是否需要独立创建文件夹${independentFolder} 文件夹目录${createPath}")
val folder = File(createPath)
if (folder.exists()) {
Log.e("构建文件", "创建目录${createPath}已存在。")
return false
}
folder.mkdirs()
val path = File(
createPath + "/" + if (index > -1) {
fileName
} else {
"$fileName.ini"
}
)
if (path.exists()) {
Log.e("构建文件", "目标文件${path}已存在。")
return false
}
return FileOperator.writeFile(path, generatingCode(context))
}
/**
* 生成代码
* @return String
*/
private fun generatingCode(context: Context): String {
val staticCode = getCode()
//如果为空,那么返回空
if (staticCode.isBlank()) {
Log.e("获取模板解析器", "静态代码为空。")
return staticCode
}
val sourceFile = SourceFile(staticCode)
val parserList = getTemplateParserList(context)
if (parserList.isEmpty()) {
Log.w("生成代码", "此模板没有解析器,返回静态代码。")
return staticCode
} else {
parserList.forEach {
if (it.needParse) {
val input = it.getInput()
if (input.isBlank()) {
Log.w("生成代码", "模板${it.code}输入为空,跳过处理。")
} else {
Log.d("生成代码", "已将${it.code}的值设置为${input}")
val section = it.section
if (section == null) {
sourceFile.writeValue(it.code, input)
} else {
sourceFile.writeValueFromSection(it.code, input, section)
}
}
} else {
Log.d("生成代码", "模板${it.code}无需处理。")
}
}
return sourceFile.text
}
}
/** /**
* 获取模板解析器列表 * 获取模板解析器列表
* @param context Context * @param context Context
* @return ArrayList<TemplateParser> * @return ArrayList<TemplateParser>
*/ */
fun getTemplateParserList(context: Context): ArrayList<TemplateParser> { fun getTemplateParserList(context: Context): ArrayList<TemplateParser> {
if (this::arrayList.isInitialized)
{
Log.d("获取模板解析器","已经被调用了一次,返回成员变量")
return arrayList
}
arrayList = ArrayList()
val gson = Gson() val gson = Gson()
val arrayList = ArrayList<TemplateParser>()
val jsonArray = jsonData?.getJSONArray("action") val jsonArray = jsonData?.getJSONArray("action")
if (jsonArray == null) { if (jsonArray == null) {
Log.e("获取模板解析器", "此模板没有action无法读取。") Log.e("获取模板解析器", "此模板没有action无法读取。")

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M823.3,303.6c-12.5,-12.4 -32.9,-12.4 -45.3,0L429.1,652.5 246,459.3c-12.5,-12.4 -32.9,-12.4 -45.3,0 -12.4,12.5 -12.4,32.9 0,45.3l205.8,215.8c6.2,6.2 14.4,9.3 22.6,9.3 8.2,0 16.4,-3.1 22.7,-9.3l371.5,-371.5c12.4,-12.5 12.4,-32.8 0,-45.3z"
android:fillColor="#FF000000"/>
</vector>

View File

@ -0,0 +1,6 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
<path android:fillColor="@android:color/white" android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
</vector>

View File

@ -20,6 +20,7 @@
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout" android:id="@+id/tabLayout"
android:background="@android:color/transparent"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

View File

@ -6,67 +6,50 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<RelativeLayout <RelativeLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:animateLayoutChanges="true"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.coordinatorlayout.widget.CoordinatorLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/coordinator" android:id="@+id/appBarLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true"> android:layout_alignParentTop="true"
android:background="?android:attr/windowBackground"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="?attr/actionBarSize" />
android:background="?android:windowBackground"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.tabs.TabLayout
android:id="@+id/toolbar" android:id="@id/tabLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="wrap_content"
android:theme="?attr/actionBarStyle" /> android:layout_marginBottom="8dp"
android:background="@android:color/transparent"
<com.google.android.material.tabs.TabLayout android:contentDescription="@string/action"
android:id="@+id/tabLayout" app:tabMode="scrollable"
android:layout_width="match_parent" app:tabTextAppearance="@style/TabLayoutTextStyle" />
android:layout_height="wrap_content" </com.google.android.material.appbar.AppBarLayout>
android:background="?android:windowBackground"
android:contentDescription="@string/action"
app:tabMode="scrollable"
app:tabTextAppearance="@style/TabLayoutTextStyle" />
</com.google.android.material.appbar.AppBarLayout> <ProgressBar
android:id="@+id/myProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> <io.github.rosemoe.sora.widget.CodeEditor
android:id="@+id/codeEditor"
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_above="@+id/recyclerview" android:layout_above="@id/recyclerview"
android:layout_below="@id/coordinator" android:layout_below="@id/appBarLayout" />
android:gravity="center"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<ProgressBar
android:id="@+id/myProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<io.github.rosemoe.sora.widget.CodeEditor
android:id="@+id/codeEditor"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview" android:id="@id/recyclerview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
@ -78,5 +61,4 @@
<include layout="@layout/edit_end" /> <include layout="@layout/edit_end" />
<include layout="@layout/edit_start" /> <include layout="@layout/edit_start" />
</androidx.drawerlayout.widget.DrawerLayout> </androidx.drawerlayout.widget.DrawerLayout>

View File

@ -7,12 +7,11 @@
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:fitsSystemWindows="false"> android:fitsSystemWindows="false">
<com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/rootLayout" android:id="@+id/rootLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -27,13 +26,21 @@
android:id="@+id/tabLayout" android:id="@+id/tabLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone" android:background="@android:color/transparent"
app:tabMode="fixed" android:visibility="gone">
app:tabTextAppearance="@style/TabLayoutTextStyle">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="已安装" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="模板社区" />
</com.google.android.material.tabs.TabLayout> </com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<fragment <fragment
@ -41,6 +48,8 @@
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
app:defaultNavHost="true" app:defaultNavHost="true"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" /> app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
@ -55,16 +64,15 @@
android:text="@string/create" android:text="@string/create"
app:icon="@drawable/add" /> app:icon="@drawable/add" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout>
<com.google.android.material.navigation.NavigationView <com.google.android.material.navigation.NavigationView
android:id="@+id/navaiagtion" android:id="@+id/navaiagtion"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="start" android:layout_gravity="start"
app:elevation="2dp"
android:fitsSystemWindows="false" android:fitsSystemWindows="false"
app:elevation="2dp"
app:menu="@menu/menu_drawer_left" /> app:menu="@menu/menu_drawer_left" />
</androidx.drawerlayout.widget.DrawerLayout> </androidx.drawerlayout.widget.DrawerLayout>

View File

@ -8,6 +8,7 @@
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
tools:context=".OrderListActivity"> tools:context=".OrderListActivity">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -18,6 +19,16 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" /> android:layout_height="?attr/actionBarSize" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:tabMode="scrollable">
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
@ -31,8 +42,6 @@
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"> app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -47,27 +56,20 @@
android:visibility="gone" /> android:visibility="gone" />
<LinearLayout <LinearLayout
android:visibility="gone"
android:id="@+id/contentLayout" android:id="@+id/contentLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical"
android:visibility="gone">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
app:tabMode="scrollable"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2" android:id="@+id/viewPager2"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -86,7 +86,7 @@
</LinearLayout> </LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/fab" android:id="@+id/fab"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -94,6 +94,7 @@
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"
android:layout_margin="16dp" android:layout_margin="16dp"
android:src="@drawable/complete" /> app:icon="@drawable/build"
android:text="@string/build_unit"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -5,41 +5,33 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:windowBackground"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize" />
android:theme="?attr/actionBarStyle"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout" android:id="@+id/tabLayout"
android:background="@android:color/transparent"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
app:tabMode="fixed"
app:tabTextAppearance="@style/TabLayoutTextStyle">
<com.google.android.material.tabs.TabItem <com.google.android.material.tabs.TabItem
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/all_units" /> android:text="全部" />
<com.google.android.material.tabs.TabItem <com.google.android.material.tabs.TabItem
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/recently_opened" /> android:text="最近" />
</com.google.android.material.tabs.TabLayout> </com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
@ -47,17 +39,18 @@
android:id="@+id/pager" android:id="@+id/pager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="8dp"
android:layout_marginHorizontal="16dp" android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" /> app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/fab" android:id="@+id/fab"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"
android:layout_margin="16dp" android:layout_margin="16dp"
android:src="@drawable/add" /> android:text="@string/create_unit"
app:icon="@drawable/add" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="80dp" android:layout_height="wrap_content"
android:background="?android:windowBackground" android:background="?android:windowBackground"
android:padding="8dp"> android:padding="8dp">
@ -10,14 +10,13 @@
android:layout_width="45dp" android:layout_width="45dp"
android:layout_height="45dp" android:layout_height="45dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginRight="16dp" android:layout_marginEnd="16dp"
android:src="@drawable/image" /> android:src="@drawable/image" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_toRightOf="@id/iconView" android:layout_toEndOf="@id/iconView"
android:gravity="center_vertical"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView

View File

@ -1,35 +1,42 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:orientation="vertical">
<RelativeLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="match_parent"
android:orientation="vertical">
<TextView <RelativeLayout
android:id="@+id/unitPathView" android:layout_width="match_parent"
style="@style/TextAppearance.Material3.BodyMedium" android:layout_height="wrap_content">
<TextView
android:id="@+id/unitPathView"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/select_path_button"
android:text="@string/unit_path" />
<Button
android:id="@+id/select_path_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:text="@string/change_path" />
</RelativeLayout>
<ExpandableListView
android:id="@+id/expandableList"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent" />
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/select_path_button"
android:text="@string/unit_path" />
<Button </LinearLayout>
android:id="@+id/select_path_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:text="@string/change_path" />
</RelativeLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<ExpandableListView
android:id="@+id/expandableList"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@ -21,6 +21,8 @@
<TextView <TextView
android:ellipsize="end"
android:singleLine="true"
android:id="@+id/describeView" android:id="@+id/describeView"
style="@style/TextAppearance.Material3.BodyMedium" style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -23,21 +23,29 @@
<TextView <TextView
android:id="@+id/modError" android:id="@+id/modError"
style="@style/TextAppearance.Material3.TitleLarge"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:text="@string/not_find_mod" android:text="@string/not_find_mod"
style="@style/TextAppearance.Material3.TitleLarge"
android:visibility="gone" /> android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/modList" android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:visibility="gone"
android:layout_marginLeft="8dp" android:layout_height="match_parent">
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:visibility="gone" /> <androidx.recyclerview.widget.RecyclerView
android:id="@+id/modList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout> </LinearLayout>

View File

@ -786,7 +786,7 @@
<string name="change_server_complete">The server has changed.</string> <string name="change_server_complete">The server has changed.</string>
<string name="order_manager">The order management</string> <string name="order_manager">The order management</string>
<string name="log_out">logout</string> <string name="log_out">logout</string>
<string name="user_info">%1$s uid:%2$s</string> <string name="user_info">%1$s uid:%2$s location:%3$s</string>
<string name="use_coupon">Will use coupons to create orders, still continue\? (After creating the order, use the coupon)</string> <string name="use_coupon">Will use coupons to create orders, still continue\? (After creating the order, use the coupon)</string>
<string name="use">use</string> <string name="use">use</string>
<string name="account_or_email">Account/email</string> <string name="account_or_email">Account/email</string>

View File

@ -785,7 +785,7 @@
<string name="change_server_complete">サーバーを変更しました。</string> <string name="change_server_complete">サーバーを変更しました。</string>
<string name="order_manager">注文管理</string> <string name="order_manager">注文管理</string>
<string name="log_out">掲載</string> <string name="log_out">掲載</string>
<string name="user_info">最近ログイン:%1$s uid:%2$s</string> <string name="user_info">最近ログイン:%1$s uid:%2$s 住所:%3$s</string>
<string name="use_coupon">クーポンを使った注文を作成しますが、継続しますか\?(注文作成完了後、クーポンを消費)</string> <string name="use_coupon">クーポンを使った注文を作成しますが、継続しますか\?(注文作成完了後、クーポンを消費)</string>
<string name="use">使用</string> <string name="use">使用</string>
<string name="account_or_email">アカウント/ eメール</string> <string name="account_or_email">アカウント/ eメール</string>

View File

@ -785,7 +785,7 @@
<string name="change_server_complete">Сервер был изменен.</string> <string name="change_server_complete">Сервер был изменен.</string>
<string name="order_manager">Управление заказом</string> <string name="order_manager">Управление заказом</string>
<string name="log_out">напечата</string> <string name="log_out">напечата</string>
<string name="user_info">Зарегистрировано недавно :% $uid:% $2</string> <string name="user_info">Зарегистрировано недавно :%1$s uid:%2$s местожительство:%3$s</string>
<string name="use_coupon">Мы используем купоны, чтобы создать порядок. (после создания заказа, купоны будут расходуться)</string> <string name="use_coupon">Мы используем купоны, чтобы создать порядок. (после создания заказа, купоны будут расходуться)</string>
<string name="use">использова</string> <string name="use">использова</string>
<string name="account_or_email">Номер счета/письмо</string> <string name="account_or_email">Номер счета/письмо</string>

View File

@ -25,6 +25,7 @@
<string name="create_unit_complete">单位创建完成</string> <string name="create_unit_complete">单位创建完成</string>
<string name="create_unit_failed">单位创建失败</string> <string name="create_unit_failed">单位创建失败</string>
<string name="create_uniting">正在构建单位...</string> <string name="create_uniting">正在构建单位...</string>
<string name="build_unit">构建单位</string>
<string name="dialog_ok">确定</string> <string name="dialog_ok">确定</string>
<string name="activation_app">激活铁锈助手</string> <string name="activation_app">激活铁锈助手</string>
<string name="activation_app_tip">您的激活时间已过,请激活铁锈助手。</string> <string name="activation_app_tip">您的激活时间已过,请激活铁锈助手。</string>
@ -98,7 +99,7 @@
<string name="enter_file_path">请输入文件路径。</string> <string name="enter_file_path">请输入文件路径。</string>
<string name="create_bookmark">创建书签</string> <string name="create_bookmark">创建书签</string>
<string name="name_error">请输入模组名称。</string> <string name="name_error">请输入模组名称。</string>
<string name="unit_name_error">请输入单位名称。</string> <string name="file_name_error">请输入文件名称。</string>
<string name="action_name_error">请输入活动名称。</string> <string name="action_name_error">请输入活动名称。</string>
<string name="database_null">此数据集无法加载,错误原因:%1$s。</string> <string name="database_null">此数据集无法加载,错误原因:%1$s。</string>
<string name="describe_error">请输入描述。</string> <string name="describe_error">请输入描述。</string>
@ -748,6 +749,7 @@
<string name="undo">撤销</string> <string name="undo">撤销</string>
<string name="redo">重做</string> <string name="redo">重做</string>
<string name="del_mod">删除</string> <string name="del_mod">删除</string>
<string name="delete_error">删除失败。</string>
<string name="need_save">[未保存]%1$s</string> <string name="need_save">[未保存]%1$s</string>
<string name="game_data_and_synchronization">游戏数据与同步</string> <string name="game_data_and_synchronization">游戏数据与同步</string>
<string name="game_data_and_synchronization_describe">管理已同步的游戏数据。</string> <string name="game_data_and_synchronization_describe">管理已同步的游戏数据。</string>
@ -800,7 +802,7 @@
<string name="change_server_complete">已更改服务器。</string> <string name="change_server_complete">已更改服务器。</string>
<string name="order_manager">订单管理</string> <string name="order_manager">订单管理</string>
<string name="log_out">登出</string> <string name="log_out">登出</string>
<string name="user_info">最近登录:%1$s uid:%2$s</string> <string name="user_info">最近登录:%1$s uid:%2$s ip归属地:%3$s</string>
<string name="use_coupon">将使用优惠券创建订单,仍继续嘛?(创建订单完成后,将优惠券消耗)</string> <string name="use_coupon">将使用优惠券创建订单,仍继续嘛?(创建订单完成后,将优惠券消耗)</string>
<string name="use">使用</string> <string name="use">使用</string>
<string name="account_or_email">账号/电子邮件</string> <string name="account_or_email">账号/电子邮件</string>
@ -873,6 +875,7 @@
<string name="template_id">模板id</string> <string name="template_id">模板id</string>
<string name="subscription">订阅</string> <string name="subscription">订阅</string>
<string name="de_subscription">退订</string> <string name="de_subscription">退订</string>
<string name="de_subscription_msg">要退订%1$s嘛?</string>
<!-- <string name="search_suggestions_null">无搜索建议。</string>--> <!-- <string name="search_suggestions_null">无搜索建议。</string>-->
<!-- <string name="search_suggestions_number">共%1$d个搜索建议。</string>--> <!-- <string name="search_suggestions_number">共%1$d个搜索建议。</string>-->

View File

@ -1,5 +1,7 @@
package com.coldmint.rust.core package com.coldmint.rust.core
import android.os.Handler
import android.os.Looper
import com.coldmint.rust.core.dataBean.TemplateDataBean import com.coldmint.rust.core.dataBean.TemplateDataBean
import com.coldmint.rust.core.dataBean.template.TemplateInfo import com.coldmint.rust.core.dataBean.template.TemplateInfo
import com.coldmint.rust.core.dataBean.template.TemplatePackage import com.coldmint.rust.core.dataBean.template.TemplatePackage
@ -64,6 +66,18 @@ class LocalTemplatePackage(val directest: File) : TemplatePackage {
return info?.name ?: directest.name return info?.name ?: directest.name
} }
override fun getDescription(): String {
val info = getInfo()
return info?.description ?: ""
}
override fun delete(token: String, func: (Boolean) -> Unit) {
func.invoke(FileOperator.delete_files(directest))
}
override fun isLocal(): Boolean {
return true
}
/** /**

View File

@ -497,10 +497,10 @@ class SourceFile(text: String) {
stringBuilder.append(value) stringBuilder.append(value)
stringBuilder.append(sinfo.substring(endnum, sinfo.length - 1)) stringBuilder.append(sinfo.substring(endnum, sinfo.length - 1))
stringBuilder.append(info.substring(sectionendnum, info.length - 2)) stringBuilder.append(info.substring(sectionendnum, info.length - 2))
if (hasSymbol) { text = if (hasSymbol) {
text = stringBuilder.toString() stringBuilder.toString()
} else { } else {
text = stringBuilder.substring(1) stringBuilder.substring(1)
} }
return true return true
} }

View File

@ -155,7 +155,7 @@ data class CompileConfiguration(
* Reference 引用是一种特殊的数据类型编译器会尝试编译此值若无法编译则使用原始值 * Reference 引用是一种特殊的数据类型编译器会尝试编译此值若无法编译则使用原始值
*/ */
enum class CodeBlockType { enum class CodeBlockType {
Key, Value, Section, Note, VariableName, Reference Key, Value, Section, Note, VariableName, Reference, Symbol
} }
/** /**

View File

@ -0,0 +1,136 @@
package com.coldmint.rust.core.dataBean
import android.util.Log
import com.coldmint.rust.core.dataBean.template.Template
import com.coldmint.rust.core.dataBean.template.TemplatePackage
import com.coldmint.rust.core.interfaces.ApiCallBack
import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.core.web.TemplatePhp
import com.google.gson.annotations.SerializedName
import org.json.JSONObject
/**
* 订阅信息
* @property code Int
* @property `data` List<Data>
* @property message String
* @constructor
*/
data class SubscriptionData(
@SerializedName("code")
val code: Int,
@SerializedName("data")
val `data`: List<Data>,
@SerializedName("message")
val message: String
) {
data class Data(
@SerializedName("appVersionName")
val appVersionName: String,
@SerializedName("appVersionNumber")
val appVersionNumber: String,
@SerializedName("createTime")
val createTime: String,
@SerializedName("describe")
val describe: String,
@SerializedName("developer")
val developer: String,
@SerializedName("id")
val id: String,
@SerializedName("modificationTime")
val modificationTime: String,
@SerializedName("name")
val name1: String,
@SerializedName("public")
val `public`: String,
@SerializedName("subscriptionNumber")
val subscriptionNumber: String,
@SerializedName("templateList")
val templateList: List<Template>,
@SerializedName("templateNumber")
val templateNumber: String,
@SerializedName("versionName")
val versionName: String,
@SerializedName("versionNumber")
val versionNumber: String
) : TemplatePackage {
data class Template(
@SerializedName("content")
val content: String,
@SerializedName("createTime")
val createTime: String,
@SerializedName("deleted")
val deleted: String,
@SerializedName("developer")
val developer: String,
@SerializedName("id")
val id: String,
@SerializedName("modificationTime")
val modificationTime: String,
@SerializedName("packageId")
val packageId: String,
@SerializedName("title")
val title: String
) : com.coldmint.rust.core.dataBean.template.Template {
private val jsonObject: JSONObject by lazy {
JSONObject(content)
}
override fun getJson(): JSONObject {
return jsonObject
}
override fun getName(language: String): String {
return title
}
override fun getIcon(): Any? {
return null
}
override fun isLocal(): Boolean {
return false
}
override fun getLink(): String {
return id
}
}
override fun getName(): String {
return name1
}
override fun getDescription(): String {
return describe
}
override fun delete(token: String, func: (Boolean) -> Unit) {
TemplatePhp.instance.deleteSubscription(token, id, object : ApiCallBack<ApiResponse> {
override fun onResponse(t: ApiResponse) {
if (t.code == ServerConfiguration.Success_Code) {
Log.d("取消订阅", "成功。")
func.invoke(true)
} else {
Log.e("取消订阅", t.message)
func.invoke(false)
}
}
override fun onFailure(e: Exception) {
e.printStackTrace()
Log.e("取消订阅", e.toString())
func.invoke(false)
}
})
}
override fun isLocal(): Boolean {
return false
}
}
}

View File

@ -1,4 +1,4 @@
package com.coldmint.rust.core.dataBean.webTemplate package com.coldmint.rust.core.dataBean
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
@ -22,10 +22,6 @@ data class WebTemplatePackageListData(
val describe: String, val describe: String,
@SerializedName("developer") @SerializedName("developer")
val developer: String, val developer: String,
@SerializedName("downloadNumber")
val downloadNumber: Int,
@SerializedName("templateNumber")
val templateNumber: Int,
@SerializedName("id") @SerializedName("id")
val id: String, val id: String,
@SerializedName("modificationTime") @SerializedName("modificationTime")
@ -33,12 +29,16 @@ data class WebTemplatePackageListData(
@SerializedName("name") @SerializedName("name")
val name: String, val name: String,
@SerializedName("public") @SerializedName("public")
val `public`: Boolean, val `public`: String,
@SerializedName("subscribe")
var subscribe: Boolean,
@SerializedName("subscriptionNumber")
val subscriptionNumber: String,
@SerializedName("templateNumber")
val templateNumber: String,
@SerializedName("versionName") @SerializedName("versionName")
val versionName: String, val versionName: String,
@SerializedName("versionNumber") @SerializedName("versionNumber")
val versionNumber: String, val versionNumber: String
@SerializedName("subscribe")
val subscribe: Boolean
) )
} }

View File

@ -9,8 +9,27 @@ interface TemplatePackage {
* 实现获取名称方法 * 实现获取名称方法
* @return String * @return String
*/ */
fun getName():String fun getName(): String
/**
* 获取描述
* @return String
*/
fun getDescription(): String
/**
* 实现删除方法本地模板删除远程模板退订
* @return Boolean
*/
fun delete(token: String, func: (Boolean) -> Unit)
/**
* 是否为本地模板包
* @return Boolean
*/
fun isLocal():Boolean
} }

View File

@ -0,0 +1,70 @@
package com.coldmint.rust.core.dataBean.template
import com.google.gson.annotations.SerializedName
import org.json.JSONObject
/**
* 网络模板详情
* @property code Int
* @property `data` Data
* @property message String
* @constructor
*/
data class WebTemplateData(
@SerializedName("code")
val code: Int,
@SerializedName("data")
val `data`: Data,
@SerializedName("message")
val message: String
) {
data class Data(
@SerializedName("content")
val content: String,
@SerializedName("createTime")
val createTime: String,
@SerializedName("deleted")
val deleted: String,
@SerializedName("developer")
val developer: String,
@SerializedName("id")
val id: String,
@SerializedName("modificationTime")
val modificationTime: String,
@SerializedName("packageId")
val packageId: String,
@SerializedName("title")
val title: String,
) : Template {
private lateinit var jsonObject: JSONObject
override fun getJson(): JSONObject {
if (!this::jsonObject.isInitialized) {
jsonObject = JSONObject(content)
}
return jsonObject
}
override fun getName(language: String): String {
return if (getJson().has("name_$language")) {
return getJson().getString("name_$language")
} else {
return getJson().getString("name")
}
}
override fun getIcon(): Any? {
return null
}
override fun isLocal(): Boolean {
return false
}
override fun getLink(): String {
return id
}
}
}

View File

@ -19,6 +19,7 @@ data class SpaceInfoData(
val praise: Int, val praise: Int,
val expirationTime: String, val expirationTime: String,
val userName: String, val userName: String,
val gender: Int val gender: Int,
val location: String
) )
} }

View File

@ -10,7 +10,7 @@ interface TemplateParser {
/** /**
* 实现获取用户输入 * 实现获取用户输入
*/ */
val input: String fun getInput(): String
/** /**
* 实现实例化视图 * 实现实例化视图

View File

@ -18,8 +18,10 @@ class InputParser(val context: Context, val data: InputParserDataBean) : Templat
private val parserInputBinding: ParserInputBinding = private val parserInputBinding: ParserInputBinding =
ParserInputBinding.inflate(LayoutInflater.from(context)) ParserInputBinding.inflate(LayoutInflater.from(context))
override val input: String override fun getInput(): String {
get() = parserInputBinding.inputView.text.toString() return parserInputBinding.inputView.text.toString()
}
override val contextView: View override val contextView: View
get() { get() {

View File

@ -12,6 +12,7 @@ import com.coldmint.rust.core.databinding.ParserIntroduceBinding
import com.coldmint.rust.core.interfaces.TemplateParser import com.coldmint.rust.core.interfaces.TemplateParser
/** /**
* 注释
* @author Cold Mint * @author Cold Mint
* @date 2021/12/17 14:55 * @date 2021/12/17 14:55
*/ */
@ -24,9 +25,11 @@ class IntroducingParser(
LayoutInflater.from(context) LayoutInflater.from(context)
) )
override fun getInput(): String {
return ""
}
override val input: String
get() = ""
override val contextView: View override val contextView: View
get() { get() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

View File

@ -18,15 +18,15 @@ class ListParser(val context: Context, val data: ListParserDataBean) : TemplateP
) )
private val itemList: List<String> = data.itemList.split(",") private val itemList: List<String> = data.itemList.split(",")
private val dataList: List<String>? = data.dataList?.split(",") private val dataList: List<String>? = data.dataList?.split(",")
override val input: String override fun getInput(): String {
get() { val index = parserListBinding.spacer.selectedItemPosition
val index = parserListBinding.spacer.selectedItemPosition return if (dataList != null && dataList.size == itemList.size) {
return if (dataList != null && dataList.size == itemList.size) { dataList[index]
dataList[index] } else {
} else { itemList[index]
itemList[index]
}
} }
}
override val contextView: View override val contextView: View
get() { get() {

View File

@ -4,7 +4,9 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
import com.coldmint.rust.core.dataBean.ApiResponse import com.coldmint.rust.core.dataBean.ApiResponse
import com.coldmint.rust.core.dataBean.webTemplate.WebTemplatePackageListData import com.coldmint.rust.core.dataBean.SubscriptionData
import com.coldmint.rust.core.dataBean.WebTemplatePackageListData
import com.coldmint.rust.core.dataBean.template.WebTemplateData
import com.coldmint.rust.core.interfaces.ApiCallBack import com.coldmint.rust.core.interfaces.ApiCallBack
import com.google.gson.Gson import com.google.gson.Gson
import okhttp3.* import okhttp3.*
@ -21,57 +23,8 @@ class TemplatePhp {
private constructor() private constructor()
/**
* 发送错误报告
* @param website 网址(如果程序已崩溃需要重新读取设置的网址)
* @param message String 消息
* @param versionName 版本名
* @param versionNumber 版本号
* @param apiCallBack ApiCallBack<CouponListDataBean>
*/
fun send(
message: String,
versionName: String,
versionNumber: Int,
apiCallBack: ApiCallBack<ApiResponse>, website: String = ServerConfiguration.website
) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBodyBuilder: FormBody.Builder =
FormBody.Builder().add("message", message).add("versionName", versionName)
.add("versionNumber", versionNumber.toString())
val requestBody = requestBodyBuilder.build()
val request =
Request.Builder()
.url(website + "php/error.php?action=send")
.post(requestBody).build()
val call = okHttpClient.newCall(request)
val handler = Handler(Looper.getMainLooper())
val gson = Gson()
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
handler.post { apiCallBack.onFailure(e) }
}
override fun onResponse(call: Call, response: Response) {
try {
val data = response.body!!.string()
Log.d("错误反馈数据", data)
val finalApiResponse =
gson.fromJson(data, ApiResponse::class.java)
handler.post {
apiCallBack.onResponse(finalApiResponse)
}
} catch (e: Exception) {
e.printStackTrace()
handler.post {
apiCallBack.onFailure(e)
}
}
}
})
}
/** /**
*获取公开的模板包列表 *获取公开的模板包列表
@ -118,6 +71,188 @@ class TemplatePhp {
}) })
} }
/**
*获取模板详情
* @param apiCallBack ApiCallBack<CouponListDataBean>
*/
fun getTemplate(
id: String,
apiCallBack: ApiCallBack<WebTemplateData>
) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBodyBuilder: FormBody.Builder =
FormBody.Builder().add("id", id)
val requestBody = requestBodyBuilder.build()
val request =
Request.Builder()
.url(ServerConfiguration.website + "php/template.php?action=getTemplate")
.post(requestBody).build()
val call = okHttpClient.newCall(request)
val handler = Handler(Looper.getMainLooper())
val gson = Gson()
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
handler.post { apiCallBack.onFailure(e) }
}
override fun onResponse(call: Call, response: Response) {
try {
val data = response.body!!.string()
Log.d("获取网络模板详情", data)
val finalWebTemplatePackageListData =
gson.fromJson(data, WebTemplateData::class.java)
handler.post {
apiCallBack.onResponse(finalWebTemplatePackageListData)
}
} catch (e: Exception) {
e.printStackTrace()
handler.post {
apiCallBack.onFailure(e)
}
}
}
})
}
/**
*获用户订阅的模板列表
* @param apiCallBack ApiCallBack<SubscriptionData>
*/
fun getSubscriptionDataList(
token: String,
apiCallBack: ApiCallBack<SubscriptionData>
) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBodyBuilder: FormBody.Builder =
FormBody.Builder().add("token", token)
val requestBody = requestBodyBuilder.build()
val request =
Request.Builder()
.url(ServerConfiguration.website + "php/template.php?action=getSubscriptionData")
.post(requestBody).build()
val call = okHttpClient.newCall(request)
val handler = Handler(Looper.getMainLooper())
val gson = Gson()
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
handler.post { apiCallBack.onFailure(e) }
}
override fun onResponse(call: Call, response: Response) {
try {
val data = response.body!!.string()
Log.d("获取网络订阅", data)
val finalSubscriptionData =
gson.fromJson(data, SubscriptionData::class.java)
handler.post {
apiCallBack.onResponse(finalSubscriptionData)
}
} catch (e: Exception) {
e.printStackTrace()
handler.post {
apiCallBack.onFailure(e)
}
}
}
})
}
/**
*订阅模板
* @param apiCallBack ApiCallBack<CouponListDataBean>
*/
fun subscription(
token: String,
packageId: String,
apiCallBack: ApiCallBack<ApiResponse>
) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBodyBuilder: FormBody.Builder =
FormBody.Builder().add("token", token).add("packageId", packageId)
val requestBody = requestBodyBuilder.build()
val request =
Request.Builder()
.url(ServerConfiguration.website + "php/template.php?action=subscription")
.post(requestBody).build()
val call = okHttpClient.newCall(request)
val handler = Handler(Looper.getMainLooper())
val gson = Gson()
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
handler.post { apiCallBack.onFailure(e) }
}
override fun onResponse(call: Call, response: Response) {
try {
val data = response.body!!.string()
Log.d("订阅模板", data)
val finalApiResponse =
gson.fromJson(data, ApiResponse::class.java)
handler.post {
apiCallBack.onResponse(finalApiResponse)
}
} catch (e: Exception) {
e.printStackTrace()
handler.post {
apiCallBack.onFailure(e)
}
}
}
})
}
/**
*退订模板
* @param apiCallBack ApiCallBack<CouponListDataBean>
*/
fun deleteSubscription(
token: String,
packageId: String,
apiCallBack: ApiCallBack<ApiResponse>
) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBodyBuilder: FormBody.Builder =
FormBody.Builder().add("token", token).add("packageId", packageId)
val requestBody = requestBodyBuilder.build()
val request =
Request.Builder()
.url(ServerConfiguration.website + "php/template.php?action=deleteSubscription")
.post(requestBody).build()
val call = okHttpClient.newCall(request)
val handler = Handler(Looper.getMainLooper())
val gson = Gson()
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
handler.post { apiCallBack.onFailure(e) }
}
override fun onResponse(call: Call, response: Response) {
try {
val data = response.body!!.string()
Log.d("退订模板", data)
val finalApiResponse =
gson.fromJson(data, ApiResponse::class.java)
handler.post {
apiCallBack.onResponse(finalApiResponse)
}
} catch (e: Exception) {
e.printStackTrace()
handler.post {
apiCallBack.onFailure(e)
}
}
}
})
}
/** /**
* 创建模板包 * 创建模板包
* @param id String 模板包id * @param id String 模板包id

View File

@ -24,8 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="@string/title" android:text="@string/title" />
android:visibility="gone" />
<CheckBox <CheckBox
android:id="@+id/checkbox" android:id="@+id/checkbox"
@ -64,6 +63,7 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>