فهرست منبع

Scale the printer card's body text and icons with its size (#1848)

Switching a card from M to XL made it wider, enlarged the printer name
and the thumbnail, and left everything else where it was. The AMS slot
labels, temperatures, filament names, status text and every small button
stayed pinned between 8 and 11 pixels -- under the smallest size used
anywhere else in the app -- so a full-width card carried the same tiny
text as the compact one. Browser zoom does not answer this: it enlarges
the whole page and so preserves the very disparity being reported.

The card root now carries ten custom properties derived from cardSize,
and the 200 fixed sizes in its subtree reference them: text-[10px]
becomes text-[length:var(--pc-t10,10px)], w-3 h-3 becomes
w-[var(--pc-i3,0.75rem)]. L draws the body 20% larger and XL 40%,
icons included, so the controls grow with the text instead of staying
fiddly to hit.

Custom properties rather than an em-based root font-size. Setting
font-size on the card would silently reshape any text that declares no
size of its own, and would break for portalled content. Each converted
class names its old fixed value as the fallback, so anything rendering
outside a card root is untouched -- which is what leaves the portalled
temperature popover exactly as it is. Its four sites stay fixed on
purpose, as does the page chrome; the conversion was scoped from the
function declarations rather than line numbers, and afterwards only
those four intended sites still hold a literal px value.

S and M stay at 1.0. S is the dense fleet view where density is the
point and M is the default, so an existing install looks identical until
the user reaches for a size that is already asking for more room -- the
same control the request asked this to follow.

The AMS-HT card needed separate work, because its temperature and
humidity readings sit beside the slot rather than under it. That single
slot was the only growable item on its row, so it took every spare pixel
and pushed the readings hard against the card's edge; it is now capped
at roughly two ordinary slots, which keeps them clear at any card width.
The card itself is capped at one full AMS card's width, so a unit that
wraps onto a line of its own no longer stretches that slot across the
whole card.

The AMS slot minimums are deliberately NOT scaled. Raising them was
tried and reverted: those cards already grow to fill their row, so
3.5rem is a floor they sit well above, and raising it only cost a unit
its place on the row -- which is what pushed the AMS-HT onto a line by
itself and exposed the stretching above. A test pins them at 3.5rem at
XL so this reads as a decision rather than a missed spot.
maziggy 1 ماه پیش
والد
کامیت
78cbd82259

+ 1 - 1
CHANGELOG.md

@@ -9,7 +9,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **The external spool can be hidden from the printer card (#1782, reporter @Arn0uDz)** — An external spool holder that never gets used still occupies a full card's width in the **Filaments** row, next to the AMS units that are actually being used. An eye icon at the right-hand end of that row's header now hides it, and clicking it again brings it back, so nothing is lost behind a settings page you would have to remember. The choice is remembered per printer and stored in the browser, like the card size and the offline-printer filter — one machine in a fleet can be tidied up without touching the others, and nothing changes for anyone else using the same Bambuddy. The icon is deliberately absent on a printer with no AMS: there the external spool is the entire filament section, and hiding it would leave an empty row. That guard also covers the case of an AMS being unplugged from a printer whose external spool was hidden earlier — the spool reappears rather than leaving a blank row behind. On the H2D and H2S both external positions share one card and so hide together. Translated in all locales, wiki updated, covered by frontend tests.
 - **The external spool can be hidden from the printer card (#1782, reporter @Arn0uDz)** — An external spool holder that never gets used still occupies a full card's width in the **Filaments** row, next to the AMS units that are actually being used. An eye icon at the right-hand end of that row's header now hides it, and clicking it again brings it back, so nothing is lost behind a settings page you would have to remember. The choice is remembered per printer and stored in the browser, like the card size and the offline-printer filter — one machine in a fleet can be tidied up without touching the others, and nothing changes for anyone else using the same Bambuddy. The icon is deliberately absent on a printer with no AMS: there the external spool is the entire filament section, and hiding it would leave an empty row. That guard also covers the case of an AMS being unplugged from a printer whose external spool was hidden earlier — the spool reappears rather than leaving a blank row behind. On the H2D and H2S both external positions share one card and so hide together. Translated in all locales, wiki updated, covered by frontend tests.
 
 
 ### Changed
 ### Changed
-- **The L and XL printer cards now scale their text and icons, not just their width (#1848, reporter @misterff1)** — Switching a card from M to XL made it wider, enlarged the printer name and the thumbnail, and left everything else exactly as it was: the AMS slot labels, temperatures, filament names, status text and every small button stayed pinned between 8 and 11 pixels, well under the smallest size used anywhere else in Bambuddy. The result was a full-width card carrying the same tiny text as the compact one, which is precisely the opposite of what someone reaching for a bigger card is asking for. Browser zoom is not an answer to this, since it enlarges the entire page and so preserves the very disparity being complained about. The card body now scales along with the card: L draws it 20% larger and XL 40% larger, icons included, so the controls grow with the text rather than staying fiddly to hit. S and M are deliberately untouched — S is the dense fleet view where density is the point, and M is the default, so an existing install looks identical until you reach for a size that is already asking for more room. Wiki updated. Covered by frontend tests.
+- **The L and XL printer cards now scale their text and icons, not just their width (#1848, reporter @misterff1)** — Switching a card from M to XL made it wider, enlarged the printer name and the thumbnail, and left everything else exactly as it was: the AMS slot labels, temperatures, filament names, status text and every small button stayed pinned between 8 and 11 pixels, well under the smallest size used anywhere else in Bambuddy. The result was a full-width card carrying the same tiny text as the compact one, which is precisely the opposite of what someone reaching for a bigger card is asking for. Browser zoom is not an answer to this, since it enlarges the entire page and so preserves the very disparity being complained about. The card body now scales along with the card: L draws it 20% larger and XL 40% larger, icons included, so the controls grow with the text rather than staying fiddly to hit. The AMS-HT card needed two adjustments of its own, since its temperature and humidity readings sit beside the slot rather than under it. Its single slot was the only thing on that row able to grow, so it swallowed every spare pixel and pushed the readings hard against the card's edge — it is now capped at roughly two ordinary slots, which keeps them clear at any card width. The card itself also gained a ceiling of one full AMS card's width, so a unit that wraps onto a line of its own no longer stretches that single slot across the whole card. S and M are deliberately untouched — S is the dense fleet view where density is the point, and M is the default, so an existing install looks identical until you reach for a size that is already asking for more room. Wiki updated. Covered by frontend tests.
 
 
 - **Error and warning toasts now stay up twice as long** — Every pop-up notification disappeared after three seconds regardless of what it said. That is about right for "Settings saved", which confirms something you just did and is skimmed rather than read, but errors and warnings are a different kind of message: they carry a reason, often one relayed from the printer or the backend, and they run to a couple of lines. Three seconds was not long enough to finish reading one, and a missed error message is gone for good — there is no notification history to go back to. Errors and warnings now hold for six seconds. Success and informational toasts keep the three-second default, so the common case of clicking something and seeing it confirmed is unchanged, and the close button and the manual dismiss work exactly as before on all of them. The background print-dispatch toast is unaffected: it stays up while it has work in progress and clears itself shortly after the last job settles. Covered by frontend tests.
 - **Error and warning toasts now stay up twice as long** — Every pop-up notification disappeared after three seconds regardless of what it said. That is about right for "Settings saved", which confirms something you just did and is skimmed rather than read, but errors and warnings are a different kind of message: they carry a reason, often one relayed from the printer or the backend, and they run to a couple of lines. Three seconds was not long enough to finish reading one, and a missed error message is gone for good — there is no notification history to go back to. Errors and warnings now hold for six seconds. Success and informational toasts keep the three-second default, so the common case of clicking something and seeing it confirmed is unchanged, and the close button and the manual dismiss work exactly as before on all of them. The background print-dispatch toast is unaffected: it stays up while it has work in progress and clears itself shortly after the last job settles. Covered by frontend tests.
 
 

+ 130 - 1
frontend/src/__tests__/pages/PrintersPageCardScale.test.tsx

@@ -32,6 +32,23 @@ const mockPrinter = {
   updated_at: '2024-01-01T00:00:00Z',
   updated_at: '2024-01-01T00:00:00Z',
 };
 };
 
 
+const baseTray = {
+  tray_color: 'FF0000FF',
+  tray_type: 'PLA',
+  tray_sub_brands: 'PLA Basic',
+  tray_info_idx: 'GFA00',
+  remain: 80,
+  k: 0.02,
+  cali_idx: null,
+  tag_uid: null,
+  tray_uuid: null,
+  nozzle_temp_min: 190,
+  nozzle_temp_max: 230,
+  drying_temp: null,
+  drying_time: null,
+  state: 3,
+};
+
 const STATUS = {
 const STATUS = {
   connected: true,
   connected: true,
   state: 'IDLE',
   state: 'IDLE',
@@ -43,7 +60,38 @@ const STATUS = {
   filename: null,
   filename: null,
   wifi_signal: -29,
   wifi_signal: -29,
   speed_level: 2,
   speed_level: 2,
-  ams: [],
+  ams: [
+    {
+      id: 0,
+      humidity: 30,
+      temp: 28.2,
+      is_ams_ht: false,
+      serial_number: 'AMS00',
+      sw_ver: '03.00.21.29',
+      dry_time: 0,
+      dry_status: 0,
+      dry_sub_status: 0,
+      dry_sf_reason: [],
+      module_type: 'n3f',
+      tray: [0, 1, 2, 3].map((id) => ({ id, ...baseTray })),
+    },
+    {
+      // AMS-HT: a single tray, with its temperature and humidity readings
+      // beside the slot rather than under it.
+      id: 128,
+      humidity: 52,
+      temp: 28.6,
+      is_ams_ht: true,
+      serial_number: 'HT00',
+      sw_ver: '03.00.21.29',
+      dry_time: 0,
+      dry_status: 0,
+      dry_sub_status: 0,
+      dry_sf_reason: [],
+      module_type: 'n3s',
+      tray: [{ id: 0, ...baseTray }],
+    },
+  ],
   vt_tray: [],
   vt_tray: [],
 };
 };
 
 
@@ -61,6 +109,39 @@ async function cardStyleAt(cardSize: string) {
   return card.style;
   return card.style;
 }
 }
 
 
+/** The AMS slot grid's track sizing, once the status has populated the card. */
+async function slotGridColumns(): Promise<string> {
+  return waitFor(() => {
+    const grid = document.querySelector<HTMLElement>('#printer-card-1 [style*="minmax"]');
+    if (!grid) throw new Error('AMS slot grid not rendered');
+    return grid.style.gridTemplateColumns;
+  });
+}
+
+/** The AMS-HT card's own sizing — it is the unit whose readings sit beside the slot. */
+async function htCardStyle(): Promise<CSSStyleDeclaration> {
+  return waitFor(() => {
+    const el = [...document.querySelectorAll<HTMLElement>('#printer-card-1 [class*="rounded-[10px]"]')]
+      .find((d) => /^HT-/.test((d.textContent || '').trim()));
+    if (!el) throw new Error('AMS-HT card not rendered');
+    return el.style;
+  });
+}
+
+/**
+ * The single filament slot inside the AMS-HT card. Scoped through the card
+ * itself, since the card carries a max-width of its own.
+ */
+async function htSlotStyle(): Promise<CSSStyleDeclaration> {
+  return waitFor(() => {
+    const card = [...document.querySelectorAll<HTMLElement>('#printer-card-1 [class*="rounded-[10px]"]')]
+      .find((d) => /^HT-/.test((d.textContent || '').trim()));
+    const el = card?.querySelector<HTMLElement>('[style*="max-width"]');
+    if (!el) throw new Error('AMS-HT slot not rendered');
+    return el.style;
+  });
+}
+
 describe('PrintersPage — printer card body scale (#1848)', () => {
 describe('PrintersPage — printer card body scale (#1848)', () => {
   beforeEach(() => {
   beforeEach(() => {
     store = {};
     store = {};
@@ -119,6 +200,54 @@ describe('PrintersPage — printer card body scale (#1848)', () => {
     }
     }
   });
   });
 
 
+  // Scaling these along with the type was tried and reverted. The AMS cards
+  // already grow to fill their row, so 3.5rem is a floor they sit well above;
+  // raising it only costs a unit its place on the row, and a wrapped AMS-HT is
+  // then alone on its line where flex-grow stretches its single slot across the
+  // whole card.
+  it('leaves the AMS slot columns at their fixed floor, at every size', async () => {
+    await cardStyleAt('2');
+    expect(await slotGridColumns()).toContain('3.5rem');
+  });
+
+  it('still leaves them alone at XL, where the type is largest', async () => {
+    await cardStyleAt('4');
+    expect(await slotGridColumns()).toContain('3.5rem');
+    expect(await slotGridColumns()).not.toContain('4.9rem');
+  });
+
+  // The AMS-HT does need its width scaled: its readings sit beside the slot,
+  // so bigger type eats the room they occupy.
+  it('widens the AMS-HT card with the type, and caps how wide it can get', async () => {
+    await cardStyleAt('3');
+    const ht = await htCardStyle();
+
+    expect(ht.minWidth).toBe('13.2rem'); // 11rem * 1.2
+    expect(ht.flex).toContain('13.2rem');
+    // Without a ceiling, an AMS-HT that wraps onto a line of its own is the
+    // only flex item there and grow stretches its single slot across the
+    // entire card, stranding the readings at the far edge.
+    expect(ht.maxWidth).toBe('calc(4 * 3.5rem + 3 * 0.25rem + 1rem)');
+  });
+
+  it('leaves the AMS-HT card as it was at M', async () => {
+    await cardStyleAt('2');
+    expect((await htCardStyle()).minWidth).toBe('11rem');
+  });
+
+  // The AMS-HT's single slot is the only growable item on its row, so it took
+  // every spare pixel and pushed the readings beside it hard against the card
+  // edge. Capping it is what keeps them clear.
+  it('caps the AMS-HT slot so it cannot swallow the row', async () => {
+    await cardStyleAt('2');
+    expect((await htSlotStyle()).maxWidth).toBe('7.25rem');
+  });
+
+  it('scales that cap with the type, since the slot label scales too', async () => {
+    await cardStyleAt('4');
+    expect((await htSlotStyle()).maxWidth).toBe('10.15rem'); // 7.25rem * 1.4
+  });
+
   it('drives real elements, not just the root variables', async () => {
   it('drives real elements, not just the root variables', async () => {
     await cardStyleAt('3');
     await cardStyleAt('3');
 
 

+ 44 - 8
frontend/src/pages/PrintersPage.tsx

@@ -4733,7 +4733,31 @@ function PrinterCard({
               const canHideExternalSpool = amsData.length > 0 && status.vt_tray.length > 0;
               const canHideExternalSpool = amsData.length > 0 && status.vt_tray.length > 0;
               const showExternalSpool = !(canHideExternalSpool && externalSpoolHidden);
               const showExternalSpool = !(canHideExternalSpool && externalSpoolHidden);
               const isDualNozzle = printer.nozzle_count === 2 || status?.temperatures?.nozzle_2 !== undefined;
               const isDualNozzle = printer.nozzle_count === 2 || status?.temperatures?.nozzle_2 !== undefined;
-              const filamentSlotClass = 'min-w-14';
+              const bodyScale = CARD_BODY_SCALE[cardSize] ?? 1;
+              // Rounded because 11 * 1.2 is 13.200000000000001 in binary
+              // floating point, and that lands verbatim in the DOM.
+              const scaledRem = (base: number) => `${Math.round(base * bodyScale * 1000) / 1000}rem`;
+              // Deliberately NOT scaled with the body (#1848). These AMS cards
+              // already grow to fill the row, so the 3.5rem is a floor they sit
+              // well above in practice -- raising it just costs a unit its place
+              // on the row. Losing one matters: a wrapped AMS-HT is then alone on
+              // its line, and flex-grow stretches its single slot across the whole
+              // card. The AMS-HT's own width does scale, below, because its
+              // readings sit beside the slot rather than under it.
+              const slotMinWidth = '3.5rem';
+              const filamentSlotStyle: React.CSSProperties = { minWidth: slotMinWidth };
+              // The AMS-HT holds a single spool, and its slot is the only thing
+              // on that row able to grow -- so it swallowed every spare pixel and
+              // shoved the temperature and humidity hard against the card's edge.
+              // Capping it at roughly two ordinary slots keeps the readings clear
+              // of the edge; the cap scales because the text inside the slot does.
+              const htSlotStyle: React.CSSProperties = {
+                minWidth: slotMinWidth,
+                maxWidth: scaledRem(7.25),
+              };
+              const slotGridStyle = (columns: number): React.CSSProperties => ({
+                gridTemplateColumns: `repeat(${columns}, minmax(${slotMinWidth}, 1fr))`,
+              });
               // #1762 (comment 2): while a print is running/paused, overlay a small
               // #1762 (comment 2): while a print is running/paused, overlay a small
               // "P1 / P2 / P3" pill on each slot referenced by the active print's
               // "P1 / P2 / P3" pill on each slot referenced by the active print's
               // mapping. Catches the reporter's scenario — "any X1C" queue job
               // mapping. Catches the reporter's scenario — "any X1C" queue job
@@ -4746,7 +4770,7 @@ function PrinterCard({
               const getAmsCardStyle = (slotCount: number): React.CSSProperties => {
               const getAmsCardStyle = (slotCount: number): React.CSSProperties => {
                 const boundedSlotCount = Math.max(1, slotCount);
                 const boundedSlotCount = Math.max(1, slotCount);
                 const gapCount = Math.max(0, boundedSlotCount - 1);
                 const gapCount = Math.max(0, boundedSlotCount - 1);
-                const minWidth = `calc(${boundedSlotCount} * 3.5rem + ${gapCount} * 0.25rem + 1rem)`;
+                const minWidth = `calc(${boundedSlotCount} * ${slotMinWidth} + ${gapCount} * 0.25rem + 1rem)`;
                 return {
                 return {
                   flex: `1 1 ${minWidth}`,
                   flex: `1 1 ${minWidth}`,
                   minWidth,
                   minWidth,
@@ -4914,7 +4938,7 @@ function PrinterCard({
                               </div>
                               </div>
                             )}
                             )}
                             {/* Slots grid: 4 columns - always render 4 slots */}
                             {/* Slots grid: 4 columns - always render 4 slots */}
-                            <div className="grid w-full grid-cols-[repeat(4,minmax(3.5rem,1fr))] gap-1">
+                            <div className="grid w-full gap-1" style={slotGridStyle(4)}>
                               {[0, 1, 2, 3].map((slotIdx) => {
                               {[0, 1, 2, 3].map((slotIdx) => {
                                 // Find tray data for this slot (may be undefined if data incomplete)
                                 // Find tray data for this slot (may be undefined if data incomplete)
                                 // Use array index if available, as tray.id may not always be set
                                 // Use array index if available, as tray.id may not always be set
@@ -5057,7 +5081,7 @@ function PrinterCard({
 
 
                                 // Wrapper with menu button, dropdown, and loading overlay (outside hover card)
                                 // Wrapper with menu button, dropdown, and loading overlay (outside hover card)
                                 return (
                                 return (
-                                  <div key={slotIdx} className={`relative group w-full ${filamentSlotClass}`}>
+                                  <div key={slotIdx} className="relative group w-full" style={filamentSlotStyle}>
                                     {/* Loading overlay during RFID re-read */}
                                     {/* Loading overlay during RFID re-read */}
                                     {isRefreshing && (
                                     {isRefreshing && (
                                       <div className="absolute inset-0 bg-bambu-dark-tertiary/80 rounded flex items-center justify-center z-20">
                                       <div className="absolute inset-0 bg-bambu-dark-tertiary/80 rounded flex items-center justify-center z-20">
@@ -5351,7 +5375,19 @@ function PrinterCard({
                         // like regular AMS), so they need more horizontal room than a 1-slot basis.
                         // like regular AMS), so they need more horizontal room than a 1-slot basis.
                         // Without this override, the L view squishes HT into a sliver next to the
                         // Without this override, the L view squishes HT into a sliver next to the
                         // 4-slot AMS neighbors.
                         // 4-slot AMS neighbors.
-                        const htCardStyle: React.CSSProperties = { flex: '1 1 11rem', minWidth: '11rem' };
+                        // 11rem holds one slot plus the temperature/humidity
+                        // column beside it; both grow with the body scale.
+                        const htCardWidth = scaledRem(11);
+                        const htCardStyle: React.CSSProperties = {
+                          flex: `1 1 ${htCardWidth}`,
+                          minWidth: htCardWidth,
+                          // An AMS-HT is never wider than a full AMS. Without a
+                          // ceiling, a unit that wraps onto a line of its own is
+                          // the only flex item there and grow stretches its single
+                          // slot across the entire card, leaving the readings
+                          // stranded at the far edge.
+                          maxWidth: `calc(4 * ${slotMinWidth} + 3 * 0.25rem + 1rem)`,
+                        };
                         return (
                         return (
                           <div key={ams.id} style={htCardStyle} className="min-w-0 p-2 bg-bambu-dark rounded-[10px] space-y-1">
                           <div key={ams.id} style={htCardStyle} className="min-w-0 p-2 bg-bambu-dark rounded-[10px] space-y-1">
                             {/* Row 1: Label + Nozzle + Drying */}
                             {/* Row 1: Label + Nozzle + Drying */}
@@ -5442,7 +5478,7 @@ function PrinterCard({
                             {/* Row 2: Slot (left) + Stats (right stacked) */}
                             {/* Row 2: Slot (left) + Stats (right stacked) */}
                             <div className="flex gap-1.5 max-[550px]:flex-col max-[550px]:items-start">
                             <div className="flex gap-1.5 max-[550px]:flex-col max-[550px]:items-start">
                               {/* Slot wrapper with loading overlay */}
                               {/* Slot wrapper with loading overlay */}
-                              <div className="relative group min-w-14 flex-1">
+                              <div className="relative group flex-1" style={htSlotStyle}>
                                 {/* Loading overlay during RFID re-read */}
                                 {/* Loading overlay during RFID re-read */}
                                 {isHtRefreshing && (
                                 {isHtRefreshing && (
                                   <div className="absolute inset-0 bg-bambu-dark-tertiary/80 rounded flex items-center justify-center z-20">
                                   <div className="absolute inset-0 bg-bambu-dark-tertiary/80 rounded flex items-center justify-center z-20">
@@ -5629,7 +5665,7 @@ function PrinterCard({
                           <div className="flex w-full min-h-7 items-center gap-1.5 rounded-lg bg-bambu-dark-secondary px-2 py-1">
                           <div className="flex w-full min-h-7 items-center gap-1.5 rounded-lg bg-bambu-dark-secondary px-2 py-1">
                             <span className="block min-w-0 flex-1 truncate text-[length:var(--pc-t10,10px)] text-white font-medium">{t('printers.external')}</span>
                             <span className="block min-w-0 flex-1 truncate text-[length:var(--pc-t10,10px)] text-white font-medium">{t('printers.external')}</span>
                           </div>
                           </div>
-                          <div className={`grid w-full ${status.vt_tray.length > 1 ? 'grid-cols-[repeat(2,minmax(3.5rem,1fr))]' : 'grid-cols-[minmax(3.5rem,1fr)]'} gap-1`}>
+                          <div className="grid w-full gap-1" style={slotGridStyle(status.vt_tray.length > 1 ? 2 : 1)}>
                             {[...status.vt_tray].sort((a, b) => (a.id ?? 254) - (b.id ?? 254)).map((extTray) => {
                             {[...status.vt_tray].sort((a, b) => (a.id ?? 254) - (b.id ?? 254)).map((extTray) => {
                               const extTrayId = extTray.id ?? 254;
                               const extTrayId = extTray.id ?? 254;
                               // On dual-nozzle (H2C/H2D), tray_now=254 means "external spool"
                               // On dual-nozzle (H2C/H2D), tray_now=254 means "external spool"
@@ -5721,7 +5757,7 @@ function PrinterCard({
                               );
                               );
 
 
                               return (
                               return (
-                                <div key={extTrayId} className={`relative group w-full ${filamentSlotClass}`}>
+                                <div key={extTrayId} className="relative group w-full" style={filamentSlotStyle}>
                                   {!isEmpty ? (
                                   {!isEmpty ? (
                                     <FilamentHoverCard
                                     <FilamentHoverCard
                                       data={extFilamentData}
                                       data={extFilamentData}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
static/assets/index-B3jj6-fz.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
static/assets/index-B67xFyee.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
static/assets/index-CJAv6Q5F.css


+ 2 - 2
static/index.html

@@ -26,8 +26,8 @@
 
 
     <!-- Splash screens for iOS -->
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-Dl70tNWe.js"></script>
-    <link rel="stylesheet" crossorigin href="/assets/index-CJAv6Q5F.css">
+    <script type="module" crossorigin src="/assets/index-B67xFyee.js"></script>
+    <link rel="stylesheet" crossorigin href="/assets/index-B3jj6-fz.css">
   </head>
   </head>
   <body>
   <body>
     <div id="root"></div>
     <div id="root"></div>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است