Graphic support download and detail

This commit is contained in:
ryoii 2020-04-11 18:52:39 +08:00
parent 6a9f5ec11e
commit cbeeaafc72
5 changed files with 172 additions and 27 deletions

View File

@ -10,6 +10,7 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.command.CommandManager.runCommand import net.mamoe.mirai.console.command.CommandManager.runCommand
import net.mamoe.mirai.console.command.ConsoleCommandSender import net.mamoe.mirai.console.command.ConsoleCommandSender
import net.mamoe.mirai.console.graphical.event.ReloadEvent
import net.mamoe.mirai.console.graphical.model.* import net.mamoe.mirai.console.graphical.model.*
import net.mamoe.mirai.console.graphical.view.dialog.InputDialog import net.mamoe.mirai.console.graphical.view.dialog.InputDialog
import net.mamoe.mirai.console.graphical.view.dialog.VerificationCodeFragment import net.mamoe.mirai.console.graphical.view.dialog.VerificationCodeFragment
@ -35,8 +36,16 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
private val consoleInfo = ConsoleInfo() private val consoleInfo = ConsoleInfo()
private val sdf by lazy { private val sdf by lazy { SimpleDateFormat("HH:mm:ss") }
SimpleDateFormat("HH:mm:ss")
init {
// 监听插件重载事件以重新从console获取插件列表
subscribe<ReloadEvent> {
pluginList.clear()
// 不能直接赋值pluginList已经被bind不能更换对象
pluginList.addAll(getPluginsFromConsole())
}
} }
fun login(qq: String, psd: String) { fun login(qq: String, psd: String) {
@ -148,6 +157,15 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
return false return false
} }
fun reloadPlugins() {
with(PluginManager) {
disablePlugins()
loadPlugins()
}
fire(ReloadEvent) // 广播插件重载事件
}
} }
class GraphicalLoginSolver : LoginSolver() { class GraphicalLoginSolver : LoginSolver() {

View File

@ -0,0 +1,5 @@
package net.mamoe.mirai.console.graphical.event
import tornadofx.FXEvent
object ReloadEvent : FXEvent()

View File

@ -1,28 +1,52 @@
package net.mamoe.mirai.console.graphical.view package net.mamoe.mirai.console.graphical.view
import com.jfoenix.controls.JFXTreeTableColumn import com.jfoenix.controls.JFXTreeTableColumn
import javafx.application.Platform
import javafx.collections.ObservableList import javafx.collections.ObservableList
import javafx.geometry.Pos import javafx.geometry.Pos
import javafx.scene.control.Button
import javafx.scene.control.TreeTableCell import javafx.scene.control.TreeTableCell
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.center.PluginCenter import net.mamoe.mirai.console.center.PluginCenter
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
import net.mamoe.mirai.console.graphical.event.ReloadEvent
import net.mamoe.mirai.console.graphical.model.PluginModel import net.mamoe.mirai.console.graphical.model.PluginModel
import net.mamoe.mirai.console.graphical.stylesheet.PluginViewStyleSheet import net.mamoe.mirai.console.graphical.stylesheet.PluginViewStyleSheet
import net.mamoe.mirai.console.graphical.util.jfxButton import net.mamoe.mirai.console.graphical.util.jfxButton
import net.mamoe.mirai.console.graphical.util.jfxTreeTableView import net.mamoe.mirai.console.graphical.util.jfxTreeTableView
import net.mamoe.mirai.console.graphical.view.dialog.PluginDetailFragment
import net.mamoe.mirai.console.plugins.PluginManager
import tornadofx.* import tornadofx.*
class PluginsCenterView : View() { class PluginsCenterView : View() {
private val controller = find<MiraiGraphicalUIController>() private val controller = find<MiraiGraphicalUIController>()
private val center = PluginCenter.Default private val center = PluginCenter.Default
private val plugins: ObservableList<PluginModel> by lazy(::fetch) private val plugins: ObservableList<PluginModel> = observableListOf()
init {
// 监听插件重载,情况插件列表,重新载入。
// 同时把页面刷新按键的listener也初始化
subscribe<ReloadEvent> { plugins.clear() }
}
override val root = jfxTreeTableView(plugins) { override val root = jfxTreeTableView(plugins) {
addStylesheet(PluginViewStyleSheet::class) addStylesheet(PluginViewStyleSheet::class)
placeholder = button("从崔云获取插件列表") {
action {
isDisable = true
runAsync {
fetch()
}.ui {
plugins.addAll(it)
isDisable = false
}
}
}
isShowRoot = false isShowRoot = false
columns.addAll( columns.addAll(
JFXTreeTableColumn<PluginModel, String>("插件名").apply { JFXTreeTableColumn<PluginModel, String>("插件名").apply {
@ -73,7 +97,7 @@ class PluginsCenterView : View() {
jfxButton("下载") { jfxButton("下载") {
action { download(item) } action { download(item, this) }
} }
} }
@ -90,39 +114,62 @@ class PluginsCenterView : View() {
} }
private fun fetch(): ObservableList<PluginModel> = private fun fetch(): List<PluginModel> = mutableListOf<PluginModel>().apply {
runAsync { runBlocking {
val ret = observableListOf<PluginModel>() var page = 1
runBlocking { while (true) {
var page = 1 val map = center.fetchPlugin(page++)
while (true) { if (map.isEmpty()) return@runBlocking
val map = center.fetchPlugin(page++) map.forEach {
if (map.isEmpty()) return@runBlocking with(
map.forEach { PluginModel(
with(PluginModel(
it.value.name, it.value.name,
it.value.version, it.value.version,
it.value.author, it.value.author,
it.value.description, it.value.description,
it.value it.value
)) { )
ret.add(this) ) {
controller.checkUpdate(this) add(this)
controller.checkAmbiguous(this) controller.checkUpdate(this)
} controller.checkAmbiguous(this)
} }
} }
} }
return@runAsync ret }
}.get()
private fun detail(pluginModel: PluginModel) {
//to show pluginModel.insight
} }
private fun download(pluginModel: PluginModel) { private fun detail(pluginModel: PluginModel) {
// controller.checkAmbiguous(pluginModel) runAsync {
// do nothing runBlocking { center.findPlugin(pluginModel.name) }
}.ui {
it?.apply {
PluginDetailFragment(this).openModal()
}
}
}
private fun download(pluginModel: PluginModel, button: Button) {
button.isDisable = true
button.text = "连接中..."
runAsync {
runBlocking {
center.downloadPlugin(pluginModel.name) {
// download process
Platform.runLater {
button.text = "$it%"
}
}
}
}.ui {
with(button) {
isDisable = false
text = "重载插件"
setOnAction {
controller.reloadPlugins()
}
}
}
} }
} }

View File

@ -3,6 +3,7 @@ package net.mamoe.mirai.console.graphical.view
import com.jfoenix.controls.JFXTreeTableColumn import com.jfoenix.controls.JFXTreeTableColumn
import javafx.scene.control.TreeTableCell import javafx.scene.control.TreeTableCell
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
import net.mamoe.mirai.console.graphical.event.ReloadEvent
import net.mamoe.mirai.console.graphical.model.PluginModel import net.mamoe.mirai.console.graphical.model.PluginModel
import net.mamoe.mirai.console.graphical.stylesheet.PluginViewStyleSheet import net.mamoe.mirai.console.graphical.stylesheet.PluginViewStyleSheet
import net.mamoe.mirai.console.graphical.util.jfxButton import net.mamoe.mirai.console.graphical.util.jfxButton

View File

@ -0,0 +1,74 @@
package net.mamoe.mirai.console.graphical.view.dialog
import javafx.geometry.Insets
import net.mamoe.mirai.console.center.PluginCenter
import net.mamoe.mirai.console.graphical.util.jfxTextfield
import tornadofx.Fragment
import tornadofx.form
import tornadofx.vbox
class PluginDetailFragment(info: PluginCenter.PluginInfo) : Fragment() {
override val root = vbox {
prefWidth = 450.0
padding = Insets(25.0)
spacing = 25.0
jfxTextfield(info.name) {
promptText = "插件名"
isLabelFloat = true
}
jfxTextfield(info.version) {
promptText = "版本号"
isLabelFloat = true
}
jfxTextfield(info.coreVersion) {
promptText = "Mirai核心版本"
isLabelFloat = true
}
jfxTextfield(info.consoleVersion) {
promptText = "Mirai控制台版本"
isLabelFloat = true
}
jfxTextfield(info.tags.joinToString(",")) {
promptText = "标签"
isLabelFloat = true
}
jfxTextfield(info.author) {
promptText = "作者"
isLabelFloat = true
}
jfxTextfield(info.description) {
promptText = "描述"
isLabelFloat = true
}
jfxTextfield(info.usage) {
promptText = "使用方法"
isLabelFloat = true
}
jfxTextfield(info.vcs) {
promptText = "仓库地址"
isLabelFloat = true
}
jfxTextfield(info.commands.joinToString("\n\n")) {
promptText = "命令"
isLabelFloat = true
}
jfxTextfield(info.changeLog.joinToString("\n\n")) {
promptText = "修改日志"
isLabelFloat = true
}
}
}