2023-04-09 13:35:35 +08:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2022-09-14 13:01:10 +08:00
|
|
|
import QtQuick
|
|
|
|
import QtQuick.Layouts
|
|
|
|
import QtQuick.Controls
|
2024-01-25 03:23:29 +08:00
|
|
|
import Fk
|
2023-05-19 10:08:36 +08:00
|
|
|
import Fk.RoomElement
|
2022-04-15 18:37:20 +08:00
|
|
|
|
|
|
|
Item {
|
2022-04-30 15:27:56 +08:00
|
|
|
id: root
|
2022-04-15 18:37:20 +08:00
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
property bool loaded: false
|
2022-04-15 18:37:20 +08:00
|
|
|
|
2023-04-21 17:49:30 +08:00
|
|
|
Rectangle {
|
|
|
|
anchors.fill: listView
|
|
|
|
color: "#88EEEEEE"
|
|
|
|
radius: 6
|
|
|
|
}
|
|
|
|
|
2023-02-26 16:51:29 +08:00
|
|
|
ListView {
|
2023-04-21 17:49:30 +08:00
|
|
|
id: listView
|
2023-06-16 23:53:44 +08:00
|
|
|
clip: true
|
2023-04-21 17:49:30 +08:00
|
|
|
width: 130
|
|
|
|
height: parent.height - 20
|
|
|
|
y: 10
|
2022-04-30 15:27:56 +08:00
|
|
|
ScrollBar.vertical: ScrollBar {}
|
|
|
|
model: ListModel {
|
|
|
|
id: packages
|
|
|
|
}
|
2022-04-15 18:37:20 +08:00
|
|
|
|
2023-04-21 17:49:30 +08:00
|
|
|
highlight: Rectangle { color: "#E91E63"; radius: 5 }
|
|
|
|
highlightMoveDuration: 500
|
|
|
|
|
|
|
|
delegate: Item {
|
|
|
|
width: listView.width
|
|
|
|
height: 40
|
|
|
|
|
|
|
|
Text {
|
2024-01-25 03:23:29 +08:00
|
|
|
text: luatr(name)
|
2023-04-21 17:49:30 +08:00
|
|
|
anchors.centerIn: parent
|
|
|
|
}
|
|
|
|
|
|
|
|
TapHandler {
|
|
|
|
onTapped: {
|
|
|
|
listView.currentIndex = index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onCurrentIndexChanged: { vanishAnim.start(); }
|
|
|
|
}
|
|
|
|
|
|
|
|
GridView {
|
|
|
|
id: gridView
|
2023-06-16 23:53:44 +08:00
|
|
|
clip: true
|
2023-04-21 17:49:30 +08:00
|
|
|
width: root.width - listView.width - cardDetail.width - 16
|
|
|
|
height: parent.height - 20
|
|
|
|
y: 10
|
|
|
|
anchors.left: listView.right
|
|
|
|
anchors.leftMargin: 8 + (width % 100) / 2
|
|
|
|
cellHeight: 140
|
|
|
|
cellWidth: 100
|
|
|
|
|
|
|
|
delegate: CardItem {
|
|
|
|
autoBack: false
|
2024-02-27 02:28:13 +08:00
|
|
|
showDetail: false
|
2023-04-21 17:49:30 +08:00
|
|
|
property int dupCount: 0
|
|
|
|
|
|
|
|
Text {
|
|
|
|
anchors.right: parent.right
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
text: parent.dupCount ? ("x" + parent.dupCount.toString()) : ""
|
|
|
|
font.pixelSize: 36
|
|
|
|
color: "white"
|
|
|
|
style: Text.Outline
|
|
|
|
}
|
|
|
|
|
|
|
|
Component.onCompleted: {
|
2023-06-09 17:23:02 +08:00
|
|
|
const data = modelData;
|
2023-04-21 17:49:30 +08:00
|
|
|
if (!data.cards) {
|
|
|
|
name = data.name;
|
|
|
|
suit = data.suit;
|
|
|
|
number = data.number;
|
|
|
|
cid = data.cid;
|
|
|
|
} else {
|
|
|
|
name = data.name;
|
|
|
|
cid = data.cid;
|
|
|
|
suit = "";
|
|
|
|
number = 0;
|
|
|
|
color = "";
|
|
|
|
dupCount = data.cards.length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onClicked: {
|
|
|
|
cardDetail.cid = modelData.cid;
|
|
|
|
cardDetail.cards = modelData.cards;
|
|
|
|
cardDetail.updateCard();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ParallelAnimation {
|
|
|
|
id: vanishAnim
|
|
|
|
PropertyAnimation {
|
|
|
|
target: gridView
|
|
|
|
property: "opacity"
|
|
|
|
to: 0
|
|
|
|
duration: 150
|
|
|
|
easing.type: Easing.InOutQuad
|
|
|
|
}
|
|
|
|
PropertyAnimation {
|
|
|
|
target: gridView
|
|
|
|
property: "y"
|
|
|
|
to: 30
|
|
|
|
duration: 150
|
|
|
|
easing.type: Easing.InOutQuad
|
|
|
|
}
|
|
|
|
onFinished: {
|
2024-01-25 03:23:29 +08:00
|
|
|
const pkg = listView.model.get(listView.currentIndex).name;
|
|
|
|
const idList = lcall("GetCards", pkg);
|
|
|
|
const cardList = idList.map(id => lcall("GetCardData", id));
|
2023-04-21 17:49:30 +08:00
|
|
|
|
2023-06-09 17:23:02 +08:00
|
|
|
const groupedCardList = [];
|
2023-04-21 17:49:30 +08:00
|
|
|
let groupedCards = {};
|
|
|
|
cardList.forEach(c => {
|
2023-06-09 17:23:02 +08:00
|
|
|
const name = c.name;
|
2023-04-21 17:49:30 +08:00
|
|
|
if (!groupedCards[name]) {
|
|
|
|
groupedCardList.push(name);
|
|
|
|
groupedCards[name] = [];
|
|
|
|
}
|
|
|
|
groupedCards[name].push({
|
|
|
|
cid: c.cid,
|
|
|
|
suit: c.suit,
|
|
|
|
number: c.number,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-06-09 17:23:02 +08:00
|
|
|
const model = [];
|
2023-04-21 17:49:30 +08:00
|
|
|
groupedCardList.forEach(name => {
|
2023-06-09 17:23:02 +08:00
|
|
|
const cards = groupedCards[name];
|
2023-04-21 17:49:30 +08:00
|
|
|
if (cards.length === 1) {
|
|
|
|
model.push({
|
|
|
|
name: name,
|
|
|
|
extension: pkg,
|
|
|
|
suit: cards[0].suit,
|
|
|
|
number: cards[0].number,
|
|
|
|
cid: cards[0].cid,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
model.push({
|
|
|
|
name: name,
|
|
|
|
cid: cards[0].cid,
|
|
|
|
cards: cards,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
});
|
|
|
|
gridView.model = model;
|
|
|
|
appearAnim.start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SequentialAnimation {
|
|
|
|
id: appearAnim
|
|
|
|
PauseAnimation { duration: 200 }
|
|
|
|
ParallelAnimation {
|
|
|
|
PropertyAnimation {
|
|
|
|
target: gridView
|
|
|
|
property: "opacity"
|
|
|
|
to: 1
|
|
|
|
duration: 150
|
|
|
|
easing.type: Easing.InOutQuad
|
|
|
|
}
|
|
|
|
PropertyAnimation {
|
|
|
|
target: gridView
|
|
|
|
property: "y"
|
|
|
|
from: 20
|
|
|
|
to: 10
|
|
|
|
duration: 150
|
|
|
|
easing.type: Easing.InOutQuad
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
id: cardDetail
|
|
|
|
width: 310
|
|
|
|
height: parent.height - 20
|
|
|
|
y: 10
|
|
|
|
anchors.right: parent.right
|
|
|
|
anchors.rightMargin: 10
|
|
|
|
color: "#88EEEEEE"
|
|
|
|
radius: 8
|
|
|
|
|
|
|
|
property int cid: 1
|
|
|
|
property var cards
|
|
|
|
function updateCard() {
|
2024-01-25 03:23:29 +08:00
|
|
|
const data = lcall("GetCardData", cid);
|
2023-04-21 17:49:30 +08:00
|
|
|
const suitTable = {
|
|
|
|
spade: "♠", heart: '<font color="red">♥</font>',
|
|
|
|
club: "♣", diamond: '<font color="red">♦</font>',
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cards) {
|
|
|
|
detailCard.setData(data);
|
|
|
|
detailCard.dupCount = 0;
|
|
|
|
} else {
|
|
|
|
detailCard.cid = cid;
|
|
|
|
detailCard.color = "";
|
|
|
|
detailCard.suit = "";
|
|
|
|
detailCard.number = 0;
|
|
|
|
detailCard.dupCount = cards.length;
|
|
|
|
}
|
|
|
|
detailCard.known = true;
|
|
|
|
cardText.clear();
|
2023-12-09 21:57:47 +08:00
|
|
|
audioRow.clear();
|
2024-01-25 03:23:29 +08:00
|
|
|
cardText.append(luatr(":" + data.name));
|
2023-12-09 21:57:47 +08:00
|
|
|
addCardAudio(data)
|
2024-01-25 03:23:29 +08:00
|
|
|
const skills = lcall("GetCardSpecialSkills", cid);
|
2023-04-21 17:49:30 +08:00
|
|
|
if (skills.length > 0) {
|
2024-01-25 03:23:29 +08:00
|
|
|
cardText.append("<br/>" + luatr("Special card skills:"));
|
2023-04-21 17:49:30 +08:00
|
|
|
skills.forEach(t => {
|
2024-01-25 03:23:29 +08:00
|
|
|
cardText.append("<b>" + luatr(t) + "</b>: "
|
|
|
|
+ luatr(":" + t));
|
2023-04-21 17:49:30 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cards) {
|
2024-01-25 03:23:29 +08:00
|
|
|
cardText.append("<br/>" + luatr("Every suit & number:"));
|
2023-04-21 17:49:30 +08:00
|
|
|
cardText.append(cards.map(c => {
|
2024-01-25 03:23:29 +08:00
|
|
|
return (suitTable[c.suit] + Util.convertNumber(c.number))
|
2023-04-21 17:49:30 +08:00
|
|
|
}).join(", "));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Flickable {
|
|
|
|
flickableDirection: Flickable.VerticalFlick
|
|
|
|
contentHeight: detailLayout.height
|
|
|
|
width: parent.width - 40
|
|
|
|
height: parent.height - 40
|
|
|
|
clip: true
|
|
|
|
anchors.centerIn: parent
|
|
|
|
ScrollBar.vertical: ScrollBar {}
|
|
|
|
|
|
|
|
ColumnLayout {
|
|
|
|
id: detailLayout
|
|
|
|
width: parent.width
|
|
|
|
|
|
|
|
CardItem {
|
|
|
|
id: detailCard
|
|
|
|
Layout.alignment: Qt.AlignHCenter
|
|
|
|
cid: 1
|
|
|
|
known: false
|
2024-02-27 02:28:13 +08:00
|
|
|
showDetail: false
|
2023-04-21 17:49:30 +08:00
|
|
|
|
|
|
|
property int dupCount: 0
|
|
|
|
Text {
|
|
|
|
anchors.right: parent.right
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
text: parent.dupCount ? ("x" + parent.dupCount.toString()) : ""
|
|
|
|
font.pixelSize: 36
|
|
|
|
color: "white"
|
|
|
|
style: Text.Outline
|
2022-04-30 15:27:56 +08:00
|
|
|
}
|
2022-04-15 18:37:20 +08:00
|
|
|
}
|
2023-04-21 17:49:30 +08:00
|
|
|
|
|
|
|
TextEdit {
|
|
|
|
id: cardText
|
|
|
|
|
|
|
|
Layout.fillWidth: true
|
|
|
|
readOnly: true
|
|
|
|
selectByKeyboard: true
|
|
|
|
selectByMouse: false
|
|
|
|
wrapMode: TextEdit.WordWrap
|
|
|
|
textFormat: TextEdit.RichText
|
|
|
|
font.pixelSize: 16
|
|
|
|
}
|
2023-12-09 21:57:47 +08:00
|
|
|
|
|
|
|
GridLayout {
|
|
|
|
columns: 2
|
|
|
|
Repeater {
|
|
|
|
model: ListModel {
|
|
|
|
id: audioRow
|
|
|
|
}
|
|
|
|
Button {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
contentItem: Text {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
horizontalAlignment: Text.AlignHCenter
|
|
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
text: {
|
|
|
|
if (gender === "male") {
|
2024-01-25 03:23:29 +08:00
|
|
|
return luatr("Male Audio");
|
2023-12-09 21:57:47 +08:00
|
|
|
} else {
|
2024-01-25 03:23:29 +08:00
|
|
|
return luatr("Female Audio");
|
2023-12-09 21:57:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
font.pixelSize: 14
|
|
|
|
}
|
|
|
|
onClicked: {
|
2024-01-25 03:23:29 +08:00
|
|
|
const data = lcall("GetCardData", cardDetail.cid);
|
|
|
|
Backend.playSound("./packages/" + extension + "/audio/card/"
|
|
|
|
+ gender + "/" + data.name);
|
2023-12-09 21:57:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-30 15:27:56 +08:00
|
|
|
}
|
2022-04-15 18:37:20 +08:00
|
|
|
}
|
2022-04-30 15:27:56 +08:00
|
|
|
}
|
2022-04-15 18:37:20 +08:00
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
Button {
|
2024-01-25 03:23:29 +08:00
|
|
|
text: luatr("Quit")
|
2022-04-30 15:27:56 +08:00
|
|
|
anchors.right: parent.right
|
|
|
|
onClicked: {
|
|
|
|
mainStack.pop();
|
2022-04-15 18:37:20 +08:00
|
|
|
}
|
2022-04-30 15:27:56 +08:00
|
|
|
}
|
2022-04-15 18:37:20 +08:00
|
|
|
|
2023-12-09 21:57:47 +08:00
|
|
|
function addCardAudio(card) {
|
|
|
|
const extension = card.extension;
|
2024-01-25 03:23:29 +08:00
|
|
|
const orig_extension = lcall("GetCardExtensionByName", card.name);
|
|
|
|
const prefix = AppPath + "/packages/";
|
|
|
|
const suffix = card.name + ".mp3";
|
|
|
|
let fname = prefix + extension + "/audio/card/male/" + suffix;
|
2023-12-09 21:57:47 +08:00
|
|
|
if (Backend.exists(fname)) {
|
2024-01-25 03:23:29 +08:00
|
|
|
audioRow.append( { gender: "male", extension: extension } );
|
2023-12-09 21:57:47 +08:00
|
|
|
} else {
|
2024-01-25 03:23:29 +08:00
|
|
|
fname = prefix + orig_extension + "/audio/card/male/" + suffix;
|
2023-12-09 21:57:47 +08:00
|
|
|
if (Backend.exists(fname)) {
|
|
|
|
audioRow.append( {gender: "male", extension: orig_extension} );
|
|
|
|
}
|
|
|
|
}
|
2024-01-25 03:23:29 +08:00
|
|
|
fname = prefix + extension + "/audio/card/female/" + suffix;
|
2023-12-09 21:57:47 +08:00
|
|
|
if (Backend.exists(fname)) {
|
2024-01-25 03:23:29 +08:00
|
|
|
audioRow.append( { gender: "female", extension: extension } );
|
2023-12-09 21:57:47 +08:00
|
|
|
}else {
|
2024-01-25 03:23:29 +08:00
|
|
|
fname = prefix + orig_extension + "/audio/card/female/" + suffix;
|
2023-12-09 21:57:47 +08:00
|
|
|
if (Backend.exists(fname)) {
|
2024-01-25 03:23:29 +08:00
|
|
|
audioRow.append( { gender: "female", extension: orig_extension } );
|
2023-12-09 21:57:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-30 15:27:56 +08:00
|
|
|
function loadPackages() {
|
|
|
|
if (loaded) return;
|
2024-01-25 03:23:29 +08:00
|
|
|
const packs = lcall("GetAllCardPack");
|
2023-08-03 15:24:17 +08:00
|
|
|
packs.forEach(name => {
|
|
|
|
if (!config.serverHiddenPacks.includes(name)) {
|
|
|
|
packages.append({ name: name });
|
|
|
|
}
|
|
|
|
});
|
2022-04-30 15:27:56 +08:00
|
|
|
loaded = true;
|
|
|
|
}
|
2022-04-15 18:37:20 +08:00
|
|
|
}
|