mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-18 09:14:01 -04:00
dash: rebuild the calendar event editor on settings rows
notifications: paint the popup and toast surface once
This commit is contained in:
+1
-1
Submodule dank-qml-common updated: 07d634a3fc...f5522736ed
@@ -190,7 +190,6 @@ Singleton {
|
||||
readonly property real eventActionIconSize: Theme.iconSizeSmall
|
||||
readonly property real taskInputHeight: Theme.buttonHeightS
|
||||
readonly property real sheetWidth: 400
|
||||
readonly property real sheetFormHeight: 300
|
||||
|
||||
readonly property real mediaCardMargin: Theme.spacingL
|
||||
readonly property real mediaArtSize: 150
|
||||
|
||||
@@ -2,7 +2,7 @@ import QtQuick
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.DankDash
|
||||
import qs.Modules.Settings.Widgets
|
||||
|
||||
Column {
|
||||
id: root
|
||||
@@ -20,8 +20,10 @@ Column {
|
||||
property string fTitle: ""
|
||||
property bool fAllDay: false
|
||||
property date fDate: initialDate
|
||||
property string fStart: "10:00"
|
||||
property string fEnd: "11:00"
|
||||
property int fStartHour: 10
|
||||
property int fStartMinute: 0
|
||||
property int fEndHour: 11
|
||||
property int fEndMinute: 0
|
||||
property string fLocation: ""
|
||||
property string fDescription: ""
|
||||
property string fCalendarId: ""
|
||||
@@ -35,20 +37,6 @@ Column {
|
||||
|
||||
spacing: Theme.spacingM
|
||||
|
||||
function _parseTime(value) {
|
||||
const m = value.trim().match(/^(\d{1,2}):(\d{2})$/);
|
||||
if (!m)
|
||||
return null;
|
||||
const h = parseInt(m[1]);
|
||||
const min = parseInt(m[2]);
|
||||
if (h > 23 || min > 59)
|
||||
return null;
|
||||
return {
|
||||
"h": h,
|
||||
"m": min
|
||||
};
|
||||
}
|
||||
|
||||
function _isoFromDateTime(dateObj, h, m) {
|
||||
const d = new Date(dateObj);
|
||||
d.setHours(h, m, 0, 0);
|
||||
@@ -93,14 +81,8 @@ Column {
|
||||
startIso = _allDayIso(fDate, 0);
|
||||
endIso = _allDayIso(fDate, 1);
|
||||
} else {
|
||||
const s = _parseTime(fStart);
|
||||
const e = _parseTime(fEnd);
|
||||
if (!s || !e) {
|
||||
errorText = I18n.tr("Use HH:MM time format");
|
||||
return;
|
||||
}
|
||||
startIso = _isoFromDateTime(fDate, s.h, s.m);
|
||||
endIso = _isoFromDateTime(fDate, e.h, e.m);
|
||||
startIso = _isoFromDateTime(fDate, fStartHour, fStartMinute);
|
||||
endIso = _isoFromDateTime(fDate, fEndHour, fEndMinute);
|
||||
if (new Date(endIso).getTime() <= new Date(startIso).getTime()) {
|
||||
errorText = I18n.tr("End must be after start");
|
||||
return;
|
||||
@@ -145,8 +127,10 @@ Column {
|
||||
fTitle = eventData.title || "";
|
||||
fAllDay = !!eventData.allDay;
|
||||
fDate = eventData.start;
|
||||
fStart = Qt.formatTime(eventData.start, "HH:mm");
|
||||
fEnd = Qt.formatTime(eventData.end, "HH:mm");
|
||||
fStartHour = eventData.start.getHours();
|
||||
fStartMinute = eventData.start.getMinutes();
|
||||
fEndHour = eventData.end.getHours();
|
||||
fEndMinute = eventData.end.getMinutes();
|
||||
fLocation = eventData.location || "";
|
||||
fDescription = eventData.description || "";
|
||||
fCalendarId = eventData.calendarId || "";
|
||||
@@ -154,149 +138,101 @@ Column {
|
||||
fReminder = eventData.reminders[0].minutes;
|
||||
}
|
||||
|
||||
DankFlickable {
|
||||
SettingsGroup {
|
||||
width: parent.width
|
||||
height: Math.min(DashMetrics.sheetFormHeight, form.implicitHeight)
|
||||
showScrollBar: false
|
||||
contentWidth: width
|
||||
contentHeight: form.implicitHeight
|
||||
clip: true
|
||||
slotColor: Theme.chipSurface
|
||||
|
||||
Column {
|
||||
id: form
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
SettingsTextFieldRow {
|
||||
text: I18n.tr("Title")
|
||||
leftIconName: "title"
|
||||
placeholderText: I18n.tr("Event title")
|
||||
value: root.fTitle
|
||||
onValueEdited: value => root.fTitle = value
|
||||
onAccepted: root.save()
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: parent.width
|
||||
labelText: I18n.tr("Title")
|
||||
leftIconName: "title"
|
||||
leftIconSize: Theme.iconSizeSmall
|
||||
placeholderText: I18n.tr("Event title")
|
||||
text: root.fTitle
|
||||
onTextChanged: root.fTitle = text
|
||||
SettingsToggleRow {
|
||||
text: I18n.tr("All day")
|
||||
checked: root.fAllDay
|
||||
onToggled: checked => root.fAllDay = checked
|
||||
}
|
||||
|
||||
SettingsRow {
|
||||
title: I18n.tr("Date")
|
||||
subtitle: Qt.formatDate(root.fDate, "ddd, MMM d yyyy")
|
||||
subtitleColor: Theme.surfaceText
|
||||
|
||||
DankActionButton {
|
||||
iconName: I18n.isRtl ? "chevron_right" : "chevron_left"
|
||||
Accessible.name: I18n.tr("Previous")
|
||||
onClicked: root.shiftDate(-1)
|
||||
}
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: I18n.tr("All day")
|
||||
checked: root.fAllDay
|
||||
onToggled: checked => root.fAllDay = checked
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
DankActionButton {
|
||||
id: prevDay
|
||||
iconName: I18n.isRtl ? "chevron_right" : "chevron_left"
|
||||
Accessible.name: I18n.tr("Previous")
|
||||
iconSize: Theme.iconSizeSmall
|
||||
onClicked: root.shiftDate(-1)
|
||||
}
|
||||
|
||||
StyledText {
|
||||
width: parent.width - prevDay.width - nextDay.width - parent.spacing * 2
|
||||
text: Qt.formatDate(root.fDate, "ddd, MMM d yyyy")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
height: Theme.buttonHeightXS
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: nextDay
|
||||
iconName: I18n.isRtl ? "chevron_left" : "chevron_right"
|
||||
Accessible.name: I18n.tr("Next")
|
||||
iconSize: Theme.iconSizeSmall
|
||||
onClicked: root.shiftDate(1)
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
visible: !root.fAllDay
|
||||
|
||||
DankTextField {
|
||||
width: (parent.width - Theme.spacingS) / 2
|
||||
labelText: I18n.tr("Start")
|
||||
leftIconName: "schedule"
|
||||
leftIconSize: Theme.iconSizeSmall
|
||||
placeholderText: "HH:MM"
|
||||
text: root.fStart
|
||||
onTextChanged: root.fStart = text
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: (parent.width - Theme.spacingS) / 2
|
||||
labelText: I18n.tr("End")
|
||||
placeholderText: "HH:MM"
|
||||
text: root.fEnd
|
||||
onTextChanged: root.fEnd = text
|
||||
}
|
||||
}
|
||||
|
||||
DankDropdown {
|
||||
width: parent.width
|
||||
text: I18n.tr("Calendar")
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
options: root._cals.map(c => c.name)
|
||||
currentValue: root._calendarName(root.fCalendarId)
|
||||
onValueChanged: value => {
|
||||
for (let i = 0; i < root._cals.length; i++) {
|
||||
if (root._cals[i].name === value) {
|
||||
root.fCalendarId = root._cals[i].id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DankDropdown {
|
||||
width: parent.width
|
||||
text: I18n.tr("Reminder", "noun, calendar event reminder time dropdown label")
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
options: root._remLabels
|
||||
currentValue: root._remLabels[Math.max(0, root._remMins.indexOf(root.fReminder))]
|
||||
onValueChanged: value => {
|
||||
const idx = root._remLabels.indexOf(value);
|
||||
if (idx >= 0)
|
||||
root.fReminder = root._remMins[idx];
|
||||
}
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: parent.width
|
||||
labelText: I18n.tr("Location", "calendar event venue field label", true)
|
||||
leftIconName: "place"
|
||||
leftIconSize: Theme.iconSizeSmall
|
||||
placeholderText: I18n.tr("Add location")
|
||||
text: root.fLocation
|
||||
onTextChanged: root.fLocation = text
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
width: parent.width
|
||||
labelText: I18n.tr("Notes", "noun, calendar event notes field label")
|
||||
leftIconName: "notes"
|
||||
leftIconSize: Theme.iconSizeSmall
|
||||
placeholderText: I18n.tr("Add notes")
|
||||
text: root.fDescription
|
||||
onTextChanged: root.fDescription = text
|
||||
DankActionButton {
|
||||
iconName: I18n.isRtl ? "chevron_left" : "chevron_right"
|
||||
Accessible.name: I18n.tr("Next")
|
||||
onClicked: root.shiftDate(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: root.errorText
|
||||
visible: root.errorText !== ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.error
|
||||
wrapMode: Text.WordWrap
|
||||
SettingsTimeRow {
|
||||
visible: !root.fAllDay
|
||||
is24Hour: SettingsData.use24HourClock
|
||||
startTitle: I18n.tr("Start")
|
||||
startHour: root.fStartHour
|
||||
startMinute: root.fStartMinute
|
||||
endTitle: I18n.tr("End")
|
||||
endHour: root.fEndHour
|
||||
endMinute: root.fEndMinute
|
||||
onStartChanged: (hour, minute) => {
|
||||
root.fStartHour = hour;
|
||||
root.fStartMinute = minute;
|
||||
}
|
||||
onEndChanged: (hour, minute) => {
|
||||
root.fEndHour = hour;
|
||||
root.fEndMinute = minute;
|
||||
}
|
||||
}
|
||||
|
||||
SettingsDropdownRow {
|
||||
text: I18n.tr("Calendar")
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
options: root._cals.map(c => c.name)
|
||||
currentValue: root._calendarName(root.fCalendarId)
|
||||
onValueChanged: value => {
|
||||
const cal = root._cals.find(c => c.name === value);
|
||||
if (cal)
|
||||
root.fCalendarId = cal.id;
|
||||
}
|
||||
}
|
||||
|
||||
SettingsDropdownRow {
|
||||
text: I18n.tr("Reminder", "noun, calendar event reminder time dropdown label")
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
options: root._remLabels
|
||||
currentValue: root._remLabels[Math.max(0, root._remMins.indexOf(root.fReminder))]
|
||||
onValueChanged: value => {
|
||||
const idx = root._remLabels.indexOf(value);
|
||||
if (idx >= 0)
|
||||
root.fReminder = root._remMins[idx];
|
||||
}
|
||||
}
|
||||
|
||||
SettingsTextFieldRow {
|
||||
text: I18n.tr("Location", "calendar event venue field label", true)
|
||||
leftIconName: "place"
|
||||
placeholderText: I18n.tr("Add location")
|
||||
value: root.fLocation
|
||||
onValueEdited: value => root.fLocation = value
|
||||
}
|
||||
|
||||
SettingsTextFieldRow {
|
||||
text: I18n.tr("Notes", "noun, calendar event notes field label")
|
||||
leftIconName: "notes"
|
||||
placeholderText: I18n.tr("Add notes")
|
||||
value: root.fDescription
|
||||
onValueEdited: value => root.fDescription = value
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -307,16 +243,14 @@ Column {
|
||||
DankButton {
|
||||
text: root.saving ? I18n.tr("Saving...") : I18n.tr("Save")
|
||||
iconName: "check"
|
||||
buttonHeight: Theme.buttonHeightS
|
||||
backgroundColor: Theme.primary
|
||||
textColor: Theme.onPrimary
|
||||
enabled: !root.saving
|
||||
onClicked: root.save()
|
||||
}
|
||||
|
||||
DankButton {
|
||||
text: I18n.tr("Cancel")
|
||||
buttonHeight: Theme.buttonHeightS
|
||||
backgroundColor: "transparent"
|
||||
textColor: Theme.primary
|
||||
onClicked: root.closeRequested()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,6 +596,13 @@ Card {
|
||||
}
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
cornerRadius: taskItem.radius
|
||||
stateColor: taskItem.accentColor
|
||||
disabled: !taskItem.modelData || taskItem.isEditing || !root.interactive
|
||||
onClicked: taskItem.activate()
|
||||
}
|
||||
|
||||
FocusRing {}
|
||||
|
||||
onIndexChanged: visualIndex = index
|
||||
@@ -777,15 +784,6 @@ Card {
|
||||
}
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
anchors.leftMargin: taskItem.leadingWidth
|
||||
anchors.rightMargin: taskItem.trailingWidth
|
||||
cornerRadius: taskItem.radius
|
||||
stateColor: taskItem.accentColor
|
||||
disabled: !taskItem.modelData || taskItem.isEditing || !root.interactive
|
||||
onClicked: taskItem.activate()
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
|
||||
@@ -181,6 +181,8 @@ FocusScope {
|
||||
panelWidth: DashMetrics.sheetWidth
|
||||
iconName: "edit_calendar"
|
||||
title: eventData ? I18n.tr("Edit event") : I18n.tr("New event")
|
||||
statusText: editorLoader.item?.errorText ?? ""
|
||||
statusColor: Theme.error
|
||||
|
||||
onDismissed: {
|
||||
eventData = null;
|
||||
@@ -188,6 +190,8 @@ FocusScope {
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: editorLoader
|
||||
|
||||
width: parent.width
|
||||
active: editorSheet.visible
|
||||
|
||||
|
||||
@@ -87,6 +87,13 @@ Item {
|
||||
return Qt.point(guideX ?? snapped.x, guideY ?? snapped.y);
|
||||
}
|
||||
|
||||
function pinPosition() {
|
||||
geometry.savePosition(geometry.widgetX, geometry.widgetY);
|
||||
SettingsData.updateDesktopWidgetInstanceConfig(instanceId, {
|
||||
autoPosition: false
|
||||
});
|
||||
}
|
||||
|
||||
function commitPosition(finalX, finalY) {
|
||||
if (stock && finalX === stock.x && finalY === stock.y) {
|
||||
SessionData.resetDesktopWidgetInstanceGeometry(instanceId, ["x", "y"]);
|
||||
@@ -223,8 +230,10 @@ Item {
|
||||
geometry.dragOverrideH = next.height;
|
||||
}
|
||||
onResizeEnded: {
|
||||
resizing = false;
|
||||
geometry.saveSize(geometry.dragOverrideW, geometry.dragOverrideH);
|
||||
if (root.automaticPlacement)
|
||||
root.pinPosition();
|
||||
resizing = false;
|
||||
geometry.clearDragOverrides();
|
||||
}
|
||||
onResizeCanceled: {
|
||||
|
||||
@@ -95,8 +95,20 @@ FocusScope {
|
||||
readonly property real edgeInset: Theme.spacingXL * 2
|
||||
property bool completed: false
|
||||
property var lockedPositions: ({})
|
||||
// Snapshot taken when a drag or resize starts so the auto-placed clock cannot jump under the pointer.
|
||||
property var heldPlacement: ({})
|
||||
readonly property string backgroundKey: LockPlacementService.backgroundKey(screenName, width, height)
|
||||
readonly property var autoPositions: editMode && completed ? currentPlacement() : lockedPositions
|
||||
readonly property var autoPositions: {
|
||||
if (!editMode || !completed)
|
||||
return lockedPositions;
|
||||
if (interactingItem)
|
||||
return heldPlacement;
|
||||
return currentPlacement();
|
||||
}
|
||||
onInteractingItemChanged: {
|
||||
if (interactingItem)
|
||||
heldPlacement = currentPlacement();
|
||||
}
|
||||
|
||||
function currentPlacement() {
|
||||
return LockPlacementService.layoutFor(screenName, LockPlacementService.sampleFor(screenName, backgroundKey), placementKey, placeClocks);
|
||||
@@ -218,6 +230,15 @@ FocusScope {
|
||||
return null;
|
||||
}
|
||||
|
||||
readonly property var interactingItem: {
|
||||
for (let i = 0; i < repeater.count; i++) {
|
||||
const item = repeater.itemAt(i);
|
||||
if (item && item.interacting)
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
x: (parent.width - width) / 2
|
||||
width: Theme.dividerWidth
|
||||
|
||||
@@ -842,6 +842,8 @@ Item {
|
||||
}
|
||||
if (root.pam.passwd.active)
|
||||
return I18n.tr("Authenticating...", "lock screen status text while the password is checked");
|
||||
if (root.passwordVisibility !== "always")
|
||||
return "";
|
||||
return I18n.tr("Password", "lock screen password field placeholder") + "…";
|
||||
}
|
||||
color: {
|
||||
|
||||
@@ -16,7 +16,9 @@ Item {
|
||||
readonly property int notificationMode: cfg.mode ?? 1
|
||||
readonly property bool resizable: true
|
||||
readonly property real minWidth: Theme.listItemTwoLineHeight * 2
|
||||
readonly property real minHeight: Theme.listItemHeight
|
||||
readonly property real minHeight: Theme.buttonHeightXS
|
||||
readonly property real defaultWidth: LockMetrics.notificationCardWidth
|
||||
readonly property real defaultHeight: fullContent ? LockMetrics.notificationMaxHeight : Theme.buttonHeightS
|
||||
|
||||
readonly property var notifications: NotificationService.groupedNotifications
|
||||
readonly property int totalCount: {
|
||||
@@ -46,53 +48,98 @@ Item {
|
||||
|
||||
readonly property bool editPlaceholder: !hasNotifications && (lockHost?.demoMode ?? false)
|
||||
readonly property bool chips: notificationMode === 2 && !editPlaceholder
|
||||
readonly property bool fullContent: notificationMode === 3 && !editPlaceholder
|
||||
readonly property var visibleGroups: appNameGroups.slice(0, LockMetrics.notificationLimit)
|
||||
readonly property int hiddenGroups: Math.max(0, appNameGroups.length - LockMetrics.notificationLimit)
|
||||
|
||||
implicitWidth: chips ? contentLoader.implicitWidth : LockMetrics.notificationCardWidth
|
||||
implicitWidth: contentLoader.implicitWidth
|
||||
implicitHeight: hasNotifications || editPlaceholder ? contentLoader.implicitHeight : 0
|
||||
clip: true
|
||||
|
||||
Loader {
|
||||
id: contentLoader
|
||||
anchors.left: parent.left
|
||||
anchors.right: root.chips ? undefined : parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.fill: parent
|
||||
active: root.hasNotifications || root.editPlaceholder
|
||||
sourceComponent: {
|
||||
if (root.notificationMode === 1 || root.editPlaceholder)
|
||||
return countOnlyComponent;
|
||||
return root.chips ? chipRowComponent : notificationListComponent;
|
||||
if (root.chips)
|
||||
return chipRowComponent;
|
||||
if (root.fullContent)
|
||||
return notificationListComponent;
|
||||
return countOnlyComponent;
|
||||
}
|
||||
}
|
||||
|
||||
component Chip: Rectangle {
|
||||
default property alias content: chipContent.data
|
||||
readonly property real contentWidth: chipContent.implicitWidth
|
||||
height: Theme.buttonHeightXS
|
||||
width: contentWidth + Theme.spacingM * 2
|
||||
radius: Theme.cornerRadiusM
|
||||
color: Theme.notificationFloatingSurface
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineVariant
|
||||
|
||||
Row {
|
||||
id: chipContent
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: chipRowComponent
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
Item {
|
||||
id: chipHost
|
||||
|
||||
Repeater {
|
||||
model: root.visibleGroups
|
||||
property int fitCount: root.visibleGroups.length
|
||||
readonly property int hiddenCount: root.appNameGroups.length - fitCount
|
||||
implicitWidth: chipRow.implicitWidth
|
||||
implicitHeight: chipRow.implicitHeight
|
||||
|
||||
Rectangle {
|
||||
id: chip
|
||||
function measure() {
|
||||
const widths = [];
|
||||
for (let i = 0; i < chipRepeater.count; i++)
|
||||
widths.push(chipRepeater.itemAt(i)?.width ?? 0);
|
||||
const total = count => widths.slice(0, count).reduce((sum, w) => sum + w, 0) + Math.max(0, count - 1) * chipRow.spacing;
|
||||
const overflow = count => root.appNameGroups.length > count ? moreMetrics.width + Theme.spacingM * 2 + chipRow.spacing : 0;
|
||||
let count = widths.length;
|
||||
while (count > 1 && total(count) + overflow(count) > width)
|
||||
count--;
|
||||
fitCount = count;
|
||||
}
|
||||
|
||||
required property var modelData
|
||||
readonly property string appIcon: NotificationService.notificationAppIcon(modelData.latestNotification?.appIcon || "", modelData.latestNotification?.desktopEntry || "")
|
||||
onWidthChanged: Qt.callLater(measure)
|
||||
Component.onCompleted: measure()
|
||||
|
||||
height: Theme.buttonHeightXS
|
||||
width: chipRow.implicitWidth + Theme.spacingM * 2
|
||||
radius: Theme.cornerRadiusM
|
||||
color: Theme.notificationFloatingSurface
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineVariant
|
||||
Accessible.name: modelData.appName
|
||||
TextMetrics {
|
||||
id: moreMetrics
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Theme.fontWeightMedium
|
||||
text: I18n.tr("+ %1 more", "lock screen notification list overflow, %1 is a count of hidden apps").arg(root.appNameGroups.length)
|
||||
onWidthChanged: Qt.callLater(chipHost.measure)
|
||||
}
|
||||
|
||||
Row {
|
||||
id: chipRow
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
Row {
|
||||
id: chipRow
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
id: chipRepeater
|
||||
model: root.visibleGroups
|
||||
onItemAdded: Qt.callLater(chipHost.measure)
|
||||
onItemRemoved: Qt.callLater(chipHost.measure)
|
||||
|
||||
Chip {
|
||||
id: chip
|
||||
|
||||
required property var modelData
|
||||
required property int index
|
||||
readonly property string appIcon: NotificationService.notificationAppIcon(modelData.latestNotification?.appIcon || "", modelData.latestNotification?.desktopEntry || "")
|
||||
|
||||
visible: index < chipHost.fitCount
|
||||
Accessible.name: modelData.appName
|
||||
onWidthChanged: Qt.callLater(chipHost.measure)
|
||||
|
||||
Item {
|
||||
width: Theme.iconSizeSmall
|
||||
@@ -151,24 +198,17 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: root.hiddenGroups > 0
|
||||
height: Theme.buttonHeightXS
|
||||
width: moreText.implicitWidth + Theme.spacingM * 2
|
||||
radius: Theme.cornerRadiusM
|
||||
color: Theme.notificationFloatingSurface
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineVariant
|
||||
Chip {
|
||||
visible: chipHost.hiddenCount > 0
|
||||
|
||||
StyledText {
|
||||
id: moreText
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("+ %1 more", "lock screen notification list overflow, %1 is a count of hidden apps").arg(root.hiddenGroups)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Theme.fontWeightMedium
|
||||
color: Theme.onSurfaceVariant
|
||||
StyledText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: I18n.tr("+ %1 more", "lock screen notification list overflow, %1 is a count of hidden apps").arg(chipHost.hiddenCount)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Theme.fontWeightMedium
|
||||
color: Theme.onSurfaceVariant
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,28 +217,42 @@ Item {
|
||||
Component {
|
||||
id: countOnlyComponent
|
||||
|
||||
LockNotificationCard {
|
||||
implicitHeight: Theme.listItemHeight
|
||||
color: Theme.notificationFloatingSurface
|
||||
Accessible.name: countLabel.text
|
||||
Item {
|
||||
implicitWidth: countPill.width
|
||||
implicitHeight: countPill.height
|
||||
|
||||
Row {
|
||||
Rectangle {
|
||||
id: countPill
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
width: countRow.implicitWidth + Theme.spacingL * 2
|
||||
height: Theme.buttonHeightS
|
||||
radius: Theme.fullRadius(width, height)
|
||||
color: Theme.notificationFloatingSurface
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineVariant
|
||||
scale: Math.min(1, parent.width / width, parent.height / height)
|
||||
Accessible.name: countLabel.text
|
||||
|
||||
DankIcon {
|
||||
name: "notifications"
|
||||
size: Theme.iconSize
|
||||
color: Theme.onSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Row {
|
||||
id: countRow
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
id: countLabel
|
||||
text: root.editPlaceholder ? I18n.tr("Notifications") : root.totalCount === 1 ? I18n.tr("1 notification") : I18n.tr("%1 notifications").arg(root.totalCount)
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.onSurface
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
DankIcon {
|
||||
name: "notifications"
|
||||
size: Theme.iconSizeSmall + Theme.spacingXXS
|
||||
color: Theme.onSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: countLabel
|
||||
text: root.editPlaceholder ? I18n.tr("Notifications") : root.totalCount === 1 ? I18n.tr("1 notification") : I18n.tr("%1 notifications").arg(root.totalCount)
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Theme.fontWeightMedium
|
||||
color: Theme.onSurface
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,46 +261,52 @@ Item {
|
||||
Component {
|
||||
id: notificationListComponent
|
||||
|
||||
DankFlickable {
|
||||
implicitHeight: Math.min(notificationColumn.implicitHeight, LockMetrics.notificationMaxHeight, Math.max(0, (root.lockHost?.height ?? 0) - (root.parent?.y ?? 0) - Theme.spacingXL))
|
||||
height: Math.min(notificationColumn.implicitHeight, root.height)
|
||||
contentHeight: notificationColumn.implicitHeight
|
||||
clip: true
|
||||
Item {
|
||||
implicitWidth: LockMetrics.notificationCardWidth
|
||||
implicitHeight: Math.min(notificationColumn.implicitHeight, LockMetrics.notificationMaxHeight)
|
||||
|
||||
Column {
|
||||
id: notificationColumn
|
||||
DankFlickable {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
spacing: Theme.groupedListGap
|
||||
height: Math.min(notificationColumn.implicitHeight, parent.height)
|
||||
contentHeight: notificationColumn.implicitHeight
|
||||
clip: true
|
||||
|
||||
Repeater {
|
||||
id: notificationRepeater
|
||||
model: root.appNameGroups.slice(0, LockMetrics.notificationLimit)
|
||||
|
||||
Notifications.NotificationCard {
|
||||
required property var modelData
|
||||
required property int index
|
||||
width: notificationColumn.width
|
||||
notificationData: modelData.latestNotification
|
||||
groupCount: modelData.count
|
||||
interactive: false
|
||||
headerOnly: false
|
||||
showActions: false
|
||||
showDismiss: false
|
||||
showClose: false
|
||||
showTime: !headerOnly
|
||||
animateHeight: false
|
||||
firstInGroup: index === 0
|
||||
lastInGroup: index === notificationRepeater.count - 1
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Column {
|
||||
id: notificationColumn
|
||||
width: parent.width
|
||||
visible: root.appNameGroups.length > LockMetrics.notificationLimit
|
||||
text: I18n.tr("+ %1 more", "lock screen notification list overflow, %1 is a count of hidden apps").arg(root.appNameGroups.length - LockMetrics.notificationLimit)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.lockScreenContentColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
spacing: Theme.groupedListGap
|
||||
|
||||
Repeater {
|
||||
id: notificationRepeater
|
||||
model: root.visibleGroups
|
||||
|
||||
Notifications.NotificationCard {
|
||||
required property var modelData
|
||||
required property int index
|
||||
width: notificationColumn.width
|
||||
notificationData: modelData.latestNotification
|
||||
groupCount: modelData.count
|
||||
interactive: false
|
||||
headerOnly: false
|
||||
showActions: false
|
||||
showDismiss: false
|
||||
showClose: false
|
||||
showTime: !headerOnly
|
||||
animateHeight: false
|
||||
firstInGroup: index === 0
|
||||
lastInGroup: index === notificationRepeater.count - 1
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
visible: root.appNameGroups.length > LockMetrics.notificationLimit
|
||||
text: I18n.tr("+ %1 more", "lock screen notification list overflow, %1 is a count of hidden apps").arg(root.appNameGroups.length - LockMetrics.notificationLimit)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.lockScreenContentColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,7 +667,7 @@ PanelWindow {
|
||||
anchors.fill: parent
|
||||
anchors.margins: content.cardInset
|
||||
radius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : NotificationMetrics.popupRadius
|
||||
color: Theme.notificationFloatingSurface
|
||||
color: "transparent"
|
||||
|
||||
HoverHandler {
|
||||
id: cardHoverHandler
|
||||
@@ -711,7 +711,7 @@ PanelWindow {
|
||||
dismissText: I18n.tr("Clear")
|
||||
animateHeight: false
|
||||
outerRadius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : NotificationMetrics.popupRadius
|
||||
color: Theme.notificationFloatingSurface
|
||||
color: "transparent"
|
||||
onExpandRequested: win.descriptionExpanded = !win.descriptionExpanded
|
||||
onCloseRequested: win.dismissPopupReliably()
|
||||
onDismissRequested: {
|
||||
|
||||
@@ -107,7 +107,7 @@ PanelWindow {
|
||||
y: shadowBuffer
|
||||
width: root.toastWidth
|
||||
height: root.toastHeight
|
||||
color: {
|
||||
readonly property color surfaceColor: {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
return Theme.error;
|
||||
@@ -119,6 +119,7 @@ PanelWindow {
|
||||
return Theme.readableSurface;
|
||||
}
|
||||
}
|
||||
color: "transparent"
|
||||
radius: Theme.windowRadius
|
||||
opacity: presented ? 1 : 0
|
||||
|
||||
@@ -452,7 +453,7 @@ PanelWindow {
|
||||
level: Theme.elevationLevel3
|
||||
fallbackOffset: 6
|
||||
targetRadius: toast.radius
|
||||
targetColor: toast.color
|
||||
targetColor: toast.surfaceColor
|
||||
shadowOpacity: Theme.elevationLevel3 && Theme.elevationLevel3.alpha !== undefined ? Theme.elevationLevel3.alpha : 0.3
|
||||
shadowEnabled: Theme.elevationEnabled
|
||||
}
|
||||
@@ -480,7 +481,7 @@ PanelWindow {
|
||||
WindowBlur {
|
||||
targetWindow: root
|
||||
blurEnabled: root.presented
|
||||
surfaceColor: toast.color
|
||||
surfaceColor: toast.surfaceColor
|
||||
blurX: toast.x
|
||||
blurY: toast.y
|
||||
blurWidth: root.presented ? toast.width : 0
|
||||
|
||||
Reference in New Issue
Block a user