dashboard/media: improve ui
This commit is contained in:
parent
603caa945a
commit
06f366e27e
4 changed files with 82 additions and 269 deletions
|
|
@ -18,6 +18,7 @@ StyledRect {
|
|||
property real padding: type === IconButton.Text ? Appearance.padding.small / 2 : Appearance.padding.smaller
|
||||
property alias font: label.font
|
||||
property int type: IconButton.Filled
|
||||
property bool disabled
|
||||
|
||||
property alias stateLayer: stateLayer
|
||||
property alias label: label
|
||||
|
|
@ -36,13 +37,15 @@ StyledRect {
|
|||
return Colours.palette.m3onPrimary;
|
||||
return type === IconButton.Tonal ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurfaceVariant;
|
||||
}
|
||||
property color disabledColour: Qt.alpha(Colours.palette.m3onSurface, 0.1)
|
||||
property color disabledOnColour: Qt.alpha(Colours.palette.m3onSurface, 0.38)
|
||||
|
||||
signal clicked
|
||||
|
||||
onCheckedChanged: internalChecked = checked
|
||||
|
||||
radius: internalChecked ? Appearance.rounding.small : implicitHeight / 2
|
||||
color: type === IconButton.Text ? "transparent" : internalChecked ? activeColour : inactiveColour
|
||||
color: type === IconButton.Text ? "transparent" : disabled ? disabledColour : internalChecked ? activeColour : inactiveColour
|
||||
|
||||
implicitWidth: implicitHeight
|
||||
implicitHeight: label.implicitHeight + padding * 2
|
||||
|
|
@ -51,6 +54,7 @@ StyledRect {
|
|||
id: stateLayer
|
||||
|
||||
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
|
||||
disabled: root.disabled
|
||||
|
||||
function onClicked(): void {
|
||||
if (root.toggle)
|
||||
|
|
@ -63,7 +67,7 @@ StyledRect {
|
|||
id: label
|
||||
|
||||
anchors.centerIn: parent
|
||||
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
|
||||
color: root.disabled ? root.disabledOnColour : root.internalChecked ? root.activeOnColour : root.inactiveOnColour
|
||||
fill: !root.toggle || root.internalChecked ? 1 : 0
|
||||
|
||||
Behavior on fill {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Elevation {
|
|||
radius: Appearance.rounding.small / 2
|
||||
level: 2
|
||||
|
||||
implicitWidth: column.implicitWidth
|
||||
implicitWidth: Math.max(200, column.implicitWidth)
|
||||
implicitHeight: root.expanded ? column.implicitHeight : 0
|
||||
opacity: root.expanded ? 1 : 0
|
||||
|
||||
|
|
@ -31,6 +31,8 @@ Elevation {
|
|||
ColumnLayout {
|
||||
id: column
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
|
|
|
|||
|
|
@ -16,15 +16,21 @@ Row {
|
|||
property real verticalPadding: Appearance.padding.smaller
|
||||
property int type: SplitButton.Filled
|
||||
property bool disabled
|
||||
property string fallbackIcon
|
||||
property string fallbackText
|
||||
|
||||
property alias menuItems: menu.items
|
||||
property alias active: menu.active
|
||||
property alias expanded: menu.expanded
|
||||
property alias menu: menu
|
||||
property alias iconLabel: iconLabel
|
||||
property alias label: label
|
||||
property alias stateLayer: stateLayer
|
||||
|
||||
property color colour: type == SplitButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondaryContainer
|
||||
property color textColour: type == SplitButton.Filled ? Colours.palette.m3onPrimary : Colours.palette.m3onSecondaryContainer
|
||||
readonly property color disabledColour: Qt.alpha(Colours.palette.m3onSurface, 0.1)
|
||||
readonly property color disabledTextColour: Qt.alpha(Colours.palette.m3onSurface, 0.38)
|
||||
property color disabledColour: Qt.alpha(Colours.palette.m3onSurface, 0.1)
|
||||
property color disabledTextColour: Qt.alpha(Colours.palette.m3onSurface, 0.38)
|
||||
|
||||
spacing: Math.floor(Appearance.spacing.small / 2)
|
||||
|
||||
|
|
@ -62,7 +68,7 @@ Row {
|
|||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
animate: true
|
||||
text: root.active?.activeIcon ?? ""
|
||||
text: root.active?.activeIcon ?? root.fallbackIcon
|
||||
color: root.disabled ? root.disabledTextColour : root.textColour
|
||||
fill: 1
|
||||
}
|
||||
|
|
@ -73,7 +79,7 @@ Row {
|
|||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: implicitWidth
|
||||
animate: true
|
||||
text: root.active?.activeText ?? ""
|
||||
text: root.active?.activeText ?? root.fallbackText
|
||||
color: root.disabled ? root.disabledTextColour : root.textColour
|
||||
clip: true
|
||||
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ Item {
|
|||
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
|
||||
color: Players.active ? Colours.palette.m3primary : Colours.palette.m3onSurface
|
||||
font.pointSize: Appearance.font.size.normal
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
StyledText {
|
||||
|
|
@ -184,6 +185,7 @@ Item {
|
|||
text: Players.active?.trackAlbum || qsTr("Unknown album")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.small
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
StyledText {
|
||||
|
|
@ -210,73 +212,30 @@ Item {
|
|||
spacing: Appearance.spacing.small
|
||||
|
||||
PlayerControl {
|
||||
type: IconButton.Text
|
||||
icon: "skip_previous"
|
||||
canUse: Players.active?.canGoPrevious ?? false
|
||||
|
||||
function onClicked(): void {
|
||||
Players.active?.previous();
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
id: playBtn
|
||||
|
||||
property int fontSize: Appearance.font.size.extraLarge
|
||||
property int padding
|
||||
property bool fill: true
|
||||
property bool primary
|
||||
function onClicked(): void {
|
||||
}
|
||||
|
||||
implicitWidth: Math.max(playIcon.implicitWidth, playIcon.implicitHeight) + padding * 2
|
||||
implicitHeight: implicitWidth
|
||||
|
||||
radius: Players.active?.isPlaying ? Appearance.rounding.small : implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
|
||||
color: {
|
||||
if (!Players.active?.canTogglePlaying)
|
||||
return Qt.alpha(Colours.palette.m3onSurface, 0.1);
|
||||
return Players.active?.isPlaying ? Colours.palette.m3primary : Colours.palette.m3primaryContainer;
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
disabled: !Players.active?.canTogglePlaying
|
||||
color: Players.active?.isPlaying ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer
|
||||
|
||||
function onClicked(): void {
|
||||
Players.active?.togglePlaying();
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
id: playIcon
|
||||
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: -font.pointSize * 0.02
|
||||
anchors.verticalCenterOffset: font.pointSize * 0.02
|
||||
|
||||
animate: true
|
||||
fill: 1
|
||||
text: Players.active?.isPlaying ? "pause" : "play_arrow"
|
||||
color: {
|
||||
if (!Players.active?.canTogglePlaying)
|
||||
return Qt.alpha(Colours.palette.m3onSurface, 0.38);
|
||||
return Players.active?.isPlaying ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer;
|
||||
}
|
||||
font.pointSize: Appearance.font.size.extraLarge
|
||||
}
|
||||
|
||||
Behavior on radius {
|
||||
Anim {}
|
||||
}
|
||||
font.pointSize: Math.round(Appearance.font.size.large * 1.5)
|
||||
disabled: !Players.active?.canGoPrevious
|
||||
onClicked: Players.active?.previous()
|
||||
}
|
||||
|
||||
PlayerControl {
|
||||
icon: "skip_next"
|
||||
canUse: Players.active?.canGoNext ?? false
|
||||
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
|
||||
label.animate: true
|
||||
toggle: true
|
||||
padding: Appearance.padding.small / 2
|
||||
checked: Players.active?.isPlaying
|
||||
font.pointSize: Math.round(Appearance.font.size.large * 1.5)
|
||||
disabled: !Players.active?.canTogglePlaying
|
||||
onClicked: Players.active?.togglePlaying()
|
||||
}
|
||||
|
||||
function onClicked(): void {
|
||||
Players.active?.next();
|
||||
}
|
||||
PlayerControl {
|
||||
type: IconButton.Text
|
||||
icon: "skip_next"
|
||||
font.pointSize: Math.round(Appearance.font.size.large * 1.5)
|
||||
disabled: !Players.active?.canGoNext
|
||||
onClicked: Players.active?.next()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -284,7 +243,7 @@ Item {
|
|||
id: slider
|
||||
|
||||
enabled: !!Players.active
|
||||
implicitWidth: controls.implicitWidth * 1.5
|
||||
implicitWidth: 280
|
||||
implicitHeight: Appearance.padding.normal * 3
|
||||
|
||||
onMoved: {
|
||||
|
|
@ -348,166 +307,60 @@ Item {
|
|||
spacing: Appearance.spacing.small
|
||||
|
||||
PlayerControl {
|
||||
icon: "flip_to_front"
|
||||
canUse: Players.active?.canRaise ?? false
|
||||
fontSize: Appearance.font.size.larger
|
||||
type: IconButton.Text
|
||||
icon: "move_up"
|
||||
inactiveOnColour: Colours.palette.m3secondary
|
||||
padding: Appearance.padding.small
|
||||
fill: false
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
|
||||
function onClicked(): void {
|
||||
font.pointSize: Appearance.font.size.large
|
||||
disabled: !Players.active?.canRaise
|
||||
onClicked: {
|
||||
Players.active?.raise();
|
||||
root.visibilities.dashboard = false;
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
SplitButton {
|
||||
id: playerSelector
|
||||
|
||||
property bool expanded
|
||||
disabled: !Players.list.length
|
||||
active: menuItems.find(m => m.modelData === Players.active) ?? menuItems[0]
|
||||
menu.onItemSelected: item => Players.manualActive = item.modelData
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
menuItems: playerList.instances
|
||||
fallbackIcon: "music_off"
|
||||
fallbackText: qsTr("No players")
|
||||
|
||||
implicitWidth: slider.implicitWidth * 0.6
|
||||
implicitHeight: currentPlayer.implicitHeight + Appearance.padding.smaller * 2
|
||||
radius: Appearance.rounding.normal
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
z: 1
|
||||
label.Layout.maximumWidth: slider.implicitWidth * 0.28
|
||||
label.elide: Text.ElideRight
|
||||
|
||||
StateLayer {
|
||||
disabled: Players.list.length <= 1
|
||||
stateLayer.disabled: true
|
||||
menu.anchors.top: undefined
|
||||
menu.anchors.bottom: menu.parent.top
|
||||
menu.anchors.bottomMargin: Appearance.spacing.small
|
||||
|
||||
function onClicked(): void {
|
||||
playerSelector.expanded = !playerSelector.expanded;
|
||||
}
|
||||
}
|
||||
Variants {
|
||||
id: playerList
|
||||
|
||||
RowLayout {
|
||||
id: currentPlayer
|
||||
model: Players.list
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Appearance.spacing.small
|
||||
MenuItem {
|
||||
required property MprisPlayer modelData
|
||||
|
||||
PlayerIcon {
|
||||
player: Players.active
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: playerSelector.implicitWidth - implicitHeight - parent.spacing - Appearance.padding.normal * 2
|
||||
text: Players.active ? Players.getIdentity(Players.active) : qsTr("No players")
|
||||
color: Players.active ? Colours.palette.m3onSurface : Colours.palette.m3onSurfaceVariant
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
Elevation {
|
||||
anchors.fill: playerSelectorBg
|
||||
radius: playerSelectorBg.radius
|
||||
opacity: playerSelector.expanded ? 1 : 0
|
||||
level: 2
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {
|
||||
duration: Appearance.anim.durations.expressiveDefaultSpatial
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledClippingRect {
|
||||
id: playerSelectorBg
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
implicitWidth: playerSelector.expanded ? playerList.implicitWidth : playerSelector.implicitWidth
|
||||
implicitHeight: playerSelector.expanded ? playerList.implicitHeight : playerSelector.implicitHeight
|
||||
|
||||
color: Colours.palette.m3secondaryContainer
|
||||
radius: Appearance.rounding.normal
|
||||
opacity: playerSelector.expanded ? 1 : 0
|
||||
|
||||
ColumnLayout {
|
||||
id: playerList
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
model: [...Players.list].sort((a, b) => (a === Players.active) - (b === Players.active))
|
||||
|
||||
Item {
|
||||
id: player
|
||||
|
||||
required property MprisPlayer modelData
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: playerSelector.implicitWidth
|
||||
implicitWidth: playerInner.implicitWidth + Appearance.padding.normal * 2
|
||||
implicitHeight: playerInner.implicitHeight + Appearance.padding.smaller * 2
|
||||
|
||||
StateLayer {
|
||||
disabled: !playerSelector.expanded
|
||||
|
||||
function onClicked(): void {
|
||||
playerSelector.expanded = false;
|
||||
Players.manualActive = player.modelData;
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: playerInner
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Appearance.spacing.small
|
||||
|
||||
PlayerIcon {
|
||||
player: player.modelData
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: Players.getIdentity(player.modelData)
|
||||
color: Colours.palette.m3onSecondaryContainer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {
|
||||
duration: Appearance.anim.durations.expressiveDefaultSpatial
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on implicitWidth {
|
||||
Anim {
|
||||
duration: Appearance.anim.durations.expressiveDefaultSpatial
|
||||
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on implicitHeight {
|
||||
Anim {
|
||||
duration: Appearance.anim.durations.expressiveDefaultSpatial
|
||||
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
|
||||
}
|
||||
icon: modelData === Players.active ? "check" : ""
|
||||
text: Players.getIdentity(modelData)
|
||||
activeIcon: "animated_images"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayerControl {
|
||||
type: IconButton.Text
|
||||
icon: "delete"
|
||||
canUse: Players.active?.canQuit ?? false
|
||||
fontSize: Appearance.font.size.larger
|
||||
inactiveOnColour: Colours.palette.m3error
|
||||
padding: Appearance.padding.small
|
||||
fill: false
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
|
||||
function onClicked(): void {
|
||||
Players.active?.quit();
|
||||
}
|
||||
font.pointSize: Appearance.font.size.large
|
||||
disabled: !Players.active?.canQuit
|
||||
onClicked: Players.active?.quit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -536,69 +389,17 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
component PlayerIcon: Loader {
|
||||
id: loader
|
||||
component PlayerControl: IconButton {
|
||||
Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? Appearance.padding.large : internalChecked ? Appearance.padding.smaller : 0)
|
||||
radius: stateLayer.pressed ? Appearance.rounding.small / 2 : internalChecked ? Appearance.rounding.small : implicitHeight / 2
|
||||
radiusAnim.duration: Appearance.anim.durations.expressiveFastSpatial
|
||||
radiusAnim.easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
|
||||
|
||||
required property MprisPlayer player
|
||||
readonly property string icon: Icons.getAppIcon(player?.identity)
|
||||
|
||||
Layout.fillHeight: true
|
||||
sourceComponent: !player || icon === "image://icon/" ? fallbackIcon : playerImage
|
||||
|
||||
Component {
|
||||
id: playerImage
|
||||
|
||||
IconImage {
|
||||
implicitWidth: height
|
||||
source: loader.icon
|
||||
Behavior on Layout.preferredWidth {
|
||||
Anim {
|
||||
duration: Appearance.anim.durations.expressiveFastSpatial
|
||||
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fallbackIcon
|
||||
|
||||
MaterialIcon {
|
||||
text: loader.player ? "animated_images" : "music_off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component PlayerControl: StyledRect {
|
||||
id: control
|
||||
|
||||
required property string icon
|
||||
required property bool canUse
|
||||
property int fontSize: Appearance.font.size.extraLarge
|
||||
property int padding
|
||||
property bool fill: true
|
||||
function onClicked(): void {
|
||||
}
|
||||
|
||||
implicitWidth: Math.max(icon.implicitWidth, icon.implicitHeight) + padding * 2
|
||||
implicitHeight: implicitWidth
|
||||
radius: Appearance.rounding.full
|
||||
|
||||
StateLayer {
|
||||
disabled: !control.canUse
|
||||
color: Colours.palette.m3onSurface
|
||||
|
||||
function onClicked(): void {
|
||||
control.onClicked();
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
id: icon
|
||||
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: -font.pointSize * 0.02
|
||||
anchors.verticalCenterOffset: font.pointSize * 0.02
|
||||
|
||||
animate: true
|
||||
fill: control.fill ? 1 : 0
|
||||
text: control.icon
|
||||
color: control.canUse ? Colours.palette.m3onSurface : Colours.palette.m3outline
|
||||
font.pointSize: control.fontSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue