Merge remote-tracking branch 'origin/master'

This commit is contained in:
jiahua.liu 2020-02-18 12:33:21 +08:00
commit 3844ef3311
11 changed files with 207 additions and 79 deletions

View File

@ -8,16 +8,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Setup Java JDK
uses: actions/setup-java@v1.3.0
with:
# The Java version to make available on the path. Takes a whole or semver Java version, or 1.x syntax (e.g. 1.8 => Java 8.x)
java-version: 11
# The package type (jre, jdk, jdk+fx)
java-package: jdk+fx
- name: Gradle Command
uses: eskatos/gradle-command-action@v1
with:
# Gradle command line arguments, see gradle --help
arguments: build -x mirai-core:jvmTest
- uses: actions/checkout@v1
- name: setup-android
uses: msfjarvis/setup-android@0.2
with:
# Gradle tasks to run - If you want to run ./gradlew assemble, specify assemble here.
gradleTasks: build -x mirai-core:jvmTest

View File

@ -1,9 +1,15 @@
plugins {
id("kotlinx-serialization")
id("org.openjfx.javafxplugin") version "0.0.8"
id("kotlin")
id("java")
}
javafx {
version = "11"
modules = listOf("javafx.controls")
//mainClassName = "Application"
}
apply(plugin = "com.github.johnrengelman.shadow")
@ -29,6 +35,7 @@ dependencies {
api(project(":mirai-console"))
runtimeOnly(files("../mirai-core-qqandroid/build/classes/kotlin/jvm/main"))
api(group = "no.tornado", name = "tornadofx", version = "1.7.19")
api(group = "com.jfoenix", name = "jfoenix", version = "9.0.8")
api("org.bouncycastle:bcprov-jdk15on:1.64")
// classpath is not set correctly by IDE
}

View File

@ -0,0 +1,44 @@
package net.mamoe.mirai.console.graphical.util
import com.jfoenix.controls.*
import javafx.beans.value.ObservableValue
import javafx.collections.ObservableList
import javafx.event.EventTarget
import javafx.scene.Node
import javafx.scene.control.*
import tornadofx.SortedFilteredList
import tornadofx.attachTo
import tornadofx.bind
internal fun EventTarget.jfxTabPane(op: TabPane.() -> Unit = {}) = JFXTabPane().attachTo(this, op)
internal fun EventTarget.jfxButton(text: String = "", graphic: Node? = null, op: Button.() -> Unit = {}) =
JFXButton(text).attachTo(this, op) {
if (graphic != null) it.graphic = graphic
}
fun EventTarget.jfxTextfield(value: String? = null, op: TextField.() -> Unit = {}) = JFXTextField().attachTo(this, op) {
if (value != null) it.text = value
}
fun EventTarget.jfxTextfield(property: ObservableValue<String>, op: TextField.() -> Unit = {}) = jfxTextfield().apply {
bind(property)
op(this)
}
fun EventTarget.jfxPasswordfield(value: String? = null, op: TextField.() -> Unit = {}) = JFXPasswordField().attachTo(this, op) {
if (value != null) it.text = value
}
fun EventTarget.jfxPasswordfield(property: ObservableValue<String>, op: TextField.() -> 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
}
}

View File

@ -1,27 +1,31 @@
package net.mamoe.mirai.console.graphical.view
import com.jfoenix.controls.JFXTextField
import javafx.beans.property.SimpleStringProperty
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
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 LoginFragment : Fragment() {
private val controller = find<MiraiGraphicalUIController>(FX.defaultScope)
private val qq = SimpleStringProperty()
private val psd = SimpleStringProperty()
private val qq = SimpleStringProperty("0")
private val psd = SimpleStringProperty("")
override val root = form {
fieldset("登录") {
field("QQ") {
textfield(qq)
jfxTextfield(qq)
}
field("密码") {
passwordfield(psd)
}
button("登录").action {
controller.login(qq.value, psd.value)
close()
jfxPasswordfield(psd)
}
}
jfxButton("登录").action {
controller.login(qq.value, psd.value)
close()
}
}
}

View File

@ -1,10 +1,20 @@
package net.mamoe.mirai.console.graphical.view
import com.jfoenix.controls.JFXListCell
import javafx.geometry.Insets
import javafx.geometry.Pos
import javafx.scene.control.Tab
import javafx.scene.control.TabPane
import javafx.stage.Modality
import net.mamoe.mirai.Bot
import javafx.scene.image.Image
import javafx.scene.paint.Color
import javafx.scene.text.FontWeight
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
import net.mamoe.mirai.console.graphical.model.BotModel
import net.mamoe.mirai.console.graphical.util.jfxButton
import net.mamoe.mirai.console.graphical.util.jfxListView
import net.mamoe.mirai.console.graphical.util.jfxTabPane
import tornadofx.*
import java.io.FileInputStream
class PrimaryView : View() {
@ -12,45 +22,87 @@ class PrimaryView : View() {
override val root = borderpane {
top = menubar {
menu("机器人") {
item("登录").action {
find<LoginFragment>().openModal(
modality = Modality.APPLICATION_MODAL,
resizable = false
)
prefWidth = 1000.0
prefHeight = 650.0
left = vbox {
imageview(Image(PrimaryView::class.java.classLoader.getResourceAsStream("logo.png")))
// bot list
jfxListView(controller.botList) {
fitToParentSize()
setCellFactory {
object : JFXListCell<BotModel>() {
var tab: Tab? = null
init {
onDoubleClick {
if (tab == null) {
(center as TabPane).tab(item.uin.toString()) {
listview(item.logHistory)
onDoubleClick { close() }
tab = this
}
} else {
(center as TabPane).tabs.add(tab)
}
tab?.select()
}
}
override fun updateItem(item: BotModel?, empty: Boolean) {
super.updateItem(item, empty)
if (item != null && !empty) {
graphic = null
text = item.uin.toString()
} else {
graphic = null
text = ""
}
}
}
}
}
hbox {
padding = Insets(10.0)
spacing = 10.0
alignment = Pos.CENTER
jfxButton("L").action {
find<LoginFragment>().openModal()
}
jfxButton("P")
jfxButton("S")
style { backgroundColor += c("00BCD4") }
children.style(true) {
backgroundColor += c("00BCD4")
fontSize = 15.px
fontWeight = FontWeight.BOLD
textFill = Color.WHITE
borderRadius += box(25.px)
backgroundRadius += box(25.px)
}
}
}
left = listview(controller.botList) {
fitToParentHeight()
center = jfxTabPane {
tab("Main") {
listview(controller.mainLog) {
cellFormat {
graphic = vbox {
label(it.uin.toString())
// label(stringBinding(it.botProperty) { if (value != null) value.nick else "登陆中" })
}
onDoubleClick {
(center as TabPane).tab(it.uin.toString()) {
listview(it.logHistory)
isClosable = true
select()
fitToParentSize()
cellFormat {
graphic = label(it) {
maxWidthProperty().bind(this@listview.widthProperty())
isWrapText = true
}
}
}
}
}
center = tabpane {
tab("Main") {
listview(controller.mainLog)
isClosable = false
}
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -28,6 +28,8 @@ import kotlin.contracts.contract
/**
* 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话.
*
* @see CoroutineScope.incoming
*/
@UseExperimental(ExperimentalContracts::class)
@MessageDsl
@ -49,6 +51,8 @@ inline fun <R> CoroutineScope.subscribeMessages(crossinline listeners: MessageSu
/**
* 订阅来自所有 [Bot] 的所有群消息事件
*
* @see CoroutineScope.incoming
*/
@UseExperimental(ExperimentalContracts::class)
@MessageDsl
@ -65,6 +69,8 @@ inline fun <R> CoroutineScope.subscribeGroupMessages(crossinline listeners: Mess
/**
* 订阅来自所有 [Bot] 的所有好友消息事件
*
* @see CoroutineScope.incoming
*/
@UseExperimental(ExperimentalContracts::class)
@MessageDsl
@ -81,6 +87,8 @@ inline fun <R> CoroutineScope.subscribeFriendMessages(crossinline listeners: Mes
/**
* 订阅来自这个 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话.
*
* @see CoroutineScope.incoming
*/
@UseExperimental(ExperimentalContracts::class)
@MessageDsl
@ -97,6 +105,8 @@ inline fun <R> Bot.subscribeMessages(crossinline listeners: MessageSubscribersBu
/**
* 订阅来自这个 [Bot] 的所有群消息事件
*
* @see CoroutineScope.incoming
*/
@UseExperimental(ExperimentalContracts::class)
@MessageDsl
@ -113,6 +123,8 @@ inline fun <R> Bot.subscribeGroupMessages(crossinline listeners: MessageSubscrib
/**
* 订阅来自这个 [Bot] 的所有好友消息事件.
*
* @see CoroutineScope.incoming
*/
@UseExperimental(ExperimentalContracts::class)
@MessageDsl
@ -129,9 +141,15 @@ inline fun <R> Bot.subscribeFriendMessages(crossinline listeners: MessageSubscri
/**
* 返回一个指定事件的接收通道
*
* @param capacity [Channel] 的参数, 参见 [Channel.Factory] 中的常量.
*
* @see subscribeFriendMessages
* @see subscribeMessages
* @see subscribeGroupMessages
*/
inline fun <reified E : Event> Bot.incoming(): ReceiveChannel<E> {
return Channel<E>(8).apply {
inline fun <reified E : Event> CoroutineScope.incoming(capacity: Int = Channel.RENDEZVOUS): ReceiveChannel<E> {
return Channel<E>(capacity).apply {
subscribeAlways<E> {
send(this)
}

View File

@ -90,6 +90,15 @@ internal object EventListenerManager {
private val lock = atomic(false)
private fun setLockValue(value: Boolean) {
lock.value = value
}
@Suppress("BooleanLiteralArgument")
private fun trySetLockTrue(): Boolean {
return lock.compareAndSet(false, true)
}
@Suppress("UNCHECKED_CAST", "BooleanLiteralArgument")
internal tailrec fun <E : Event> get(clazz: KClass<out E>): EventListeners<E> {
registries.forEach {
@ -97,10 +106,10 @@ internal object EventListenerManager {
return it.listeners as EventListeners<E>
}
}
if (lock.compareAndSet(false, true)) {
if (trySetLockTrue()) {
val registry = Registry(clazz, EventListeners())
registries.addLast(registry)
lock.value = false
setLockValue(false)
return registry.listeners as EventListeners<E>
}
return get(clazz)

View File

@ -28,8 +28,10 @@ import net.mamoe.mirai.message.sendAsImageTo
import net.mamoe.mirai.qqandroid.Bot
import net.mamoe.mirai.qqandroid.QQAndroid
import net.mamoe.mirai.utils.FileBasedDeviceInfo
import net.mamoe.mirai.utils.MiraiInternalAPI
import java.io.File
@MiraiInternalAPI
private fun readTestAccount(): BotAccount? {
val file = File("testAccount.txt")
if (!file.exists() || !file.canRead()) {
@ -59,7 +61,7 @@ suspend fun main() {
bot.messageDSL()
directlySubscribe(bot)
bot.network.awaitDisconnection()//等到直到断开连接
bot.join()//等到直到断开连接
}
/**

View File

@ -176,7 +176,7 @@ suspend fun main() {
}
bot.network.awaitDisconnection()//等到直到断开连接
bot.join()//等到直到断开连接
}
private fun newTestTempFile(filename: String = "${UUID.randomUUID()}", suffix: String = ".tmp"): File =

View File

@ -44,7 +44,6 @@ include(':mirai-core-qqandroid')
include(':mirai-japt')
include(':mirai-console')
include(':mirai-console-graphical')
include(':mirai-console-terminal')
//include(':mirai-api')
include(':mirai-api-http')
@ -54,24 +53,23 @@ include(':mirai-demos:mirai-demo-java')
include(':mirai-plugins')
include(':mirai-plugins:image-sender')
def javaVersion = System.getProperty("java.version")
def versionPos = javaVersion.indexOf(".")
if (versionPos==-1) versionPos = javaVersion.indexOf("-")
if (versionPos==-1){
println("jdk version unknown")
}else{
def javaVersionNum = javaVersion.substring(0, versionPos).toInteger()
if (javaVersionNum >= 11) {
println("jdk版本为 "+ javaVersionNum)
//include(':mirai-debug')
} else {
println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 最低需要 JDK 11 才能引入模块 `:mirai-debug`")
try{
def javaVersion = System.getProperty("java.version")
def versionPos = javaVersion.indexOf(".")
if (versionPos==-1) versionPos = javaVersion.indexOf("-")
if (versionPos==-1){
println("jdk version unknown")
}else{
def javaVersionNum = javaVersion.substring(0, versionPos).toInteger()
if (javaVersionNum >= 11) {
println("jdk版本为 "+ javaVersionNum)
include(':mirai-console-graphical')
} else {
println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 最低需要 JDK 11 才能引入模块 `:mirai-debug`")
}
}
}catch(Exception ignored){
}
project(':mirai-demos:mirai-demo-1').projectDir = file('mirai-demos/mirai-demo-1')
project(':mirai-demos:mirai-demo-gentleman').projectDir = file('mirai-demos/mirai-demo-gentleman')
project(':mirai-demos:mirai-demo-java').projectDir = file('mirai-demos/mirai-demo-java')
project(':mirai-plugins:image-sender').projectDir = file('mirai-plugins/image-sender')
enableFeaturePreview('GRADLE_METADATA')