mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-24 06:50:08 +08:00
Remove mirai-console-graphical
This commit is contained in:
parent
00d7430f06
commit
53149d1d36
@ -1,6 +0,0 @@
|
||||
### Mirai Console Graphical
|
||||
支持windows/mac
|
||||
有正式UI界面实现的CONSOLE
|
||||
优点: 适合新手/完全不懂编程的/界面美丽
|
||||
缺点: 不能在linux服务器运行
|
||||
所使用插件系统与terminal版本一致 可以来回切换
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id("kotlinx-serialization")
|
||||
id("org.openjfx.javafxplugin") version "0.0.8"
|
||||
id("kotlin")
|
||||
id("java")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
javafx {
|
||||
version = "13.0.2"
|
||||
modules = listOf("javafx.controls")
|
||||
//mainClassName = "Application"
|
||||
}
|
||||
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
|
||||
|
||||
/*
|
||||
tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>() {
|
||||
manifest {
|
||||
attributes["Main-Class"] = "net.mamoe.mirai.console.graphical.MiraiGraphicalLoader"
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
version = Versions.Mirai.consoleGraphical
|
||||
|
||||
description = "Graphical frontend for mirai-console"
|
||||
|
||||
dependencies {
|
||||
compileOnly("net.mamoe:mirai-core:${Versions.core}")
|
||||
implementation(project(":mirai-console"))
|
||||
|
||||
api(group = "no.tornado", name = "tornadofx", version = "1.7.19")
|
||||
api(group = "com.jfoenix", name = "jfoenix", version = "9.0.8")
|
||||
|
||||
testApi(project(":mirai-console"))
|
||||
testApi(kotlinx("coroutines-core", Versions.coroutines))
|
||||
testApi(group = "org.yaml", name = "snakeyaml", version = "1.25")
|
||||
testApi("net.mamoe:mirai-core:${Versions.core}")
|
||||
testApi("net.mamoe:mirai-core-qqandroid:${Versions.core}")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
all {
|
||||
|
||||
languageSettings.useExperimentalAnnotation("kotlin.Experimental")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
|
||||
languageSettings.progressiveMode = true
|
||||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val sourcesJar by tasks.registering(Jar::class) {
|
||||
classifier = "sources"
|
||||
from(sourceSets.main.get().allSource)
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical
|
||||
|
||||
import kotlinx.coroutines.cancel
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import tornadofx.launch
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class MiraiConsoleGraphicalLoader {
|
||||
companion object {
|
||||
internal var coreVersion :String = "0.0.0"
|
||||
internal var consoleVersion: String = "0.0.0"
|
||||
@JvmStatic
|
||||
fun load(
|
||||
coreVersion: String,
|
||||
consoleVersion: String
|
||||
) {
|
||||
this.coreVersion = coreVersion
|
||||
this.consoleVersion = consoleVersion
|
||||
Runtime.getRuntime().addShutdownHook(thread(start = false) {
|
||||
MiraiConsole.cancel()
|
||||
})
|
||||
launch<MiraiGraphicalUI>()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical
|
||||
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController
|
||||
import net.mamoe.mirai.console.graphical.stylesheet.PrimaryStyleSheet
|
||||
import net.mamoe.mirai.console.graphical.view.Decorator
|
||||
import tornadofx.App
|
||||
import tornadofx.find
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
//object MiraiGraphicalLoader {
|
||||
// @JvmStatic
|
||||
// fun main(args: Array<String>) {
|
||||
// launch<MiraiGraphicalUI>(args)
|
||||
// }
|
||||
//}
|
||||
|
||||
class MiraiGraphicalUI : App(Decorator::class, PrimaryStyleSheet::class) {
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
MiraiConsole.start(
|
||||
find<MiraiGraphicalFrontEndController>(),
|
||||
MiraiConsoleGraphicalLoader.coreVersion,
|
||||
MiraiConsoleGraphicalLoader.consoleVersion
|
||||
)
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
MiraiConsole.stop()
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
@ -1,214 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.controller
|
||||
|
||||
import javafx.application.Platform
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.stage.Modality
|
||||
import javafx.stage.StageStyle
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandManager.runCommand
|
||||
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.view.dialog.InputDialog
|
||||
import net.mamoe.mirai.console.graphical.view.dialog.VerificationCodeFragment
|
||||
import net.mamoe.mirai.console.plugins.PluginManager
|
||||
import net.mamoe.mirai.console.utils.MiraiConsoleFrontEnd
|
||||
import net.mamoe.mirai.network.CustomLoginFailedException
|
||||
import net.mamoe.mirai.utils.LoginSolver
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.SimpleLogger
|
||||
import net.mamoe.mirai.utils.SimpleLogger.LogPriority
|
||||
import tornadofx.Controller
|
||||
import tornadofx.Scope
|
||||
import tornadofx.find
|
||||
import tornadofx.observableListOf
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.collections.List
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.mutableMapOf
|
||||
import kotlin.collections.set
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
class MiraiGraphicalFrontEndController : Controller(), MiraiConsoleFrontEnd {
|
||||
|
||||
private val settingModel = find<GlobalSettingModel>()
|
||||
private val loginSolver = GraphicalLoginSolver()
|
||||
private val cache = mutableMapOf<Long, BotModel>()
|
||||
val mainLog = observableListOf<Pair<String, String>>()
|
||||
|
||||
|
||||
val botList = observableListOf<BotModel>()
|
||||
val pluginList: ObservableList<PluginModel> by lazy(::getPluginsFromConsole)
|
||||
|
||||
private val consoleInfo = ConsoleInfo()
|
||||
|
||||
internal val sdf by lazy { SimpleDateFormat("HH:mm:ss") }
|
||||
|
||||
init {
|
||||
// 监听插件重载事件,以重新从console获取插件列表
|
||||
subscribe<ReloadEvent> {
|
||||
pluginList.clear()
|
||||
|
||||
// 不能直接赋值,pluginList已经被bind,不能更换对象
|
||||
pluginList.addAll(getPluginsFromConsole())
|
||||
}
|
||||
}
|
||||
|
||||
fun login(qq: String, psd: String) {
|
||||
CommandManager.runCommand(ConsoleCommandSender, "login $qq $psd")
|
||||
}
|
||||
|
||||
fun logout(qq: Long) {
|
||||
cache.remove(qq)?.apply {
|
||||
botList.remove(this)
|
||||
if (botProperty.value != null && bot.isActive) {
|
||||
bot.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun sendCommand(command: String) = runCommand(ConsoleCommandSender, command)
|
||||
|
||||
|
||||
private val mainLogger = SimpleLogger(null) { priority: LogPriority, message: String?, e: Throwable? ->
|
||||
Platform.runLater {
|
||||
val time = sdf.format(Date())
|
||||
mainLog.apply {
|
||||
add("[$time] $message" to priority.name)
|
||||
trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun loggerFor(identity: Long): MiraiLogger {
|
||||
return if (identity == 0L) return mainLogger
|
||||
else cache[identity]?.logger ?: kotlin.error("bot not found: $identity")
|
||||
}
|
||||
|
||||
|
||||
override fun prePushBot(identity: Long) = Platform.runLater {
|
||||
if (!cache.containsKey(identity)) {
|
||||
BotModel(identity).also {
|
||||
cache[identity] = it
|
||||
botList.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun pushBot(bot: Bot) = Platform.runLater {
|
||||
cache[bot.id]?.bot = bot
|
||||
}
|
||||
|
||||
override fun pushVersion(consoleVersion: String, consoleBuild: String, coreVersion: String) {
|
||||
Platform.runLater {
|
||||
consoleInfo.consoleVersion = consoleVersion
|
||||
consoleInfo.consoleBuild = consoleBuild
|
||||
consoleInfo.coreVersion = coreVersion
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun requestInput(hint: String): String =
|
||||
suspendCancellableCoroutine {
|
||||
Platform.runLater {
|
||||
it.resume(InputDialog(hint).open())
|
||||
}
|
||||
}
|
||||
|
||||
override fun pushBotAdminStatus(identity: Long, admins: List<Long>) = Platform.runLater {
|
||||
cache[identity]?.admins?.setAll(admins)
|
||||
}
|
||||
|
||||
override fun createLoginSolver(): LoginSolver = loginSolver
|
||||
|
||||
private fun getPluginsFromConsole(): ObservableList<PluginModel> =
|
||||
PluginManager.getAllPluginDescriptions().map(::PluginModel).toObservable()
|
||||
|
||||
fun checkUpdate(plugin: PluginModel) {
|
||||
pluginList.forEach {
|
||||
if (it.name == plugin.name && it.author == plugin.author) {
|
||||
if (plugin.version > it.version) {
|
||||
it.expired = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return `true` when command is ambiguous
|
||||
*/
|
||||
fun checkAmbiguous(plugin: PluginModel): Boolean {
|
||||
plugin.insight?.commands?.forEach { name ->
|
||||
CommandManager.commands.forEach {
|
||||
if (name == it.name) return true
|
||||
}
|
||||
} ?: return false
|
||||
return false
|
||||
}
|
||||
|
||||
internal fun ObservableList<*>.trim() {
|
||||
while (size > settingModel.item.maxLongNum) {
|
||||
this.removeAt(0)
|
||||
}
|
||||
}
|
||||
|
||||
fun reloadPlugins() {
|
||||
|
||||
with(PluginManager) {
|
||||
reloadPlugins()
|
||||
}
|
||||
|
||||
fire(ReloadEvent) // 广播插件重载事件
|
||||
}
|
||||
}
|
||||
|
||||
class GraphicalLoginSolver : LoginSolver() {
|
||||
override suspend fun onSolvePicCaptcha(bot: Bot, data: ByteArray): String? {
|
||||
val code = VerificationCodeModel(VerificationCode(data))
|
||||
|
||||
// UI必须在UI线程执行,requestInput在协程种被调用
|
||||
Platform.runLater {
|
||||
find<VerificationCodeFragment>(Scope(code)).openModal(
|
||||
stageStyle = StageStyle.UNDECORATED,
|
||||
escapeClosesWindow = false,
|
||||
modality = Modality.NONE,
|
||||
resizable = false,
|
||||
block = true
|
||||
)
|
||||
}
|
||||
|
||||
// 阻塞协程直到验证码已经输入
|
||||
while (code.isDirty || code.code.value == null) {
|
||||
delay(1000)
|
||||
if (code.code.value === VerificationCodeFragment.MAGIC_KEY) {
|
||||
throw LoginCancelledManuallyException()
|
||||
}
|
||||
}
|
||||
return code.code.value
|
||||
}
|
||||
|
||||
|
||||
override suspend fun onSolveSliderCaptcha(bot: Bot, url: String): String? {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
override suspend fun onSolveUnsafeDeviceLoginVerify(bot: Bot, url: String): String? {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
class LoginCancelledManuallyException : CustomLoginFailedException(true, "取消登录")
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.event
|
||||
|
||||
import tornadofx.FXEvent
|
||||
|
||||
object ReloadEvent : FXEvent()
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.model
|
||||
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController
|
||||
import net.mamoe.mirai.utils.SimpleLogger
|
||||
import tornadofx.*
|
||||
import java.util.*
|
||||
|
||||
class BotModel(val uin: Long) {
|
||||
val botProperty = SimpleObjectProperty<Bot>(null)
|
||||
var bot: Bot by botProperty
|
||||
|
||||
val logHistory = observableListOf<Pair<String, String>>()
|
||||
val logger: SimpleLogger =
|
||||
SimpleLogger(uin.toString()) { priority: SimpleLogger.LogPriority, message: String?, e: Throwable? ->
|
||||
|
||||
val frontend = find<MiraiGraphicalFrontEndController>()
|
||||
|
||||
frontend.run {
|
||||
logHistory.apply {
|
||||
val time = sdf.format(Date())
|
||||
add("[$time] $uin $message" to priority.name)
|
||||
trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val admins = observableListOf<Long>()
|
||||
}
|
||||
|
||||
class BotViewModel(botModel: BotModel? = null) : ItemViewModel<BotModel>(botModel) {
|
||||
val bot = bind(BotModel::botProperty)
|
||||
val logHistory = bind(BotModel::logHistory)
|
||||
val admins = bind(BotModel::admins)
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.model
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
class ConsoleInfo {
|
||||
|
||||
val consoleVersionProperty = SimpleStringProperty()
|
||||
var consoleVersion by consoleVersionProperty
|
||||
|
||||
val consoleBuildProperty = SimpleStringProperty()
|
||||
var consoleBuild by consoleBuildProperty
|
||||
|
||||
val coreVersionProperty = SimpleStringProperty()
|
||||
var coreVersion by coreVersionProperty
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.model
|
||||
|
||||
import javafx.beans.property.SimpleLongProperty
|
||||
import tornadofx.ItemViewModel
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
class GlobalSetting {
|
||||
val maxLogNumProperty = SimpleLongProperty(4096)
|
||||
var maxLongNum: Long by maxLogNumProperty
|
||||
}
|
||||
|
||||
class GlobalSettingModel(setting: GlobalSetting) : ItemViewModel<GlobalSetting>(setting) {
|
||||
constructor() : this(GlobalSetting())
|
||||
|
||||
val maxLogNum = bind(GlobalSetting::maxLogNumProperty)
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.model
|
||||
|
||||
import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject
|
||||
import javafx.beans.property.SimpleBooleanProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import net.mamoe.mirai.console.center.PluginCenter
|
||||
import net.mamoe.mirai.console.plugins.PluginDescription
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
class PluginModel(
|
||||
val name: String,
|
||||
val version: String,
|
||||
val author: String,
|
||||
val description: String,
|
||||
var insight: PluginCenter.PluginInsight? = null
|
||||
) : RecursiveTreeObject<PluginModel>() {
|
||||
constructor(plugin: PluginDescription) : this(plugin.name, plugin.version, plugin.author, plugin.info)
|
||||
|
||||
val nameProperty = SimpleStringProperty(this, "nameProperty", name)
|
||||
val versionProperty = SimpleStringProperty(this, "versionProperty", version)
|
||||
val authorProperty = SimpleStringProperty(this, "authorProperty", author)
|
||||
val descriptionProperty = SimpleStringProperty(this, "descriptionProperty", description)
|
||||
|
||||
val enabledProperty = SimpleBooleanProperty(this, "enabledProperty")
|
||||
var enabled by enabledProperty
|
||||
|
||||
val expiredProperty = SimpleBooleanProperty(this, "expiredProperty", false)
|
||||
var expired by expiredProperty
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.model
|
||||
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import tornadofx.ItemViewModel
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
class VerificationCode(data: ByteArray = ByteArray(0)) {
|
||||
val codeProperty = SimpleStringProperty(null)
|
||||
var code: String? by codeProperty
|
||||
|
||||
val dataProperty: SimpleObjectProperty<ByteArray> = SimpleObjectProperty()
|
||||
val data: ByteArray by dataProperty
|
||||
|
||||
init {
|
||||
dataProperty.set(data)
|
||||
}
|
||||
}
|
||||
|
||||
class VerificationCodeModel(code: VerificationCode) : ItemViewModel<VerificationCode>(code) {
|
||||
constructor() : this(VerificationCode())
|
||||
|
||||
val code = bind(VerificationCode::codeProperty)
|
||||
val data = bind(VerificationCode::dataProperty)
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.stylesheet
|
||||
|
||||
import javafx.scene.layout.BackgroundRepeat
|
||||
import javafx.scene.paint.Color
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import tornadofx.Stylesheet
|
||||
import tornadofx.cssclass
|
||||
import tornadofx.csselement
|
||||
import java.io.File
|
||||
import kotlin.random.Random
|
||||
|
||||
open class BaseStyleSheet : Stylesheet() {
|
||||
|
||||
companion object {
|
||||
const val primaryColor = "0EA987"
|
||||
const val stressColor = "35867C"
|
||||
const val secondaryColor = "32CABA"
|
||||
const val lightColor ="9FD1CC"
|
||||
const val fontColor = "FFFFFF"
|
||||
val TRANSPARENT: Color = Color.TRANSPARENT
|
||||
|
||||
val rootPane by cssclass("root-pane")
|
||||
val jfxTabPane by cssclass("jfx-tab-pane")
|
||||
val myButtonBar by cssclass("my-button-bar")
|
||||
|
||||
val vBox by csselement("VBox")
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
rootPane {
|
||||
|
||||
child(imageView) {}
|
||||
|
||||
|
||||
jfxTabPane {
|
||||
val bg = File(MiraiConsole.path, "background")
|
||||
if (!bg.exists()) bg.mkdir()
|
||||
if (bg.isDirectory) {
|
||||
bg.listFiles()!!.filter { file -> file.extension in listOf("jpg", "jpeg", "png", "gif") }
|
||||
.randomElement()?.also {
|
||||
backgroundImage += it.toURI()
|
||||
backgroundRepeat += BackgroundRepeat.REPEAT to BackgroundRepeat.REPEAT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listView {
|
||||
backgroundColor += TRANSPARENT
|
||||
|
||||
listCell {
|
||||
backgroundColor += TRANSPARENT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Collection<T>.randomElement(): T? {
|
||||
if (isEmpty())
|
||||
return null
|
||||
return elementAt(Random.nextInt(size))
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.stylesheet
|
||||
|
||||
import javafx.scene.Cursor
|
||||
import javafx.scene.effect.BlurType
|
||||
import javafx.scene.effect.DropShadow
|
||||
import javafx.scene.paint.Color
|
||||
import javafx.scene.text.FontWeight
|
||||
import tornadofx.box
|
||||
import tornadofx.c
|
||||
import tornadofx.csselement
|
||||
import tornadofx.px
|
||||
|
||||
class LoginViewStyleSheet : BaseStyleSheet() {
|
||||
|
||||
companion object {
|
||||
val vBox by csselement("VBox")
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
/*
|
||||
* center box
|
||||
*/
|
||||
vBox {
|
||||
maxWidth = 500.px
|
||||
maxHeight = 500.px
|
||||
|
||||
backgroundColor += c(primaryColor, 0.3)
|
||||
backgroundRadius += box(15.px)
|
||||
|
||||
padding = box(50.px, 100.px)
|
||||
spacing = 25.px
|
||||
|
||||
borderRadius += box(15.px)
|
||||
effect = DropShadow(BlurType.THREE_PASS_BOX, Color.GRAY, 10.0, 0.0, 15.0, 15.0)
|
||||
}
|
||||
|
||||
textField {
|
||||
prefHeight = 30.px
|
||||
textFill = Color.BLACK
|
||||
fontWeight = FontWeight.BOLD
|
||||
}
|
||||
|
||||
/*
|
||||
* login button
|
||||
*/
|
||||
button {
|
||||
backgroundColor += c(stressColor, 0.8)
|
||||
padding = box(10.px, 0.px)
|
||||
prefWidth = 500.px
|
||||
textFill = Color.WHITE
|
||||
fontWeight = FontWeight.BOLD
|
||||
cursor = Cursor.HAND
|
||||
}
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.stylesheet
|
||||
|
||||
import javafx.geometry.Pos
|
||||
import javafx.scene.paint.Color
|
||||
import javafx.scene.text.FontWeight
|
||||
import tornadofx.box
|
||||
import tornadofx.c
|
||||
import tornadofx.cssclass
|
||||
import tornadofx.px
|
||||
|
||||
class PluginViewStyleSheet : BaseStyleSheet() {
|
||||
|
||||
companion object {
|
||||
val jfxTreeTableView by cssclass("jfx-tree-table-view")
|
||||
val treeTableRowCell by cssclass("tree-table-row-cell")
|
||||
val columnHeader by cssclass("column-header")
|
||||
val columnHeaderBg by cssclass("column-header-background")
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
jfxTreeTableView {
|
||||
backgroundColor += TRANSPARENT
|
||||
|
||||
columnHeader {
|
||||
borderWidth += box(0.px)
|
||||
|
||||
label {
|
||||
textFill = Color.BLACK
|
||||
}
|
||||
}
|
||||
|
||||
columnHeaderBg {
|
||||
backgroundColor += c(lightColor, 0.4)
|
||||
}
|
||||
|
||||
treeTableCell {
|
||||
alignment = Pos.CENTER
|
||||
}
|
||||
|
||||
treeTableRowCell {
|
||||
|
||||
fontWeight = FontWeight.SEMI_BOLD
|
||||
|
||||
|
||||
backgroundColor += TRANSPARENT
|
||||
|
||||
and(":selected") {
|
||||
backgroundColor += c(stressColor, 1.0)
|
||||
}
|
||||
|
||||
and(":hover:filled") {
|
||||
backgroundColor += c(stressColor, 0.6)
|
||||
and(":selected") {
|
||||
backgroundColor += c(stressColor, 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.stylesheet
|
||||
|
||||
import javafx.scene.Cursor
|
||||
import javafx.scene.text.FontWeight
|
||||
import tornadofx.box
|
||||
import tornadofx.c
|
||||
import tornadofx.cssclass
|
||||
import tornadofx.px
|
||||
|
||||
class PrimaryStyleSheet : BaseStyleSheet() {
|
||||
companion object {
|
||||
// window
|
||||
val jfxTitle by cssclass("jfx-decorator-buttons-container")
|
||||
val container by cssclass("jfx-decorator-content-container")
|
||||
|
||||
// jfx tab
|
||||
val jfxTabHeader by cssclass("tab-header-background")
|
||||
val closeButton by cssclass("tab-close-button")
|
||||
|
||||
// jfx list view
|
||||
val leftPane by cssclass("left-pane")
|
||||
val jfxListView by cssclass("jfx-list-view")
|
||||
val jfxListCell by cssclass("jfx-list-cell")
|
||||
}
|
||||
|
||||
init {
|
||||
/*
|
||||
* window
|
||||
*/
|
||||
jfxTitle {
|
||||
backgroundColor += c(primaryColor)
|
||||
}
|
||||
|
||||
container {
|
||||
borderColor += box(c(primaryColor))
|
||||
borderWidth += box(0.px, 4.px, 4.px, 4.px)
|
||||
}
|
||||
|
||||
/*
|
||||
* bot list
|
||||
*/
|
||||
rootPane {
|
||||
leftPane {
|
||||
|
||||
backgroundColor += c(primaryColor)
|
||||
// 这个padding有bug,十分神奇
|
||||
padding = box(0.px, 4.px, 0.px, 0.px)
|
||||
spacing = 4.px
|
||||
|
||||
jfxListView {
|
||||
|
||||
// placeholder
|
||||
vBox {
|
||||
spacing = 15.px
|
||||
|
||||
label {
|
||||
textFill = c(fontColor)
|
||||
fontWeight = FontWeight.BOLD
|
||||
}
|
||||
|
||||
button {
|
||||
textFill = c(fontColor)
|
||||
fontWeight = FontWeight.BOLD
|
||||
backgroundColor += c(secondaryColor, 0.8)
|
||||
padding = box(2.px, 10.px)
|
||||
cursor = Cursor.HAND
|
||||
}
|
||||
}
|
||||
|
||||
jfxListCell {
|
||||
backgroundColor += c(100, 100, 100, 0.4)
|
||||
backgroundRadius += box(5.px)
|
||||
|
||||
label {
|
||||
textFill = c(fontColor)
|
||||
fontWeight = FontWeight.BOLD
|
||||
}
|
||||
|
||||
button {
|
||||
opacity = 0.0
|
||||
backgroundRadius += box(10.px)
|
||||
backgroundColor += c(fontColor, 0.1)
|
||||
cursor = Cursor.HAND
|
||||
|
||||
and(hover) {
|
||||
opacity = 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* tab pane
|
||||
*/
|
||||
jfxTabHeader {
|
||||
backgroundColor += c(primaryColor)
|
||||
}
|
||||
|
||||
jfxTabPane {
|
||||
|
||||
// 日志列表样式
|
||||
vBox {
|
||||
padding = box(15.px)
|
||||
spacing = 15.px
|
||||
}
|
||||
|
||||
myButtonBar {
|
||||
spacing = 15.px
|
||||
|
||||
button {
|
||||
backgroundColor += c(secondaryColor, 0.8)
|
||||
padding = box(2.px, 10.px)
|
||||
cursor = Cursor.HAND
|
||||
textFill = c(fontColor)
|
||||
fontSize = 12.px
|
||||
}
|
||||
}
|
||||
|
||||
listView {
|
||||
// 字体在label里,大坑
|
||||
label {
|
||||
fontSize = 13.px
|
||||
}
|
||||
|
||||
listCell {
|
||||
|
||||
and(":WARNING") {
|
||||
backgroundColor += c("FFFF00", 0.3) // Yellow
|
||||
}
|
||||
|
||||
and(":ERROR") {
|
||||
backgroundColor += c("FF0000", 0.3) // Red
|
||||
}
|
||||
|
||||
and(":selected") {
|
||||
backgroundColor += c(stressColor, 1.0)
|
||||
}
|
||||
|
||||
and(":hover:filled") {
|
||||
backgroundColor += c(stressColor, 0.6)
|
||||
and(":selected") {
|
||||
backgroundColor += c(stressColor, 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 调整滚动条
|
||||
scrollBar {
|
||||
|
||||
backgroundColor += TRANSPARENT
|
||||
|
||||
// 隐藏水平滚动条
|
||||
and(horizontal) {
|
||||
prefHeight = 0.px
|
||||
s(incrementArrow, decrementArrow) { backgroundColor += TRANSPARENT }
|
||||
}
|
||||
|
||||
and(vertical) {
|
||||
thumb {
|
||||
backgroundColor += c(stressColor, 0.6)
|
||||
}
|
||||
|
||||
track {
|
||||
backgroundColor += TRANSPARENT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 去除JFoenix默认样式
|
||||
tab {
|
||||
and(":closable") {
|
||||
borderWidth += box(0.px)
|
||||
borderInsets += box(6.px, 0.px)
|
||||
}
|
||||
|
||||
closeButton {
|
||||
and(hover) { cursor = Cursor.HAND }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.util
|
||||
|
||||
import com.jfoenix.controls.*
|
||||
import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject
|
||||
import javafx.beans.value.ObservableValue
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.event.EventTarget
|
||||
import javafx.scene.Node
|
||||
import javafx.scene.control.ListView
|
||||
import tornadofx.SortedFilteredList
|
||||
import tornadofx.attachTo
|
||||
import tornadofx.bind
|
||||
|
||||
internal fun EventTarget.jfxTabPane(op: JFXTabPane.() -> Unit = {}) = JFXTabPane().attachTo(this, op)
|
||||
|
||||
internal fun EventTarget.jfxButton(text: String = "", graphic: Node? = null, op: JFXButton.() -> Unit = {}) =
|
||||
JFXButton(text).attachTo(this, op) {
|
||||
if (graphic != null) it.graphic = graphic
|
||||
it.buttonType = JFXButton.ButtonType.RAISED
|
||||
}
|
||||
|
||||
fun EventTarget.jfxTextfield(value: String? = null, op: JFXTextField.() -> Unit = {}) =
|
||||
JFXTextField().attachTo(this, op) {
|
||||
if (value != null) it.text = value
|
||||
}
|
||||
|
||||
fun EventTarget.jfxTextfield(property: ObservableValue<String>, op: JFXTextField.() -> Unit = {}) =
|
||||
jfxTextfield().apply {
|
||||
bind(property)
|
||||
op(this)
|
||||
}
|
||||
|
||||
fun EventTarget.jfxPasswordfield(value: String? = null, op: JFXPasswordField.() -> Unit = {}) =
|
||||
JFXPasswordField().attachTo(this, op) {
|
||||
if (value != null) it.text = value
|
||||
}
|
||||
|
||||
fun EventTarget.jfxPasswordfield(property: ObservableValue<String>, op: JFXPasswordField.() -> Unit = {}) =
|
||||
jfxPasswordfield().apply {
|
||||
bind(property)
|
||||
op(this)
|
||||
}
|
||||
|
||||
internal fun <T> EventTarget.jfxListView(values: ObservableList<T>? = null, op: ListView<T>.() -> Unit = {}) =
|
||||
JFXListView<T>().attachTo(this, op) {
|
||||
if (values != null) {
|
||||
if (values is SortedFilteredList<T>) values.bindTo(it)
|
||||
else it.items = values
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : RecursiveTreeObject<T>?> EventTarget.jfxTreeTableView(
|
||||
items: ObservableList<T>? = null,
|
||||
op: JFXTreeTableView<T>.() -> Unit = {}
|
||||
) = JFXTreeTableView<T>(RecursiveTreeItem(items, RecursiveTreeObject<T>::getChildren)).attachTo(this, op)
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.util
|
||||
|
||||
import com.jfoenix.svg.SVGGlyph
|
||||
import javafx.scene.paint.Color
|
||||
|
||||
class SVG {
|
||||
companion object {
|
||||
var close = SVGGlyph(
|
||||
0,
|
||||
"CLOSE",
|
||||
"M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z",
|
||||
Color.WHITE
|
||||
).apply { setSize(8.0, 8.0) }
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.util
|
||||
|
||||
import javafx.event.EventTarget
|
||||
import javafx.geometry.Pos
|
||||
import javafx.scene.layout.HBox
|
||||
import tornadofx.addClass
|
||||
import tornadofx.hbox
|
||||
|
||||
fun EventTarget.myButtonBar(alignment: Pos = Pos.BASELINE_LEFT, op: HBox.() -> Unit = {}) = hbox {
|
||||
addClass("my-button-bar")
|
||||
this.alignment = alignment
|
||||
op()
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.view
|
||||
|
||||
import com.jfoenix.controls.JFXDecorator
|
||||
import tornadofx.View
|
||||
|
||||
class Decorator : View() {
|
||||
|
||||
override val root = JFXDecorator(primaryStage, find<PrimaryView>().root).apply {
|
||||
prefWidth = 1000.0
|
||||
prefHeight = 650.0
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.view
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import javafx.geometry.Pos
|
||||
import javafx.scene.image.Image
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController
|
||||
import net.mamoe.mirai.console.graphical.stylesheet.LoginViewStyleSheet
|
||||
import net.mamoe.mirai.console.graphical.util.jfxButton
|
||||
import net.mamoe.mirai.console.graphical.util.jfxPasswordfield
|
||||
import net.mamoe.mirai.console.graphical.util.jfxTextfield
|
||||
import tornadofx.*
|
||||
|
||||
class LoginView : View("CNM") {
|
||||
|
||||
private val controller = find<MiraiGraphicalFrontEndController>()
|
||||
private val qq = SimpleStringProperty("")
|
||||
private val psd = SimpleStringProperty("")
|
||||
|
||||
override val root = borderpane {
|
||||
|
||||
addStylesheet(LoginViewStyleSheet::class)
|
||||
|
||||
center = vbox {
|
||||
|
||||
imageview(Image(LoginView::class.java.classLoader.getResourceAsStream("character.png"))) {
|
||||
alignment = Pos.CENTER
|
||||
}
|
||||
|
||||
jfxTextfield(qq) {
|
||||
promptText = "QQ"
|
||||
isLabelFloat = true
|
||||
}
|
||||
|
||||
jfxPasswordfield(psd) {
|
||||
promptText = "Password"
|
||||
isLabelFloat = true
|
||||
}
|
||||
|
||||
jfxButton("Login").action {
|
||||
runAsync {
|
||||
runBlocking { controller.login(qq.value, psd.value) }
|
||||
}.ui {
|
||||
qq.value = ""
|
||||
psd.value = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.view
|
||||
|
||||
import com.jfoenix.controls.JFXTreeTableColumn
|
||||
import javafx.application.Platform
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.geometry.Pos
|
||||
import javafx.scene.control.Button
|
||||
import javafx.scene.control.TreeTableCell
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController
|
||||
import net.mamoe.mirai.console.graphical.event.ReloadEvent
|
||||
import net.mamoe.mirai.console.graphical.model.PluginModel
|
||||
import net.mamoe.mirai.console.graphical.stylesheet.PluginViewStyleSheet
|
||||
import net.mamoe.mirai.console.graphical.util.jfxButton
|
||||
import net.mamoe.mirai.console.graphical.util.jfxTreeTableView
|
||||
import net.mamoe.mirai.console.graphical.view.dialog.PluginDetailFragment
|
||||
import tornadofx.*
|
||||
|
||||
class PluginsCenterView : View() {
|
||||
|
||||
private val controller = find<MiraiGraphicalFrontEndController>()
|
||||
private val center get() = MiraiConsole.frontEnd.pluginCenter
|
||||
private val plugins: ObservableList<PluginModel> = observableListOf()
|
||||
|
||||
init {
|
||||
// 监听插件重载,情况插件列表,重新载入。
|
||||
// 同时把页面刷新,按键的listener也初始化
|
||||
subscribe<ReloadEvent> { plugins.clear() }
|
||||
}
|
||||
|
||||
override val root = jfxTreeTableView(plugins) {
|
||||
|
||||
addStylesheet(PluginViewStyleSheet::class)
|
||||
|
||||
placeholder = button("从崔云获取插件列表") {
|
||||
action {
|
||||
isDisable = true
|
||||
runAsync {
|
||||
fetch()
|
||||
}.ui {
|
||||
plugins.addAll(it)
|
||||
isDisable = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isShowRoot = false
|
||||
columns.addAll(
|
||||
JFXTreeTableColumn<PluginModel, String>("插件名").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
|
||||
setCellValueFactory {
|
||||
return@setCellValueFactory it.value.value.nameProperty
|
||||
}
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("版本").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
|
||||
setCellValueFactory {
|
||||
return@setCellValueFactory it.value.value.versionProperty
|
||||
}
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("作者").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
|
||||
setCellValueFactory {
|
||||
return@setCellValueFactory it.value.value.authorProperty
|
||||
}
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("介绍").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.48))
|
||||
|
||||
setCellValueFactory {
|
||||
return@setCellValueFactory it.value.value.descriptionProperty
|
||||
}
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, PluginModel>("操作").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.2))
|
||||
|
||||
setCellValueFactory { return@setCellValueFactory it.value.valueProperty() }
|
||||
|
||||
setCellFactory {
|
||||
return@setCellFactory object : TreeTableCell<PluginModel, PluginModel>() {
|
||||
override fun updateItem(item: PluginModel?, empty: Boolean) {
|
||||
if (item != null && !empty) {
|
||||
graphic = hbox {
|
||||
|
||||
spacing = 15.0
|
||||
alignment = Pos.CENTER
|
||||
|
||||
jfxButton("详情") {
|
||||
action { detail(item) }
|
||||
}
|
||||
|
||||
|
||||
jfxButton(if (item.expired) "更新" else "下载") {
|
||||
action { download(item, this) }
|
||||
}
|
||||
|
||||
}
|
||||
text = ""
|
||||
} else {
|
||||
graphic = null
|
||||
text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private fun fetch(): List<PluginModel> = mutableListOf<PluginModel>().apply {
|
||||
runBlocking {
|
||||
var page = 1
|
||||
while (true) {
|
||||
val map = center.fetchPlugin(page++)
|
||||
if (map.isEmpty()) return@runBlocking
|
||||
map.forEach {
|
||||
with(
|
||||
PluginModel(
|
||||
it.value.name,
|
||||
it.value.version,
|
||||
it.value.author,
|
||||
it.value.description,
|
||||
it.value
|
||||
)
|
||||
) {
|
||||
add(this)
|
||||
controller.checkUpdate(this)
|
||||
controller.checkAmbiguous(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun detail(pluginModel: PluginModel) {
|
||||
runAsync {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.view
|
||||
|
||||
import com.jfoenix.controls.JFXTreeTableColumn
|
||||
import javafx.scene.control.TreeTableCell
|
||||
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController
|
||||
import net.mamoe.mirai.console.graphical.model.PluginModel
|
||||
import net.mamoe.mirai.console.graphical.stylesheet.PluginViewStyleSheet
|
||||
import net.mamoe.mirai.console.graphical.util.jfxButton
|
||||
import net.mamoe.mirai.console.graphical.util.jfxTreeTableView
|
||||
import tornadofx.View
|
||||
import tornadofx.addStylesheet
|
||||
import tornadofx.visibleWhen
|
||||
|
||||
class PluginsView : View() {
|
||||
|
||||
private val controller = find<MiraiGraphicalFrontEndController>()
|
||||
val plugins = controller.pluginList
|
||||
|
||||
override val root = jfxTreeTableView(plugins) {
|
||||
|
||||
addStylesheet(PluginViewStyleSheet::class)
|
||||
|
||||
isShowRoot = false
|
||||
columns.addAll(
|
||||
JFXTreeTableColumn<PluginModel, String>("插件名").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
|
||||
setCellValueFactory {
|
||||
return@setCellValueFactory it.value.value.nameProperty
|
||||
}
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("版本").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
|
||||
setCellValueFactory {
|
||||
return@setCellValueFactory it.value.value.versionProperty
|
||||
}
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("作者").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.1))
|
||||
|
||||
setCellValueFactory {
|
||||
return@setCellValueFactory it.value.value.authorProperty
|
||||
}
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, String>("介绍").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.6))
|
||||
|
||||
setCellValueFactory {
|
||||
return@setCellValueFactory it.value.value.descriptionProperty
|
||||
}
|
||||
},
|
||||
JFXTreeTableColumn<PluginModel, PluginModel>("操作").apply {
|
||||
prefWidthProperty().bind(this@jfxTreeTableView.widthProperty().multiply(0.08))
|
||||
|
||||
setCellValueFactory { return@setCellValueFactory it.value.valueProperty() }
|
||||
|
||||
setCellFactory {
|
||||
return@setCellFactory object : TreeTableCell<PluginModel, PluginModel>() {
|
||||
override fun updateItem(item: PluginModel?, empty: Boolean) {
|
||||
if (item != null && !empty) {
|
||||
graphic = jfxButton("更新") {
|
||||
visibleWhen(item.expiredProperty)
|
||||
|
||||
// to do update
|
||||
}
|
||||
text = ""
|
||||
} else {
|
||||
graphic = null
|
||||
text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.view
|
||||
|
||||
import com.jfoenix.controls.JFXButton
|
||||
import com.jfoenix.controls.JFXListCell
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.geometry.Pos
|
||||
import javafx.scene.control.Alert
|
||||
import javafx.scene.control.ButtonType
|
||||
import javafx.scene.control.Tab
|
||||
import javafx.scene.control.TabPane
|
||||
import javafx.scene.image.Image
|
||||
import javafx.scene.input.Clipboard
|
||||
import javafx.scene.input.KeyCode
|
||||
import javafx.scene.layout.Priority
|
||||
import javafx.stage.FileChooser
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController
|
||||
import net.mamoe.mirai.console.graphical.model.BotModel
|
||||
import net.mamoe.mirai.console.graphical.util.*
|
||||
import tornadofx.*
|
||||
|
||||
class PrimaryView : View() {
|
||||
|
||||
private val controller = find<MiraiGraphicalFrontEndController>()
|
||||
private lateinit var mainTabPane: TabPane
|
||||
|
||||
override val root = borderpane {
|
||||
|
||||
addClass("root-pane")
|
||||
|
||||
left = vbox {
|
||||
|
||||
addClass("left-pane")
|
||||
|
||||
imageview(Image(PrimaryView::class.java.classLoader.getResourceAsStream("logo.png"))) {
|
||||
fitHeight = 40.0
|
||||
alignment = Pos.CENTER
|
||||
isPreserveRatio = true
|
||||
}
|
||||
|
||||
// bot list
|
||||
jfxListView(controller.botList) {
|
||||
fitToParentHeight()
|
||||
|
||||
placeholder = vbox {
|
||||
|
||||
alignment = Pos.CENTER
|
||||
|
||||
label("Bot列表为空,请登录一个Bot")
|
||||
|
||||
jfxButton("登录") {
|
||||
buttonType = JFXButton.ButtonType.FLAT
|
||||
}.action {
|
||||
// select login pane
|
||||
mainTabPane.selectionModel.selectLast()
|
||||
}
|
||||
}
|
||||
|
||||
setCellFactory {
|
||||
object : JFXListCell<BotModel>() {
|
||||
var tab: Tab? = null
|
||||
|
||||
init {
|
||||
onDoubleClick {
|
||||
tab?.select() ?: mainTabPane.logTab(
|
||||
text = item.uin.toString(),
|
||||
logs = item.logHistory
|
||||
).select().also { tab = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateItem(item: BotModel?, empty: Boolean) {
|
||||
super.updateItem(item, empty)
|
||||
if (item != null && !empty) {
|
||||
graphic = hbox {
|
||||
|
||||
alignment = Pos.CENTER_LEFT
|
||||
|
||||
label(item.uin.toString())
|
||||
pane {
|
||||
hgrow = Priority.ALWAYS
|
||||
}
|
||||
jfxButton(graphic = SVG.close) {
|
||||
buttonType = JFXButton.ButtonType.FLAT
|
||||
tooltip("退出登录")
|
||||
}.action {
|
||||
alert(Alert.AlertType.CONFIRMATION, "${item.uin}将会退出登录,是否确认") {
|
||||
if (it == ButtonType.OK) {
|
||||
tab?.close()
|
||||
controller.logout(item.uin)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
text = ""
|
||||
} else {
|
||||
graphic = null
|
||||
text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
center = vbox {
|
||||
|
||||
jfxTabPane {
|
||||
|
||||
fitToParentHeight()
|
||||
|
||||
tabClosingPolicy = TabPane.TabClosingPolicy.ALL_TABS
|
||||
|
||||
logTab("Main", controller.mainLog, closeable = false)
|
||||
|
||||
fixedTab("Plugins").content = find<PluginsView>().root
|
||||
|
||||
fixedTab("Plugins Center").content = find<PluginsCenterView>().root
|
||||
|
||||
fixedTab("Settings").content = find<SettingsView>().root
|
||||
|
||||
fixedTab("Login").content = find<LoginView>().root
|
||||
|
||||
mainTabPane = this
|
||||
}
|
||||
|
||||
// command input
|
||||
textfield {
|
||||
|
||||
promptText = "在这里输出命令"
|
||||
|
||||
setOnKeyPressed {
|
||||
if (it.code == KeyCode.ENTER) {
|
||||
runAsync {
|
||||
runBlocking { controller.sendCommand(text) }
|
||||
}.ui { text = "" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Tab.select() = apply {
|
||||
if (!mainTabPane.tabs.contains(this)) mainTabPane.tabs.add(this)
|
||||
mainTabPane.selectionModel.select(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun TabPane.fixedTab(title: String) = tab(title) { isClosable = false }
|
||||
|
||||
private fun TabPane.logTab(
|
||||
text: String? = null,
|
||||
logs: ObservableList<Pair<String, String>>,
|
||||
closeable: Boolean = true,
|
||||
op: Tab.() -> Unit = {}
|
||||
) = tab(text) {
|
||||
|
||||
this.isClosable = closeable
|
||||
|
||||
vbox {
|
||||
myButtonBar(alignment = Pos.BASELINE_RIGHT) {
|
||||
|
||||
jfxButton("导出日志").action {
|
||||
val path = chooseFile(
|
||||
"选择保存路径",
|
||||
arrayOf(FileChooser.ExtensionFilter("日志", "txt")),
|
||||
FileChooserMode.Save,
|
||||
owner = FX.primaryStage
|
||||
) {
|
||||
initialFileName = "$text.txt"
|
||||
}
|
||||
runAsyncWithOverlay {
|
||||
path.firstOrNull()?.run {
|
||||
if (!exists()) createNewFile()
|
||||
writer().use {
|
||||
logs.forEach { log -> it.appendln(log.first) }
|
||||
}
|
||||
true
|
||||
} ?: false
|
||||
}.ui {// isSucceed: Boolean ->
|
||||
// notify something
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listview(logs) {
|
||||
|
||||
fitToParentSize()
|
||||
cellFormat {
|
||||
|
||||
addPseudoClass(it.second)
|
||||
|
||||
graphic = label(it.first) {
|
||||
maxWidthProperty().bind(this@listview.widthProperty())
|
||||
isWrapText = true
|
||||
|
||||
|
||||
contextmenu {
|
||||
item("复制").action {
|
||||
Clipboard.getSystemClipboard().putString(it.first)
|
||||
}
|
||||
item("删除").action {
|
||||
logs.remove(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
also(op)
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.view
|
||||
|
||||
import javafx.geometry.Pos
|
||||
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController
|
||||
import net.mamoe.mirai.console.graphical.model.GlobalSettingModel
|
||||
import net.mamoe.mirai.console.graphical.util.jfxButton
|
||||
import net.mamoe.mirai.console.graphical.util.jfxTextfield
|
||||
import net.mamoe.mirai.console.graphical.util.myButtonBar
|
||||
import tornadofx.*
|
||||
import java.awt.Desktop
|
||||
import java.io.File
|
||||
|
||||
class SettingsView : View() {
|
||||
|
||||
private val controller = find<MiraiGraphicalFrontEndController>()
|
||||
private val settingModel = find<GlobalSettingModel>()
|
||||
|
||||
override val root = vbox {
|
||||
|
||||
myButtonBar(alignment = Pos.BASELINE_RIGHT) {
|
||||
jfxButton("撤掉").action {
|
||||
settingModel.rollback()
|
||||
}
|
||||
jfxButton("保存").action {
|
||||
settingModel.commit()
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
fieldset("插件目录") {
|
||||
field {
|
||||
jfxTextfield((System.getProperty("user.dir") + "/plugins/").replace("//", "/")) { isEditable = false }
|
||||
jfxButton("打开目录").action {
|
||||
(System.getProperty("user.dir") + "/plugins/").replace("//", "/").also { path ->
|
||||
Desktop.getDesktop().takeIf { it.isSupported(Desktop.Action.OPEN) }?.open(File(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fieldset("背景目录") {
|
||||
field {
|
||||
jfxTextfield((System.getProperty("user.dir") + "/background/").replace("//", "/")) { isEditable = false }
|
||||
jfxButton("打开目录").action {
|
||||
(System.getProperty("user.dir") + "/background/").replace("//", "/").also { path ->
|
||||
Desktop.getDesktop().takeIf { it.isSupported(Desktop.Action.OPEN) }?.open(File(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fieldset("最大日志容量") {
|
||||
field {
|
||||
jfxTextfield().bind(settingModel.maxLogNum)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.view.dialog
|
||||
|
||||
import javafx.scene.control.TextField
|
||||
import javafx.stage.Modality
|
||||
import javafx.stage.StageStyle
|
||||
import tornadofx.*
|
||||
|
||||
class InputDialog(title: String) : Fragment() {
|
||||
|
||||
private lateinit var input: TextField
|
||||
|
||||
init {
|
||||
titleProperty.value = title
|
||||
}
|
||||
|
||||
override val root = form {
|
||||
|
||||
fieldset {
|
||||
field(title) {
|
||||
input = textfield("")
|
||||
}
|
||||
|
||||
buttonbar {
|
||||
|
||||
button("提交").action { close() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun open(): String {
|
||||
// 阻塞窗口直到关闭
|
||||
openModal(
|
||||
stageStyle = StageStyle.DECORATED,
|
||||
modality = Modality.APPLICATION_MODAL,
|
||||
block = true
|
||||
)
|
||||
return input.text
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
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.vbox
|
||||
|
||||
class PluginDetailFragment(info: PluginCenter.PluginInfo) : Fragment() {
|
||||
|
||||
init {
|
||||
title = info.name
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.graphical.view.dialog
|
||||
|
||||
import javafx.scene.image.Image
|
||||
import net.mamoe.mirai.console.graphical.model.VerificationCodeModel
|
||||
import tornadofx.*
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
class VerificationCodeFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
val MAGIC_KEY = String("CANCEL".toByteArray())
|
||||
}
|
||||
|
||||
val code = find<VerificationCodeModel>()
|
||||
|
||||
override val root = vbox {
|
||||
// 显示验证码
|
||||
imageview(Image(ByteArrayInputStream(code.data.value)))
|
||||
|
||||
form {
|
||||
fieldset {
|
||||
field("验证码") {
|
||||
textfield(code.code)
|
||||
}
|
||||
}
|
||||
|
||||
buttonbar {
|
||||
button("提交").action {
|
||||
code.commit()
|
||||
this@VerificationCodeFragment.close()
|
||||
}
|
||||
button("取消").action {
|
||||
code.code.value =
|
||||
MAGIC_KEY
|
||||
code.commit()
|
||||
this@VerificationCodeFragment.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
import net.mamoe.mirai.console.graphical.MiraiGraphicalUI
|
||||
import tornadofx.launch
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
launch<MiraiGraphicalUI>(args)
|
||||
}
|
Loading…
Reference in New Issue
Block a user