wip: improve responsive scaling

This commit is contained in:
Meierschlumpf
2023-01-05 06:01:54 +01:00
parent d439ba1842
commit 6f8f0e90cb
3 changed files with 307 additions and 190 deletions

View File

@@ -17,156 +17,6 @@
} }
], ],
"apps": [ "apps": [
{
"id": "5df743d9-5cb1-457c-85d2-64ff86855652",
"name": "Your app",
"url": "https://homarr.dev",
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"network": {
"enabledStatusChecker": false,
"okStatus": []
},
"behaviour": {
"isOpeningNewTab": true,
"externalUrl": "https://homarr.dev"
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 0,
"y": 7
},
"size": {
"width": 6,
"height": 4
}
},
"integration": {
"type": null,
"properties": []
}
},
{
"id": "76217a87-7151-42d0-b0cf-1b72aef63f83",
"name": "Small app",
"url": "https://homarr.dev",
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"network": {
"enabledStatusChecker": false,
"okStatus": []
},
"behaviour": {
"isOpeningNewTab": true,
"externalUrl": "https://homarr.dev"
},
"area": {
"type": "category",
"properties": {
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 4,
"y": 0
},
"size": {
"width": 1,
"height": 1
}
},
"integration": {
"type": null,
"properties": []
}
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330",
"name": "Contribute",
"url": "https://github.com/ajnart/homarr",
"behaviour": {
"onClickUrl": "https://github.com/ajnart/homarr",
"externalUrl": "https://github.com/ajnart/homarr",
"isOpeningNewTab": true
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/github.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "category",
"properties": {
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 7,
"y": 0
},
"size": {
"width": 1,
"height": 1
}
}
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a337",
"name": "Discord",
"url": "https://discord.com/invite/aCsmEV5RgA",
"behaviour": {
"onClickUrl": "https://discord.com/invite/aCsmEV5RgA",
"isOpeningNewTab": true,
"externalUrl": "https://discord.com/invite/aCsmEV5RgA"
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/discord.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "category",
"properties": {
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 6,
"y": 0
},
"size": {
"width": 1,
"height": 1
}
}
},
{ {
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33a", "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33a",
"name": "Documentation", "name": "Documentation",
@@ -236,13 +86,163 @@
}, },
"shape": { "shape": {
"location": { "location": {
"x": 5, "x": 6,
"y": 1
},
"size": {
"width": 1,
"height": 2
}
}
},
{
"id": "76217a87-7151-42d0-b0cf-1b72aef63f83",
"name": "Small app",
"url": "https://homarr.dev",
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"network": {
"enabledStatusChecker": false,
"okStatus": []
},
"behaviour": {
"isOpeningNewTab": true,
"externalUrl": "https://homarr.dev"
},
"area": {
"type": "category",
"properties": {
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 4,
"y": 0 "y": 0
}, },
"size": { "size": {
"width": 1, "width": 1,
"height": 1 "height": 1
} }
},
"integration": {
"type": null,
"properties": []
}
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a337",
"name": "Discord",
"url": "https://discord.com/invite/aCsmEV5RgA",
"behaviour": {
"onClickUrl": "https://discord.com/invite/aCsmEV5RgA",
"isOpeningNewTab": true,
"externalUrl": "https://discord.com/invite/aCsmEV5RgA"
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/discord.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "category",
"properties": {
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 5,
"y": 2
},
"size": {
"width": 1,
"height": 2
}
}
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330",
"name": "Contribute",
"url": "https://github.com/ajnart/homarr",
"behaviour": {
"onClickUrl": "https://github.com/ajnart/homarr",
"externalUrl": "https://github.com/ajnart/homarr",
"isOpeningNewTab": true
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/github.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "category",
"properties": {
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 7,
"y": 0
},
"size": {
"width": 1,
"height": 1
}
}
},
{
"id": "5df743d9-5cb1-457c-85d2-64ff86855652",
"name": "Your app",
"url": "https://homarr.dev",
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"network": {
"enabledStatusChecker": false,
"okStatus": []
},
"behaviour": {
"isOpeningNewTab": true,
"externalUrl": "https://homarr.dev"
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 0,
"y": 7
},
"size": {
"width": 6,
"height": 4
}
},
"integration": {
"type": null,
"properties": []
} }
}, },
{ {
@@ -269,7 +269,7 @@
"shape": { "shape": {
"location": { "location": {
"x": 8, "x": 8,
"y": 10 "y": 9
}, },
"size": { "size": {
"width": 4, "width": 4,
@@ -297,10 +297,10 @@
"shape": { "shape": {
"location": { "location": {
"x": 0, "x": 0,
"y": 2 "y": 0
}, },
"size": { "size": {
"width": 5, "width": 3,
"height": 5 "height": 5
} }
} }
@@ -323,8 +323,8 @@
"y": 0 "y": 0
}, },
"size": { "size": {
"width": 4, "width": 3,
"height": 1 "height": 2
} }
} }
}, },
@@ -341,12 +341,12 @@
}, },
"shape": { "shape": {
"location": { "location": {
"x": 8, "x": 9,
"y": 0 "y": 0
}, },
"size": { "size": {
"width": 4, "width": 3,
"height": 1 "height": 2
} }
} }
} }

View File

@@ -0,0 +1,88 @@
import { GridStackNode } from 'fily-publish-gridstack';
type GridstackColumnSortingFn = (
column: number,
prevColumn: number,
newNodes: GridStackNode[],
nodes: GridStackNode[]
) => void;
const getGridstackAttribute = (node: GridStackNode, path: 'x' | 'y' | 'w' | 'h'): number =>
parseInt(node.el!.getAttribute(`data-gridstack-${path}`)!, 10);
const getGridstackAttributes = (node: GridStackNode) => ({
width: getGridstackAttribute(node, 'w'),
height: getGridstackAttribute(node, 'h'),
x: getGridstackAttribute(node, 'x'),
y: getGridstackAttribute(node, 'y'),
});
type Type = ReturnType<typeof getGridstackAttributes> & { node: GridStackNode };
const nextItem = (start: number, end: number, nodes: Type[]): number => {
const next = nodes
.filter((x) => x.y <= end && x.y + x.height - 1 > end)
.sort((a, b) => a.y + a.height - (b.y + b.height))
.at(0);
if (!next) return end;
return nextItem(start, next.height - 1 + next.y, nodes);
};
const nextRowHeight = (nodes: Type[], values: number[], current = 0) => {
const item = nodes.find((x) => x.y >= current);
if (!item) return;
const next = nextItem(item.y, item.y + item.height - 1, nodes);
values.push(next + 1 - item.y);
nextRowHeight(nodes, values, next);
};
const getRowHeights = (nodes: Type[]) => {
const rowHeights: number[] = [];
nextRowHeight(
nodes,
rowHeights
);
return rowHeights;
};
const sortNodesByYAndX = (a: GridStackNode, b: GridStackNode) => {
const aAttributes = getGridstackAttributes(a);
const bAttributes = getGridstackAttributes(b);
const differenceY = aAttributes.y - bAttributes.y;
return differenceY !== 0 ? differenceY : aAttributes.x - bAttributes.x;
};
export const commonColumnSorting: GridstackColumnSortingFn = (
column,
prevColumn,
newNodes,
nodes
) => {
if (column === prevColumn) {
newNodes.concat(nodes);
return;
}
let nextRow = 0;
let available = column;
const sortedNodes = nodes.sort(sortNodesByYAndX);
const mappedNodes = sortedNodes.map((node) => ({
...getGridstackAttributes(node),
node,
}));
const rowHeights = getRowHeights(mappedNodes);
const rowItems: Type[][] = [];
// TODO: fix issue with spaces between.
let rowTotal = 0;
rowHeights.forEach(height => {
rowItems.push(mappedNodes.filter(node => node.y >= rowTotal && node.y < rowTotal + height));
rowTotal += height;
});
console.log(rowItems);
};

View File

@@ -16,8 +16,46 @@ import { AppType } from '../../../../types/app';
import { AreaType } from '../../../../types/area'; import { AreaType } from '../../../../types/area';
import { IWidget } from '../../../../widgets/widgets'; import { IWidget } from '../../../../widgets/widgets';
import { useEditModeStore } from '../../Views/useEditModeStore'; import { useEditModeStore } from '../../Views/useEditModeStore';
import { commonColumnSorting } from './column-sorting';
import { initializeGridstack } from './init-gridstack'; import { initializeGridstack } from './init-gridstack';
const getGridstackAttribute = (node: GridStackNode, path: 'x' | 'y' | 'w' | 'h'): number => parseInt(node.el!.getAttribute(`data-gridstack-${path}`)!, 10);
const getGridstackAttributes = (node: GridStackNode) => ({
width: getGridstackAttribute(node, 'w'),
height: getGridstackAttribute(node, 'h'),
x: getGridstackAttribute(node, 'x'),
y: getGridstackAttribute(node, 'y'),
});
type Type = (ReturnType<typeof getGridstackAttributes> & { node: GridStackNode });
const nextItem = (start: number, end: number, nodes: Type[]): number => {
const next = nodes
.filter(x => x.y <= end && x.y + x.height - 1 > end)
.sort((a, b) => (a.y + a.height) - (b.y + b.height))
.at(0);
if (!next) return end;
return nextItem(start, next.height - 1 + next.y, nodes);
};
const nextRowHeight = (nodes: Type[], values: number[], current = 0) => {
const item = nodes.find(x => x.y >= current);
if (!item) return;
const next = nextItem(item.y, item.y + item.height - 1, nodes);
values.push(next + 1 - item.y);
nextRowHeight(nodes, values, next);
};
const getRowHeights = (nodes: GridStackNode[]) => {
const rowHeights: number[] = [];
nextRowHeight(nodes.map((node) => ({
...getGridstackAttributes(node),
node,
})), rowHeights);
return rowHeights;
};
interface UseGristackReturnType { interface UseGristackReturnType {
apps: AppType[]; apps: AppType[];
widgets: IWidget<string, any>[]; widgets: IWidget<string, any>[];
@@ -90,24 +128,16 @@ export const useGridstack = (
if (areaType === 'sidebar') return; if (areaType === 'sidebar') return;
gridRef.current?.column( gridRef.current?.column(
wrapperColumnCount, wrapperColumnCount,
(column, prevColumn, newNodes, nodes) => { /*(column, prevColumn, newNodes, nodes) => {
let nextRow = 0; let nextRow = 0;
let available = column; let available = column;
let maxHeightInRow = 1;
if (column === prevColumn) { if (column === prevColumn) {
newNodes.concat(nodes); newNodes.concat(nodes);
return; return;
} }
const getGridstackAttribute = (node: GridStackNode, path: 'x' | 'y' | 'w' | 'h'): number => parseInt(node.el!.getAttribute(`data-gridstack-${path}`)!, 10);
const getGridstackAttributes = (node: GridStackNode) => ({
width: getGridstackAttribute(node, 'w'),
height: getGridstackAttribute(node, 'h'),
x: getGridstackAttribute(node, 'x'),
y: getGridstackAttribute(node, 'y'),
});
const sortNodes = (a: GridStackNode, b: GridStackNode) => { const sortNodes = (a: GridStackNode, b: GridStackNode) => {
const aAttributes = getGridstackAttributes(a); const aAttributes = getGridstackAttributes(a);
const bAttributes = getGridstackAttributes(b); const bAttributes = getGridstackAttributes(b);
@@ -117,36 +147,39 @@ export const useGridstack = (
return differenceY !== 0 ? differenceY : aAttributes.x - bAttributes.x; return differenceY !== 0 ? differenceY : aAttributes.x - bAttributes.x;
}; };
const sorted = nodes.sort(sortNodes); const sortedNodes = nodes.sort(sortNodes);
const rowHeights = getRowHeights(sortedNodes);
console.log(sorted); sortedNodes.forEach((node) => {
sorted.forEach((node) => {
const newnode = node; const newnode = node;
const width = parseInt(newnode.el!.getAttribute('data-gridstack-w')!, 10); const width = parseInt(newnode.el!.getAttribute('data-gridstack-w')!, 10);
const height = parseInt(newnode.el!.getAttribute('data-gridstack-h')!, 10); const height = parseInt(newnode.el!.getAttribute('data-gridstack-h')!, 10);
const x = parseInt(newnode.el!.getAttribute('data-gridstack-x')!, 10); const x = parseInt(newnode.el!.getAttribute('data-gridstack-x')!, 10);
const y = parseInt(newnode.el!.getAttribute('data-gridstack-y')!, 10); const y = parseInt(newnode.el!.getAttribute('data-gridstack-y')!, 10);
const moveYDown = 1; maxHeightInRow = height > maxHeightInRow ? height : maxHeightInRow;
const continueInNextRow = () => {
nextRow += maxHeightInRow;
maxHeightInRow = 1;
available = column;
return nextRow;
};
if (column === 3) { if (column === 3) {
newnode.x = available >= width ? 3 - available : 0; newnode.x = available >= width ? 3 - available : 0;
newnode.y = available === 3 || available >= width ? nextRow : nextRow += moveYDown; newnode.y = available === 3 || available >= width ? nextRow : continueInNextRow();
if (width > 3) { if (width > 3) {
newnode.w = 3; newnode.w = 3;
nextRow += moveYDown; continueInNextRow();
available = 3;
} else if (available >= width) { } else if (available >= width) {
available -= width; available -= width;
if (available === 0) { if (available === 0) {
nextRow += moveYDown; continueInNextRow();
available = 3;
} }
} else if (available < width) { } else if (available < width) {
newnode.y = newnode.y! + moveYDown; newnode.y = continueInNextRow();
available = 3 - width; available = 3 - width;
nextRow += moveYDown;
} }
} else if (column === 6) { } else if (column === 6) {
newnode.x = available >= width ? 6 - available : 0; newnode.x = available >= width ? 6 - available : 0;
@@ -154,29 +187,25 @@ export const useGridstack = (
if (width > 6) { if (width > 6) {
newnode.w = 6; newnode.w = 6;
nextRow += moveYDown; continueInNextRow();
available = 6;
} else if (available >= width) { } else if (available >= width) {
available -= width; available -= width;
if (available === 0) { if (available === 0) {
nextRow += moveYDown; continueInNextRow();
available = 6;
} }
} else if (available < width) { } else if (available < width) {
newnode.y = newnode.y! + moveYDown; newnode.y = continueInNextRow();
available = 6 - width; available = 6 - width;
nextRow += moveYDown;
} }
} else { } else {
newnode.x = y % 2 === 1 ? x + 6 : x; newnode.x = y % 2 === 1 ? x + 6 : x;
newnode.y = Math.floor(y / 2); newnode.y = Math.floor(y / 2);
} }
console.log(newnode);
newNodes.push(newnode); newNodes.push(newnode);
}); });
} }*/
commonColumnSorting
); );
}, [wrapperColumnCount]); }, [wrapperColumnCount]);