mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 08:20:36 +00:00
fix: Widen worker charts
This commit is contained in:
@@ -489,7 +489,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 131;
|
CURRENT_PROJECT_VERSION = 132;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -511,7 +511,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 131;
|
CURRENT_PROJECT_VERSION = 132;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -530,7 +530,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 131;
|
CURRENT_PROJECT_VERSION = 132;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -547,7 +547,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 131;
|
CURRENT_PROJECT_VERSION = 132;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -679,7 +679,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 131;
|
CURRENT_PROJECT_VERSION = 132;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -702,7 +702,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 131;
|
CURRENT_PROJECT_VERSION = 132;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>131</string>
|
<string>132</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|||||||
@@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000669">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000253">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.917785">
|
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.303267">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: build_app" time="130.084682">
|
<testcase classname="fastlane.lanes" name="2: build_app" time="131.526213">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="203.665249">
|
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="206.79174">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2026.0403.1+45
|
version: 2026.0404.1+46
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.9.2
|
sdk: ^3.9.2
|
||||||
|
|||||||
@@ -450,15 +450,40 @@ export function DashboardShell() {
|
|||||||
|
|
||||||
// --- Composition stacked area chart ---
|
// --- Composition stacked area chart ---
|
||||||
|
|
||||||
|
const MIN_CHART_W = 320;
|
||||||
|
const COMPOSITION_CHART_H = 236;
|
||||||
|
|
||||||
|
function useResponsiveChartWidth(minWidth = MIN_CHART_W) {
|
||||||
|
const [element, setElement] = useState<HTMLDivElement | null>(null);
|
||||||
|
const [width, setWidth] = useState(minWidth);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!element) return;
|
||||||
|
|
||||||
|
const sync = () => setWidth(Math.max(element.clientWidth, minWidth));
|
||||||
|
sync();
|
||||||
|
|
||||||
|
if (typeof ResizeObserver === "undefined") return;
|
||||||
|
|
||||||
|
const observer = new ResizeObserver(sync);
|
||||||
|
observer.observe(element);
|
||||||
|
|
||||||
|
return () => { observer.disconnect(); };
|
||||||
|
}, [element, minWidth]);
|
||||||
|
|
||||||
|
return { setElement, width };
|
||||||
|
}
|
||||||
|
|
||||||
function CompositionChart({ points }: { points: CompositionPoint[] }) {
|
function CompositionChart({ points }: { points: CompositionPoint[] }) {
|
||||||
const [hover, setHover] = useState<number | null>(null);
|
const [hover, setHover] = useState<number | null>(null);
|
||||||
|
const { setElement, width } = useResponsiveChartWidth();
|
||||||
const count = points.length;
|
const count = points.length;
|
||||||
if (count === 0) return null;
|
if (count === 0) return null;
|
||||||
|
|
||||||
const maxVal = Math.max(...points.map((p) => p.human + p.overhead), 1);
|
const maxVal = Math.max(...points.map((p) => p.human + p.overhead), 1);
|
||||||
const innerW = 100;
|
|
||||||
const innerH = 188;
|
|
||||||
const pad = { top: 16, right: 16, bottom: 32, left: 48 };
|
const pad = { top: 16, right: 16, bottom: 32, left: 48 };
|
||||||
|
const innerW = Math.max(width - pad.left - pad.right, 240);
|
||||||
|
const innerH = COMPOSITION_CHART_H - pad.top - pad.bottom;
|
||||||
|
|
||||||
const xs = points.map((_, i) => i / Math.max(count - 1, 1));
|
const xs = points.map((_, i) => i / Math.max(count - 1, 1));
|
||||||
|
|
||||||
@@ -473,11 +498,10 @@ function CompositionChart({ points }: { points: CompositionPoint[] }) {
|
|||||||
const gridLines = niceGridLines(maxVal, 3);
|
const gridLines = niceGridLines(maxVal, 3);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative select-none">
|
<div ref={setElement} className="relative select-none">
|
||||||
<svg
|
<svg
|
||||||
viewBox={`${-pad.left} ${-pad.top} ${innerW + pad.left + pad.right} ${innerH + pad.top + pad.bottom}`}
|
viewBox={`${-pad.left} ${-pad.top} ${innerW + pad.left + pad.right} ${innerH + pad.top + pad.bottom}`}
|
||||||
className="h-auto max-h-[280px] w-full"
|
className="h-[236px] w-full"
|
||||||
preserveAspectRatio="xMidYMid meet"
|
|
||||||
onMouseLeave={() => setHover(null)}
|
onMouseLeave={() => setHover(null)}
|
||||||
>
|
>
|
||||||
<defs>
|
<defs>
|
||||||
@@ -569,6 +593,7 @@ const CHART_PAD = { top: 20, right: 16, bottom: 32, left: 48 };
|
|||||||
|
|
||||||
function TrafficChart({ points, maxValue: _rawMax }: { points: ChartPoint[]; maxValue: number }) {
|
function TrafficChart({ points, maxValue: _rawMax }: { points: ChartPoint[]; maxValue: number }) {
|
||||||
const [hover, setHover] = useState<number | null>(null);
|
const [hover, setHover] = useState<number | null>(null);
|
||||||
|
const { setElement, width } = useResponsiveChartWidth();
|
||||||
const count = points.length;
|
const count = points.length;
|
||||||
if (count === 0) return null;
|
if (count === 0) return null;
|
||||||
|
|
||||||
@@ -579,7 +604,7 @@ function TrafficChart({ points, maxValue: _rawMax }: { points: ChartPoint[]; max
|
|||||||
}));
|
}));
|
||||||
const maxValue = Math.max(...normalized.map((p) => p.perNode), 1);
|
const maxValue = Math.max(...normalized.map((p) => p.perNode), 1);
|
||||||
|
|
||||||
const innerW = 100;
|
const innerW = Math.max(width - CHART_PAD.left - CHART_PAD.right, 240);
|
||||||
const innerH = CHART_H - CHART_PAD.top - CHART_PAD.bottom;
|
const innerH = CHART_H - CHART_PAD.top - CHART_PAD.bottom;
|
||||||
|
|
||||||
const peakIdx = normalized.reduce((best, p, i) => (p.perNode > normalized[best].perNode ? i : best), 0);
|
const peakIdx = normalized.reduce((best, p, i) => (p.perNode > normalized[best].perNode ? i : best), 0);
|
||||||
@@ -599,11 +624,10 @@ function TrafficChart({ points, maxValue: _rawMax }: { points: ChartPoint[]; max
|
|||||||
.filter((_, i) => i % labelStep === 0 || i === count - 1);
|
.filter((_, i) => i % labelStep === 0 || i === count - 1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative select-none">
|
<div ref={setElement} className="relative select-none">
|
||||||
<svg
|
<svg
|
||||||
viewBox={`${-CHART_PAD.left} ${-CHART_PAD.top} ${innerW + CHART_PAD.left + CHART_PAD.right} ${CHART_H}`}
|
viewBox={`${-CHART_PAD.left} ${-CHART_PAD.top} ${innerW + CHART_PAD.left + CHART_PAD.right} ${CHART_H}`}
|
||||||
className="h-auto max-h-[280px] w-full"
|
className="h-[240px] w-full"
|
||||||
preserveAspectRatio="xMidYMid meet"
|
|
||||||
onMouseLeave={() => setHover(null)}
|
onMouseLeave={() => setHover(null)}
|
||||||
>
|
>
|
||||||
<defs>
|
<defs>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import "../index.css";
|
|||||||
<slot />
|
<slot />
|
||||||
<script>
|
<script>
|
||||||
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
function apply(e) { document.documentElement.classList.toggle("dark", e.matches); }
|
function apply(e: MediaQueryList | MediaQueryListEvent) { document.documentElement.classList.toggle("dark", e.matches); }
|
||||||
apply(mq);
|
apply(mq);
|
||||||
mq.addEventListener("change", apply);
|
mq.addEventListener("change", apply);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user