mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-14 23:34:01 -04:00
settings: some changes ref #3635
cc: add trash icon to drag and crush things cc: allow anchoring footer items to start or end
This commit is contained in:
@@ -180,13 +180,25 @@ Item {
|
||||
|
||||
DankSearchField {
|
||||
id: searchField
|
||||
|
||||
property real sideInset: root.searchActive ? Theme.spacingS : Theme.spacingL
|
||||
|
||||
Behavior on sideInset {
|
||||
enabled: Theme.currentAnimationSpeed !== SettingsData.AnimationSpeed.None
|
||||
NumberAnimation {
|
||||
duration: Theme.expressiveDurations.expressiveFastSpatial
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Theme.expressiveCurves.expressiveFastSpatial
|
||||
}
|
||||
}
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.leftMargin: Theme.spacingL
|
||||
anchors.rightMargin: Theme.spacingL
|
||||
anchors.topMargin: Theme.spacingM
|
||||
height: Theme.iconButtonSize + Theme.spacingM
|
||||
anchors.leftMargin: sideInset
|
||||
anchors.rightMargin: sideInset
|
||||
anchors.topMargin: SettingsMetrics.searchBarGap
|
||||
height: SettingsMetrics.searchBarHeight
|
||||
placeholderText: I18n.tr("Search settings", "settings search field placeholder")
|
||||
onFocusStateChanged: hasFocus => root.searchFocused = hasFocus
|
||||
onTextChanged: {
|
||||
@@ -262,7 +274,7 @@ Item {
|
||||
anchors.right: parent.right
|
||||
anchors.top: searchField.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.topMargin: SettingsMetrics.sidebarGroupGap
|
||||
anchors.topMargin: SettingsMetrics.searchBarGap
|
||||
clip: true
|
||||
contentHeight: sidebarColumn.height
|
||||
|
||||
|
||||
@@ -19,15 +19,23 @@ Item {
|
||||
property var items: []
|
||||
property bool onTop: false
|
||||
property var transientSurfaceTracker: null
|
||||
// A grid tile hovering the row: {"cells", "at"}.
|
||||
// A grid tile hovering the row: {"cells", "end", "at"}, with `at` counted within the start or end group.
|
||||
property var incoming: null
|
||||
// Takes (savedIndex, cells, scenePoint) and returns true when it takes the dropped item.
|
||||
property var dropHandler: null
|
||||
// Takes the dragged item's scene rect and returns true while something outside the row will take it.
|
||||
property var leavesRow: null
|
||||
property int liftedIndex: -1
|
||||
property int liftedAt: -1
|
||||
property var liftedSlot: null
|
||||
property point liftedPoint: Qt.point(0, 0)
|
||||
property bool gridDragging: false
|
||||
property point gridDragPoint: Qt.point(0, 0)
|
||||
// Set from the pointer, not bound: the slot reads the widths that the incoming tile changes.
|
||||
property var gridSlot: null
|
||||
property var resizePreview: null
|
||||
property Item flyingItem: null
|
||||
readonly property bool dragging: gridDragging || liftedIndex >= 0
|
||||
readonly property bool overTrash: trashContains(liftedIndex >= 0 ? liftedPoint : gridDragPoint)
|
||||
|
||||
signal addWidgetRequested
|
||||
signal resetRequested
|
||||
@@ -51,6 +59,7 @@ Item {
|
||||
readonly property int capacity: Math.max(0, Math.floor((trackWidth + spacing) / pitch))
|
||||
readonly property var fills: items.map(item => resizePreview?.index === item.index ? resizePreview.fill : WidgetUtils.footerFills(item.widget))
|
||||
readonly property var mins: items.map(item => WidgetUtils.footerMinCells(item.widget.id))
|
||||
readonly property var ends: items.map(item => WidgetUtils.footerEnds(item.widget))
|
||||
// Fill items count at their minimum, so a drop or a neighbour growing takes room from them first.
|
||||
readonly property var fixedCells: WidgetUtils.fitFooterCells(items.map((item, i) => fills[i] ? mins[i] : (resizePreview?.index === item.index ? resizePreview.cells : WidgetUtils.footerCells(item.widget))), mins, capacity)
|
||||
readonly property int fixedUsed: fixedCells.reduce((sum, count) => sum + count, 0)
|
||||
@@ -68,32 +77,25 @@ Item {
|
||||
});
|
||||
}
|
||||
readonly property var layout: {
|
||||
const shown = groups();
|
||||
const lifted = items.findIndex(item => item.index === liftedIndex);
|
||||
const order = items.map((item, i) => i).filter(i => i !== lifted && cells[i] > 0);
|
||||
const gapAt = lifted >= 0 ? liftedAt : (incoming?.at ?? -1);
|
||||
const gap = lifted >= 0 ? liftedSlot : incoming;
|
||||
const gapCells = lifted >= 0 ? cells[lifted] : (incoming?.cells ?? 0);
|
||||
const offsets = [];
|
||||
let offset = 0;
|
||||
let gapOffset = -1;
|
||||
for (let k = 0; k <= order.length; k++) {
|
||||
if (k === gapAt) {
|
||||
gapOffset = offset;
|
||||
offset += gapCells * pitch;
|
||||
}
|
||||
if (k === order.length)
|
||||
break;
|
||||
offsets[order[k]] = offset;
|
||||
offset += cells[order[k]] * pitch + (order[k] === slackIndex ? fillSlack : 0);
|
||||
}
|
||||
const endGapAt = gap?.end ? gap.at : -1;
|
||||
const endFrom = trackWidth + spacing - groupWidth(shown.ends) - (endGapAt >= 0 ? gapCells * pitch : 0);
|
||||
const start = placeGroup(shown.starts, 0, gap && !gap.end ? gap.at : -1, gapCells);
|
||||
const end = placeGroup(shown.ends, endFrom, endGapAt, gapCells);
|
||||
return {
|
||||
"offsets": offsets,
|
||||
"gapOffset": gapOffset,
|
||||
"offsets": Object.assign(start.offsets, end.offsets),
|
||||
"gapOffset": Math.max(start.gapOffset, end.gapOffset),
|
||||
"gapCells": gapCells
|
||||
};
|
||||
}
|
||||
|
||||
implicitHeight: CcMetrics.footerHeight
|
||||
|
||||
onGridDragPointChanged: gridSlot = gridDragging ? insertionAt(gridDragPoint) : null
|
||||
|
||||
function spanWidth(count) {
|
||||
return count * pitch - spacing;
|
||||
}
|
||||
@@ -106,38 +108,106 @@ Item {
|
||||
return capacity - fixedUsed;
|
||||
}
|
||||
|
||||
function trashContains(scenePosition) {
|
||||
if (!editMode || !dragging)
|
||||
return false;
|
||||
return trash.contains(trash.mapFromItem(null, scenePosition.x, scenePosition.y));
|
||||
}
|
||||
|
||||
function containsScene(scenePosition) {
|
||||
const point = mapFromItem(null, scenePosition.x, scenePosition.y);
|
||||
return point.x >= 0 && point.x <= width && point.y >= -CcMetrics.gridGap && point.y <= height + CcMetrics.gridGap;
|
||||
}
|
||||
|
||||
function spanAt(i) {
|
||||
return cells[i] * pitch + (i === slackIndex ? fillSlack : 0);
|
||||
}
|
||||
|
||||
function groupWidth(group) {
|
||||
return group.reduce((sum, i) => sum + spanAt(i), 0);
|
||||
}
|
||||
|
||||
// Shown items other than the lifted one, split into the start and end groups in saved order.
|
||||
function groups() {
|
||||
const shown = items.map((item, i) => i).filter(i => items[i].index !== liftedIndex && cells[i] > 0);
|
||||
return {
|
||||
"starts": shown.filter(i => !ends[i]),
|
||||
"ends": shown.filter(i => ends[i])
|
||||
};
|
||||
}
|
||||
|
||||
function placeGroup(group, from, gapAt, gapCells) {
|
||||
const offsets = [];
|
||||
let gapOffset = -1;
|
||||
let offset = from;
|
||||
for (let k = 0; k <= group.length; k++) {
|
||||
if (k === gapAt) {
|
||||
gapOffset = offset;
|
||||
offset += gapCells * pitch;
|
||||
}
|
||||
if (k === group.length)
|
||||
break;
|
||||
offsets[group[k]] = offset;
|
||||
offset += spanAt(group[k]);
|
||||
}
|
||||
return {
|
||||
"offsets": offsets,
|
||||
"gapOffset": gapOffset
|
||||
};
|
||||
}
|
||||
|
||||
// The free space between the groups splits at its middle: the start half appends to the start group, the rest joins the end group.
|
||||
function insertionAt(scenePosition) {
|
||||
const local = track.mapFromItem(null, scenePosition.x, scenePosition.y).x - track.overhang;
|
||||
const distance = I18n.isRtl ? trackWidth - local : local;
|
||||
const shown = groups();
|
||||
let offset = 0;
|
||||
let position = 0;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].index === liftedIndex || cells[i] === 0)
|
||||
continue;
|
||||
const span = cells[i] * pitch;
|
||||
for (let k = 0; k < shown.starts.length; k++) {
|
||||
const span = spanAt(shown.starts[k]);
|
||||
if (distance < offset + span / 2)
|
||||
return position;
|
||||
return {
|
||||
"end": false,
|
||||
"at": k
|
||||
};
|
||||
offset += span;
|
||||
position++;
|
||||
}
|
||||
return position;
|
||||
const endFrom = trackWidth + spacing - groupWidth(shown.ends);
|
||||
if (distance < (offset + endFrom) / 2)
|
||||
return {
|
||||
"end": false,
|
||||
"at": shown.starts.length
|
||||
};
|
||||
offset = endFrom;
|
||||
for (let k = 0; k < shown.ends.length; k++) {
|
||||
const span = spanAt(shown.ends[k]);
|
||||
if (distance < offset + span / 2)
|
||||
return {
|
||||
"end": true,
|
||||
"at": k
|
||||
};
|
||||
offset += span;
|
||||
}
|
||||
return {
|
||||
"end": true,
|
||||
"at": shown.ends.length
|
||||
};
|
||||
}
|
||||
|
||||
// The saved index of the item a drop at `position` lands before, or -1 for the end.
|
||||
function savedIndexAt(position) {
|
||||
const shown = items.filter((item, i) => item.index !== liftedIndex && cells[i] > 0);
|
||||
return shown[position]?.index ?? -1;
|
||||
// The saved index a drop at `slot` goes before, or -1 for the end of the list.
|
||||
function savedIndexAt(slot) {
|
||||
const group = groups()[slot.end ? "ends" : "starts"];
|
||||
if (slot.at < group.length)
|
||||
return items[group[slot.at]].index;
|
||||
return group.length > 0 ? items[group[group.length - 1]].index + 1 : -1;
|
||||
}
|
||||
|
||||
function followingIndex(savedIndex) {
|
||||
const shown = items.filter((item, i) => cells[i] > 0);
|
||||
const at = shown.findIndex(item => item.index === savedIndex);
|
||||
return shown[at + 1]?.index ?? -1;
|
||||
function slotOf(savedIndex) {
|
||||
const at = items.findIndex(item => item.index === savedIndex);
|
||||
const end = ends[at] ?? false;
|
||||
return {
|
||||
"end": end,
|
||||
"at": groups()[end ? "ends" : "starts"].filter(i => i < at).length
|
||||
};
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -218,6 +288,8 @@ Item {
|
||||
return Qt.point(point.x - grab.x, point.y - grab.y);
|
||||
}
|
||||
property bool landed: false
|
||||
readonly property bool flying: lifted || landed
|
||||
readonly property bool atEnd: root.ends[index] ?? false
|
||||
|
||||
x: lifted || landed ? dragPosition.x : restX
|
||||
y: lifted || landed ? dragPosition.y : track.overhang
|
||||
@@ -226,8 +298,17 @@ Item {
|
||||
height: CcMetrics.footerHeight
|
||||
visible: cells > 0
|
||||
|
||||
// A reorder moves this entry, which is the moment a dropped item leaves the pointer for its slot.
|
||||
// A reorder or a switch of side is the moment a dropped item leaves the pointer for its slot.
|
||||
onIndexChanged: landed = false
|
||||
onAtEndChanged: landed = false
|
||||
onFlyingChanged: {
|
||||
if (flying) {
|
||||
root.flyingItem = footerItem;
|
||||
return;
|
||||
}
|
||||
if (root.flyingItem === footerItem)
|
||||
root.flyingItem = null;
|
||||
}
|
||||
|
||||
Behavior on x {
|
||||
enabled: !footerItem.lifted && !footerItem.landed && CcMetrics.animationsEnabled
|
||||
@@ -315,21 +396,23 @@ Item {
|
||||
if (active) {
|
||||
footerItem.grab = footerItem.mapFromItem(null, centroid.scenePressPosition.x, centroid.scenePressPosition.y);
|
||||
footerItem.dragScene = centroid.scenePosition;
|
||||
root.liftedPoint = centroid.scenePosition;
|
||||
root.liftedIndex = footerItem.entry.index;
|
||||
root.liftedAt = root.insertionAt(centroid.scenePosition);
|
||||
root.liftedSlot = root.insertionAt(centroid.scenePosition);
|
||||
return;
|
||||
}
|
||||
footerItem.landed = root.dropHandler?.(footerItem.entry.index, footerItem.cells, footerItem.dragScene) ?? false;
|
||||
root.liftedIndex = -1;
|
||||
root.liftedAt = -1;
|
||||
root.liftedSlot = null;
|
||||
}
|
||||
onCentroidChanged: {
|
||||
if (!active)
|
||||
return;
|
||||
footerItem.dragScene = centroid.scenePosition;
|
||||
root.liftedPoint = centroid.scenePosition;
|
||||
const visual = footerItem.mapToItem(null, 0, 0, footerItem.width, footerItem.height);
|
||||
const leaving = root.leavesRow?.(visual) ?? false;
|
||||
root.liftedAt = leaving ? -1 : root.insertionAt(footerItem.dragScene);
|
||||
const leaving = !root.overTrash && (root.leavesRow?.(visual) ?? false);
|
||||
root.liftedSlot = leaving || root.overTrash ? null : root.insertionAt(footerItem.dragScene);
|
||||
root.itemMoved(footerItem.entry.index, visual, leaving);
|
||||
}
|
||||
}
|
||||
@@ -342,7 +425,7 @@ Item {
|
||||
anchors.rightMargin: CcMetrics.footerGap
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: root.spacing
|
||||
visible: root.editMode
|
||||
visible: root.editMode && !root.dragging
|
||||
|
||||
DankActionButton {
|
||||
buttonSize: Theme.iconButtonSize
|
||||
@@ -369,6 +452,36 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
id: trash
|
||||
|
||||
anchors.right: trailing.left
|
||||
anchors.rightMargin: CcMetrics.footerGap
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: root.editActionsWidth
|
||||
height: CcMetrics.footerHeight
|
||||
radius: Theme.fullRadius(width, height)
|
||||
color: root.overTrash ? Theme.errorContainer : CcMetrics.tileInactiveColor
|
||||
visible: root.editMode && root.dragging
|
||||
Accessible.role: Accessible.Graphic
|
||||
Accessible.name: I18n.tr("Remove")
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "delete"
|
||||
size: CcMetrics.iconBoxIconSize
|
||||
filled: root.overTrash
|
||||
color: root.overTrash ? Theme.onErrorContainer : CcMetrics.tileInactiveContent
|
||||
}
|
||||
}
|
||||
|
||||
CcMenu {
|
||||
id: editMenu
|
||||
|
||||
@@ -403,10 +516,12 @@ Item {
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: CcMetrics.footerHeight
|
||||
// One column, the same pill as a small button docked beside it.
|
||||
width: root.spanWidth(1)
|
||||
height: CcMetrics.footerHeight
|
||||
|
||||
DankActionButton {
|
||||
anchors.fill: parent
|
||||
buttonSize: CcMetrics.footerHeight
|
||||
iconName: "check"
|
||||
iconSize: CcMetrics.iconBoxIconSize
|
||||
@@ -418,6 +533,7 @@ Item {
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
anchors.fill: parent
|
||||
buttonSize: CcMetrics.footerHeight
|
||||
iconName: "edit"
|
||||
iconSize: CcMetrics.iconBoxIconSize
|
||||
@@ -430,4 +546,29 @@ Item {
|
||||
onClicked: root.editToggled()
|
||||
}
|
||||
}
|
||||
|
||||
// The track's layer only draws inside the row, so a lifted item is shown from here while it travels.
|
||||
ShaderEffectSource {
|
||||
readonly property real pad: PopoutMetrics.editOverflow
|
||||
readonly property point at: {
|
||||
const item = root.flyingItem;
|
||||
if (!item)
|
||||
return Qt.point(0, 0);
|
||||
item.x;
|
||||
item.y;
|
||||
trackScale.xScale;
|
||||
return root.mapFromItem(item, -pad, -pad);
|
||||
}
|
||||
|
||||
visible: root.flyingItem !== null
|
||||
sourceItem: root.flyingItem
|
||||
hideSource: true
|
||||
smooth: true
|
||||
mipmap: true
|
||||
sourceRect: root.flyingItem ? Qt.rect(-pad, -pad, root.flyingItem.width + pad * 2, root.flyingItem.height + pad * 2) : Qt.rect(0, 0, 0, 0)
|
||||
x: at.x
|
||||
y: at.y
|
||||
width: sourceRect.width * trackScale.xScale
|
||||
height: sourceRect.height * trackScale.yScale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,10 +174,18 @@ FocusScope {
|
||||
if (!widgetGrid.heldOutside)
|
||||
return false;
|
||||
const savedIndex = widgetGrid.savedIndex(index);
|
||||
const before = footer.savedIndexAt(footer.insertionAt(scenePoint));
|
||||
if (footer.trashContains(scenePoint)) {
|
||||
Qt.callLater(() => {
|
||||
widgetModel.removeWidget(savedIndex);
|
||||
widgetGrid.cancelInteraction();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
const slot = footer.insertionAt(scenePoint);
|
||||
const before = footer.savedIndexAt(slot);
|
||||
const cells = Math.min(WidgetUtils.footerCells(gridDragWidget), footer.freeCells());
|
||||
Qt.callLater(() => {
|
||||
WidgetUtils.moveToFooter(savedIndex, before, cells);
|
||||
WidgetUtils.moveToFooter(savedIndex, before, cells, slot.end);
|
||||
widgetGrid.cancelInteraction();
|
||||
});
|
||||
return true;
|
||||
@@ -205,6 +213,10 @@ FocusScope {
|
||||
}
|
||||
|
||||
function dropFromFooter(index, scenePoint) {
|
||||
if (footer.trashContains(scenePoint)) {
|
||||
Qt.callLater(() => widgetModel.removeWidget(index));
|
||||
return true;
|
||||
}
|
||||
if (widgetGrid.externalItem) {
|
||||
const placed = widgetGrid.committedItems();
|
||||
const cell = placed.pop();
|
||||
@@ -215,13 +227,15 @@ FocusScope {
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (footer.liftedAt < 0)
|
||||
const slot = footer.liftedSlot;
|
||||
if (!slot)
|
||||
return false;
|
||||
const before = footer.savedIndexAt(footer.liftedAt);
|
||||
if (before === footer.followingIndex(index))
|
||||
const current = footer.slotOf(index);
|
||||
if (slot.end === current.end && slot.at === current.at)
|
||||
return false;
|
||||
const before = footer.savedIndexAt(slot);
|
||||
const cells = WidgetUtils.footerCells(SettingsData.controlCenterWidgets[index]);
|
||||
Qt.callLater(() => WidgetUtils.moveToFooter(index, before, cells));
|
||||
Qt.callLater(() => WidgetUtils.moveToFooter(index, before, cells, slot.end));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -394,7 +408,7 @@ FocusScope {
|
||||
screenName: root.host.triggerScreen?.name || ""
|
||||
tapToClose: root.host.headerTogglesClose ?? false
|
||||
runningToplevels: root.runningToplevels
|
||||
dragsOutside: (index, scenePoint, tile) => root.footerTakesGridDrag(tile)
|
||||
dragsOutside: (index, scenePoint, tile) => footer.trashContains(scenePoint) || root.footerTakesGridDrag(tile)
|
||||
dropHandler: (index, scenePoint) => root.dropFromGrid(index, scenePoint)
|
||||
onExpandClicked: widgetData => root.openWidgetPage(widgetData)
|
||||
onRemoveWidget: index => widgetModel.removeWidget(index)
|
||||
@@ -433,10 +447,11 @@ FocusScope {
|
||||
onTop: root.footerOnTop
|
||||
transientSurfaceTracker: root.host.transientSurfaceTracker
|
||||
items: root.footerItems
|
||||
incoming: root.gridDragWidget !== null && widgetGrid.heldOutside ? {
|
||||
"cells": Math.min(WidgetUtils.footerCells(root.gridDragWidget), footer.freeCells()),
|
||||
"at": footer.insertionAt(widgetGrid.dragScenePoint)
|
||||
} : null
|
||||
gridDragging: root.gridDragWidget !== null
|
||||
gridDragPoint: widgetGrid.dragScenePoint
|
||||
incoming: root.gridDragWidget !== null && widgetGrid.heldOutside && !footer.overTrash ? Object.assign({
|
||||
"cells": Math.min(WidgetUtils.footerCells(root.gridDragWidget), footer.freeCells())
|
||||
}, footer.gridSlot) : null
|
||||
dropHandler: (index, cells, scenePoint) => root.dropFromFooter(index, scenePoint)
|
||||
leavesRow: visual => root.gridTakesFooterDrag(visual)
|
||||
opacity: body.opacity
|
||||
|
||||
@@ -43,6 +43,10 @@ function footerFills(widget) {
|
||||
return widget?.footerFill === true;
|
||||
}
|
||||
|
||||
function footerEnds(widget) {
|
||||
return widget?.footerEnd === true;
|
||||
}
|
||||
|
||||
function fitFooterCells(sizes, mins, capacity) {
|
||||
const fitted = sizes.slice();
|
||||
let over = fitted.reduce((sum, cells) => sum + cells, 0) - capacity;
|
||||
@@ -179,7 +183,7 @@ function setOption(index, key, value) {
|
||||
}
|
||||
|
||||
// Footer order is the saved order of footer entries, so the moved entry lands just before `beforeIndex`.
|
||||
function moveToFooter(index, beforeIndex, cells) {
|
||||
function moveToFooter(index, beforeIndex, cells, end) {
|
||||
const widgets = Common.SettingsData.controlCenterWidgets.slice();
|
||||
const widget = widgets[index];
|
||||
if (!widget)
|
||||
@@ -187,10 +191,15 @@ function moveToFooter(index, beforeIndex, cells) {
|
||||
const before = beforeIndex === index ? null : widgets[beforeIndex] ?? null;
|
||||
widgets.splice(index, 1);
|
||||
const at = before ? widgets.indexOf(before) : widgets.length;
|
||||
widgets.splice(at, 0, Object.assign({}, widget, {
|
||||
const moved = Object.assign({}, widget, {
|
||||
"footer": true,
|
||||
"footerW": cells
|
||||
}));
|
||||
});
|
||||
if (end)
|
||||
moved.footerEnd = true;
|
||||
else
|
||||
delete moved.footerEnd;
|
||||
widgets.splice(at, 0, moved);
|
||||
Common.SettingsData.set("controlCenterWidgets", widgets);
|
||||
}
|
||||
|
||||
@@ -230,6 +239,7 @@ function placeFromFooter(widgets, index, col, row) {
|
||||
"row": row
|
||||
});
|
||||
delete tile.footer;
|
||||
delete tile.footerEnd;
|
||||
const placed = widgets.slice();
|
||||
placed[index] = tile;
|
||||
return placed;
|
||||
|
||||
@@ -27,6 +27,8 @@ Singleton {
|
||||
readonly property real navIconSize: Theme.avatarSize
|
||||
readonly property real navItemMinHeight: Theme.listItemHeight
|
||||
readonly property real sidebarGroupGap: Theme.spacingS
|
||||
readonly property real searchBarHeight: 56
|
||||
readonly property real searchBarGap: Theme.spacingM
|
||||
readonly property real avatarSize: 64
|
||||
readonly property real splitDividerHeight: Theme.iconSize
|
||||
readonly property real buttonGroupCompactThreshold: 200
|
||||
|
||||
@@ -36,8 +36,26 @@ Rectangle {
|
||||
readonly property color glyphColor: accentPair?.onContainer ?? Theme.primary
|
||||
property bool isFirstInGroup: true
|
||||
property bool isLastInGroup: true
|
||||
readonly property real topRadius: isFirstInGroup ? Theme.groupedListOuterRadius : Theme.groupedListInnerRadius
|
||||
readonly property real bottomRadius: isLastInGroup ? Theme.groupedListOuterRadius : Theme.groupedListInnerRadius
|
||||
property real topRadius: active || isFirstInGroup ? Theme.groupedListOuterRadius : Theme.groupedListInnerRadius
|
||||
property real bottomRadius: active || isLastInGroup ? Theme.groupedListOuterRadius : Theme.groupedListInnerRadius
|
||||
|
||||
Behavior on topRadius {
|
||||
enabled: Theme.currentAnimationSpeed !== SettingsData.AnimationSpeed.None
|
||||
NumberAnimation {
|
||||
duration: Theme.expressiveDurations.expressiveFastSpatial
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Theme.expressiveCurves.expressiveFastSpatial
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on bottomRadius {
|
||||
enabled: Theme.currentAnimationSpeed !== SettingsData.AnimationSpeed.None
|
||||
NumberAnimation {
|
||||
duration: Theme.expressiveDurations.expressiveFastSpatial
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Theme.expressiveCurves.expressiveFastSpatial
|
||||
}
|
||||
}
|
||||
|
||||
width: parent?.width ?? 0
|
||||
height: Math.max(SettingsMetrics.navItemMinHeight, textColumn.implicitHeight + Theme.spacingS * 2)
|
||||
|
||||
Reference in New Issue
Block a user