dashboard: dynamic dashboard tabs + fix performance settings updating (#1253)
* [CI] chore: update flake * Dashboard perf settings save, visibility on none enabled * Dashboard heigh stutter fixed, persist current tab * restore binding * wrapper async=false * ScriptModel, centralized tabs/panes, individual toggle * fixes, missed mediaUpdateInterval, passing values --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
0d56db3b6c
commit
3e0360401b
8 changed files with 220 additions and 104 deletions
|
|
@ -258,7 +258,8 @@ Singleton {
|
||||||
return {
|
return {
|
||||||
enabled: dashboard.enabled,
|
enabled: dashboard.enabled,
|
||||||
showOnHover: dashboard.showOnHover,
|
showOnHover: dashboard.showOnHover,
|
||||||
updateInterval: dashboard.updateInterval,
|
mediaUpdateInterval: dashboard.mediaUpdateInterval,
|
||||||
|
resourceUpdateInterval: dashboard.resourceUpdateInterval,
|
||||||
dragThreshold: dashboard.dragThreshold,
|
dragThreshold: dashboard.dragThreshold,
|
||||||
performance: {
|
performance: {
|
||||||
showBattery: dashboard.performance.showBattery,
|
showBattery: dashboard.performance.showBattery,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@ JsonObject {
|
||||||
property int mediaUpdateInterval: 500
|
property int mediaUpdateInterval: 500
|
||||||
property int resourceUpdateInterval: 1000
|
property int resourceUpdateInterval: 1000
|
||||||
property int dragThreshold: 50
|
property int dragThreshold: 50
|
||||||
|
property bool showDashboard: true
|
||||||
|
property bool showMedia: true
|
||||||
|
property bool showPerformance: true
|
||||||
|
property bool showWeather: true
|
||||||
property Sizes sizes: Sizes {}
|
property Sizes sizes: Sizes {}
|
||||||
property Performance performance: Performance {}
|
property Performance performance: Performance {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,16 @@ Item {
|
||||||
// General Settings
|
// General Settings
|
||||||
property bool enabled: Config.dashboard.enabled ?? true
|
property bool enabled: Config.dashboard.enabled ?? true
|
||||||
property bool showOnHover: Config.dashboard.showOnHover ?? true
|
property bool showOnHover: Config.dashboard.showOnHover ?? true
|
||||||
property int updateInterval: Config.dashboard.updateInterval ?? 1000
|
property int mediaUpdateInterval: Config.dashboard.mediaUpdateInterval ?? 1000
|
||||||
|
property int resourceUpdateInterval: Config.dashboard.resourceUpdateInterval ?? 1000
|
||||||
property int dragThreshold: Config.dashboard.dragThreshold ?? 50
|
property int dragThreshold: Config.dashboard.dragThreshold ?? 50
|
||||||
|
|
||||||
|
// Dashboard Tabs
|
||||||
|
property bool showDashboard: Config.dashboard.showDashboard ?? true
|
||||||
|
property bool showMedia: Config.dashboard.showMedia ?? true
|
||||||
|
property bool showPerformance: Config.dashboard.showPerformance ?? true
|
||||||
|
property bool showWeather: Config.dashboard.showWeather ?? true
|
||||||
|
|
||||||
// Performance Resources
|
// Performance Resources
|
||||||
property bool showBattery: Config.dashboard.performance.showBattery ?? false
|
property bool showBattery: Config.dashboard.performance.showBattery ?? false
|
||||||
property bool showGpu: Config.dashboard.performance.showGpu ?? true
|
property bool showGpu: Config.dashboard.performance.showGpu ?? true
|
||||||
|
|
@ -38,8 +45,13 @@ Item {
|
||||||
function saveConfig() {
|
function saveConfig() {
|
||||||
Config.dashboard.enabled = root.enabled;
|
Config.dashboard.enabled = root.enabled;
|
||||||
Config.dashboard.showOnHover = root.showOnHover;
|
Config.dashboard.showOnHover = root.showOnHover;
|
||||||
Config.dashboard.updateInterval = root.updateInterval;
|
Config.dashboard.mediaUpdateInterval = root.mediaUpdateInterval;
|
||||||
|
Config.dashboard.resourceUpdateInterval = root.resourceUpdateInterval;
|
||||||
Config.dashboard.dragThreshold = root.dragThreshold;
|
Config.dashboard.dragThreshold = root.dragThreshold;
|
||||||
|
Config.dashboard.showDashboard = root.showDashboard;
|
||||||
|
Config.dashboard.showMedia = root.showMedia;
|
||||||
|
Config.dashboard.showPerformance = root.showPerformance;
|
||||||
|
Config.dashboard.showWeather = root.showWeather;
|
||||||
Config.dashboard.performance.showBattery = root.showBattery;
|
Config.dashboard.performance.showBattery = root.showBattery;
|
||||||
Config.dashboard.performance.showGpu = root.showGpu;
|
Config.dashboard.performance.showGpu = root.showGpu;
|
||||||
Config.dashboard.performance.showCpu = root.showCpu;
|
Config.dashboard.performance.showCpu = root.showCpu;
|
||||||
|
|
|
||||||
|
|
@ -38,44 +38,91 @@ SectionContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionContainer {
|
RowLayout {
|
||||||
contentSpacing: Appearance.spacing.normal
|
Layout.fillWidth: true
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
SliderInput {
|
SwitchRow {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
label: qsTr("Show Dashboard tab")
|
||||||
label: qsTr("Update interval")
|
checked: root.rootItem.showDashboard
|
||||||
value: root.rootItem.updateInterval
|
onToggled: checked => {
|
||||||
from: 100
|
root.rootItem.showDashboard = checked;
|
||||||
to: 10000
|
|
||||||
stepSize: 100
|
|
||||||
suffix: "ms"
|
|
||||||
validator: IntValidator { bottom: 100; top: 10000 }
|
|
||||||
formatValueFunction: (val) => Math.round(val).toString()
|
|
||||||
parseValueFunction: (text) => parseInt(text)
|
|
||||||
|
|
||||||
onValueModified: (newValue) => {
|
|
||||||
root.rootItem.updateInterval = Math.round(newValue);
|
|
||||||
root.rootItem.saveConfig();
|
root.rootItem.saveConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SliderInput {
|
SwitchRow {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
label: qsTr("Show Media tab")
|
||||||
|
checked: root.rootItem.showMedia
|
||||||
|
onToggled: checked => {
|
||||||
|
root.rootItem.showMedia = checked;
|
||||||
|
root.rootItem.saveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
label: qsTr("Drag threshold")
|
SwitchRow {
|
||||||
value: root.rootItem.dragThreshold
|
Layout.fillWidth: true
|
||||||
from: 0
|
label: qsTr("Show Performance tab")
|
||||||
to: 100
|
checked: root.rootItem.showPerformance
|
||||||
suffix: "px"
|
onToggled: checked => {
|
||||||
validator: IntValidator { bottom: 0; top: 100 }
|
root.rootItem.showPerformance = checked;
|
||||||
formatValueFunction: (val) => Math.round(val).toString()
|
root.rootItem.saveConfig();
|
||||||
parseValueFunction: (text) => parseInt(text)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onValueModified: (newValue) => {
|
SwitchRow {
|
||||||
root.rootItem.dragThreshold = Math.round(newValue);
|
Layout.fillWidth: true
|
||||||
|
label: qsTr("Show Weather tab")
|
||||||
|
checked: root.rootItem.showWeather
|
||||||
|
onToggled: checked => {
|
||||||
|
root.rootItem.showWeather = checked;
|
||||||
root.rootItem.saveConfig();
|
root.rootItem.saveConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SliderInput {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
label: qsTr("Media update interval")
|
||||||
|
value: root.rootItem.mediaUpdateInterval
|
||||||
|
from: 100
|
||||||
|
to: 10000
|
||||||
|
stepSize: 100
|
||||||
|
suffix: "ms"
|
||||||
|
validator: IntValidator {
|
||||||
|
bottom: 100
|
||||||
|
top: 10000
|
||||||
|
}
|
||||||
|
formatValueFunction: val => Math.round(val).toString()
|
||||||
|
parseValueFunction: text => parseInt(text)
|
||||||
|
|
||||||
|
onValueModified: newValue => {
|
||||||
|
root.rootItem.mediaUpdateInterval = Math.round(newValue);
|
||||||
|
root.rootItem.saveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SliderInput {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
label: qsTr("Drag threshold")
|
||||||
|
value: root.rootItem.dragThreshold
|
||||||
|
from: 0
|
||||||
|
to: 100
|
||||||
|
suffix: "px"
|
||||||
|
validator: IntValidator {
|
||||||
|
bottom: 0
|
||||||
|
top: 100
|
||||||
|
}
|
||||||
|
formatValueFunction: val => Math.round(val).toString()
|
||||||
|
parseValueFunction: text => parseInt(text)
|
||||||
|
|
||||||
|
onValueModified: newValue => {
|
||||||
|
root.rootItem.dragThreshold = Math.round(newValue);
|
||||||
|
root.rootItem.saveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ SectionContainer {
|
||||||
opts.push({
|
opts.push({
|
||||||
"label": qsTr("Battery"),
|
"label": qsTr("Battery"),
|
||||||
"propertyName": "showBattery",
|
"propertyName": "showBattery",
|
||||||
"onToggled": function(checked) {
|
"onToggled": function (checked) {
|
||||||
root.rootItem.showBattery = checked;
|
root.rootItem.showBattery = checked;
|
||||||
root.rootItem.saveConfig();
|
root.rootItem.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
@ -41,39 +41,39 @@ SectionContainer {
|
||||||
|
|
||||||
if (root.gpuAvailable)
|
if (root.gpuAvailable)
|
||||||
opts.push({
|
opts.push({
|
||||||
"label": qsTr("GPU"),
|
"label": qsTr("GPU"),
|
||||||
"propertyName": "showGpu",
|
"propertyName": "showGpu",
|
||||||
"onToggled": function(checked) {
|
"onToggled": function (checked) {
|
||||||
root.rootItem.showGpu = checked;
|
root.rootItem.showGpu = checked;
|
||||||
root.rootItem.saveConfig();
|
root.rootItem.saveConfig();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
opts.push({
|
opts.push({
|
||||||
"label": qsTr("CPU"),
|
"label": qsTr("CPU"),
|
||||||
"propertyName": "showCpu",
|
"propertyName": "showCpu",
|
||||||
"onToggled": function(checked) {
|
"onToggled": function (checked) {
|
||||||
root.rootItem.showCpu = checked;
|
root.rootItem.showCpu = checked;
|
||||||
root.rootItem.saveConfig();
|
root.rootItem.saveConfig();
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"label": qsTr("Memory"),
|
"label": qsTr("Memory"),
|
||||||
"propertyName": "showMemory",
|
"propertyName": "showMemory",
|
||||||
"onToggled": function(checked) {
|
"onToggled": function (checked) {
|
||||||
root.rootItem.showMemory = checked;
|
root.rootItem.showMemory = checked;
|
||||||
root.rootItem.saveConfig();
|
root.rootItem.saveConfig();
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"label": qsTr("Storage"),
|
"label": qsTr("Storage"),
|
||||||
"propertyName": "showStorage",
|
"propertyName": "showStorage",
|
||||||
"onToggled": function(checked) {
|
"onToggled": function (checked) {
|
||||||
root.rootItem.showStorage = checked;
|
root.rootItem.showStorage = checked;
|
||||||
root.rootItem.saveConfig();
|
root.rootItem.saveConfig();
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"label": qsTr("Network"),
|
"label": qsTr("Network"),
|
||||||
"propertyName": "showNetwork",
|
"propertyName": "showNetwork",
|
||||||
"onToggled": function(checked) {
|
"onToggled": function (checked) {
|
||||||
root.rootItem.showNetwork = checked;
|
root.rootItem.showNetwork = checked;
|
||||||
root.rootItem.saveConfig();
|
root.rootItem.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
@ -82,4 +82,25 @@ SectionContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SliderInput {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
label: qsTr("Resource update interval")
|
||||||
|
value: root.rootItem.resourceUpdateInterval
|
||||||
|
from: 100
|
||||||
|
to: 10000
|
||||||
|
stepSize: 100
|
||||||
|
suffix: "ms"
|
||||||
|
validator: IntValidator {
|
||||||
|
bottom: 100
|
||||||
|
top: 10000
|
||||||
|
}
|
||||||
|
formatValueFunction: val => Math.round(val).toString()
|
||||||
|
parseValueFunction: text => parseInt(text)
|
||||||
|
|
||||||
|
onValueModified: newValue => {
|
||||||
|
root.rootItem.resourceUpdateInterval = Math.round(newValue);
|
||||||
|
root.rootItem.saveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,37 @@ Item {
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
required property PersistentProperties state
|
required property PersistentProperties state
|
||||||
required property FileDialog facePicker
|
required property FileDialog facePicker
|
||||||
|
|
||||||
|
readonly property var dashboardTabs: {
|
||||||
|
const allTabs = [
|
||||||
|
{
|
||||||
|
component: dashComponent,
|
||||||
|
iconName: "dashboard",
|
||||||
|
text: qsTr("Dashboard"),
|
||||||
|
enabled: Config.dashboard.showDashboard
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: mediaComponent,
|
||||||
|
iconName: "queue_music",
|
||||||
|
text: qsTr("Media"),
|
||||||
|
enabled: Config.dashboard.showMedia
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: performanceComponent,
|
||||||
|
iconName: "speed",
|
||||||
|
text: qsTr("Performance"),
|
||||||
|
enabled: Config.dashboard.showPerformance && (Config.dashboard.performance.showCpu || Config.dashboard.performance.showGpu || Config.dashboard.performance.showMemory || Config.dashboard.performance.showStorage || Config.dashboard.performance.showNetwork || Config.dashboard.performance.showBattery)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: weatherComponent,
|
||||||
|
iconName: "cloud",
|
||||||
|
text: qsTr("Weather"),
|
||||||
|
enabled: Config.dashboard.showWeather
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return allTabs.filter(tab => tab.enabled);
|
||||||
|
}
|
||||||
|
|
||||||
readonly property real nonAnimWidth: view.implicitWidth + viewWrapper.anchors.margins * 2
|
readonly property real nonAnimWidth: view.implicitWidth + viewWrapper.anchors.margins * 2
|
||||||
readonly property real nonAnimHeight: tabs.implicitHeight + tabs.anchors.topMargin + view.implicitHeight + viewWrapper.anchors.margins * 2
|
readonly property real nonAnimHeight: tabs.implicitHeight + tabs.anchors.topMargin + view.implicitHeight + viewWrapper.anchors.margins * 2
|
||||||
|
|
||||||
|
|
@ -31,6 +62,7 @@ Item {
|
||||||
|
|
||||||
nonAnimWidth: root.nonAnimWidth - anchors.margins * 2
|
nonAnimWidth: root.nonAnimWidth - anchors.margins * 2
|
||||||
state: root.state
|
state: root.state
|
||||||
|
tabs: root.dashboardTabs
|
||||||
}
|
}
|
||||||
|
|
||||||
ClippingRectangle {
|
ClippingRectangle {
|
||||||
|
|
@ -86,31 +118,56 @@ Item {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: row
|
id: row
|
||||||
|
|
||||||
Pane {
|
Repeater {
|
||||||
index: 0
|
model: ScriptModel {
|
||||||
sourceComponent: Dash {
|
values: root.dashboardTabs
|
||||||
visibilities: root.visibilities
|
}
|
||||||
state: root.state
|
|
||||||
facePicker: root.facePicker
|
delegate: Loader {
|
||||||
|
id: paneLoader
|
||||||
|
|
||||||
|
required property int index
|
||||||
|
required property var modelData
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
|
||||||
|
sourceComponent: modelData.component
|
||||||
|
|
||||||
|
Component.onCompleted: active = Qt.binding(() => {
|
||||||
|
if (index === view.currentIndex)
|
||||||
|
return true;
|
||||||
|
const vx = Math.floor(view.visibleArea.xPosition * view.contentWidth);
|
||||||
|
const vex = Math.floor(vx + view.visibleArea.widthRatio * view.contentWidth);
|
||||||
|
return (vx >= x && vx <= x + implicitWidth) || (vex >= x && vex <= x + implicitWidth);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Pane {
|
Component {
|
||||||
index: 1
|
id: dashComponent
|
||||||
sourceComponent: Media {
|
Dash {
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
}
|
state: root.state
|
||||||
|
facePicker: root.facePicker
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Pane {
|
Component {
|
||||||
index: 2
|
id: mediaComponent
|
||||||
sourceComponent: Performance {}
|
Media {
|
||||||
|
visibilities: root.visibilities
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Pane {
|
Component {
|
||||||
index: 3
|
id: performanceComponent
|
||||||
sourceComponent: Weather {}
|
Performance {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: weatherComponent
|
||||||
|
Weather {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on contentX {
|
Behavior on contentX {
|
||||||
|
|
@ -132,21 +189,4 @@ Item {
|
||||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component Pane: Loader {
|
|
||||||
id: pane
|
|
||||||
|
|
||||||
required property int index
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
|
|
||||||
Component.onCompleted: active = Qt.binding(() => {
|
|
||||||
// Always keep current tab loaded
|
|
||||||
if (pane.index === view.currentIndex)
|
|
||||||
return true;
|
|
||||||
const vx = Math.floor(view.visibleArea.xPosition * view.contentWidth);
|
|
||||||
const vex = Math.floor(vx + view.visibleArea.widthRatio * view.contentWidth);
|
|
||||||
return (vx >= x && vx <= x + implicitWidth) || (vex >= x && vex <= x + implicitWidth);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ Item {
|
||||||
|
|
||||||
required property real nonAnimWidth
|
required property real nonAnimWidth
|
||||||
required property PersistentProperties state
|
required property PersistentProperties state
|
||||||
|
required property var tabs
|
||||||
|
|
||||||
readonly property alias count: bar.count
|
readonly property alias count: bar.count
|
||||||
|
|
||||||
implicitHeight: bar.implicitHeight + indicator.implicitHeight + indicator.anchors.topMargin + separator.implicitHeight
|
implicitHeight: bar.implicitHeight + indicator.implicitHeight + indicator.anchors.topMargin + separator.implicitHeight
|
||||||
|
|
@ -30,30 +32,18 @@ Item {
|
||||||
|
|
||||||
onCurrentIndexChanged: root.state.currentTab = currentIndex
|
onCurrentIndexChanged: root.state.currentTab = currentIndex
|
||||||
|
|
||||||
Tab {
|
Repeater {
|
||||||
iconName: "dashboard"
|
model: ScriptModel {
|
||||||
text: qsTr("Dashboard")
|
values: root.tabs
|
||||||
}
|
}
|
||||||
|
|
||||||
Tab {
|
delegate: Tab {
|
||||||
iconName: "queue_music"
|
required property var modelData
|
||||||
text: qsTr("Media")
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab {
|
iconName: modelData.iconName
|
||||||
iconName: "speed"
|
text: modelData.text
|
||||||
text: qsTr("Performance")
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tab {
|
|
||||||
iconName: "cloud"
|
|
||||||
text: qsTr("Weather")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tab {
|
|
||||||
// iconName: "workspaces"
|
|
||||||
// text: qsTr("Workspaces")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
@ -62,11 +52,13 @@ Item {
|
||||||
anchors.top: bar.bottom
|
anchors.top: bar.bottom
|
||||||
anchors.topMargin: 5
|
anchors.topMargin: 5
|
||||||
|
|
||||||
implicitWidth: bar.currentItem.implicitWidth
|
implicitWidth: bar.currentItem?.implicitWidth ?? 0
|
||||||
implicitHeight: 3
|
implicitHeight: 3
|
||||||
|
|
||||||
x: {
|
x: {
|
||||||
const tab = bar.currentItem;
|
const tab = bar.currentItem;
|
||||||
|
if (!tab)
|
||||||
|
return 0;
|
||||||
const width = (root.nonAnimWidth - bar.spacing * (bar.count - 1)) / bar.count;
|
const width = (root.nonAnimWidth - bar.spacing * (bar.count - 1)) / bar.count;
|
||||||
return width * tab.TabBar.index + (width - tab.implicitWidth) / 2;
|
return width * tab.TabBar.index + (width - tab.implicitWidth) / 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,6 @@ Item {
|
||||||
running: true
|
running: true
|
||||||
interval: Appearance.anim.durations.extraLarge
|
interval: Appearance.anim.durations.extraLarge
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
content.active = Qt.binding(() => (root.visibilities.dashboard && Config.dashboard.enabled) || root.visible);
|
|
||||||
content.visible = true;
|
content.visible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue