diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml index 1df4bbb77..098b73cfa 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml @@ -22,7 +22,7 @@ Rectangle { property string downloadPath property string nsfwPath - property real availableWidth: parent.width ?? 0 + property real availableWidth: parent.width property real rowTooShortThreshold: 185 property real imageSpacing: 5 property real responsePadding: 5 @@ -31,6 +31,26 @@ Rectangle { anchors.right: parent?.right implicitHeight: columnLayout.implicitHeight + root.responsePadding * 2 + Component.onCompleted: { + // Break property bind to prevent aggressive updates + availableWidth = parent.width + } + + Connections { + target: parent + function onWidthChanged() { + updateWidthTimer.restart() + } + } + + Timer { + id: updateWidthTimer + interval: 100 + onTriggered: { + availableWidth = parent.width + } + } + radius: Appearance.rounding.normal color: Appearance.colors.colLayer1 @@ -159,45 +179,47 @@ Rectangle { } Repeater { - model: { - // Group two images every row, ensuring they are of the same height - // If the height ends up being too small, put one image in the row and continue - // In other words, this is similar to Android's gallery layout at largest zoom level - let i = 0; - let rows = []; - const responseList = root.responseData.images; - while (i < responseList.length) { - let row = { - height: 0, - images: [], - }; - const availableImageWidth = availableWidth - root.imageSpacing - (responsePadding * 2) - if (i + 1 < responseList.length) { - const img1 = responseList[i]; - const img2 = responseList[i + 1]; - // Calculate combined height if both are in the same row - // Let h = row height, w1 = h * aspect1, w2 = h * aspect2 - // w1 + w2 = availableWidth => h = availableWidth / (aspect1 + aspect2) - const combinedAspect = img1.aspect_ratio + img2.aspect_ratio; - const rowHeight = availableImageWidth / combinedAspect; - if (rowHeight >= rowTooShortThreshold) { - row.height = rowHeight; - row.images.push(img1); - row.images.push(img2); - rows.push(row); - i += 2; - continue; + model: ScriptModel { + values: { + // Group two images every row, ensuring they are of the same height + // If the height ends up being too small, put one image in the row and continue + // In other words, this is similar to Android's gallery layout at largest zoom level + let i = 0; + let rows = []; + const responseList = root.responseData.images; + while (i < responseList.length) { + let row = { + height: 0, + images: [], + }; + const availableImageWidth = availableWidth - root.imageSpacing - (responsePadding * 2) + if (i + 1 < responseList.length) { + const img1 = responseList[i]; + const img2 = responseList[i + 1]; + // Calculate combined height if both are in the same row + // Let h = row height, w1 = h * aspect1, w2 = h * aspect2 + // w1 + w2 = availableWidth => h = availableWidth / (aspect1 + aspect2) + const combinedAspect = img1.aspect_ratio + img2.aspect_ratio; + const rowHeight = availableImageWidth / combinedAspect; + if (rowHeight >= rowTooShortThreshold) { + row.height = rowHeight; + row.images.push(img1); + row.images.push(img2); + rows.push(row); + i += 2; + continue; + } } + // Otherwise, put only one image in the row + const rowHeight = (availableWidth - (responsePadding * 2)) / responseList[i].aspect_ratio; + rows.push({ + height: rowHeight, + images: [responseList[i]], + }); + i += 1; } - // Otherwise, put only one image in the row - const rowHeight = (availableWidth - (responsePadding * 2)) / responseList[i].aspect_ratio; - rows.push({ - height: rowHeight, - images: [responseList[i]], - }); - i += 1; + return rows; } - return rows; } delegate: RowLayout { id: imageRow