1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-08 04:09:15 -04:00

fix(Clipboard): stale image entry handling

- Resolved random DMS API errors & QML Warnings
This commit is contained in:
purian23
2026-06-03 03:17:02 -04:00
parent 510269dda9
commit a34fda984d
6 changed files with 290 additions and 18 deletions
@@ -89,6 +89,10 @@ Item {
if (!root.entry || root.entry.id !== requestedId) {
return;
}
if (!response.result) {
ClipboardService.refresh();
return;
}
const result = response.result;
let fullText = "";
if (result?.data) {
@@ -13,6 +13,7 @@ Item {
required property var modal
required property var listView
required property int itemIndex
property bool disposed: false
Image {
id: thumbnailImage
@@ -20,6 +21,13 @@ Item {
property bool isVisible: false
property string cachedImageData: ""
property bool loadQueued: false
property bool activeLoad: false
property bool completed: false
property int loadGeneration: 0
property var activeEntryId: null
property var activeRequest: null
property var currentEntryId: entry && entry.id !== undefined ? entry.id : null
property string currentEntryType: entryType
anchors.fill: parent
source: cachedImageData ? `data:image/png;base64,${cachedImageData}` : ""
@@ -31,29 +39,119 @@ Item {
sourceSize.width: 128
sourceSize.height: 128
onCurrentEntryIdChanged: {
if (thumbnailImage.completed) {
thumbnailImage.resetForEntry();
}
}
onCurrentEntryTypeChanged: {
if (thumbnailImage.completed) {
thumbnailImage.resetForEntry();
}
}
function hasValidEntryId() {
return entry && entry.id !== undefined && entry.id !== null;
}
function releaseActiveLoad() {
if (!thumbnailImage.activeLoad) {
return;
}
thumbnailImage.activeLoad = false;
if (modal && modal.activeImageLoads > 0) {
modal.activeImageLoads--;
}
}
function finishLoad(request) {
thumbnailImage.loadQueued = false;
thumbnailImage.activeEntryId = null;
if (!request || thumbnailImage.activeRequest === request) {
thumbnailImage.activeRequest = null;
}
thumbnailImage.releaseActiveLoad();
}
function cancelLoad() {
if (thumbnailImage.activeRequest) {
thumbnailImage.activeRequest.cancelled = true;
thumbnailImage.activeRequest = null;
}
retryTimer.stop();
visibilityTimer.stop();
thumbnailImage.loadQueued = false;
thumbnailImage.activeEntryId = null;
thumbnailImage.releaseActiveLoad();
}
function resetForEntry() {
thumbnailImage.loadGeneration++;
thumbnailImage.cachedImageData = "";
thumbnailImage.isVisible = false;
thumbnailImage.cancelLoad();
Qt.callLater(function () {
if (thumbnail.disposed) {
return;
}
thumbnailImage.checkVisibility();
});
}
function startLoad() {
if (!modal) {
thumbnailImage.loadQueued = false;
return;
}
modal.activeImageLoads++;
thumbnailImage.activeLoad = true;
thumbnailImage.loadImage();
}
function tryLoadImage() {
if (thumbnailImage.loadQueued || entryType !== "image" || thumbnailImage.cachedImageData) {
if (thumbnail.disposed || thumbnailImage.loadQueued || entryType !== "image" || thumbnailImage.cachedImageData || !thumbnailImage.hasValidEntryId()) {
return;
}
thumbnailImage.loadQueued = true;
if (modal.activeImageLoads < modal.maxConcurrentLoads) {
modal.activeImageLoads++;
thumbnailImage.loadImage();
if (modal && modal.activeImageLoads < modal.maxConcurrentLoads) {
thumbnailImage.startLoad();
} else {
retryTimer.restart();
}
}
function loadImage() {
if (!thumbnailImage.hasValidEntryId()) {
thumbnailImage.finishLoad();
return;
}
const requestedId = entry.id;
const generation = thumbnailImage.loadGeneration;
const request = {
"cancelled": false
};
thumbnailImage.activeEntryId = requestedId;
thumbnailImage.activeRequest = request;
DMSService.sendRequest("clipboard.getEntry", {
"id": entry.id
"id": requestedId
}, function (response) {
thumbnailImage.loadQueued = false;
if (modal.activeImageLoads > 0) {
modal.activeImageLoads--;
if (request.cancelled) {
return;
}
if (thumbnail.disposed || generation !== thumbnailImage.loadGeneration || thumbnailImage.activeRequest !== request || thumbnailImage.activeEntryId !== requestedId) {
return;
}
thumbnailImage.finishLoad(request);
if (!entry || entry.id !== requestedId || entryType !== "image") {
return;
}
if (response.error) {
log.warn("Failed to load image:", entry.id);
log.warn("Failed to load image:", requestedId);
return;
}
if (!response.result) {
ClipboardService.refresh();
return;
}
const data = response.result?.data;
@@ -70,9 +168,8 @@ Item {
if (!thumbnailImage.loadQueued) {
return;
}
if (modal.activeImageLoads < modal.maxConcurrentLoads) {
modal.activeImageLoads++;
thumbnailImage.loadImage();
if (modal && modal.activeImageLoads < modal.maxConcurrentLoads) {
thumbnailImage.startLoad();
} else {
retryTimer.restart();
}
@@ -80,7 +177,8 @@ Item {
}
Component.onCompleted: {
if (entryType !== "image" || listView.height <= 0) {
thumbnailImage.completed = true;
if (entryType !== "image" || listView.height <= 0 || !thumbnailImage.hasValidEntryId()) {
return;
}
@@ -94,6 +192,11 @@ Item {
}
}
Component.onDestruction: {
thumbnail.disposed = true;
thumbnailImage.cancelLoad();
}
Timer {
id: visibilityTimer
interval: 100
@@ -101,7 +204,7 @@ Item {
}
function checkVisibility() {
if (entryType !== "image" || listView.height <= 0 || isVisible) {
if (thumbnail.disposed || entryType !== "image" || listView.height <= 0 || isVisible || !thumbnailImage.hasValidEntryId()) {
return;
}
const itemY = itemIndex * (ClipboardConstants.itemHeight + listView.spacing);
@@ -57,7 +57,11 @@ Rectangle {
return;
if (response.error)
return;
const result = response.result ?? {};
if (!response.result) {
ClipboardService.refresh();
return;
}
const result = response.result;
const mimeType = (result.mimeType ?? entry?.mimeType ?? "").toString();
const data = (result.data ?? "").toString();
if (data.length === 0 || !resolvedSourceUrl(data, mimeType))