298 lines
9.9 KiB
QML
298 lines
9.9 KiB
QML
import QtQuick
|
|
import QtQuick.Controls.Basic
|
|
import QtQuick.Layouts
|
|
import qEmby
|
|
|
|
Item {
|
|
id: page
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
color: Theme.bgBase
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
anchors.leftMargin: Theme.spacingLg
|
|
anchors.rightMargin: Theme.spacingLg
|
|
anchors.topMargin: Theme.spacingLg
|
|
anchors.bottomMargin: Theme.spacingXl
|
|
spacing: Theme.spacingLg
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: Theme.spacingMd
|
|
|
|
Text {
|
|
text: qsTr("Logs")
|
|
color: Theme.textPrimary
|
|
font.pixelSize: Theme.fontTitle
|
|
font.weight: Font.ExtraBold
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Text {
|
|
text: logsPage.statsText
|
|
color: Theme.textMuted
|
|
font.pixelSize: Theme.fontBody
|
|
}
|
|
|
|
ThemedButton {
|
|
text: logsPage.refreshing ? qsTr("Refreshing…") : qsTr("Refresh")
|
|
enabled: !logsPage.refreshing
|
|
Accessible.name: qsTr("Refresh log files")
|
|
onClicked: logsPage.refresh()
|
|
}
|
|
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: Math.min(190, Math.max(118, page.height * 0.25))
|
|
radius: Theme.radiusLg
|
|
color: Theme.alpha(Theme.bgSurface, Theme.dark ? 0.64 : 0.94)
|
|
border.width: 1
|
|
border.color: Theme.alpha(Theme.borderSoft, 0.7)
|
|
|
|
ListView {
|
|
id: fileList
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: Theme.spacingXs
|
|
clip: true
|
|
model: logsPage.model
|
|
spacing: 2
|
|
boundsBehavior: Flickable.StopAtBounds
|
|
currentIndex: -1
|
|
|
|
ScrollBar.vertical: ThemedScrollBar {
|
|
}
|
|
|
|
delegate: Rectangle {
|
|
id: logRow
|
|
|
|
required property string name
|
|
required property string modified
|
|
required property string modifiedCompact
|
|
required property string sizeText
|
|
|
|
width: fileList.width
|
|
height: 42
|
|
radius: Theme.radiusMd
|
|
color: logsPage.selectedName === name ? Theme.alpha(Theme.accent, Theme.dark ? 0.2 : 0.12) : rowMouse.containsMouse ? Theme.alpha(Theme.bgRaised, 0.76) : "transparent"
|
|
border.width: logsPage.selectedName === name ? 1 : 0
|
|
border.color: Theme.alpha(Theme.accent, 0.42)
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
anchors.leftMargin: Theme.spacingMd
|
|
anchors.rightMargin: Theme.spacingSm
|
|
spacing: Theme.spacingMd
|
|
|
|
Text {
|
|
text: logRow.name
|
|
color: Theme.textPrimary
|
|
font.pixelSize: Theme.fontBody
|
|
font.weight: Font.Medium
|
|
elide: Text.ElideRight
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Text {
|
|
text: logRow.sizeText + " · " + logRow.modifiedCompact
|
|
color: Theme.textMuted
|
|
font.pixelSize: Theme.fontSmall
|
|
}
|
|
|
|
ThemedButton {
|
|
implicitWidth: 74
|
|
text: qsTr("Save…")
|
|
enabled: !logsPage.saving
|
|
Accessible.name: qsTr("Save %1").arg(logRow.name)
|
|
onClicked: logsPage.saveLog(logRow.name)
|
|
}
|
|
|
|
}
|
|
|
|
MouseArea {
|
|
id: rowMouse
|
|
|
|
anchors.fill: parent
|
|
anchors.rightMargin: 80
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
Accessible.role: Accessible.ListItem
|
|
Accessible.name: logRow.name
|
|
onClicked: logsPage.selectLog(logRow.name)
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EmptyState {
|
|
anchors.centerIn: parent
|
|
visible: logsPage.hasLoaded && !logsPage.loading && logsPage.totalCount === 0
|
|
text: qsTr("No log files found")
|
|
hint: qsTr("The server did not report any downloadable logs.")
|
|
}
|
|
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
radius: Theme.radiusLg
|
|
color: Theme.alpha(Theme.bgSurface, Theme.dark ? 0.64 : 0.94)
|
|
border.width: 1
|
|
border.color: Theme.alpha(Theme.borderSoft, 0.7)
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
spacing: 0
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
Layout.leftMargin: Theme.spacingLg
|
|
Layout.rightMargin: Theme.spacingMd
|
|
Layout.topMargin: Theme.spacingMd
|
|
Layout.bottomMargin: Theme.spacingMd
|
|
spacing: Theme.spacingMd
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: Theme.spacingXs
|
|
|
|
Text {
|
|
text: logsPage.selectedName.length > 0 ? logsPage.selectedName : qsTr("No log file selected")
|
|
color: Theme.textPrimary
|
|
font.pixelSize: Theme.fontHeading
|
|
font.weight: Font.DemiBold
|
|
elide: Text.ElideMiddle
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Text {
|
|
text: logsPage.selectedMeta
|
|
color: Theme.textMuted
|
|
font.pixelSize: Theme.fontSmall
|
|
elide: Text.ElideRight
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
}
|
|
|
|
ThemedButton {
|
|
visible: logsPage.selectedName.length > 0
|
|
text: logsPage.saving ? qsTr("Saving…") : qsTr("Save as…")
|
|
enabled: !logsPage.saving && !logsPage.contentLoading
|
|
onClicked: logsPage.saveLog(logsPage.selectedName)
|
|
}
|
|
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 1
|
|
color: Theme.borderSoft
|
|
}
|
|
|
|
ScrollView {
|
|
id: contentScroll
|
|
|
|
visible: logsPage.selectedName.length > 0 && !logsPage.contentLoading && logsPage.contentError.length === 0
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
clip: true
|
|
|
|
TextArea {
|
|
width: contentScroll.availableWidth
|
|
text: logsPage.content
|
|
readOnly: true
|
|
selectByMouse: true
|
|
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
|
|
color: Theme.textBody
|
|
selectionColor: Theme.accent
|
|
selectedTextColor: "white"
|
|
font.family: "monospace"
|
|
font.pixelSize: Theme.fontSmall
|
|
padding: Theme.spacingLg
|
|
Accessible.name: qsTr("Log contents")
|
|
|
|
background: Rectangle {
|
|
color: "transparent"
|
|
}
|
|
|
|
}
|
|
|
|
ScrollBar.vertical: ThemedScrollBar {
|
|
}
|
|
|
|
}
|
|
|
|
LoadingState {
|
|
visible: logsPage.contentLoading
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
title: qsTr("Loading log")
|
|
message: logsPage.selectedName
|
|
}
|
|
|
|
ErrorState {
|
|
visible: !logsPage.contentLoading && logsPage.contentError.length > 0
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
title: qsTr("Could not load log")
|
|
message: logsPage.contentError
|
|
retryText: qsTr("Try again")
|
|
onRetryRequested: logsPage.selectLog(logsPage.selectedName)
|
|
}
|
|
|
|
EmptyState {
|
|
visible: logsPage.selectedName.length === 0 && logsPage.totalCount > 0
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
text: qsTr("Select a log file")
|
|
hint: qsTr("Choose a file above to inspect its contents.")
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LoadingState {
|
|
anchors.fill: parent
|
|
visible: logsPage.loading && !logsPage.hasLoaded
|
|
title: qsTr("Loading logs")
|
|
message: qsTr("Fetching available server log files…")
|
|
}
|
|
|
|
ErrorState {
|
|
anchors.fill: parent
|
|
visible: !logsPage.loading && !logsPage.hasLoaded && logsPage.errorMessage.length > 0
|
|
title: qsTr("Could not load logs")
|
|
message: logsPage.errorMessage
|
|
onRetryRequested: logsPage.refresh()
|
|
}
|
|
|
|
ToastHost {
|
|
id: toastHost
|
|
|
|
anchors.fill: parent
|
|
}
|
|
|
|
Connections {
|
|
function onToastRequested(message, kind) {
|
|
toastHost.show(message, kind);
|
|
}
|
|
|
|
target: logsPage
|
|
}
|
|
|
|
}
|