mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-14 23:34:01 -04:00
190 lines
5.9 KiB
QML
190 lines
5.9 KiB
QML
import QtQuick
|
|
import QtQuick.Effects
|
|
import qs.Common
|
|
import qs.Modules.ControlCenter
|
|
import qs.Modules.DankDash
|
|
import qs.Services
|
|
import qs.Widgets
|
|
import "../utils/widgets.js" as WidgetUtils
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property var widgetData: ({})
|
|
property var widgetDef: null
|
|
property var host: null
|
|
property bool live: true
|
|
property bool interactive: true
|
|
property real columns: 2
|
|
property real rows: 2
|
|
property bool compact: false
|
|
property bool docked: false
|
|
|
|
signal optionChanged(string key, var value)
|
|
|
|
readonly property bool wide: width >= height * 2
|
|
readonly property bool background: docked || widgetData?.background === true
|
|
readonly property bool tall: height >= CcMetrics.gridRowUnit * 2
|
|
readonly property real inset: background ? (tall ? Theme.spacingM : Theme.spacingS) : 0
|
|
readonly property real avatarSide: Math.min(width, height) - inset * 2
|
|
readonly property string shape: widgetData?.shape ?? WidgetUtils.USER_SHAPES[0]
|
|
readonly property bool editMode: host?.editMode ?? false
|
|
readonly property bool tapToClose: interactive && (host?.tapToClose ?? false)
|
|
readonly property Item passthrough: shapeButton
|
|
readonly property real bodyRadius: {
|
|
if (!background)
|
|
return Theme.fullRadius(avatarSide, avatarSide);
|
|
return tall ? Math.min(CcMetrics.tallTileRadius, width / 2, height / 2) : Theme.fullRadius(width, height);
|
|
}
|
|
readonly property real fallbackGlyphRatio: 0.5
|
|
readonly property string avatarSource: PortalService.profileImageUrl
|
|
readonly property bool hasImage: picture.status === Image.Ready
|
|
|
|
width: parent?.width ?? 0
|
|
height: parent?.height ?? 0
|
|
LayoutMirroring.enabled: I18n.isRtl
|
|
LayoutMirroring.childrenInherit: true
|
|
Accessible.role: Accessible.StaticText
|
|
Accessible.name: UserInfoService.fullName || UserInfoService.username
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: root.bodyRadius
|
|
color: CcMetrics.tileInactiveColor
|
|
border.width: Theme.layerOutlineWidth
|
|
border.color: Theme.outlineMedium
|
|
visible: root.background
|
|
}
|
|
|
|
UserIdentity {
|
|
anchors.fill: parent
|
|
anchors.margins: root.inset
|
|
visible: root.wide
|
|
live: root.live && root.wide
|
|
options: root.docked ? Object.assign({}, DashRegistry.resolvedOptions("user", root.widgetData), {
|
|
"compositor": false,
|
|
"uptime": false
|
|
}) : DashRegistry.resolvedOptions("user", root.widgetData)
|
|
avatarSize: height
|
|
textGap: root.docked ? Theme.spacingS : Theme.spacingM
|
|
stacked: root.rows >= 2
|
|
contentColor: Theme.onSurface
|
|
mutedColor: Theme.onSurfaceVariant
|
|
}
|
|
|
|
Item {
|
|
id: avatar
|
|
|
|
anchors.centerIn: parent
|
|
width: root.avatarSide
|
|
height: root.avatarSide
|
|
visible: !root.wide
|
|
|
|
DankMaterialShape {
|
|
anchors.fill: parent
|
|
shape: root.shape
|
|
color: Theme.primaryContainer
|
|
visible: !root.hasImage
|
|
}
|
|
|
|
DankIcon {
|
|
anchors.centerIn: parent
|
|
name: "person"
|
|
size: Math.round(root.avatarSide * root.fallbackGlyphRatio)
|
|
color: Theme.onPrimaryContainer
|
|
filled: true
|
|
visible: !root.hasImage
|
|
}
|
|
|
|
Item {
|
|
id: avatarMask
|
|
|
|
anchors.fill: parent
|
|
layer.enabled: root.hasImage
|
|
visible: false
|
|
|
|
DankMaterialShape {
|
|
anchors.fill: parent
|
|
shape: root.shape
|
|
}
|
|
}
|
|
|
|
Image {
|
|
id: picture
|
|
|
|
anchors.fill: parent
|
|
asynchronous: true
|
|
fillMode: Image.PreserveAspectCrop
|
|
smooth: true
|
|
mipmap: true
|
|
retainWhileLoading: true
|
|
visible: root.hasImage
|
|
sourceSize.width: Math.max(1, Math.ceil(width * Screen.devicePixelRatio))
|
|
sourceSize.height: Math.max(1, Math.ceil(height * Screen.devicePixelRatio))
|
|
source: avatar.visible ? root.avatarSource : ""
|
|
layer.enabled: root.hasImage
|
|
layer.effect: MultiEffect {
|
|
maskEnabled: true
|
|
maskSource: avatarMask
|
|
maskThresholdMin: 0.5
|
|
maskSpreadAtMin: 1
|
|
}
|
|
}
|
|
}
|
|
|
|
StyledButton {
|
|
objectName: "userCloseButton"
|
|
anchors.fill: parent
|
|
visible: root.tapToClose
|
|
radius: root.bodyRadius
|
|
Accessible.name: I18n.tr("Close")
|
|
onClicked: root.host?.closeRequested()
|
|
|
|
FocusRing {
|
|
visible: parent.visualFocus
|
|
}
|
|
|
|
StateLayer {
|
|
control: parent
|
|
cornerRadius: root.bodyRadius
|
|
}
|
|
}
|
|
|
|
StyledButton {
|
|
objectName: "userAvatarButton"
|
|
x: !root.wide ? (root.width - width) / 2 : I18n.isRtl ? root.width - root.inset - width : root.inset
|
|
y: (root.height - height) / 2
|
|
width: root.avatarSide
|
|
height: root.avatarSide
|
|
radius: Theme.fullRadius(width, height)
|
|
visible: root.interactive
|
|
Accessible.name: I18n.tr("Users & accounts", "settings sidebar category")
|
|
onClicked: root.host?.accountsRequested()
|
|
|
|
FocusRing {
|
|
visible: parent.visualFocus
|
|
}
|
|
|
|
StateLayer {
|
|
control: parent
|
|
cornerRadius: parent.radius
|
|
tooltipText: parent.Accessible.name
|
|
}
|
|
}
|
|
|
|
DankActionButton {
|
|
id: shapeButton
|
|
|
|
anchors.bottom: avatar.bottom
|
|
anchors.left: avatar.left
|
|
buttonSize: CcMetrics.shapeButtonSize
|
|
iconSize: Theme.iconSizeSmall
|
|
iconName: "shuffle"
|
|
iconColor: Theme.onSurface
|
|
backgroundColor: Theme.surfaceContainerHighest
|
|
Accessible.name: I18n.tr("Shuffle")
|
|
visible: root.editMode && avatar.visible
|
|
onClicked: root.optionChanged("shape", WidgetUtils.nextUserShape(root.shape))
|
|
}
|
|
}
|