@controleonline/ui-common 1.2.97 → 1.2.98

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  {
2
- "version": "1.2.93",
3
- "rc": 1,
4
- "branch": "rc/1.2.93-rc.1",
5
- "baseMaster": "b4db94eb1ccd3bf878dc96e3d32c0249aad07402",
6
- "tasks": [77],
7
- "repositories": { "ControleOnline/ui-common": "4dfdb2d7ccb160f265115bdad3125d6ecd26bdfd" },
8
- "compositionNotes": ["Verified on Android emulator: Text width was still 0 with flexBasis auto because Yoga prioritises flex over flexGrow/flexBasis. flex:0 fixes it."],
2
+ "version": "1.2.98",
3
+ "rc": 2,
4
+ "branch": "rc/1.2.98-rc.2",
5
+ "baseMaster": "aa5ad406d201d23bb88023bc4b7a7d4f9b11fd0a",
6
+ "tasks": [88],
7
+ "repositories": { "ControleOnline/ui-common": "0c96fc6ebac3af856cfba103fa0694171f590ce1" },
8
+ "compositionNotes": ["Task 88: rodapé mostra …últimos 2 blocos quando o identificador não é IPv4. rc.2 inclui bump de versão 1.2.98 para publicação npm; supersedes rc.1."],
9
9
  "frozen": true
10
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@controleonline/ui-common",
3
- "version": "1.2.97",
3
+ "version": "1.2.98",
4
4
  "author": "ControleOnline",
5
5
  "description": "ControleOnline Common Quasar UI Component",
6
6
  "license": "MIT",
@@ -1,13 +1,10 @@
1
1
  import React, {useLayoutEffect, useMemo} from 'react';
2
2
  import {Pressable, Text, View} from 'react-native';
3
- import LegacyIcon from 'react-native-vector-icons/Feather';
4
- import HomeIcon from '@controleonline/../../src/components/HomeIcon';
3
+ import Icon from 'react-native-vector-icons/Feather';
5
4
  import {useTheme} from './DefaultProvider';
6
5
  import RuntimeInfoFooter from './RuntimeInfoFooter';
7
6
  import {resolveMenuRouteParams} from '../utils/menuNavigation';
8
7
  import createStyles from './BottomNavigationBar.styles';
9
- import softenStyles from './BottomNavigationBar.soft.styles';
10
- import {resolveHomepagePalette} from '@controleonline/../../src/styles/homepagePalette';
11
8
 
12
9
  const BottomNavigationBar = ({
13
10
  navigation,
@@ -17,10 +14,7 @@ const BottomNavigationBar = ({
17
14
  colors = {},
18
15
  testID = 'bottom-navigation',
19
16
  useModernWebChromeProps = false,
20
- appearance = 'legacy',
21
17
  }) => {
22
- const Icon = appearance === 'soft' ? HomeIcon : LegacyIcon;
23
- colors = appearance === 'soft' ? resolveHomepagePalette(colors) : colors;
24
18
  const theme = useTheme?.() || {};
25
19
  const runtimeFooter = theme?.runtimeFooter || null;
26
20
  const registerBottomNavigation =
@@ -37,14 +31,14 @@ const BottomNavigationBar = ({
37
31
 
38
32
  const styles = useMemo(
39
33
  () =>
40
- softenStyles(createStyles({
34
+ createStyles({
41
35
  activeBackground,
42
36
  dockBackground,
43
37
  dockBorder,
44
38
  dockShadow,
45
39
  activeBorder,
46
40
  useModernWebChromeProps,
47
- }), colors, appearance),
41
+ }),
48
42
  [
49
43
  activeBackground,
50
44
  activeBorder,
@@ -52,7 +46,6 @@ const BottomNavigationBar = ({
52
46
  dockBorder,
53
47
  dockShadow,
54
48
  useModernWebChromeProps,
55
- appearance,
56
49
  ],
57
50
  );
58
51
 
@@ -123,11 +116,8 @@ const BottomNavigationBar = ({
123
116
  ? [styles.host, styles.hostPointerEventsBoxNone]
124
117
  : styles.host;
125
118
  const footerProps = {
126
- appearance,
127
119
  appVersion: runtimeFooter?.appVersion,
128
- colors: appearance === 'soft'
129
- ? {...runtimeFooter?.colors, footerBackground: colors.footerBackground, footerText: colors.footerText}
130
- : runtimeFooter?.colors || {},
120
+ colors: runtimeFooter?.colors || {},
131
121
  mainCompany: runtimeFooter?.mainCompany,
132
122
  device: runtimeFooter?.device,
133
123
  useModernWebChromeProps,
@@ -12,10 +12,6 @@ const styles = StyleSheet.create({
12
12
  shell: {
13
13
  flex: 1,
14
14
  },
15
- translationPending: {
16
- visibility: 'hidden',
17
- opacity: 0,
18
- },
19
15
  content: {
20
16
  flex: 1,
21
17
  minHeight: 0,
@@ -395,18 +395,15 @@ export const DefaultProvider = ({
395
395
 
396
396
  useWebThemePalette({resolveDomainThemeColors, baseThemeColors, mainCompany, resolveThemePalette, runtimeColors, applyPaletteToRuntimeColors, applyThemeCssVariables, actions, currentCompany, isShopClientApp});
397
397
 
398
- const translationPending = requiresTranslateBootstrap && !isTranslateBootstrapReady;
398
+ if (requiresTranslateBootstrap && !isTranslateBootstrapReady) {
399
+ return <View style={providerStyles.loadingContainer} />;
400
+ }
399
401
 
400
402
  return (
401
403
  <ThemeContext.Provider value={themeContextValue}>
402
404
  <View
403
- pointerEvents={translationPending ? 'none' : 'auto'}
404
- aria-hidden={translationPending}
405
405
  style={[
406
406
  providerStyles.shell,
407
- // Keep navigation mounted while translations load. Unmounting it
408
- // resets the login route and repeatedly registers the bottom bar.
409
- translationPending && providerStyles.translationPending,
410
407
  {
411
408
  backgroundColor: colors?.background || runtimeColors.background,
412
409
  },
@@ -19,7 +19,6 @@ const {
19
19
  } = require('@controleonline/ui-common/src/react/utils/bottomNavigationToolbar');
20
20
 
21
21
  const RuntimeBottomNavigationBar = ({
22
- appearance = 'legacy',
23
22
  activeRouteName: activeRouteNameProp,
24
23
  colors: colorsOverride,
25
24
  disabled: disabledOverride,
@@ -160,7 +159,6 @@ const RuntimeBottomNavigationBar = ({
160
159
 
161
160
  return (
162
161
  <BottomNavigationBar
163
- appearance={appearance}
164
162
  activeRouteName={effectiveActiveRoute}
165
163
  colors={colors}
166
164
  disabled={isDisabled}
@@ -22,7 +22,6 @@ import {
22
22
  } from '@controleonline/ui-common/src/react/utils/runtimeFooter';
23
23
  import styles from './RuntimeInfoFooter.styles';
24
24
  import RuntimeFooterMarqueeText from './RuntimeFooterMarqueeText';
25
- import resolveHomeFooterSpacing from './RuntimeInfoFooter.home.spacing';
26
25
 
27
26
  const ROTATION_INTERVAL_MS = 4000;
28
27
  const COMPACT_BREAKPOINT = 720;
@@ -67,7 +66,6 @@ const RuntimeInfoFooter = ({
67
66
  device,
68
67
  colors,
69
68
  useModernWebChromeProps = false,
70
- appearance = 'legacy',
71
69
  }) => {
72
70
  const {width} = useWindowDimensions();
73
71
  const insets = useSafeAreaInsets();
@@ -260,7 +258,6 @@ const RuntimeInfoFooter = ({
260
258
  : inlineText
261
259
  ) || primaryText || device?.id || '';
262
260
  const backgroundColor = colors?.footerBackground;
263
- const homeSpacing = resolveHomeFooterSpacing(appearance, Platform.OS, insets.bottom);
264
261
  const borderColor = colors?.footerBorder;
265
262
  const textColor = resolveVisibleFooterTextColor(colors);
266
263
  const loadingColor = colors?.footerLink || colors?.primary || textColor;
@@ -270,9 +267,7 @@ const RuntimeInfoFooter = ({
270
267
  : styles.shell;
271
268
 
272
269
  return (
273
- <View {...shellProps} style={[shellStyle, homeSpacing && {
274
- paddingBottom: homeSpacing.safeAreaBottom, backgroundColor,
275
- }]}>
270
+ <View {...shellProps} style={shellStyle}>
276
271
  <View
277
272
  testID="runtime-info-footer"
278
273
  style={[
@@ -281,8 +276,7 @@ const RuntimeInfoFooter = ({
281
276
  {
282
277
  backgroundColor,
283
278
  borderTopColor: borderColor,
284
- paddingBottom: homeSpacing ? homeSpacing.contentPadding : bottomInset,
285
- ...(homeSpacing && !showDebugInfo ? {paddingTop: homeSpacing.contentPadding} : {}),
279
+ paddingBottom: bottomInset,
286
280
  },
287
281
  ]}>
288
282
  <View style={styles.primaryRow}>
@@ -156,7 +156,6 @@ const useDisplayUri = uri => {
156
156
 
157
157
  const UserAvatar = ({
158
158
  imageUrl,
159
- imageHeaders,
160
159
  email,
161
160
  name,
162
161
  size = 40,
@@ -216,8 +215,7 @@ const UserAvatar = ({
216
215
  <View style={containerStyle}>
217
216
  {displayUri ? (
218
217
  <Image
219
- source={imageHeaders && Platform.OS !== 'web' && displayUri === imageUrl
220
- ? {uri: displayUri, headers: imageHeaders} : {uri: displayUri}}
218
+ source={{uri: displayUri}}
221
219
  style={styles.image}
222
220
  onError={() => setSourceIndex(index => index + 1)}
223
221
  />
@@ -128,6 +128,26 @@ const formatRuntimeFooterVersion = version => {
128
128
  return normalizedVersion ? `v${normalizedVersion}` : '';
129
129
  };
130
130
 
131
+ const IPV4_PATTERN = /^(\d{1,3}\.){3}\d{1,3}$/;
132
+
133
+ // IPv4 is shown in full; other ':'-separated ids (IPv6/MAC-like) are shortened
134
+ // to an ellipsis plus the last two blocks, e.g. "…46f4:eb0b".
135
+ const formatRuntimeFooterIdentifier = value => {
136
+ const identifier = safeTrim(value);
137
+
138
+ if (!identifier || IPV4_PATTERN.test(identifier) || !identifier.includes(':')) {
139
+ return identifier;
140
+ }
141
+
142
+ const blocks = identifier.split(':').filter(Boolean);
143
+
144
+ if (blocks.length <= 2) {
145
+ return identifier;
146
+ }
147
+
148
+ return `…${blocks.slice(-2).join(':')}`;
149
+ };
150
+
131
151
  const getRuntimeFooterWebHost = () => {
132
152
  const hostname = safeTrim(globalThis?.location?.hostname);
133
153
 
@@ -364,9 +384,9 @@ const getRuntimeFooterDebugInfo = ({device, appVersion, deviceConfig}) => {
364
384
  const nativeIdentifier = nativeIdentifierCandidates[0]?.value || '';
365
385
  const runtimeDetail = operationModeLabel
366
386
  ? operationModeLabel
367
- : isWebRuntime
368
- ? webIdentifier
369
- : nativeIdentifier;
387
+ : formatRuntimeFooterIdentifier(
388
+ isWebRuntime ? webIdentifier : nativeIdentifier,
389
+ );
370
390
  const runtimeDetailSource = operationModeLabel
371
391
  ? 'device_config.configs.pos-operation-mode'
372
392
  : isWebRuntime
@@ -444,6 +464,7 @@ module.exports = {
444
464
  getRuntimeFooterStoredVersion,
445
465
  getRuntimeFooterTextLines,
446
466
  getRuntimeFooterVersionCandidates,
467
+ formatRuntimeFooterIdentifier,
447
468
  getRuntimeFooterWebIdentifierCandidates,
448
469
  getRuntimeFooterText,
449
470
  getRuntimeFooterWebHost,
@@ -2,6 +2,7 @@ const assert = require('node:assert/strict')
2
2
  const {after, before, test} = require('node:test')
3
3
 
4
4
  const {
5
+ formatRuntimeFooterIdentifier,
5
6
  getRuntimeFooterDebugInfo,
6
7
  getRuntimeFooterNativeIdentifierCandidates,
7
8
  getRuntimeFooterPrimaryText,
@@ -487,3 +488,28 @@ test('hides runtime device information on the customer paylist only', () => {
487
488
  assert.equal(shouldShowRuntimeFooter('LoginPage'), true)
488
489
  assert.equal(shouldShowRuntimeFooter('WalletsPage'), true)
489
490
  })
491
+
492
+ test('formats runtime identifier: IPv4 full, non-IPv4 shortened to last two blocks', () => {
493
+ assert.equal(formatRuntimeFooterIdentifier('179.110.95.138'), '179.110.95.138')
494
+ assert.equal(
495
+ formatRuntimeFooterIdentifier('2804:18:1119:f433:54b4:a587:46f4:eb0b'),
496
+ '…46f4:eb0b',
497
+ )
498
+ assert.equal(formatRuntimeFooterIdentifier('aa:bb:cc:dd:ee:ff'), '…ee:ff')
499
+ assert.equal(formatRuntimeFooterIdentifier('::1'), '::1')
500
+ assert.equal(formatRuntimeFooterIdentifier('abc'), 'abc')
501
+ assert.equal(formatRuntimeFooterIdentifier(''), '')
502
+ assert.equal(formatRuntimeFooterIdentifier(null), '')
503
+ })
504
+
505
+ test('primary text shortens IPv6 public ip', () => {
506
+ const text = getRuntimeFooterPrimaryText({
507
+ device: {
508
+ type: 'PDV',
509
+ systemName: 'web',
510
+ metadata: {network: {publicIp: '2804:18:1119:f433:54b4:a587:46f4:eb0b'}},
511
+ },
512
+ appVersion: '1.10.68',
513
+ })
514
+ assert.ok(text.includes('(…46f4:eb0b)'), text)
515
+ })
@@ -1,16 +0,0 @@
1
- # Homepage ADMIN/MANAGER — app-community#1056
2
-
3
- Soft appearance is opt-in for HomePage only. Existing menu routes/parameters, permissions, stores and translations are preserved. App-provided homepage colors and components are used only in this appearance. Default consumers retain their current behavior.
4
-
5
- Source: https://github.com/ControleOnline/app-community/issues/1056
6
- Local evidence: 40 homepage tests and 34 runtime footer/zoom tests passed. No production authorization.
7
-
8
- ## Web login translation bootstrap
9
-
10
- Keep the navigation tree mounted while translations initialize. Hide the shell and disable pointer/accessibility interaction until the existing translation readiness contract succeeds. Unmounting navigation during login resets its route and repeatedly mounts/registers the bottom bar, causing React maximum update depth. No route, permission, translation source, theme or zoom changes. Native behavior is unchanged.
11
-
12
- Regression evidence: app-community homepage bootstrapNavigation.test.js reproduced maximum update depth before the fix, then passed after it. 44 tests across 9 homepage suites passed. Runtime Dev reproduced the unfixed bug; new runtime verification is required after consuming ui-common 1.2.96.
13
-
14
- Release 1.2.96 uses the task-only c91510d source plus version metadata. The integration merge into dev preserves independent team work, but those changes are excluded from this homepage package. Publication uses the existing tag-triggered trusted publishing workflow.
15
-
16
- Release 1.2.97 completes the web bootstrap gate with visibility:hidden and aria-hidden: pending descendants cannot receive keyboard focus while navigation stays mounted. Native behavior remains unchanged.
@@ -1,28 +0,0 @@
1
- import {Platform} from 'react-native';
2
-
3
- // Only the homepage opts into this chrome; preserve all default navigation styles.
4
- export default (styles, colors, appearance) => appearance !== 'soft' ? styles : {
5
- ...styles,
6
- dock: [styles.dock, {
7
- paddingHorizontal: 0,
8
- paddingTop: 0,
9
- paddingBottom: 0,
10
- borderWidth: 0,
11
- borderTopWidth: 1,
12
- borderColor: colors.navigationBorder,
13
- borderTopLeftRadius: 0,
14
- borderTopRightRadius: 0,
15
- elevation: 0,
16
- shadowOpacity: 0,
17
- ...(Platform.OS === 'web' ? {boxShadow: 'none'} : {}),
18
- }],
19
- itemsRow: [styles.itemsRow, {minHeight: 64, paddingHorizontal: 12, paddingVertical: 5}],
20
- item: [styles.item, {minHeight: 54, borderRadius: 12}],
21
- itemLabel: [styles.itemLabel, {fontSize: 11, fontWeight: '400'}],
22
- footerSlot: [styles.footerSlot, {
23
- borderTopWidth: 1,
24
- borderColor: colors.navigationBorder,
25
- paddingHorizontal: 0,
26
- minHeight: 28,
27
- }],
28
- };
@@ -1,5 +0,0 @@
1
- // Keep the native safe area outside the centered content row.
2
- export default (appearance, platform, bottomInset) => appearance === 'soft' ? {
3
- contentPadding: 4,
4
- safeAreaBottom: platform === 'web' ? 0 : Math.max(Number(bottomInset) || 0, 0),
5
- } : null;