diff --git a/.easignore b/.easignore deleted file mode 100644 index 4709527..0000000 --- a/.easignore +++ /dev/null @@ -1,41 +0,0 @@ -# Applied when EAS bundles the workspace root for an iOS build of apps/mobile -# (see apps/flux/core/src/services/interactive-terminal/create-shell.ts). -# Keep yarn-workspace context (root package.json, yarn.lock, .yarnrc.yml, -# .yarn/patches/) and apps/mobile/ — exclude everything else so EAS uploads -# stay small. - -node_modules/ -**/node_modules/ -.yarn/cache/ -.yarn/install-state.gz -.yarn/unplugged/ - -apps/web/ - -config/ -shared/ -# Re-include the metro polyfills directory: `shared/` above is unanchored and -# would otherwise match `apps/mobile/polyfills/shared/`, which holds the -# expo-image and empty-component shims that metro.config.js redirects to via -# SHARED_ALIASES. Without these files in the EAS upload, EAGER_BUNDLE fails -# with `Unable to resolve module expo-image` on every file that imports it. -!apps/mobile/polyfills/shared/ -examples/ -playwright-report/ -test-results/ -caches/ - -Dockerfile -docker-compose.test.yml -README.md -.dockerignore -.eslintignore -.gitignore -.oxfmtrc.json -.oxlintrc.json - -*.log -*.tgz -.env -.env.* -.DS_Store diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 72e8ffc..0000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/.yarn/patches/@expo+cli+54.0.1.patch b/.yarn/patches/@expo+cli+54.0.1.patch deleted file mode 100644 index debae97..0000000 --- a/.yarn/patches/@expo+cli+54.0.1.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js b/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js -index b5cba1b..2cbb2a5 100644 ---- a/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js -+++ b/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js -@@ -143,7 +143,9 @@ class ExpoGoManifestHandlerMiddleware extends _ManifestMiddleware.ManifestMiddle - codeSigningInfo - }); - const expoUpdatesManifest = { -- id: _crypto().default.randomUUID(), -+ id: _crypto().default.randomUUID({ -+ disableEntropyCache: true -+ }), - createdAt: new Date().toISOString(), - runtimeVersion, - launchAsset: { diff --git a/.yarn/patches/@expo+metro-runtime+6.1.2.patch b/.yarn/patches/@expo+metro-runtime+6.1.2.patch deleted file mode 100644 index 4ac6b52..0000000 --- a/.yarn/patches/@expo+metro-runtime+6.1.2.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/src/error-overlay/ErrorOverlay.tsx b/src/error-overlay/ErrorOverlay.tsx -index 983dc52..bbe737c 100644 ---- a/src/error-overlay/ErrorOverlay.tsx -+++ b/src/error-overlay/ErrorOverlay.tsx -@@ -30,6 +30,7 @@ const HEADER_TITLE_MAP = { - export function LogBoxInspectorContainer() { - const { selectedLogIndex, logs } = useLogs(); - const log = logs[selectedLogIndex]; -+ return null; - if (log == null) { - return null; - } -diff --git a/src/error-overlay/toast/ErrorToast.tsx b/src/error-overlay/toast/ErrorToast.tsx -index 87a0c8b..c044c8f 100644 ---- a/src/error-overlay/toast/ErrorToast.tsx -+++ b/src/error-overlay/toast/ErrorToast.tsx -@@ -34,6 +34,7 @@ export function ErrorToast(props: Props) { - - useSymbolicatedLog(log); - -+ return null; - return ( - - diff --git a/.yarn/patches/@react-native-community+netinfo+11.4.1.patch b/.yarn/patches/@react-native-community+netinfo+11.4.1.patch deleted file mode 100644 index adc2d8a..0000000 --- a/.yarn/patches/@react-native-community+netinfo+11.4.1.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff --git a/src/internal/nativeInterface.ts b/src/internal/nativeInterface.ts -index 8b514f4..9135364 100644 ---- a/src/internal/nativeInterface.ts -+++ b/src/internal/nativeInterface.ts -@@ -7,28 +7,15 @@ - * @format - */ - --import {NativeEventEmitter} from 'react-native'; -+import { NativeEventEmitter } from 'react-native'; - import RNCNetInfo from './nativeModule'; - --// Produce an error if we don't have the native module --if (!RNCNetInfo) { -- throw new Error(`@react-native-community/netinfo: NativeModule.RNCNetInfo is null. To fix this issue try these steps: -- --• Run \`react-native link @react-native-community/netinfo\` in the project root. --• Rebuild and re-run the app. --• If you are using CocoaPods on iOS, run \`pod install\` in the \`ios\` directory and then rebuild and re-run the app. You may also need to re-open Xcode to get the new pods. --• Check that the library was linked correctly when you used the link command by running through the manual installation instructions in the README. --* If you are getting this error while unit testing you need to mock the native module. Follow the guide in the README. -- --If none of these fix the issue, please open an issue on the Github repository: https://github.com/react-native-community/react-native-netinfo`); --} -- - /** - * We export the native interface in this way to give easy shared access to it between the - * JavaScript code and the tests - */ - let nativeEventEmitter: NativeEventEmitter | null = null; --const nativeInterface = Object.assign(RNCNetInfo, { -+const nativeInterface = RNCNetInfo ? Object.assign(RNCNetInfo, { - get eventEmitter(): NativeEventEmitter { - if (!nativeEventEmitter) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment -@@ -39,5 +26,5 @@ const nativeInterface = Object.assign(RNCNetInfo, { - /// @ts-ignore - return nativeEventEmitter; - }, --}); -+}) : {}; - export default nativeInterface; diff --git a/.yarn/patches/expo-router+6.0.11.patch b/.yarn/patches/expo-router+6.0.11.patch deleted file mode 100644 index 1da7e25..0000000 --- a/.yarn/patches/expo-router+6.0.11.patch +++ /dev/null @@ -1,506 +0,0 @@ -diff --git a/assets/native-tabs.module.css b/assets/native-tabs.module.css -index f29cec5..0d71dad 100644 ---- a/assets/native-tabs.module.css -+++ b/assets/native-tabs.module.css -@@ -22,22 +22,27 @@ - } - - .navigationMenuRoot { -- top: 24px; -+ bottom: 24px; - left: 50%; - transform: translateX(-50%); - position: fixed; - z-index: 10; - display: flex; -- background-color: var(--expo-router-tabs-background-color, #272727); -- height: 40px; -- border-radius: 25px; -+ background-color: var(--expo-router-tabs-background-color, rgba(30, 30, 30, 0.88)); -+ backdrop-filter: blur(20px); -+ -webkit-backdrop-filter: blur(20px); -+ height: 56px; -+ border-radius: 28px; - align-items: center; -- justify-content: flex-start; -- padding: 5px; -+ justify-content: center; -+ padding: 4px; - box-sizing: border-box; - margin: 0; -- max-width: 90vw; -- overflow-x: auto; -+ max-width: 95vw; -+ overflow: hidden; -+ border: 1px solid rgba(255, 255, 255, 0.12); -+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.08); -+ gap: 2px; - } - - .navigationMenuTrigger { -@@ -48,36 +53,64 @@ - height: 100%; - background-color: transparent; - border: none; -- margin: 0; -- height: 100%; -- border-radius: 20px; -- padding: 0 20px; -+ border-radius: 24px; -+ padding: 6px 16px; -+ transition: background-color 0.2s ease, backdrop-filter 0.2s ease; - cursor: pointer; -- outline-color: var(--expo-router-tabs-tab-outline-color, #444444); -+ outline-color: var(--expo-router-tabs-tab-outline-color, rgba(255, 255, 255, 0.2)); - position: relative; -+ display: flex; -+ flex-direction: column; -+ align-items: center; -+ justify-content: center; -+ gap: 2px; -+} -+ -+.tabIcon { -+ display: flex; -+ align-items: center; -+ justify-content: center; -+ color: var(--expo-router-tabs-icon-color, rgba(255, 255, 255, 0.6)); -+ font-size: 18px; -+ width: 20px; -+ height: 20px; -+} -+ -+.tabIcon > * { -+ color: inherit; -+} -+ -+.navigationMenuTrigger[data-state="active"] .tabIcon { -+ color: var(--expo-router-tabs-active-icon-color, #ffffff); - } - - .navigationMenuTrigger[data-state="active"] { -- background-color: var(--expo-router-tabs-active-background-color, #444444); -+ background-color: var(--expo-router-tabs-active-background-color, rgba(255, 255, 255, 0.15)); -+ backdrop-filter: blur(10px); -+ -webkit-backdrop-filter: blur(10px); -+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); - } - - .tabText { - font-weight: var(--expo-router-tabs-font-weight, 500); -- font-size: var(--expo-router-tabs-font-size, 15px); -+ font-size: var(--expo-router-tabs-font-size, 11px); - font-family: var(--expo-router-tabs-font-family); - font-style: var(--expo-router-tabs-font-style, normal); - opacity: var(--expo-router-tabs-text-opacity, 1); -- color: var(--expo-router-tabs-text-color, #8b8b8b); -+ color: var(--expo-router-tabs-text-color, rgba(255, 255, 255, 0.6)); - white-space: nowrap; - } - - .navigationMenuTrigger[data-state="active"] .tabText { - color: var(--expo-router-tabs-active-text-color, #ffffff); -- font-size: var(--expo-router-tabs-active-font-size, var(--expo-router-tabs-font-size, 15px)); -+} -+ -+.navigationMenuTrigger:not([data-state="active"]):hover { -+ background-color: rgba(255, 255, 255, 0.08); - } - - .navigationMenuTrigger:not([data-state="active"]) .tabText:hover { -- opacity: var(--expo-router-tabs-text-hover-opacity, 0.6); -+ opacity: var(--expo-router-tabs-text-hover-opacity, 0.9); - } - - .tabBadge { -@@ -107,3 +140,101 @@ - min-height: var(--expo-router-tabs-local-badge-size); - border-radius: calc(var(--expo-router-tabs-local-badge-size) / 2); - } -+ -+/* More screen styles - Apple Settings inspired */ -+.moreScreen { -+ flex: 1; -+ display: flex; -+ flex-direction: column; -+ background-color: #000000; -+ max-height: 100%; -+ max-width: 100%; -+ overflow-y: auto; -+ padding-bottom: 120px; -+} -+ -+.moreScreenHeader { -+ padding: 60px 20px 8px; -+} -+ -+.moreScreenTitle { -+ font-family: var(--expo-router-tabs-font-family); -+ font-size: 34px; -+ font-weight: 700; -+ color: #ffffff; -+ margin: 0; -+ letter-spacing: 0.37px; -+} -+ -+.moreScreenContent { -+ display: flex; -+ flex-direction: column; -+ padding: 20px 20px 0; -+} -+ -+.moreScreenGroup { -+ background-color: #1c1c1e; -+ border-radius: 10px; -+ overflow: hidden; -+} -+ -+.moreScreenItem { -+ display: flex; -+ align-items: center; -+ gap: 12px; -+ padding: 8px 16px 8px 12px; -+ min-height: 44px; -+ border: none; -+ background-color: transparent; -+ cursor: pointer; -+ font-family: var(--expo-router-tabs-font-family); -+ text-align: left; -+ transition: background-color 0.1s ease; -+ position: relative; -+ width: 100%; -+ box-sizing: border-box; -+} -+ -+.moreScreenItem:hover { -+ background-color: rgba(255, 255, 255, 0.08); -+} -+ -+.moreScreenItem:active { -+ background-color: rgba(255, 255, 255, 0.12); -+} -+ -+/* Separator line between items */ -+.moreScreenItem:not(:last-child)::after { -+ content: ''; -+ position: absolute; -+ bottom: 0; -+ left: 54px; -+ right: 0; -+ height: 0.5px; -+ background-color: rgba(84, 84, 88, 0.65); -+} -+ -+.moreScreenItemIcon { -+ display: flex; -+ align-items: center; -+ justify-content: center; -+ width: 30px; -+ height: 30px; -+ border-radius: 6px; -+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.17) 0%, rgba(255, 255, 255, 0) 100%), #636366; -+ color: #ffffff; -+ flex-shrink: 0; -+} -+ -+.moreScreenItemLabel { -+ flex: 1; -+ font-size: 17px; -+ font-weight: 400; -+ color: #ffffff; -+ letter-spacing: -0.41px; -+} -+ -+.moreScreenItemChevron { -+ color: rgba(235, 235, 245, 0.3); -+ flex-shrink: 0; -+} -diff --git a/build/getLinkingConfig.js b/build/getLinkingConfig.js -index 2a0ee73..302afc0 100644 ---- a/build/getLinkingConfig.js -+++ b/build/getLinkingConfig.js -@@ -8,6 +8,7 @@ const constants_1 = require("./constants"); - const getReactNavigationConfig_1 = require("./getReactNavigationConfig"); - const getRoutesRedirects_1 = require("./getRoutesRedirects"); - const linking_1 = require("./link/linking"); -+const isAnythingApp = expo_modules_core_1.Platform.OS === 'ios' && !globalThis.expo?.modules?.ExpoGo; - function getNavigationConfig(routes, metaOnly, { sitemap, notFound }) { - const config = (0, getReactNavigationConfig_1.getReactNavigationConfig)(routes, metaOnly); - const sitemapRoute = (() => { -@@ -61,7 +62,10 @@ function getLinkingConfig(routes, context, getRouteInfo, { metaOnly = true, serv - // Expo Router calls `getInitialURL` twice, which may confuse the user if they provide a custom `getInitialURL`. - // Therefor we memoize the result. - if (!hasCachedInitialUrl) { -- if (expo_modules_core_1.Platform.OS === 'web') { -+ if (isAnythingApp) { -+ initialUrl = '/'; -+ } -+ else if (expo_modules_core_1.Platform.OS === 'web') { - initialUrl = serverUrl ?? (0, linking_1.getInitialURL)(); - } - else { -diff --git a/build/link/linking.js b/build/link/linking.js -index b9535b5..ec99c96 100644 ---- a/build/link/linking.js -+++ b/build/link/linking.js -@@ -47,6 +47,7 @@ Object.defineProperty(exports, "getStateFromPath", { enumerable: true, get: func - const useLinking_1 = require("../fork/useLinking"); - const getRoutesRedirects_1 = require("../getRoutesRedirects"); - const isExpoGo = typeof expo !== 'undefined' && globalThis.expo?.modules?.ExpoGo; -+const isAnythingApp = react_native_1.Platform.OS === 'ios' && !globalThis.expo?.modules?.ExpoGo; - // A custom getInitialURL is used on native to ensure the app always starts at - // the root path if it's launched from something other than a deep link. - // This helps keep the native functionality working like the web functionality. -@@ -124,7 +125,12 @@ function subscribe(nativeLinking, redirects) { - } - }; - } -- const subscription = Linking.addEventListener('url', callback); -+ let subscription; -+ -+ if (!isAnythingApp) { -+ subscription = Linking.addEventListener('url', callback); -+ } -+ - return () => { - // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7 - subscription?.remove?.(); -diff --git a/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js b/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js -index cd3d597..8bc0b00 100644 ---- a/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js -+++ b/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js -@@ -129,6 +129,16 @@ function appendLabelOptions(options, props) { - else { - options.title = props.children; - options.selectedLabelStyle = props.selectedStyle; -+ // Extract label color for web -+ if (props.style?.color) { -+ options.webLabelColor = props.style.color; -+ } -+ if (props.color) { -+ options.webLabelColor = props.color; -+ } -+ if (props.selectedStyle?.color) { -+ options.webLabelSelectedColor = props.selectedStyle.color; -+ } - } - } - function appendIconOptions(options, props) { -@@ -136,6 +146,21 @@ function appendIconOptions(options, props) { - const icon = convertIconSrcToIconOption(props); - options.icon = icon?.icon; - options.selectedIcon = icon?.selectedIcon; -+ // Preserve icon info for web rendering -+ const srcValue = typeof props.src === 'object' && 'selected' in props.src ? props.src.default : props.src; -+ if ((0, react_1.isValidElement)(srcValue) && srcValue.type === elements_1.VectorIcon) { -+ options.webIconFamily = srcValue.props.family; -+ options.webIconName = srcValue.props.name; -+ // Extract colors from VectorIcon props for web -+ if (srcValue.props.color) { -+ options.webIconColor = srcValue.props.color; -+ } -+ if (srcValue.props.selectedColor) { -+ options.webIconSelectedColor = srcValue.props.selectedColor; -+ } -+ } else { -+ options.webIcon = srcValue; -+ } - } - else if ('sf' in props && process.env.EXPO_OS === 'ios') { - if (typeof props.sf === 'string') { -@@ -169,6 +194,13 @@ function appendIconOptions(options, props) { - options.selectedIcon = undefined; - } - options.selectedIconColor = props.selectedColor; -+ // Extract icon color for web -+ if (props.color) { -+ options.webIconColor = props.color; -+ } -+ if (props.selectedColor) { -+ options.webIconSelectedColor = props.selectedColor; -+ } - } - function convertIconSrcToIconOption(icon) { - if (icon && icon.src) { -diff --git a/build/native-tabs/NativeBottomTabs/NativeTabsView.web.js b/build/native-tabs/NativeBottomTabs/NativeTabsView.web.js -index d3d738b..a27f83d 100644 ---- a/build/native-tabs/NativeBottomTabs/NativeTabsView.web.js -+++ b/build/native-tabs/NativeBottomTabs/NativeTabsView.web.js -@@ -41,16 +41,45 @@ const react_tabs_1 = require("@radix-ui/react-tabs"); - const react_1 = __importStar(require("react")); - const utils_1 = require("./utils"); - const native_tabs_module_css_1 = __importDefault(require("../../../assets/native-tabs.module.css")); -+ -+const MAX_VISIBLE_TABS = 5; -+ - function NativeTabsView(props) { - const { builder, focusedIndex } = props; - const { state, descriptors, navigation } = builder; - const { routes } = state; -+ const [showMoreScreen, setShowMoreScreen] = (0, react_1.useState)(false); - const defaultTabName = (0, react_1.useMemo)(() => state.routes[focusedIndex]?.name ?? state.routes[0].name, []); - const value = state.routes[focusedIndex]?.name ?? state.routes[0].name; - const currentTabKey = state.routes[focusedIndex]?.key ?? state.routes[0].key; -- const items = routes -- .filter(({ key }) => (0, utils_1.shouldTabBeVisible)(descriptors[key].options)) -- .map((route) => ()); -+ -+ const visibleRoutes = routes.filter(({ key }) => (0, utils_1.shouldTabBeVisible)(descriptors[key].options)); -+ const hasOverflow = visibleRoutes.length > MAX_VISIBLE_TABS; -+ const primaryRoutes = hasOverflow ? visibleRoutes.slice(0, MAX_VISIBLE_TABS - 1) : visibleRoutes; -+ const overflowRoutes = hasOverflow ? visibleRoutes.slice(MAX_VISIBLE_TABS - 1) : []; -+ -+ // Check if an overflow tab is currently active -+ const isOverflowTabActive = overflowRoutes.some(route => route.name === value); -+ -+ const items = primaryRoutes.map((route) => ( -+ setShowMoreScreen(false)} -+ forceInactive={showMoreScreen} -+ isActive={route.name === value && !showMoreScreen} -+ /> -+ )); -+ - const children = routes - .filter(({ key }) => (0, utils_1.shouldTabBeVisible)(descriptors[key].options)) - .map((route) => { -@@ -58,26 +87,116 @@ function NativeTabsView(props) { - {descriptors[route.key].render()} - ); - }); -- return ( { -- navigation.dispatch({ -- type: 'JUMP_TO', -- target: state.key, -- payload: { -- name: value, -- }, -- }); -+ -+ const handleNavigate = (routeName) => { -+ navigation.dispatch({ -+ type: 'JUMP_TO', -+ target: state.key, -+ payload: { -+ name: routeName, -+ }, -+ }); -+ setShowMoreScreen(false); -+ }; -+ -+ return ( { -+ handleNavigate(newValue); - }} style={convertNativeTabsPropsToStyleVars(props, descriptors[currentTabKey]?.options)}> -+ -+ {/* More Screen - shown when More tab is active */} -+ {showMoreScreen && ( -+
-+
-+

More

-+
-+
-+
-+ {overflowRoutes.map((route) => ( -+ -+ ))} -+
-+
-+
-+ )} -+ -+ {/* Tab Content - hidden when More screen is shown */} -+ {!showMoreScreen && children} -+ - - {items} -+ {hasOverflow && ( -+ -+ )} - -- {children} -
); - } -+ -+function OverflowTabIcon(props) { -+ const { webIcon, webIconFamily, webIconName } = props; -+ if (webIconFamily && webIconName) { -+ const IconComponent = webIconFamily; -+ return ; -+ } else if (webIcon) { -+ return webIcon; -+ } -+ return null; -+} -+ - function TabItem(props) { -- const { title, badgeValue, route } = props; -+ const { title, badgeValue, route, webIcon, webIconFamily, webIconName, webIconColor, webIconSelectedColor, webLabelColor, webLabelSelectedColor, onClick, forceInactive, isActive } = props; - const isBadgeEmpty = badgeValue === ' '; -- return ( -- {title} -+ const dataState = forceInactive ? "inactive" : (isActive ? "active" : "inactive"); -+ -+ // Resolve colors based on active state -+ const resolvedIconColor = isActive && webIconSelectedColor ? webIconSelectedColor : webIconColor; -+ const resolvedLabelColor = isActive && webLabelSelectedColor ? webLabelSelectedColor : webLabelColor; -+ -+ const iconStyle = resolvedIconColor ? { color: resolvedIconColor } : {}; -+ const labelStyle = resolvedLabelColor ? { color: resolvedLabelColor } : {}; -+ -+ let iconElement = null; -+ if (webIconFamily && webIconName) { -+ const IconComponent = webIconFamily; -+ iconElement = (); -+ } else if (webIcon) { -+ iconElement = ({webIcon}); -+ } -+ return ( -+ {iconElement} -+ {title} - {badgeValue && (
- {badgeValue} -
)} diff --git a/.yarn/patches/expo-store-review+9.0.8.patch b/.yarn/patches/expo-store-review+9.0.8.patch deleted file mode 100644 index c7fa56e..0000000 --- a/.yarn/patches/expo-store-review+9.0.8.patch +++ /dev/null @@ -1,375 +0,0 @@ -diff --git a/build/ExpoStoreReview.d.ts b/build/ExpoStoreReview.d.ts -index 00e8119..ed3992e 100644 ---- a/build/ExpoStoreReview.d.ts -+++ b/build/ExpoStoreReview.d.ts -@@ -1,6 +1,9 @@ - declare const _default: Partial<{ - isAvailableAsync: () => Promise; - requestReview: () => Promise; -+ prePromptReview: () => Promise; -+ resetReviewState: () => Promise; -+ hasUserRated: () => Promise; - }>; - export default _default; - //# sourceMappingURL=ExpoStoreReview.d.ts.map -\ No newline at end of file -diff --git a/build/ExpoStoreReview.d.ts.map b/build/ExpoStoreReview.d.ts.map -index aec682b..0a49993 100644 ---- a/build/ExpoStoreReview.d.ts.map -+++ b/build/ExpoStoreReview.d.ts.map -@@ -1 +1 @@ --{"version":3,"file":"ExpoStoreReview.d.ts","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"wBACqB,OAAO,CAAC;IAC3B,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC,CAAC;AAHF,wBAGG"} -\ No newline at end of file -+{"version":3,"file":"ExpoStoreReview.d.ts","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"wBACqB,OAAO,CAAC;IAC3B,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,YAAY,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACtC,CAAC;AANF,wBAMG"} -\ No newline at end of file -diff --git a/build/ExpoStoreReview.d.ts.map.orig b/build/ExpoStoreReview.d.ts.map.orig -new file mode 100644 -index 0000000..4e06d74 ---- /dev/null -+++ b/build/ExpoStoreReview.d.ts.map.orig -@@ -0,0 +1 @@ -+{"version":3,"file":"ExpoStoreReview.d.ts","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"wBACqB,OAAO,CAAC;IAC3B,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,CAAC;AALF,wBAKG"} -\ No newline at end of file -diff --git a/build/ExpoStoreReview.d.ts.map.rej b/build/ExpoStoreReview.d.ts.map.rej -new file mode 100644 -index 0000000..93ac91c ---- /dev/null -+++ b/build/ExpoStoreReview.d.ts.map.rej -@@ -0,0 +1,5 @@ -+@@ -1,1 +1,1 @@ -+-{"version":3,"file":"ExpoStoreReview.d.ts","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"wBACqB,OAAO,CAAC;IAC3B,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC,CAAC;AAHF,wBAGG"} -+\ No newline at end of line -++{"version":3,"file":"ExpoStoreReview.d.ts","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"wBACqB,OAAO,CAAC;IAC3B,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,YAAY,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACtC,CAAC;AANF,wBAMG"} -+\ No newline at end of line -diff --git a/build/ExpoStoreReview.js.map b/build/ExpoStoreReview.js.map -index 80fdadb..7fdbdfa 100644 ---- a/build/ExpoStoreReview.js.map -+++ b/build/ExpoStoreReview.js.map -@@ -1 +1 @@ --{"version":3,"file":"ExpoStoreReview.js","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,eAAe,EAGb,CAAC","sourcesContent":["// Unimplemented on web\nexport default {} as Partial<{\n isAvailableAsync: () => Promise;\n requestReview: () => Promise;\n}>;\n"]} -\ No newline at end of file -+{"version":3,"file":"ExpoStoreReview.js","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,eAAe,EAMb,CAAC","sourcesContent":["// Unimplemented on web\nexport default {} as Partial<{\n isAvailableAsync: () => Promise;\n requestReview: () => Promise;\n prePromptReview: () => Promise;\n resetReviewState: () => Promise;\n hasUserRated: () => Promise;\n}>;\n"]} -\ No newline at end of file -diff --git a/build/ExpoStoreReview.js.map.orig b/build/ExpoStoreReview.js.map.orig -new file mode 100644 -index 0000000..867130c ---- /dev/null -+++ b/build/ExpoStoreReview.js.map.orig -@@ -0,0 +1 @@ -+{"version":3,"file":"ExpoStoreReview.js","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,eAAe,EAKb,CAAC","sourcesContent":["// Unimplemented on web\nexport default {} as Partial<{\n isAvailableAsync: () => Promise;\n requestReview: () => Promise;\n prePromptReview: () => Promise;\n resetReviewState: () => Promise;\n}>;\n"]} -\ No newline at end of file -diff --git a/build/ExpoStoreReview.js.map.rej b/build/ExpoStoreReview.js.map.rej -new file mode 100644 -index 0000000..8a0b07d ---- /dev/null -+++ b/build/ExpoStoreReview.js.map.rej -@@ -0,0 +1,5 @@ -+@@ -1,1 +1,1 @@ -+-{"version":3,"file":"ExpoStoreReview.js","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,eAAe,EAGb,CAAC","sourcesContent":["// Unimplemented on web\nexport default {} as Partial<{\n isAvailableAsync: () => Promise;\n requestReview: () => Promise;\n}>;\n"]} -+\ No newline at end of line -++{"version":3,"file":"ExpoStoreReview.js","sourceRoot":"","sources":["../src/ExpoStoreReview.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,eAAe,EAMb,CAAC","sourcesContent":["// Unimplemented on web\nexport default {} as Partial<{\n isAvailableAsync: () => Promise;\n requestReview: () => Promise;\n prePromptReview: () => Promise;\n resetReviewState: () => Promise;\n hasUserRated: () => Promise;\n}>;\n"]} -+\ No newline at end of line -diff --git a/build/ExpoStoreReview.native.js b/build/ExpoStoreReview.native.js -index 39755d3..a110bfe 100644 ---- a/build/ExpoStoreReview.native.js -+++ b/build/ExpoStoreReview.native.js -@@ -1,3 +1,4 @@ - import { requireNativeModule } from 'expo-modules-core'; --export default requireNativeModule('ExpoStoreReview'); -+ -+export default globalThis && globalThis.expo && globalThis.expo.modules && globalThis.expo.modules.ExpoStoreReview ? requireNativeModule('ExpoStoreReview') : {}; - //# sourceMappingURL=ExpoStoreReview.native.js.map -diff --git a/build/StoreReview.d.ts b/build/StoreReview.d.ts -index 00cf30a..0f91d73 100644 ---- a/build/StoreReview.d.ts -+++ b/build/StoreReview.d.ts -@@ -7,6 +7,25 @@ - * - On Web, it will resolve to `false`. - */ - export declare function isAvailableAsync(): Promise; -+/** -+ * Shows a pre-prompt alert asking the user if they'd like to rate the app. If they select "Yes", -+ * it will then show the native store review prompt. This is useful for improving review conversion rates. -+ * Currently only available on iOS. -+ */ -+export declare function prePromptReview(): Promise; -+/** -+ * Resets the review state stored in UserDefaults. This allows you to clear the -+ * tracking of whether the user has already been prompted for a review. -+ * Currently only available on iOS. -+ */ -+export declare function resetReviewState(): Promise; -+/** -+ * Checks whether the user has already rated the app (i.e., they selected "Rate Now" -+ * in the pre-prompt dialog). This can be used to conditionally show or hide rating prompts. -+ * Currently only available on iOS. -+ * @return A promise that resolves to true if the user has rated, false otherwise. -+ */ -+export declare function hasUserRated(): Promise; - /** - * In ideal circumstances this will open a native modal and allow the user to select a star rating - * that will then be applied to the App Store, without leaving the app. If the device is running -diff --git a/build/StoreReview.d.ts.map b/build/StoreReview.d.ts.map -index 4ce88d2..6f7f508 100644 ---- a/build/StoreReview.d.ts.map -+++ b/build/StoreReview.d.ts.map -@@ -1 +1 @@ --{"version":3,"file":"StoreReview.d.ts","sourceRoot":"","sources":["../src/StoreReview.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAEzD;AAGD;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBnD;AAGD;;;;;GAKG;AACH,wBAAgB,QAAQ,IAAI,MAAM,GAAG,IAAI,CAQxC;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAElD"} -\ No newline at end of file -+{"version":3,"file":"StoreReview.d.ts","sourceRoot":"","sources":["../src/StoreReview.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAEzD;AAGD;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAMrD;AAGD;;;;GAIG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD;AAGD;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAOrD;AAGD;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBnD;AAGD;;;;;GAKG;AACH,wBAAgB,QAAQ,IAAI,MAAM,GAAG,IAAI,CAQxC;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAElD"} -\ No newline at end of file -diff --git a/build/StoreReview.js b/build/StoreReview.js -index 5ddf98b..232423f 100644 ---- a/build/StoreReview.js -+++ b/build/StoreReview.js -@@ -15,6 +15,47 @@ export async function isAvailableAsync() { - return StoreReview.isAvailableAsync?.() ?? false; - } - // @needsAudit -+/** -+ * Shows a pre-prompt alert asking the user if they'd like to rate the app. If they select "Yes", -+ * it will then show the native store review prompt. This is useful for improving review conversion rates. -+ * Currently only available on iOS. -+ */ -+export async function prePromptReview() { -+ if (StoreReview?.prePromptReview) { -+ return StoreReview.prePromptReview(); -+ } -+ // Fallback: if prePromptReview is not available, just do nothing -+ // (This will be the case on web and Android) -+} -+// @needsAudit -+/** -+ * Resets the review state by clearing the last review request timestamp and rating status. -+ * This is useful for testing or if you want to allow the review prompt to be shown again -+ * regardless of the normal rate limiting. Currently only available on iOS. -+ */ -+export async function resetReviewState() { -+ if (StoreReview?.resetReviewState) { -+ return StoreReview.resetReviewState(); -+ } -+ // Fallback: if resetReviewState is not available, just do nothing -+ // (This will be the case on web and Android) -+} -+// @needsAudit -+/** -+ * Checks whether the user has already rated the app (i.e., they selected "Rate Now" -+ * in the pre-prompt dialog). This can be used to conditionally show or hide rating prompts. -+ * Currently only available on iOS. -+ * @return A promise that resolves to true if the user has rated, false otherwise. -+ */ -+export async function hasUserRated() { -+ if (StoreReview?.hasUserRated) { -+ return StoreReview.hasUserRated(); -+ } -+ // Fallback: if hasUserRated is not available, return false -+ // (This will be the case on web and Android) -+ return false; -+} -+// @needsAudit - /** - * In ideal circumstances this will open a native modal and allow the user to select a star rating - * that will then be applied to the App Store, without leaving the app. If the device is running -diff --git a/build/StoreReview.js.map b/build/StoreReview.js.map -index cd16b26..56882e2 100644 ---- a/build/StoreReview.js.map -+++ b/build/StoreReview.js.map -@@ -1 +1 @@ --{"version":3,"file":"StoreReview.js","sourceRoot":"","sources":["../src/StoreReview.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAE5C,cAAc;AACd;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,OAAO,WAAW,CAAC,gBAAgB,EAAE,EAAE,IAAI,KAAK,CAAC;AACnD,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,WAAW,EAAE,aAAa,EAAE,CAAC;QAC/B,OAAO,WAAW,CAAC,aAAa,EAAE,CAAC;IACrC,CAAC;IACD,6GAA6G;IAC7G,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,qDAAqD,EAAE,GAAG,CAAC,CAAC;QAC3E,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,iDAAiD;QACjD,OAAO,CAAC,IAAI,CACV,+JAA+J,CAChK,CAAC;IACJ,CAAC;AACH,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC;IACxC,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,UAAU,EAAE,GAAG,EAAE,CAAC;QAC7C,OAAO,UAAU,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC;IAC5C,CAAC;SAAM,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,UAAU,EAAE,OAAO,EAAE,CAAC;QAC5D,OAAO,UAAU,CAAC,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,OAAO,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,gBAAgB,EAAE,CAAC,CAAC;AACpD,CAAC","sourcesContent":["import Constants from 'expo-constants';\nimport { Platform } from 'expo-modules-core';\nimport { Linking } from 'react-native';\n\nimport StoreReview from './ExpoStoreReview';\n\n// @needsAudit\n/**\n * Determines if the platform has the capabilities to use `StoreReview.requestReview()`.\n * @return\n * This returns a promise fulfills with `boolean`, depending on the platform:\n * - On iOS, it will resolve to `true` unless the app is distributed through TestFlight.\n * - On Android, it will resolve to `true` if the device is running Android 5.0+.\n * - On Web, it will resolve to `false`.\n */\nexport async function isAvailableAsync(): Promise {\n return StoreReview.isAvailableAsync?.() ?? false;\n}\n\n// @needsAudit\n/**\n * In ideal circumstances this will open a native modal and allow the user to select a star rating\n * that will then be applied to the App Store, without leaving the app. If the device is running\n * a version of Android lower than 5.0, this will attempt to get the store URL and link the user to it.\n */\nexport async function requestReview(): Promise {\n if (StoreReview?.requestReview) {\n return StoreReview.requestReview();\n }\n // If StoreReview is unavailable then get the store URL from `app.config.js` or `app.json` and open the store\n const url = storeUrl();\n if (url) {\n const supported = await Linking.canOpenURL(url);\n if (!supported) {\n console.warn(\"StoreReview.requestReview(): Can't open store url: \", url);\n } else {\n await Linking.openURL(url);\n }\n } else {\n // If the store URL is missing, let the dev know.\n console.warn(\n \"StoreReview.requestReview(): Couldn't link to store, please make sure the `android.playStoreUrl` & `ios.appStoreUrl` fields are filled out in your `app.json`\"\n );\n }\n}\n\n// @needsAudit\n/**\n * This uses the `Constants` API to get the `Constants.expoConfig.ios.appStoreUrl` on iOS, or the\n * `Constants.expoConfig.android.playStoreUrl` on Android.\n *\n * On Web this will return `null`.\n */\nexport function storeUrl(): string | null {\n const expoConfig = Constants.expoConfig;\n if (Platform.OS === 'ios' && expoConfig?.ios) {\n return expoConfig.ios.appStoreUrl ?? null;\n } else if (Platform.OS === 'android' && expoConfig?.android) {\n return expoConfig.android.playStoreUrl ?? null;\n }\n return null;\n}\n\n// @needsAudit\n/**\n * @return This returns a promise that fulfills to `true` if `StoreReview.requestReview()` is capable\n * directing the user to some kind of store review flow. If the app config (`app.json`) does not\n * contain store URLs and native store review capabilities are not available then the promise\n * will fulfill to `false`.\n *\n * @example\n * ```ts\n * if (await StoreReview.hasAction()) {\n * // you can call StoreReview.requestReview()\n * }\n * ```\n */\nexport async function hasAction(): Promise {\n return !!storeUrl() || (await isAvailableAsync());\n}\n"]} -\ No newline at end of file -+{"version":3,"file":"StoreReview.js","sourceRoot":"","sources":["../src/StoreReview.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAE5C,cAAc;AACd;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,OAAO,WAAW,CAAC,gBAAgB,EAAE,EAAE,IAAI,KAAK,CAAC;AACnD,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,WAAW,EAAE,eAAe,EAAE,CAAC;QACjC,OAAO,WAAW,CAAC,eAAe,EAAE,CAAC;IACvC,CAAC;IACD,iEAAiE;IACjE,6CAA6C;AAC/C,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,WAAW,EAAE,gBAAgB,EAAE,CAAC;QAClC,OAAO,WAAW,CAAC,gBAAgB,EAAE,CAAC;IACxC,CAAC;IACD,iEAAiE;IACjE,6CAA6C;AAC/C,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,WAAW,EAAE,YAAY,EAAE,CAAC;QAC9B,OAAO,WAAW,CAAC,YAAY,EAAE,CAAC;IACpC,CAAC;IACD,yEAAyE;IACzE,6CAA6C;IAC7C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,WAAW,EAAE,aAAa,EAAE,CAAC;QAC/B,OAAO,WAAW,CAAC,aAAa,EAAE,CAAC;IACrC,CAAC;IACD,6GAA6G;IAC7G,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,qDAAqD,EAAE,GAAG,CAAC,CAAC;QAC3E,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,iDAAiD;QACjD,OAAO,CAAC,IAAI,CACV,+JAA+J,CAChK,CAAC;IACJ,CAAC;AACH,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC;IACxC,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,UAAU,EAAE,GAAG,EAAE,CAAC;QAC7C,OAAO,UAAU,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC;IAC5C,CAAC;SAAM,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,UAAU,EAAE,OAAO,EAAE,CAAC;QAC5D,OAAO,UAAU,CAAC,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,OAAO,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,gBAAgB,EAAE,CAAC,CAAC;AACpD,CAAC","sourcesContent":["import Constants from 'expo-constants';\nimport { Platform } from 'expo-modules-core';\nimport { Linking } from 'react-native';\n\nimport StoreReview from './ExpoStoreReview';\n\n// @needsAudit\n/**\n * Determines if the platform has the capabilities to use `StoreReview.requestReview()`.\n * @return\n * This returns a promise fulfills with `boolean`, depending on the platform:\n * - On iOS, it will resolve to `true` unless the app is distributed through TestFlight.\n * - On Android, it will resolve to `true` if the device is running Android 5.0+.\n * - On Web, it will resolve to `false`.\n */\nexport async function isAvailableAsync(): Promise {\n return StoreReview.isAvailableAsync?.() ?? false;\n}\n\n// @needsAudit\n/**\n * Shows a pre-prompt alert asking the user if they'd like to rate the app. If they select \"Yes\",\n * it will then show the native store review prompt. This is useful for improving review conversion rates.\n * Currently only available on iOS.\n */\nexport async function prePromptReview(): Promise {\n if (StoreReview?.prePromptReview) {\n return StoreReview.prePromptReview();\n }\n // Fallback: if prePromptReview is not available, just do nothing\n // (This will be the case on web and Android)\n}\n\n// @needsAudit\n/**\n * Resets the review state stored in UserDefaults. This allows you to clear the\n * tracking of whether the user has already been prompted for a review.\n * Currently only available on iOS.\n */\nexport async function resetReviewState(): Promise {\n if (StoreReview?.resetReviewState) {\n return StoreReview.resetReviewState();\n }\n // Fallback: if resetReviewState is not available, just do nothing\n // (This will be the case on web and Android)\n}\n\n// @needsAudit\n/**\n * Checks whether the user has already rated the app (i.e., they selected \"Rate Now\"\n * in the pre-prompt dialog). This can be used to conditionally show or hide rating prompts.\n * Currently only available on iOS.\n * @return A promise that resolves to true if the user has rated, false otherwise.\n */\nexport async function hasUserRated(): Promise {\n if (StoreReview?.hasUserRated) {\n return StoreReview.hasUserRated();\n }\n // Fallback: if hasUserRated is not available, return false\n // (This will be the case on web and Android)\n return false;\n}\n\n// @needsAudit\n/**\n * In ideal circumstances this will open a native modal and allow the user to select a star rating\n * that will then be applied to the App Store, without leaving the app. If the device is running\n * a version of Android lower than 5.0, this will attempt to get the store URL and link the user to it.\n */\nexport async function requestReview(): Promise {\n if (StoreReview?.requestReview) {\n return StoreReview.requestReview();\n }\n // If StoreReview is unavailable then get the store URL from `app.config.js` or `app.json` and open the store\n const url = storeUrl();\n if (url) {\n const supported = await Linking.canOpenURL(url);\n if (!supported) {\n console.warn(\"StoreReview.requestReview(): Can't open store url: \", url);\n } else {\n await Linking.openURL(url);\n }\n } else {\n // If the store URL is missing, let the dev know.\n console.warn(\n \"StoreReview.requestReview(): Couldn't link to store, please make sure the `android.playStoreUrl` & `ios.appStoreUrl` fields are filled out in your `app.json`\"\n );\n }\n}\n\n// @needsAudit\n/**\n * This uses the `Constants` API to get the `Constants.expoConfig.ios.appStoreUrl` on iOS, or the\n * `Constants.expoConfig.android.playStoreUrl` on Android.\n *\n * On Web this will return `null`.\n */\nexport function storeUrl(): string | null {\n const expoConfig = Constants.expoConfig;\n if (Platform.OS === 'ios' && expoConfig?.ios) {\n return expoConfig.ios.appStoreUrl ?? null;\n } else if (Platform.OS === 'android' && expoConfig?.android) {\n return expoConfig.android.playStoreUrl ?? null;\n }\n return null;\n}\n\n// @needsAudit\n/**\n * @return This returns a promise that fulfills to `true` if `StoreReview.requestReview()` is capable\n * directing the user to some kind of store review flow. If the app config (`app.json`) does not\n * contain store URLs and native store review capabilities are not available then the promise\n * will fulfill to `false`.\n *\n * @example\n * ```ts\n * if (await StoreReview.hasAction()) {\n * // you can call StoreReview.requestReview()\n * }\n * ```\n */\nexport async function hasAction(): Promise {\n return !!storeUrl() || (await isAvailableAsync());\n}\n"]} -\ No newline at end of file -diff --git a/ios/StoreReviewModule.swift b/ios/StoreReviewModule.swift -index c44c468..4eb6ea0 100644 ---- a/ios/StoreReviewModule.swift -+++ b/ios/StoreReviewModule.swift -@@ -1,5 +1,8 @@ - import ExpoModulesCore - import StoreKit -+import UIKit -+ -+private let HAS_RATED_KEY = "anything_has_rated" - - public class StoreReviewModule: Module { - public func definition() -> ModuleDefinition { -@@ -9,11 +12,55 @@ public class StoreReviewModule: Module { - return !isRunningFromTestFlight() - } - -+ AsyncFunction("prePromptReview") { -+ if isRunningFromTestFlight() { -+ return -+ } -+ -+ try await MainActor.run { -+ let defaults = UserDefaults.standard -+ -+ if defaults.bool(forKey: HAS_RATED_KEY) { -+ return -+ } -+ -+ guard let currentScene = getForegroundActiveScene() else { -+ throw MissingCurrentWindowSceneException() -+ } -+ -+ let keyWindow = currentScene.windows.first(where: { $0.isKeyWindow }) -+ guard let rootVC = keyWindow?.rootViewController else { -+ throw MissingCurrentWindowSceneException() -+ } -+ -+ let alert = UIAlertController( -+ title: "Thanks for using Anything!", -+ message: "Share what you love about Anything in the App Store. Your review will help us reach more people.", -+ preferredStyle: .alert -+ ) -+ -+ let noAction = UIAlertAction(title: "No Thanks", style: .cancel, handler: nil) -+ -+ let yesAction = UIAlertAction(title: "Rate Now", style: .default) { _ in -+ defaults.set(true, forKey: HAS_RATED_KEY) -+ -+ if #available(iOS 16.0, *) { -+ AppStore.requestReview(in: currentScene) -+ } else { -+ SKStoreReviewController.requestReview(in: currentScene) -+ } -+ } -+ -+ alert.addAction(noAction) -+ alert.addAction(yesAction) -+ -+ rootVC.present(alert, animated: true, completion: nil) -+ } -+ } -+ - AsyncFunction("requestReview") { - try await MainActor.run { - guard let currentScene = getForegroundActiveScene() else { -- // If no valid foreground scene is found, throw an exception -- // as the review prompt won't be visible in background - throw MissingCurrentWindowSceneException() - } - if #available(iOS 16.0, *) { -@@ -23,23 +70,30 @@ public class StoreReviewModule: Module { - } - } - } -+ -+ AsyncFunction("resetReviewState") { -+ let defaults = UserDefaults.standard -+ defaults.removeObject(forKey: HAS_RATED_KEY) -+ } -+ -+ AsyncFunction("hasUserRated") { () -> Bool in -+ let defaults = UserDefaults.standard -+ return defaults.bool(forKey: HAS_RATED_KEY) -+ } -+ - } - - private func getForegroundActiveScene() -> UIWindowScene? { -- // First try to find a foreground active scene -- if let activeScene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene { -+ if let activeScene = UIApplication.shared.connectedScenes -+ .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene { - return activeScene - } - -- // If no foreground active scene is found (e.g., app is in App Switcher), -- // try to find any foreground inactive scene -- if let foregroundScene = UIApplication.shared.connectedScenes.first(where: { -- $0.activationState == .foregroundInactive -- }) as? UIWindowScene { -+ if let foregroundScene = UIApplication.shared.connectedScenes -+ .first(where: { $0.activationState == .foregroundInactive }) as? UIWindowScene { - return foregroundScene - } - -- // If no valid foreground scene is found, return nil - return nil - } - -@@ -48,12 +102,7 @@ public class StoreReviewModule: Module { - return false - #endif - -- // For apps distributed through TestFlight or intalled from Xcode the receipt file is named "StoreKit/sandboxReceipt" -- // instead of "StoreKit/receipt" - let isSandboxEnv = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt" -- -- // Apps distributed through TestFlight or the App Store will not have an embedded provisioning profile -- // Source: https://developer.apple.com/documentation/technotes/tn3125-inside-code-signing-provisioning-profiles#Profile-location - return isSandboxEnv && !hasEmbeddedMobileProvision() - } - -diff --git a/src/ExpoStoreReview.ts b/src/ExpoStoreReview.ts -index cb9ee95..94b9581 100644 ---- a/src/ExpoStoreReview.ts -+++ b/src/ExpoStoreReview.ts -@@ -2,4 +2,7 @@ - export default {} as Partial<{ - isAvailableAsync: () => Promise; - requestReview: () => Promise; -+ prePromptReview: () => Promise; -+ resetReviewState: () => Promise; -+ hasUserRated: () => Promise; - }>; -diff --git a/src/StoreReview.ts b/src/StoreReview.ts -index a9b9094..570caa6 100644 ---- a/src/StoreReview.ts -+++ b/src/StoreReview.ts -@@ -17,6 +17,20 @@ export async function isAvailableAsync(): Promise { - return StoreReview.isAvailableAsync?.() ?? false; - } - -+// @needsAudit -+/** -+ * Shows a pre-prompt alert asking the user if they'd like to rate the app. If they select "Yes", -+ * it will then show the native store review prompt. This is useful for improving review conversion rates. -+ * Currently only available on iOS. -+ */ -+export async function prePromptReview(): Promise { -+ if (StoreReview?.prePromptReview) { -+ return StoreReview.prePromptReview(); -+ } -+ // Fallback: if prePromptReview is not available, just do nothing -+ // (This will be the case on web and Android) -+} -+ - // @needsAudit - /** - * In ideal circumstances this will open a native modal and allow the user to select a star rating -@@ -78,3 +92,33 @@ export function storeUrl(): string | null { - export async function hasAction(): Promise { - return !!storeUrl() || (await isAvailableAsync()); - } -+ -+// @needsAudit -+/** -+ * Resets the review state stored in UserDefaults. This allows you to clear the -+ * tracking of whether the user has already been prompted for a review. -+ * Currently only available on iOS. -+ */ -+export async function resetReviewState(): Promise { -+ if (StoreReview?.resetReviewState) { -+ return StoreReview.resetReviewState(); -+ } -+ // Fallback: if resetReviewState is not available, just do nothing -+ // (This will be the case on web and Android) -+} -+ -+// @needsAudit -+/** -+ * Checks whether the user has already rated the app (i.e., they selected "Rate Now" -+ * in the pre-prompt dialog). This can be used to conditionally show or hide rating prompts. -+ * Currently only available on iOS. -+ * @return A promise that resolves to true if the user has rated, false otherwise. -+ */ -+export async function hasUserRated(): Promise { -+ if (StoreReview?.hasUserRated) { -+ return StoreReview.hasUserRated(); -+ } -+ // Fallback: if hasUserRated is not available, return false -+ // (This will be the case on web and Android) -+ return false; -+} diff --git a/.yarn/patches/react-native+0.81.4.patch b/.yarn/patches/react-native+0.81.4.patch deleted file mode 100644 index 1e023b2..0000000 --- a/.yarn/patches/react-native+0.81.4.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/index.js b/index.js -index c737c93..f3edd25 100644 ---- a/index.js -+++ b/index.js -@@ -336,6 +336,9 @@ module.exports = { - return require('./src/private/components/virtualview/VirtualView') - .VirtualViewMode; - }, -+ get Slider() { -+ return require('@react-native-community/slider').default; -+ }, - // #endregion - } as ReactNativePublicAPI; - -@@ -405,15 +408,4 @@ if (__DEV__) { - * attempting to access Slider. */ - /* $FlowFixMe[invalid-export] This is intentional: Flow will error when - * attempting to access Slider. */ -- Object.defineProperty(module.exports, 'Slider', { -- configurable: true, -- get() { -- invariant( -- false, -- 'Slider has been removed from react-native core. ' + -- "It can now be installed and imported from '@react-native-community/slider' instead of 'react-native'. " + -- 'See https://github.com/callstack/react-native-slider', -- ); -- }, -- }); - } diff --git a/.yarn/patches/react-native-purchases+9.6.1.patch b/.yarn/patches/react-native-purchases+9.6.1.patch deleted file mode 100644 index 837fced..0000000 --- a/.yarn/patches/react-native-purchases+9.6.1.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/dist/utils/environment.js b/dist/utils/environment.js -index 7c5d453..8457e4b 100644 ---- a/dist/utils/environment.js -+++ b/dist/utils/environment.js -@@ -31,6 +31,12 @@ exports.shouldUseBrowserMode = shouldUseBrowserMode; - * Detects if the app is running in Expo Go - */ - function isExpoGo() { -+ if (!__DEV__) { -+ return false; -+ } -+ if (globalThis.expo && globalThis.expo.modules && globalThis.expo.modules.AnythingLauncherModule) { -+ return true; -+ } - var _a, _b; - if (!!react_native_1.NativeModules.RNPurchases) { - return false; diff --git a/.yarn/patches/react-native-purchases-ui+9.6.1.patch b/.yarn/patches/react-native-purchases-ui+9.6.1.patch deleted file mode 100644 index f0df96f..0000000 --- a/.yarn/patches/react-native-purchases-ui+9.6.1.patch +++ /dev/null @@ -1,59 +0,0 @@ -diff --git a/lib/commonjs/utils/environment.js b/lib/commonjs/utils/environment.js -index 43e5e6a..b67d36a 100644 ---- a/lib/commonjs/utils/environment.js -+++ b/lib/commonjs/utils/environment.js -@@ -31,6 +31,12 @@ function shouldUsePreviewAPIMode() { - */ - function isExpoGo() { - var _globalThis$expo; -+ if (!__DEV__) { -+ return false; -+ } -+ if (globalThis.expo && globalThis.expo.modules && globalThis.expo.modules.AnythingLauncherModule) { -+ return true; -+ } - if (!!_reactNative.NativeModules.RNPaywalls && !!_reactNative.NativeModules.RNCustomerCenter) { - return false; - } -diff --git a/lib/module/utils/environment.js b/lib/module/utils/environment.js -index 435d456..4002fe2 100644 ---- a/lib/module/utils/environment.js -+++ b/lib/module/utils/environment.js -@@ -26,6 +26,12 @@ export function shouldUsePreviewAPIMode() { - */ - function isExpoGo() { - var _globalThis$expo; -+ if (!__DEV__) { -+ return false; -+ } -+ if (globalThis.expo && globalThis.expo.modules && globalThis.expo.modules.AnythingLauncherModule) { -+ return true; -+ } - if (!!NativeModules.RNPaywalls && !!NativeModules.RNCustomerCenter) { - return false; - } -diff --git a/src/utils/environment.ts b/src/utils/environment.ts -index 5605bf2..ed86595 100644 ---- a/src/utils/environment.ts -+++ b/src/utils/environment.ts -@@ -26,6 +26,7 @@ declare global { - var expo: { - modules?: { - ExpoGo?: boolean; -+ AnythingLauncherModule?: boolean; - }; - }; - } -@@ -34,6 +35,12 @@ declare global { - * Detects if the app is running in Expo Go - */ - function isExpoGo(): boolean { -+ if (!__DEV__) { -+ return false; -+ } -+ if (globalThis.expo && globalThis.expo.modules && globalThis.expo.modules.AnythingLauncherModule) { -+ return true; -+ } - if (!!NativeModules.RNPaywalls && !!NativeModules.RNCustomerCenter) { - return false; - } diff --git a/.yarn/patches/react-native-web-refresh-control+1.1.2.patch b/.yarn/patches/react-native-web-refresh-control+1.1.2.patch deleted file mode 100644 index 81fb30b..0000000 --- a/.yarn/patches/react-native-web-refresh-control+1.1.2.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/src/RefreshControl.web.js b/src/RefreshControl.web.js -index b2351e6..c638d23 100644 ---- a/src/RefreshControl.web.js -+++ b/src/RefreshControl.web.js -@@ -1,5 +1,5 @@ - import React, { useRef, useEffect, useCallback, useMemo } from 'react' --import { View, Text, PanResponder, Animated, ActivityIndicator, findNodeHandle } from 'react-native' -+import { View, Text, PanResponder, Animated, ActivityIndicator } from 'react-native' - import PropTypes from 'prop-types' - - const arrowIcon = -@@ -77,9 +77,9 @@ export default function RefreshControl({ - onStartShouldSetPanResponderCapture: () => false, - onMoveShouldSetPanResponder: (_,gestureState) => { - if (!containerRef.current) return false -- const containerDOM = findNodeHandle(containerRef.current) -- if (!containerDOM) return false -- return containerDOM.children[0].scrollTop === 0 -+ const scrollContainer = containerRef.current?.firstChild -+ if (!scrollContainer) return false -+ return scrollContainer.scrollTop === 0 - && (Math.abs(gestureState.dy) > Math.abs(gestureState.dx) * 2 && Math.abs(gestureState.vy) > Math.abs(gestureState.vx) * 2.5) - }, - onMoveShouldSetPanResponderCapture: () => false, diff --git a/.yarn/patches/sonner-native+0.21.0.patch b/.yarn/patches/sonner-native+0.21.0.patch deleted file mode 100644 index f088284..0000000 --- a/.yarn/patches/sonner-native+0.21.0.patch +++ /dev/null @@ -1,43 +0,0 @@ -diff --git a/lib/commonjs/positioner.js b/lib/commonjs/positioner.js -index cac0f68..ec816b7 100644 ---- a/lib/commonjs/positioner.js -+++ b/lib/commonjs/positioner.js -@@ -55,8 +55,12 @@ const Positioner = ({ - return {}; - }, [position, bottom, top, offset]); - return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { -+ ...(_reactNative.Platform.OS === 'web' ? { -+ style: [{ pointerEvents: 'box-none' }, containerStyle, insetValues, style], -+ } :{ - style: [containerStyle, insetValues, style], - pointerEvents: "box-none", -+ }), - ...props, - children: children - }); -diff --git a/lib/module/positioner.js b/lib/module/positioner.js -index 476f6bb..40f1968 100644 ---- a/lib/module/positioner.js -+++ b/lib/module/positioner.js -@@ -1,7 +1,7 @@ - "use strict"; - - import React from 'react'; --import { View } from 'react-native'; -+import { View, Platform } from 'react-native'; - import { useSafeAreaInsets } from 'react-native-safe-area-context'; - import { useToastContext } from "./context.js"; - import { jsx as _jsx } from "react/jsx-runtime"; -@@ -50,8 +50,12 @@ export const Positioner = ({ - return {}; - }, [position, bottom, top, offset]); - return /*#__PURE__*/_jsx(View, { -+...(Platform.OS === 'web' ? { -+ style: [{ pointerEvents: 'box-none' }, containerStyle, insetValues, style], -+ } :{ - style: [containerStyle, insetValues, style], - pointerEvents: "box-none", -+ }), - ...props, - children: children - }); diff --git a/apps/mobile/.easignore b/apps/mobile/.easignore deleted file mode 100644 index ab35621..0000000 --- a/apps/mobile/.easignore +++ /dev/null @@ -1,38 +0,0 @@ -# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files - -# dependencies -node_modules/ - -# Expo -.expo/ -dist/ -web-build/ -expo-env.d.ts - -# Native -*.orig.* -*.jks -*.p8 -*.p12 -*.key -*.mobileprovision - -# Metro -.metro-health-check* - -# debug -npm-debug.* -yarn-debug.* -yarn-error.* - -# macOS -.DS_Store -*.pem - -# typescript -*.tsbuildinfo - -app-example - -caches/ -public/ \ No newline at end of file diff --git a/apps/mobile/.gitignore b/apps/mobile/.gitignore deleted file mode 100644 index 316a8c5..0000000 --- a/apps/mobile/.gitignore +++ /dev/null @@ -1,44 +0,0 @@ -# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files - -# dependencies -node_modules/ - -# Expo -.expo/ -dist/ -web-build/ -expo-env.d.ts - -# Native -*.orig.* -*.jks -*.p8 -*.p12 -*.key -*.mobileprovision - -# Metro -.metro-health-check* - -# debug -npm-debug.* -yarn-debug.* -yarn-error.* - -# macOS -.DS_Store -*.pem - -# local env files -.env*.local - -# typescript -*.tsbuildinfo - -app-example - -.env - -.metro-virtual/* - -caches/* \ No newline at end of file diff --git a/apps/mobile/App.tsx b/apps/mobile/App.tsx deleted file mode 100644 index a6fda90..0000000 --- a/apps/mobile/App.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { App } from 'expo-router/build/qualified-entry'; -import { ScreenViewTracker } from './src/__create/analytics'; - -// Screen-view analytics is mounted here, in the entry, rather than in -// app/_layout. The entry is platform scaffold that ships with the template, so -// the tracker reaches every app on its next rebuild WITHOUT editing each -// project's own _layout (mirrors how App.web.tsx tracks navigation at the -// root). usePathname reads expo-router's global store. -export default function MobileRoot() { - return ( - <> - - - - ); -} diff --git a/apps/mobile/App.web.tsx b/apps/mobile/App.web.tsx deleted file mode 100644 index 8281330..0000000 --- a/apps/mobile/App.web.tsx +++ /dev/null @@ -1,175 +0,0 @@ -import { usePathname, useRouter } from 'expo-router'; -import { App } from 'expo-router/build/qualified-entry'; -import React, { memo, useEffect } from 'react'; -import './src/__create/polyfills'; - -import { ErrorBoundary } from './src/__create/ErrorBoundary'; -import { SafeAreaProvider } from 'react-native-safe-area-context'; -import { Toaster } from 'sonner-native'; -import { AlertModal } from './polyfills/web/alerts.web'; -import './global.css'; - -const RUNTIME_ERROR_PATTERNS = [ - /fetch failed/i, - /networks*(error|request)/i, - /failed to fetch/i, - /load failed/i, - /ECONNREFUSED/i, - /ECONNRESET/i, - /ETIMEDOUT/i, - /ENOTFOUND/i, - /ERR_CONNECTION/i, - /aborted/i, - /timeout/i, - /socket hang up/i, - /503\b/, - /502\b/, - /504\b/, - /getaddrinfo/i, -]; - -function isRuntimeError(msg: string) { - return RUNTIME_ERROR_PATTERNS.some((p) => p.test(msg)); -} - -function postErrorToParent(message: string, name: string, stack: string) { - try { - if (window.parent !== window) { - window.parent.postMessage( - { - type: 'sandbox:error:detected', - error: { message, name, stack }, - }, - '*' - ); - } - } catch {} -} - -const GlobalErrorReporter = () => { - useEffect(() => { - if (typeof window === 'undefined') { - return; - } - const errorHandler = (event: ErrorEvent) => { - if (typeof event.preventDefault === 'function') event.preventDefault(); - console.error(event.error); - - const error = event.error; - const message = error?.message || event.message || 'Unknown error'; - if (!isRuntimeError(message)) { - postErrorToParent(message, error?.name || 'Error', error?.stack || ''); - } - }; - const unhandledRejectionHandler = (event: PromiseRejectionEvent) => { - if (typeof event.preventDefault === 'function') event.preventDefault(); - const reason = event.reason; - console.error('Unhandled promise rejection:', reason); - - const message = reason?.message || String(reason || ''); - if (isRuntimeError(message)) return; - const isCodeError = - reason instanceof TypeError || - reason instanceof ReferenceError || - reason instanceof SyntaxError || - reason?.code === 'MODULE_RESOLVE_FAILED'; - if (!isCodeError) return; - postErrorToParent(message, reason?.name || 'Error', reason?.stack || ''); - }; - window.addEventListener('error', errorHandler); - window.addEventListener('unhandledrejection', unhandledRejectionHandler); - return () => { - window.removeEventListener('error', errorHandler); - window.removeEventListener( - 'unhandledrejection', - unhandledRejectionHandler - ); - }; - }, []); - return null; -}; - -const Wrapper = memo(() => { - return ( - - - - - - - - ); -}); -const healthyResponse = { - type: 'sandbox:mobile:healthcheck:response', - healthy: true, -}; - -const useHandshakeParent = () => { - useEffect(() => { - const handleMessage = (event: MessageEvent) => { - if (event.data.type === 'sandbox:mobile:healthcheck') { - window.parent.postMessage(healthyResponse, '*'); - } - }; - window.addEventListener('message', handleMessage); - // Immediately respond to the parent window with a healthy response in - // case we missed the healthcheck message - window.parent.postMessage(healthyResponse, '*'); - return () => { - window.removeEventListener('message', handleMessage); - }; - }, []); -}; - -const CreateApp = () => { - const router = useRouter(); - const pathname = usePathname(); - useHandshakeParent(); - - useEffect(() => { - const handleMessage = (event: MessageEvent) => { - if ( - event.data.type === 'sandbox:navigation' && - event.data.pathname !== pathname - ) { - router.push(event.data.pathname); - } - }; - - window.addEventListener('message', handleMessage); - window.parent.postMessage({ type: 'sandbox:mobile:ready' }, '*'); - return () => { - window.removeEventListener('message', handleMessage); - }; - }, [router, pathname]); - - useEffect(() => { - window.parent.postMessage( - { - type: 'sandbox:mobile:navigation', - pathname, - }, - '*' - ); - }, [pathname]); - - return ( - <> - - - - ); -}; - -export default CreateApp; diff --git a/apps/mobile/__create/handle-resolve-request-error.js b/apps/mobile/__create/handle-resolve-request-error.js deleted file mode 100644 index c54c200..0000000 --- a/apps/mobile/__create/handle-resolve-request-error.js +++ /dev/null @@ -1,79 +0,0 @@ -const crypto = require('node:crypto'); -const fs = require('node:fs'); -const path = require('node:path'); -const { reportErrorToRemote } = require('./report-error-to-remote'); - -const VIRTUAL_ROOT = path.join(__dirname, '../.metro-virtual'); -const VIRTUAL_ROOT_UNRESOLVED = path.join(VIRTUAL_ROOT, 'unresolved'); - -const handleResolveRequestError = ({ - error, - context, - moduleName, - platform, -}) => { - const errorMessage = `Unable to resolve module '${moduleName}' from '${context.originModulePath}'`; - const syntheticError = new Error(errorMessage); - syntheticError.stack = error.stack; - reportErrorToRemote({ error: syntheticError }).catch((_reportError) => { - // no-op - }); - if (process.env.NODE_ENV === 'production') throw error; - if (platform === 'android') throw error; - if (!__DEV__ && process.env.EXPO_PUBLIC_CREATE_ENV !== 'DEVELOPMENT') - throw error; - - // Build a deterministic virtual file path for this failed request - const key = `${moduleName}|${context.originModulePath}|${platform}`; - const hash = crypto - .createHash('sha256') - .update(key) - .digest('hex') - .slice(0, 16); - - fs.mkdirSync(VIRTUAL_ROOT_UNRESOLVED, { recursive: true }); - const vfile = path.join(VIRTUAL_ROOT_UNRESOLVED, `throw-${hash}.js`); - - // Serialize a safe payload for the client - const payload = { - moduleName, - from: context.originModulePath, - platform, - originalMessage: String( - error?.message ? error.message : 'Unknown resolve error' - ), - }; - - const code = [ - '// Auto generated by custom Metro resolver', - '(function(){', - ` var info = ${JSON.stringify(payload)};`, - " var msg = 'Unable to resolve \"' + info.moduleName + '\" from \"' + info.from + '\"';", - " msg += '\\n\\n' + info.originalMessage;", - ' var e = new Error(msg);', - " e.name = 'ModuleResolveError';", - " e.code = 'MODULE_RESOLVE_FAILED';", - ' throw e;', - '})();', - 'export {};', // keep ESM shape harmlessly - '', - ].join('\n'); - - // Only write if content changed — avoids bumping mtime and triggering Metro rebuild loop - const existingContent = fs.existsSync(vfile) ? fs.readFileSync(vfile, 'utf8') : null; - if (existingContent !== code) { - fs.writeFileSync(vfile, code, 'utf8'); - } - - // Tell Metro to load our thrower as a real source file - return { - filePath: vfile, - type: 'sourceFile', - }; -}; - -module.exports = { - handleResolveRequestError, - VIRTUAL_ROOT, - VIRTUAL_ROOT_UNRESOLVED, -}; diff --git a/apps/mobile/__create/report-error-to-remote.js b/apps/mobile/__create/report-error-to-remote.js deleted file mode 100644 index 76f444f..0000000 --- a/apps/mobile/__create/report-error-to-remote.js +++ /dev/null @@ -1,53 +0,0 @@ -import { serializeError } from "serialize-error"; - -export const sendLogsToRemote = async (logs) => { - if ( - !process.env.EXPO_PUBLIC_LOGS_ENDPOINT || - !process.env.EXPO_PUBLIC_PROJECT_GROUP_ID || - !process.env.EXPO_PUBLIC_CREATE_TEMP_API_KEY - ) { - return { success: false }; - } - try { - const response = await fetch(process.env.EXPO_PUBLIC_LOGS_ENDPOINT, { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${process.env.EXPO_PUBLIC_CREATE_TEMP_API_KEY}`, - }, - body: JSON.stringify({ - projectGroupId: process.env.EXPO_PUBLIC_PROJECT_GROUP_ID, - logs, - }), - }); - if (!response.ok) { - return { success: false }; - } - } catch (fetchError) { - return { success: false, error: fetchError }; - } - return { success: true }; -}; - -export const reportErrorToRemote = async ({ error }) => { - if ( - !process.env.EXPO_PUBLIC_LOGS_ENDPOINT || - !process.env.EXPO_PUBLIC_PROJECT_GROUP_ID || - !process.env.EXPO_PUBLIC_CREATE_TEMP_API_KEY - ) { - console.debug( - "reportErrorToRemote: Missing environment variables for logging endpoint, project group ID, or API key.", - error, - ); - return { success: false }; - } - return sendLogsToRemote([ - { - message: JSON.stringify(serializeError(error)), - timestamp: new Date().toISOString(), - level: "error", - source: "BUILDER", - devServerId: process.env.EXPO_PUBLIC_DEV_SERVER_ID, - }, - ]); -}; diff --git a/apps/mobile/__create/report-error-to-remote.test.js b/apps/mobile/__create/report-error-to-remote.test.js deleted file mode 100644 index 82f18b0..0000000 --- a/apps/mobile/__create/report-error-to-remote.test.js +++ /dev/null @@ -1,115 +0,0 @@ -jest.mock("serialize-error", () => ({ - serializeError: jest.fn((err) => ({ - message: err instanceof Error ? err.message : String(err), - name: err instanceof Error ? err.name : "Error", - })), -})); - -let sendLogsToRemote; -let reportErrorToRemote; - -beforeEach(() => { - jest.resetAllMocks(); - jest.resetModules(); - delete process.env.EXPO_PUBLIC_LOGS_ENDPOINT; - delete process.env.EXPO_PUBLIC_PROJECT_GROUP_ID; - delete process.env.EXPO_PUBLIC_CREATE_TEMP_API_KEY; - delete process.env.EXPO_PUBLIC_DEV_SERVER_ID; - global.fetch = jest.fn(); - - // Re-require after mocks are set up - jest.doMock("serialize-error", () => ({ - serializeError: jest.fn((err) => ({ - message: err instanceof Error ? err.message : String(err), - name: err instanceof Error ? err.name : "Error", - })), - })); - const mod = require("./report-error-to-remote"); - sendLogsToRemote = mod.sendLogsToRemote; - reportErrorToRemote = mod.reportErrorToRemote; -}); - -describe("sendLogsToRemote", () => { - it("returns success: false when env vars are missing", async () => { - const result = await sendLogsToRemote([{ message: "test" }]); - expect(result).toEqual({ success: false }); - expect(global.fetch).not.toHaveBeenCalled(); - }); - - it("sends logs to the endpoint with correct auth header", async () => { - process.env.EXPO_PUBLIC_LOGS_ENDPOINT = "https://logs.test/ingest"; - process.env.EXPO_PUBLIC_PROJECT_GROUP_ID = "pg-123"; - process.env.EXPO_PUBLIC_CREATE_TEMP_API_KEY = "key-abc"; - - global.fetch = jest.fn().mockResolvedValue({ ok: true }); - - const logs = [ - { message: "hello", level: "info", timestamp: "2026-01-01T00:00:00Z" }, - ]; - const result = await sendLogsToRemote(logs); - - expect(result).toEqual({ success: true }); - expect(global.fetch).toHaveBeenCalledWith("https://logs.test/ingest", { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: "Bearer key-abc", - }, - body: JSON.stringify({ projectGroupId: "pg-123", logs }), - }); - }); - - it("returns success: false on non-ok response", async () => { - process.env.EXPO_PUBLIC_LOGS_ENDPOINT = "https://logs.test/ingest"; - process.env.EXPO_PUBLIC_PROJECT_GROUP_ID = "pg-123"; - process.env.EXPO_PUBLIC_CREATE_TEMP_API_KEY = "key-abc"; - - global.fetch = jest.fn().mockResolvedValue({ ok: false, status: 500 }); - - const result = await sendLogsToRemote([{ message: "fail" }]); - expect(result).toEqual({ success: false }); - }); - - it("returns success: false with error on network failure", async () => { - process.env.EXPO_PUBLIC_LOGS_ENDPOINT = "https://logs.test/ingest"; - process.env.EXPO_PUBLIC_PROJECT_GROUP_ID = "pg-123"; - process.env.EXPO_PUBLIC_CREATE_TEMP_API_KEY = "key-abc"; - - const networkError = new Error("Network request failed"); - global.fetch = jest.fn().mockRejectedValue(networkError); - - const result = await sendLogsToRemote([{ message: "fail" }]); - expect(result).toEqual({ success: false, error: networkError }); - }); -}); - -describe("reportErrorToRemote", () => { - it("returns success: false when env vars are missing", async () => { - const result = await reportErrorToRemote({ - error: new Error("test error"), - }); - expect(result).toEqual({ success: false }); - expect(global.fetch).not.toHaveBeenCalled(); - }); - - it("serializes error and sends as a single log entry with source BUILDER", async () => { - process.env.EXPO_PUBLIC_LOGS_ENDPOINT = "https://logs.test/ingest"; - process.env.EXPO_PUBLIC_PROJECT_GROUP_ID = "pg-123"; - process.env.EXPO_PUBLIC_CREATE_TEMP_API_KEY = "key-abc"; - process.env.EXPO_PUBLIC_DEV_SERVER_ID = "ds-456"; - - global.fetch = jest.fn().mockResolvedValue({ ok: true }); - - const error = new Error("something broke"); - await reportErrorToRemote({ error }); - - expect(global.fetch).toHaveBeenCalledTimes(1); - const body = JSON.parse(global.fetch.mock.calls[0][1].body); - expect(body.projectGroupId).toBe("pg-123"); - expect(body.logs).toHaveLength(1); - expect(body.logs[0].level).toBe("error"); - expect(body.logs[0].source).toBe("BUILDER"); - expect(body.logs[0].devServerId).toBe("ds-456"); - expect(body.logs[0].message).toContain("something broke"); - }); -}); diff --git a/apps/mobile/__create/sentry.ts b/apps/mobile/__create/sentry.ts deleted file mode 100644 index ee6a948..0000000 --- a/apps/mobile/__create/sentry.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as Sentry from "@sentry/react-native"; -import { sendLogsToRemote } from "./report-error-to-remote"; - -function isActive(): boolean { - return ( - !__DEV__ && - process.env.EXPO_PUBLIC_CREATE_ENV !== "DEVELOPMENT" && - !!process.env.EXPO_PUBLIC_SENTRY_DSN - ); -} - -let initialized = false; - -// Mirror a Sentry event into the Anything logs pipeline so native and JS -// crashes — including startup crashes that Sentry caches natively and reports -// on the next launch — surface in the Flux builder, not only the Sentry -// dashboard. -function forwardEventToRemote(event: Sentry.Event): void { - try { - const exception = event.exception?.values?.[0]; - const lines: string[] = []; - if (exception && (exception.type || exception.value)) { - lines.push(`${exception.type ?? "Error"}: ${exception.value ?? ""}`); - } else if (typeof event.message === "string") { - lines.push(event.message); - } - const frames = exception?.stacktrace?.frames; - if (frames && frames.length > 0) { - lines.push( - frames - .slice(-20) - .reverse() - .map( - (frame) => - ` at ${frame.function ?? "?"} (${frame.filename ?? "?"}:${frame.lineno ?? 0})`, - ) - .join("\n"), - ); - } - const message = lines.join("\n").trim(); - if (!message) return; - const timestamp = - typeof event.timestamp === "number" - ? new Date(event.timestamp * 1000).toISOString() - : new Date().toISOString(); - sendLogsToRemote([ - { - message: `[SENTRY] ${message}`, - timestamp, - level: "error", - source: "TEST_FLIGHT", - }, - ]); - } catch (_err) { - // Silent - } -} - -export function initSentry(): void { - try { - if (!isActive() || initialized) return; - initialized = true; - Sentry.init({ - dsn: process.env.EXPO_PUBLIC_SENTRY_DSN, - enableNativeCrashHandling: true, - beforeSend: (event) => { - forwardEventToRemote(event); - return event; - }, - }); - const projectGroupId = process.env.EXPO_PUBLIC_PROJECT_GROUP_ID; - if (projectGroupId) { - Sentry.setTag("projectGroupId", projectGroupId); - } - } catch (_err) { - // Silent — Sentry must never crash the host app - } -} diff --git a/apps/mobile/__create/testflight-logger.test.ts b/apps/mobile/__create/testflight-logger.test.ts deleted file mode 100644 index 079b4bb..0000000 --- a/apps/mobile/__create/testflight-logger.test.ts +++ /dev/null @@ -1,428 +0,0 @@ -let mockSendLogsToRemote: jest.Mock; -let mockGetItem: jest.Mock; -let mockSetItem: jest.Mock; -let mockRemoveItem: jest.Mock; -let mockFileStore: Record; -let capturedErrorHandler: ((error: Error, isFatal?: boolean) => void) | null; -let originalErrorUtils: unknown; - -const CRASH_FILE = "/doc/testflight_crash_logs.json"; - -const STORAGE_KEY = "testflight_logger_pending_logs"; -let originalDev: boolean; - -function setDevMode(value: boolean) { - (globalThis as Record).__DEV__ = value; -} - -beforeEach(() => { - originalDev = (globalThis as Record).__DEV__ as boolean; - jest.resetModules(); - jest.useFakeTimers(); - process.env.EXPO_PUBLIC_CREATE_ENV = "PRODUCTION"; - - mockSendLogsToRemote = jest.fn().mockResolvedValue({ success: true }); - mockGetItem = jest.fn().mockResolvedValue(null); - mockSetItem = jest.fn().mockResolvedValue(undefined); - mockRemoveItem = jest.fn().mockResolvedValue(undefined); - mockFileStore = {}; - - capturedErrorHandler = null; - originalErrorUtils = (globalThis as Record).ErrorUtils; - (globalThis as Record).ErrorUtils = { - getGlobalHandler: () => () => {}, - setGlobalHandler: (handler: (error: Error, isFatal?: boolean) => void) => { - capturedErrorHandler = handler; - }, - }; - - jest.doMock("./report-error-to-remote", () => ({ - sendLogsToRemote: mockSendLogsToRemote, - })); - - jest.doMock("@react-native-async-storage/async-storage", () => ({ - getItem: mockGetItem, - setItem: mockSetItem, - removeItem: mockRemoveItem, - })); - - jest.doMock("expo-file-system", () => { - class MockFile { - uri: string; - constructor(directory: string, name: string) { - this.uri = `${directory}/${name}`; - } - get exists() { - return Object.prototype.hasOwnProperty.call(mockFileStore, this.uri); - } - create() { - if (!(this.uri in mockFileStore)) mockFileStore[this.uri] = ""; - } - delete() { - delete mockFileStore[this.uri]; - } - write(content: string) { - mockFileStore[this.uri] = content; - } - textSync() { - return mockFileStore[this.uri] ?? ""; - } - } - return { File: MockFile, Paths: { document: "/doc" } }; - }); -}); - -afterEach(() => { - jest.useRealTimers(); - setDevMode(originalDev); - delete process.env.EXPO_PUBLIC_CREATE_ENV; - (globalThis as Record).ErrorUtils = originalErrorUtils; -}); - -function loadModule() { - return require("./testflight-logger") as typeof import("./testflight-logger"); -} - -describe("initTestFlightLogger", () => { - it("is a no-op when __DEV__ is true", async () => { - setDevMode(true); - const { initTestFlightLogger, getTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - - expect(getTestFlightLogger()).toBeNull(); - expect(mockSendLogsToRemote).not.toHaveBeenCalled(); - }); - - it("is a no-op when EXPO_PUBLIC_CREATE_ENV is DEVELOPMENT", async () => { - setDevMode(false); - process.env.EXPO_PUBLIC_CREATE_ENV = "DEVELOPMENT"; - const { initTestFlightLogger, getTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - - expect(getTestFlightLogger()).toBeNull(); - }); - - it("activates when not in dev mode", async () => { - setDevMode(false); - const { initTestFlightLogger, getTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - const logger = getTestFlightLogger(); - expect(logger).not.toBeNull(); - expect(logger).toHaveProperty("logError"); - }); - - it("only creates one instance on multiple calls", async () => { - setDevMode(false); - const { initTestFlightLogger, getTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - const first = getTestFlightLogger(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - const second = getTestFlightLogger(); - - expect(first).toBe(second); - }); -}); - -describe("console patching", () => { - it("intercepts console.log and buffers the message", async () => { - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - console.log("test message"); - - await jest.advanceTimersByTimeAsync(5_000); - - expect(mockSendLogsToRemote).toHaveBeenCalled(); - const logs = mockSendLogsToRemote.mock.calls[0][0]; - const logMessage = logs.find( - (l: Record) => l.message === "test message", - ); - expect(logMessage).toBeDefined(); - expect(logMessage.level).toBe("log"); - expect(logMessage.source).toBe("TEST_FLIGHT"); - }); - - it("intercepts console.error", async () => { - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - console.error("bad thing"); - - await jest.advanceTimersByTimeAsync(5_000); - - expect(mockSendLogsToRemote).toHaveBeenCalled(); - const logs = mockSendLogsToRemote.mock.calls[0][0]; - const errorLog = logs.find( - (l: Record) => l.message === "bad thing", - ); - expect(errorLog).toBeDefined(); - expect(errorLog.level).toBe("error"); - }); - - it("serializes non-string arguments as JSON", async () => { - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - console.log("count:", { x: 1 }); - - await jest.advanceTimersByTimeAsync(5_000); - - const logs = mockSendLogsToRemote.mock.calls[0][0]; - const entry = logs.find((l: Record) => - l.message.includes("count:"), - ); - expect(entry.message).toBe('count: {"x":1}'); - }); -}); - -describe("logError", () => { - it("immediately flushes error entries", async () => { - setDevMode(false); - const { initTestFlightLogger, getTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - const logger = getTestFlightLogger()!; - logger.logError("critical failure"); - - // Should flush without waiting for the 5s interval - await jest.advanceTimersByTimeAsync(0); - - expect(mockSendLogsToRemote).toHaveBeenCalled(); - const logs = mockSendLogsToRemote.mock.calls[0][0]; - expect(logs[0].message).toBe("critical failure"); - expect(logs[0].level).toBe("error"); - }); -}); - -describe("buffering and flushing", () => { - it("flushes buffer every 5 seconds", async () => { - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - console.log("entry 1"); - - // Not flushed yet at 3 seconds - await jest.advanceTimersByTimeAsync(3_000); - expect(mockSendLogsToRemote).not.toHaveBeenCalled(); - - // Flushed at 5 seconds - await jest.advanceTimersByTimeAsync(2_000); - expect(mockSendLogsToRemote).toHaveBeenCalledTimes(1); - }); - - it("auto-flushes when buffer reaches 50 entries", async () => { - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - for (let i = 0; i < 50; i++) { - console.log(`entry ${i}`); - } - - await jest.advanceTimersByTimeAsync(0); - expect(mockSendLogsToRemote).toHaveBeenCalled(); - }); -}); - -describe("persistence and retry", () => { - it("persists logs to AsyncStorage when flush fails", async () => { - mockSendLogsToRemote.mockResolvedValue({ success: false }); - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - console.log("will fail"); - - await jest.advanceTimersByTimeAsync(5_000); - - expect(mockSetItem).toHaveBeenCalledWith( - STORAGE_KEY, - expect.stringContaining("will fail"), - ); - }); - - it("restores persisted logs on startup and re-sends them", async () => { - const persistedLogs = [ - { - message: "old log", - timestamp: "2026-01-01T00:00:00Z", - level: "error", - source: "TEST_FLIGHT", - sessionId: "old-session", - }, - ]; - mockGetItem.mockResolvedValueOnce(JSON.stringify(persistedLogs)); - - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - expect(mockRemoveItem).toHaveBeenCalledWith(STORAGE_KEY); - expect(mockSendLogsToRemote).toHaveBeenCalledWith(persistedLogs); - }); - - it("re-persists restored logs if resend also fails", async () => { - const persistedLogs = [ - { - message: "stubborn log", - timestamp: "2026-01-01T00:00:00Z", - level: "error", - source: "TEST_FLIGHT", - sessionId: "old-session", - }, - ]; - mockGetItem - .mockResolvedValueOnce(JSON.stringify(persistedLogs)) - .mockResolvedValueOnce(null); - - mockSendLogsToRemote.mockResolvedValueOnce({ success: false }); - - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - expect(mockSetItem).toHaveBeenCalledWith( - STORAGE_KEY, - expect.stringContaining("stubborn log"), - ); - }); - - it("caps persisted entries at 200", async () => { - const existingLogs = Array.from({ length: 195 }, (_, i) => ({ - message: `existing ${i}`, - timestamp: "2026-01-01T00:00:00Z", - level: "log", - source: "TEST_FLIGHT", - sessionId: "s", - })); - - mockSendLogsToRemote.mockResolvedValue({ success: false }); - mockGetItem - .mockResolvedValueOnce(null) - .mockResolvedValueOnce(JSON.stringify(existingLogs)); - - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - for (let i = 0; i < 10; i++) { - console.log(`new ${i}`); - } - - await jest.advanceTimersByTimeAsync(5_000); - - const setItemCalls = mockSetItem.mock.calls; - const lastCall = setItemCalls[setItemCalls.length - 1]; - const saved = JSON.parse(lastCall[1]); - expect(saved.length).toBeLessThanOrEqual(200); - }); -}); - -describe("crash persistence", () => { - it("synchronously snapshots the buffer to the crash file on a fatal error", async () => { - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - console.log("breadcrumb before crash"); - capturedErrorHandler!(new Error("startup boom"), true); - - const crashFile = mockFileStore[CRASH_FILE]; - expect(crashFile).toContain("startup boom"); - expect(crashFile).toContain("breadcrumb before crash"); - }); - - it("does not snapshot the crash file for a non-fatal error", async () => { - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - capturedErrorHandler!(new Error("recoverable"), false); - - expect(mockFileStore[CRASH_FILE]).toBeUndefined(); - }); - - it("captures the in-flight batch when a fatal error triggers auto-flush", async () => { - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - // One short of the auto-flush threshold; the fatal error is the 50th - // entry, so addEntry's auto-flush empties `buffer` before - // persistBufferSync runs. - for (let i = 0; i < 49; i++) { - console.log(`entry ${i}`); - } - capturedErrorHandler!(new Error("boundary crash"), true); - - const crashFile = mockFileStore[CRASH_FILE]; - expect(crashFile).toContain("boundary crash"); - expect(crashFile).toContain("entry 0"); - }); - - it("ships crash-file logs on the next startup and clears the file", async () => { - mockFileStore[CRASH_FILE] = JSON.stringify([ - { - message: "[FATAL] crashed last run", - timestamp: "2026-01-01T00:00:00Z", - level: "error", - source: "TEST_FLIGHT", - sessionId: "prev", - }, - ]); - setDevMode(false); - const { initTestFlightLogger } = loadModule(); - - initTestFlightLogger(); - await jest.advanceTimersByTimeAsync(0); - - expect(mockSendLogsToRemote).toHaveBeenCalled(); - const sent = mockSendLogsToRemote.mock.calls[0][0]; - expect( - sent.some( - (entry: Record) => - entry.message === "[FATAL] crashed last run", - ), - ).toBe(true); - expect(mockFileStore[CRASH_FILE]).toBeUndefined(); - }); -}); diff --git a/apps/mobile/__create/testflight-logger.ts b/apps/mobile/__create/testflight-logger.ts deleted file mode 100644 index 6ec8285..0000000 --- a/apps/mobile/__create/testflight-logger.ts +++ /dev/null @@ -1,292 +0,0 @@ -import AsyncStorage from "@react-native-async-storage/async-storage"; -import { File, Paths } from "expo-file-system"; -import { AppState, type AppStateStatus } from "react-native"; -import { sendLogsToRemote } from "./report-error-to-remote"; - -const STORAGE_KEY = "testflight_logger_pending_logs"; -// Written synchronously from the crash handlers so logs survive a startup -// crash that tears down the JS runtime before the async network / AsyncStorage -// paths can finish. Shipped and cleared on the next launch. -const CRASH_FILE_NAME = "testflight_crash_logs.json"; -const MAX_STORED_ENTRIES = 200; -const MAX_BUFFER_SIZE = 50; -const FLUSH_INTERVAL_MS = 5_000; - -interface LogEntry { - message: string; - timestamp: string; - level: "log" | "info" | "warn" | "error" | "debug"; - source: "TEST_FLIGHT"; - sessionId: string; -} - -function isActive(): boolean { - return !__DEV__ && process.env.EXPO_PUBLIC_CREATE_ENV !== "DEVELOPMENT"; -} - -function generateSessionId(): string { - return `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`; -} - -let instance: TestFlightLogger | null = null; - -class TestFlightLogger { - private buffer: LogEntry[] = []; - // Entries spliced out of `buffer` by an in-flight `flush()` that hasn't - // confirmed delivery yet. Tracked so a crash mid-flush can still snapshot - // them — `buffer` alone would miss them. - private inFlightBatch: LogEntry[] = []; - private sessionId: string; - private flushTimer: ReturnType | null = null; - private originalConsole: Record void> = {}; - private isFlushing = false; - - constructor() { - this.sessionId = generateSessionId(); - } - - async start(): Promise { - try { - await this.restorePersistedLogs(); - this.patchConsole(); - this.hookUncaughtExceptions(); - this.hookUnhandledRejections(); - this.hookAppState(); - this.flushTimer = setInterval(() => { - this.flush(); - }, FLUSH_INTERVAL_MS); - } catch (_err) { - // Silent — the logger must never crash the host app - } - } - - logError(message: string): void { - try { - this.addEntry("error", message); - this.flush(); - } catch (_err) { - // Silent - } - } - - private addEntry(level: LogEntry["level"], message: string): void { - this.buffer.push({ - message, - timestamp: new Date().toISOString(), - level, - source: "TEST_FLIGHT", - sessionId: this.sessionId, - }); - if (this.buffer.length >= MAX_BUFFER_SIZE) { - this.flush(); - } - } - - private patchConsole(): void { - const levels = ["log", "info", "warn", "error", "debug"] as const; - for (const level of levels) { - this.originalConsole[level] = console[level].bind(console); - console[level] = (...args: unknown[]) => { - try { - const message = args - .map((arg) => { - if (typeof arg === "string") return arg; - try { - return JSON.stringify(arg); - } catch { - return String(arg); - } - }) - .join(" "); - this.addEntry(level, message); - } catch (_err) { - // Silent - } - this.originalConsole[level]?.(...args); - }; - } - } - - private hookUncaughtExceptions(): void { - const ErrorUtils = (globalThis as Record).ErrorUtils as - | { - getGlobalHandler: () => (error: Error, isFatal?: boolean) => void; - setGlobalHandler: ( - handler: (error: Error, isFatal?: boolean) => void, - ) => void; - } - | undefined; - - if (!ErrorUtils) return; - - const previousHandler = ErrorUtils.getGlobalHandler(); - ErrorUtils.setGlobalHandler((error: Error, isFatal?: boolean) => { - try { - const tag = isFatal ? "[FATAL]" : "[UNCAUGHT]"; - this.addEntry("error", `${tag} ${error.message}\n${error.stack ?? ""}`); - // Only a fatal error tears down the runtime before the async - // flush can finish, so only then is the synchronous crash-file - // snapshot needed. Non-fatal errors are delivered by flush / - // AsyncStorage retry; snapshotting them would just duplicate - // entries on the next launch. - if (isFatal) { - this.persistBufferSync(); - } - this.flush(); - } catch (_err) { - // Silent - } - previousHandler(error, isFatal); - }); - } - - private hookUnhandledRejections(): void { - const previous: ((event: PromiseRejectionEvent) => void) | null = - globalThis.onunhandledrejection; - globalThis.onunhandledrejection = (event: PromiseRejectionEvent) => { - try { - const reason = - event.reason instanceof Error - ? `${event.reason.message}\n${event.reason.stack ?? ""}` - : String(event.reason); - this.addEntry("error", `[UNHANDLED_REJECTION] ${reason}`); - this.flush(); - } catch (_err) { - // Silent - } - if (previous) { - previous(event); - } - }; - } - - private hookAppState(): void { - AppState.addEventListener("change", (state: AppStateStatus) => { - try { - this.addEntry("info", `[APP_STATE] ${state}`); - if (state === "background" || state === "inactive") { - this.flush(); - } - } catch (_err) { - // Silent - } - }); - } - - private async flush(): Promise { - if (this.isFlushing || this.buffer.length === 0) return; - this.isFlushing = true; - const batch = this.buffer.splice(0); - this.inFlightBatch = batch; - try { - const result = await sendLogsToRemote(batch); - if (!result.success) { - await this.persistLogs(batch); - } - } catch (_err) { - await this.persistLogs(batch); - } finally { - this.inFlightBatch = []; - this.isFlushing = false; - } - } - - private async persistLogs(logs: LogEntry[]): Promise { - try { - const raw = await AsyncStorage.getItem(STORAGE_KEY); - const existing: LogEntry[] = raw ? JSON.parse(raw) : []; - const merged = [...existing, ...logs].slice(-MAX_STORED_ENTRIES); - await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(merged)); - } catch (_err) { - // Silent - } - } - - // Synchronously snapshot pending logs to disk. Called from the crash - // handlers before the runtime is torn down, so a startup crash is still - // recoverable on the next launch. Includes any in-flight flush batch, - // since `addEntry`'s auto-flush may have already emptied `buffer`. - private persistBufferSync(): void { - try { - const pending = [...this.inFlightBatch, ...this.buffer]; - if (pending.length === 0) return; - const merged = [...this.readCrashLogsSync(), ...pending].slice( - -MAX_STORED_ENTRIES, - ); - const file = new File(Paths.document, CRASH_FILE_NAME); - if (file.exists) { - file.delete(); - } - file.create(); - file.write(JSON.stringify(merged)); - } catch (_err) { - // Silent — the logger must never crash the host app - } - } - - private readCrashLogsSync(): LogEntry[] { - try { - const file = new File(Paths.document, CRASH_FILE_NAME); - if (!file.exists) return []; - const parsed: unknown = JSON.parse(file.textSync()); - return Array.isArray(parsed) ? (parsed as LogEntry[]) : []; - } catch (_err) { - return []; - } - } - - private clearCrashFileSync(): void { - try { - const file = new File(Paths.document, CRASH_FILE_NAME); - if (file.exists) { - file.delete(); - } - } catch (_err) { - // Silent - } - } - - private async restorePersistedLogs(): Promise { - try { - const crashLogs = this.readCrashLogsSync(); - if (crashLogs.length > 0) { - this.clearCrashFileSync(); - } - const raw = await AsyncStorage.getItem(STORAGE_KEY); - if (raw) { - await AsyncStorage.removeItem(STORAGE_KEY); - } - const storedLogs: LogEntry[] = raw ? JSON.parse(raw) : []; - const logs = [...crashLogs, ...storedLogs]; - if (logs.length === 0) return; - const result = await sendLogsToRemote(logs); - if (!result.success) { - await this.persistLogs(logs); - } - } catch (_err) { - // Silent - } - } -} - -export function initTestFlightLogger(): void { - try { - if (!isActive()) return; - if (instance) return; - instance = new TestFlightLogger(); - instance.start(); - } catch (_err) { - // Silent - } -} - -export function getTestFlightLogger(): { - logError: (message: string) => void; -} | null { - try { - if (!isActive()) return null; - return instance; - } catch (_err) { - return null; - } -} diff --git a/apps/mobile/app.json b/apps/mobile/app.json deleted file mode 100644 index eb70818..0000000 --- a/apps/mobile/app.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "expo": { - "name": "Anything mobile app", - "version": "1.0.0", - "orientation": "portrait", - "icon": "./assets/images/icon.png", - "userInterfaceStyle": "automatic", - "newArchEnabled": true, - "ios": { - "supportsTablet": true, - "infoPlist": { - "ITSAppUsesNonExemptEncryption": false - } - }, - "android": { - "adaptiveIcon": { - "foregroundImage": "./assets/images/adaptive-icon.png", - "backgroundColor": "#ffffff" - }, - "permissions": [ - "android.permission.RECORD_AUDIO", - "android.permission.MODIFY_AUDIO_SETTINGS" - ], - "package": "xyz.create.CreateExpoEnvironment" - }, - "plugins": [ - [ - "expo-router", - { - "sitemap": false - } - ], - [ - "expo-splash-screen", - { - "image": "./assets/images/splash-icon.png", - "imageWidth": 200, - "resizeMode": "contain" - } - ], - "expo-audio", - [ - "expo-build-properties", - { - "ios": { - "useFrameworks": "static" - } - } - ], - [ - "expo-video", - { - "supportsBackgroundPlayback": true, - "supportsPictureInPicture": true - } - ], - "expo-font", - "expo-secure-store", - "expo-web-browser", - "@sentry/react-native/expo", - [ - "react-native-google-mobile-ads", - { - "androidAppId": "ca-app-pub-3940256099942544~3347511713", - "iosAppId": "ca-app-pub-3940256099942544~1458002511" - } - ] - ], - "web": { - "bundler": "metro", - "favicon": "./assets/images/favicon.png" - }, - "experiments": { - "typedRoutes": true - }, - "extra": { - "router": { - "origin": false - } - } - } -} \ No newline at end of file diff --git a/apps/mobile/assets/images/adaptive-icon.png b/apps/mobile/assets/images/adaptive-icon.png deleted file mode 100644 index eba6b34..0000000 Binary files a/apps/mobile/assets/images/adaptive-icon.png and /dev/null differ diff --git a/apps/mobile/assets/images/favicon.png b/apps/mobile/assets/images/favicon.png deleted file mode 100644 index 6e8eb9c..0000000 Binary files a/apps/mobile/assets/images/favicon.png and /dev/null differ diff --git a/apps/mobile/assets/images/icon.png b/apps/mobile/assets/images/icon.png deleted file mode 100644 index 917bc11..0000000 Binary files a/apps/mobile/assets/images/icon.png and /dev/null differ diff --git a/apps/mobile/assets/images/splash-icon.png b/apps/mobile/assets/images/splash-icon.png deleted file mode 100644 index eba6b34..0000000 Binary files a/apps/mobile/assets/images/splash-icon.png and /dev/null differ diff --git a/apps/mobile/babel.config.js b/apps/mobile/babel.config.js deleted file mode 100644 index 04bc056..0000000 --- a/apps/mobile/babel.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = (api) => { - api.cache(true); - return { - presets: [['babel-preset-expo', { unstable_transformImportMeta: true }]], - }; -}; diff --git a/apps/mobile/eas.json b/apps/mobile/eas.json deleted file mode 100644 index f959b91..0000000 --- a/apps/mobile/eas.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "cli": { - "version": ">= 15.0.15", - "appVersionSource": "remote" - }, - "build": { - "development": { - "developmentClient": true, - "distribution": "internal", - "env": { - "SENTRY_DISABLE_AUTO_UPLOAD": "true" - } - }, - "preview": { - "distribution": "internal", - "env": { - "SENTRY_DISABLE_AUTO_UPLOAD": "true" - } - }, - "production": { - "autoIncrement": true, - "android": { - "buildType": "app-bundle" - }, - "env": { - "SENTRY_DISABLE_AUTO_UPLOAD": "true" - } - } - }, - "submit": { - "production": { - "android": { - "serviceAccountKeyPath": "./google-service-account.json", - "track": "internal", - "releaseStatus": "draft", - "changesNotSentForReview": false - } - } - } -} diff --git a/apps/mobile/entrypoint.ts b/apps/mobile/entrypoint.ts deleted file mode 100644 index f1f2a24..0000000 --- a/apps/mobile/entrypoint.ts +++ /dev/null @@ -1,3 +0,0 @@ -import App from './App'; - -export default App; diff --git a/apps/mobile/fontawesome.css b/apps/mobile/fontawesome.css deleted file mode 100644 index 251d40a..0000000 --- a/apps/mobile/fontawesome.css +++ /dev/null @@ -1,8320 +0,0 @@ -/*! - * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2024 Fonticons, Inc. - */ -.fa { - font-family: var(--fa-style-family, "FontAwesome"); - font-weight: var(--fa-style, 900); -} - -.fas, -.far, -.fab, -.fa-solid, -.fa-regular, -.fa-brands, -.fa { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - display: var(--fa-display, inline-block); - font-style: normal; - font-variant: normal; - line-height: 1; - text-rendering: auto; -} - -.fas::before, -.far::before, -.fab::before, -.fa-solid::before, -.fa-regular::before, -.fa-brands::before, -.fa::before { - content: var(--fa); -} - -.fa-classic, -.fas, -.fa-solid, -.far, -.fa-regular { - font-family: "FontAwesome"; -} - -.fa-brands, -.fab { - font-family: "FontAwesome"; -} - -.fa-1x { - font-size: 1em; -} - -.fa-2x { - font-size: 2em; -} - -.fa-3x { - font-size: 3em; -} - -.fa-4x { - font-size: 4em; -} - -.fa-5x { - font-size: 5em; -} - -.fa-6x { - font-size: 6em; -} - -.fa-7x { - font-size: 7em; -} - -.fa-8x { - font-size: 8em; -} - -.fa-9x { - font-size: 9em; -} - -.fa-10x { - font-size: 10em; -} - -.fa-2xs { - font-size: 0.625em; - line-height: 0.1em; - vertical-align: 0.225em; -} - -.fa-xs { - font-size: 0.75em; - line-height: 0.08333em; - vertical-align: 0.125em; -} - -.fa-sm { - font-size: 0.875em; - line-height: 0.07143em; - vertical-align: 0.05357em; -} - -.fa-lg { - font-size: 1.25em; - line-height: 0.05em; - vertical-align: -0.075em; -} - -.fa-xl { - font-size: 1.5em; - line-height: 0.04167em; - vertical-align: -0.125em; -} - -.fa-2xl { - font-size: 2em; - line-height: 0.03125em; - vertical-align: -0.1875em; -} - -.fa-fw { - text-align: center; - width: 1.25em; -} - -.fa-ul { - list-style-type: none; - margin-left: var(--fa-li-margin, 2.5em); - padding-left: 0; -} -.fa-ul > li { - position: relative; -} - -.fa-li { - left: calc(-1 * var(--fa-li-width, 2em)); - position: absolute; - text-align: center; - width: var(--fa-li-width, 2em); - line-height: inherit; -} - -.fa-border { - border-color: var(--fa-border-color, #eee); - border-radius: var(--fa-border-radius, 0.1em); - border-style: var(--fa-border-style, solid); - border-width: var(--fa-border-width, 0.08em); - padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); -} - -.fa-pull-left { - float: left; - margin-right: var(--fa-pull-margin, 0.3em); -} - -.fa-pull-right { - float: right; - margin-left: var(--fa-pull-margin, 0.3em); -} - -.fa-beat { - animation-name: fa-beat; - animation-delay: var(--fa-animation-delay, 0s); - animation-direction: var(--fa-animation-direction, normal); - animation-duration: var(--fa-animation-duration, 1s); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-timing-function: var(--fa-animation-timing, ease-in-out); -} - -.fa-bounce { - animation-name: fa-bounce; - animation-delay: var(--fa-animation-delay, 0s); - animation-direction: var(--fa-animation-direction, normal); - animation-duration: var(--fa-animation-duration, 1s); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-timing-function: var( - --fa-animation-timing, - cubic-bezier(0.28, 0.84, 0.42, 1) - ); -} - -.fa-fade { - animation-name: fa-fade; - animation-delay: var(--fa-animation-delay, 0s); - animation-direction: var(--fa-animation-direction, normal); - animation-duration: var(--fa-animation-duration, 1s); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-timing-function: var( - --fa-animation-timing, - cubic-bezier(0.4, 0, 0.6, 1) - ); -} - -.fa-beat-fade { - animation-name: fa-beat-fade; - animation-delay: var(--fa-animation-delay, 0s); - animation-direction: var(--fa-animation-direction, normal); - animation-duration: var(--fa-animation-duration, 1s); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-timing-function: var( - --fa-animation-timing, - cubic-bezier(0.4, 0, 0.6, 1) - ); -} - -.fa-flip { - animation-name: fa-flip; - animation-delay: var(--fa-animation-delay, 0s); - animation-direction: var(--fa-animation-direction, normal); - animation-duration: var(--fa-animation-duration, 1s); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-timing-function: var(--fa-animation-timing, ease-in-out); -} - -.fa-shake { - animation-name: fa-shake; - animation-delay: var(--fa-animation-delay, 0s); - animation-direction: var(--fa-animation-direction, normal); - animation-duration: var(--fa-animation-duration, 1s); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-timing-function: var(--fa-animation-timing, linear); -} - -.fa-spin { - animation-name: fa-spin; - animation-delay: var(--fa-animation-delay, 0s); - animation-direction: var(--fa-animation-direction, normal); - animation-duration: var(--fa-animation-duration, 2s); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-timing-function: var(--fa-animation-timing, linear); -} - -.fa-spin-reverse { - --fa-animation-direction: reverse; -} - -.fa-pulse, -.fa-spin-pulse { - animation-name: fa-spin; - animation-direction: var(--fa-animation-direction, normal); - animation-duration: var(--fa-animation-duration, 1s); - animation-iteration-count: var(--fa-animation-iteration-count, infinite); - animation-timing-function: var(--fa-animation-timing, steps(8)); -} - -@media (prefers-reduced-motion: reduce) { - .fa-beat, - .fa-bounce, - .fa-fade, - .fa-beat-fade, - .fa-flip, - .fa-pulse, - .fa-shake, - .fa-spin, - .fa-spin-pulse { - animation-delay: -1ms; - animation-duration: 1ms; - animation-iteration-count: 1; - transition-delay: 0s; - transition-duration: 0s; - } -} - -@keyframes fa-beat { - 0%, - 90% { - transform: scale(1); - } - 45% { - transform: scale(var(--fa-beat-scale, 1.25)); - } -} - -@keyframes fa-bounce { - 0% { - transform: scale(1, 1) translateY(0); - } - 10% { - transform: scale( - var(--fa-bounce-start-scale-x, 1.1), - var(--fa-bounce-start-scale-y, 0.9) - ) - translateY(0); - } - 30% { - transform: scale( - var(--fa-bounce-jump-scale-x, 0.9), - var(--fa-bounce-jump-scale-y, 1.1) - ) - translateY(var(--fa-bounce-height, -0.5em)); - } - 50% { - transform: scale( - var(--fa-bounce-land-scale-x, 1.05), - var(--fa-bounce-land-scale-y, 0.95) - ) - translateY(0); - } - 57% { - transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); - } - 64% { - transform: scale(1, 1) translateY(0); - } - 100% { - transform: scale(1, 1) translateY(0); - } -} - -@keyframes fa-fade { - 50% { - opacity: var(--fa-fade-opacity, 0.4); - } -} - -@keyframes fa-beat-fade { - 0%, - 100% { - opacity: var(--fa-beat-fade-opacity, 0.4); - transform: scale(1); - } - 50% { - opacity: 1; - transform: scale(var(--fa-beat-fade-scale, 1.125)); - } -} - -@keyframes fa-flip { - 50% { - transform: rotate3d( - var(--fa-flip-x, 0), - var(--fa-flip-y, 1), - var(--fa-flip-z, 0), - var(--fa-flip-angle, -180deg) - ); - } -} - -@keyframes fa-shake { - 0% { - transform: rotate(-15deg); - } - 4% { - transform: rotate(15deg); - } - 8%, - 24% { - transform: rotate(-18deg); - } - 12%, - 28% { - transform: rotate(18deg); - } - 16% { - transform: rotate(-22deg); - } - 20% { - transform: rotate(22deg); - } - 32% { - transform: rotate(-12deg); - } - 36% { - transform: rotate(12deg); - } - 40%, - 100% { - transform: rotate(0deg); - } -} - -@keyframes fa-spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} - -.fa-rotate-90 { - transform: rotate(90deg); -} - -.fa-rotate-180 { - transform: rotate(180deg); -} - -.fa-rotate-270 { - transform: rotate(270deg); -} - -.fa-flip-horizontal { - transform: scale(-1, 1); -} - -.fa-flip-vertical { - transform: scale(1, -1); -} - -.fa-flip-both, -.fa-flip-horizontal.fa-flip-vertical { - transform: scale(-1, -1); -} - -.fa-rotate-by { - transform: rotate(var(--fa-rotate-angle, 0)); -} - -.fa-stack { - display: inline-block; - height: 2em; - line-height: 2em; - position: relative; - vertical-align: middle; - width: 2.5em; -} - -.fa-stack-1x, -.fa-stack-2x { - left: 0; - position: absolute; - text-align: center; - width: 100%; - z-index: var(--fa-stack-z-index, auto); -} - -.fa-stack-1x { - line-height: inherit; -} - -.fa-stack-2x { - font-size: 2em; -} - -.fa-inverse { - color: var(--fa-inverse, #fff); -} - -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ - -.fa-0 { - --fa: "\30"; -} - -.fa-1 { - --fa: "\31"; -} - -.fa-2 { - --fa: "\32"; -} - -.fa-3 { - --fa: "\33"; -} - -.fa-4 { - --fa: "\34"; -} - -.fa-5 { - --fa: "\35"; -} - -.fa-6 { - --fa: "\36"; -} - -.fa-7 { - --fa: "\37"; -} - -.fa-8 { - --fa: "\38"; -} - -.fa-9 { - --fa: "\39"; -} - -.fa-fill-drip { - --fa: "\f576"; -} - -.fa-arrows-to-circle { - --fa: "\e4bd"; -} - -.fa-circle-chevron-right { - --fa: "\f138"; -} - -.fa-chevron-circle-right { - --fa: "\f138"; -} - -.fa-at { - --fa: "\40"; -} - -.fa-trash-can { - --fa: "\f2ed"; -} - -.fa-trash-alt { - --fa: "\f2ed"; -} - -.fa-text-height { - --fa: "\f034"; -} - -.fa-user-xmark { - --fa: "\f235"; -} - -.fa-user-times { - --fa: "\f235"; -} - -.fa-stethoscope { - --fa: "\f0f1"; -} - -.fa-message { - --fa: "\f27a"; -} - -.fa-comment-alt { - --fa: "\f27a"; -} - -.fa-info { - --fa: "\f129"; -} - -.fa-down-left-and-up-right-to-center { - --fa: "\f422"; -} - -.fa-compress-alt { - --fa: "\f422"; -} - -.fa-explosion { - --fa: "\e4e9"; -} - -.fa-file-lines { - --fa: "\f15c"; -} - -.fa-file-alt { - --fa: "\f15c"; -} - -.fa-file-text { - --fa: "\f15c"; -} - -.fa-wave-square { - --fa: "\f83e"; -} - -.fa-ring { - --fa: "\f70b"; -} - -.fa-building-un { - --fa: "\e4d9"; -} - -.fa-dice-three { - --fa: "\f527"; -} - -.fa-calendar-days { - --fa: "\f073"; -} - -.fa-calendar-alt { - --fa: "\f073"; -} - -.fa-anchor-circle-check { - --fa: "\e4aa"; -} - -.fa-building-circle-arrow-right { - --fa: "\e4d1"; -} - -.fa-volleyball { - --fa: "\f45f"; -} - -.fa-volleyball-ball { - --fa: "\f45f"; -} - -.fa-arrows-up-to-line { - --fa: "\e4c2"; -} - -.fa-sort-down { - --fa: "\f0dd"; -} - -.fa-sort-desc { - --fa: "\f0dd"; -} - -.fa-circle-minus { - --fa: "\f056"; -} - -.fa-minus-circle { - --fa: "\f056"; -} - -.fa-door-open { - --fa: "\f52b"; -} - -.fa-right-from-bracket { - --fa: "\f2f5"; -} - -.fa-sign-out-alt { - --fa: "\f2f5"; -} - -.fa-atom { - --fa: "\f5d2"; -} - -.fa-soap { - --fa: "\e06e"; -} - -.fa-icons { - --fa: "\f86d"; -} - -.fa-heart-music-camera-bolt { - --fa: "\f86d"; -} - -.fa-microphone-lines-slash { - --fa: "\f539"; -} - -.fa-microphone-alt-slash { - --fa: "\f539"; -} - -.fa-bridge-circle-check { - --fa: "\e4c9"; -} - -.fa-pump-medical { - --fa: "\e06a"; -} - -.fa-fingerprint { - --fa: "\f577"; -} - -.fa-hand-point-right { - --fa: "\f0a4"; -} - -.fa-magnifying-glass-location { - --fa: "\f689"; -} - -.fa-search-location { - --fa: "\f689"; -} - -.fa-forward-step { - --fa: "\f051"; -} - -.fa-step-forward { - --fa: "\f051"; -} - -.fa-face-smile-beam { - --fa: "\f5b8"; -} - -.fa-smile-beam { - --fa: "\f5b8"; -} - -.fa-flag-checkered { - --fa: "\f11e"; -} - -.fa-football { - --fa: "\f44e"; -} - -.fa-football-ball { - --fa: "\f44e"; -} - -.fa-school-circle-exclamation { - --fa: "\e56c"; -} - -.fa-crop { - --fa: "\f125"; -} - -.fa-angles-down { - --fa: "\f103"; -} - -.fa-angle-double-down { - --fa: "\f103"; -} - -.fa-users-rectangle { - --fa: "\e594"; -} - -.fa-people-roof { - --fa: "\e537"; -} - -.fa-people-line { - --fa: "\e534"; -} - -.fa-beer-mug-empty { - --fa: "\f0fc"; -} - -.fa-beer { - --fa: "\f0fc"; -} - -.fa-diagram-predecessor { - --fa: "\e477"; -} - -.fa-arrow-up-long { - --fa: "\f176"; -} - -.fa-long-arrow-up { - --fa: "\f176"; -} - -.fa-fire-flame-simple { - --fa: "\f46a"; -} - -.fa-burn { - --fa: "\f46a"; -} - -.fa-person { - --fa: "\f183"; -} - -.fa-male { - --fa: "\f183"; -} - -.fa-laptop { - --fa: "\f109"; -} - -.fa-file-csv { - --fa: "\f6dd"; -} - -.fa-menorah { - --fa: "\f676"; -} - -.fa-truck-plane { - --fa: "\e58f"; -} - -.fa-record-vinyl { - --fa: "\f8d9"; -} - -.fa-face-grin-stars { - --fa: "\f587"; -} - -.fa-grin-stars { - --fa: "\f587"; -} - -.fa-bong { - --fa: "\f55c"; -} - -.fa-spaghetti-monster-flying { - --fa: "\f67b"; -} - -.fa-pastafarianism { - --fa: "\f67b"; -} - -.fa-arrow-down-up-across-line { - --fa: "\e4af"; -} - -.fa-spoon { - --fa: "\f2e5"; -} - -.fa-utensil-spoon { - --fa: "\f2e5"; -} - -.fa-jar-wheat { - --fa: "\e517"; -} - -.fa-envelopes-bulk { - --fa: "\f674"; -} - -.fa-mail-bulk { - --fa: "\f674"; -} - -.fa-file-circle-exclamation { - --fa: "\e4eb"; -} - -.fa-circle-h { - --fa: "\f47e"; -} - -.fa-hospital-symbol { - --fa: "\f47e"; -} - -.fa-pager { - --fa: "\f815"; -} - -.fa-address-book { - --fa: "\f2b9"; -} - -.fa-contact-book { - --fa: "\f2b9"; -} - -.fa-strikethrough { - --fa: "\f0cc"; -} - -.fa-k { - --fa: "\4b"; -} - -.fa-landmark-flag { - --fa: "\e51c"; -} - -.fa-pencil { - --fa: "\f303"; -} - -.fa-pencil-alt { - --fa: "\f303"; -} - -.fa-backward { - --fa: "\f04a"; -} - -.fa-caret-right { - --fa: "\f0da"; -} - -.fa-comments { - --fa: "\f086"; -} - -.fa-paste { - --fa: "\f0ea"; -} - -.fa-file-clipboard { - --fa: "\f0ea"; -} - -.fa-code-pull-request { - --fa: "\e13c"; -} - -.fa-clipboard-list { - --fa: "\f46d"; -} - -.fa-truck-ramp-box { - --fa: "\f4de"; -} - -.fa-truck-loading { - --fa: "\f4de"; -} - -.fa-user-check { - --fa: "\f4fc"; -} - -.fa-vial-virus { - --fa: "\e597"; -} - -.fa-sheet-plastic { - --fa: "\e571"; -} - -.fa-blog { - --fa: "\f781"; -} - -.fa-user-ninja { - --fa: "\f504"; -} - -.fa-person-arrow-up-from-line { - --fa: "\e539"; -} - -.fa-scroll-torah { - --fa: "\f6a0"; -} - -.fa-torah { - --fa: "\f6a0"; -} - -.fa-broom-ball { - --fa: "\f458"; -} - -.fa-quidditch { - --fa: "\f458"; -} - -.fa-quidditch-broom-ball { - --fa: "\f458"; -} - -.fa-toggle-off { - --fa: "\f204"; -} - -.fa-box-archive { - --fa: "\f187"; -} - -.fa-archive { - --fa: "\f187"; -} - -.fa-person-drowning { - --fa: "\e545"; -} - -.fa-arrow-down-9-1 { - --fa: "\f886"; -} - -.fa-sort-numeric-desc { - --fa: "\f886"; -} - -.fa-sort-numeric-down-alt { - --fa: "\f886"; -} - -.fa-face-grin-tongue-squint { - --fa: "\f58a"; -} - -.fa-grin-tongue-squint { - --fa: "\f58a"; -} - -.fa-spray-can { - --fa: "\f5bd"; -} - -.fa-truck-monster { - --fa: "\f63b"; -} - -.fa-w { - --fa: "\57"; -} - -.fa-earth-africa { - --fa: "\f57c"; -} - -.fa-globe-africa { - --fa: "\f57c"; -} - -.fa-rainbow { - --fa: "\f75b"; -} - -.fa-circle-notch { - --fa: "\f1ce"; -} - -.fa-tablet-screen-button { - --fa: "\f3fa"; -} - -.fa-tablet-alt { - --fa: "\f3fa"; -} - -.fa-paw { - --fa: "\f1b0"; -} - -.fa-cloud { - --fa: "\f0c2"; -} - -.fa-trowel-bricks { - --fa: "\e58a"; -} - -.fa-face-flushed { - --fa: "\f579"; -} - -.fa-flushed { - --fa: "\f579"; -} - -.fa-hospital-user { - --fa: "\f80d"; -} - -.fa-tent-arrow-left-right { - --fa: "\e57f"; -} - -.fa-gavel { - --fa: "\f0e3"; -} - -.fa-legal { - --fa: "\f0e3"; -} - -.fa-binoculars { - --fa: "\f1e5"; -} - -.fa-microphone-slash { - --fa: "\f131"; -} - -.fa-box-tissue { - --fa: "\e05b"; -} - -.fa-motorcycle { - --fa: "\f21c"; -} - -.fa-bell-concierge { - --fa: "\f562"; -} - -.fa-concierge-bell { - --fa: "\f562"; -} - -.fa-pen-ruler { - --fa: "\f5ae"; -} - -.fa-pencil-ruler { - --fa: "\f5ae"; -} - -.fa-people-arrows { - --fa: "\e068"; -} - -.fa-people-arrows-left-right { - --fa: "\e068"; -} - -.fa-mars-and-venus-burst { - --fa: "\e523"; -} - -.fa-square-caret-right { - --fa: "\f152"; -} - -.fa-caret-square-right { - --fa: "\f152"; -} - -.fa-scissors { - --fa: "\f0c4"; -} - -.fa-cut { - --fa: "\f0c4"; -} - -.fa-sun-plant-wilt { - --fa: "\e57a"; -} - -.fa-toilets-portable { - --fa: "\e584"; -} - -.fa-hockey-puck { - --fa: "\f453"; -} - -.fa-table { - --fa: "\f0ce"; -} - -.fa-magnifying-glass-arrow-right { - --fa: "\e521"; -} - -.fa-tachograph-digital { - --fa: "\f566"; -} - -.fa-digital-tachograph { - --fa: "\f566"; -} - -.fa-users-slash { - --fa: "\e073"; -} - -.fa-clover { - --fa: "\e139"; -} - -.fa-reply { - --fa: "\f3e5"; -} - -.fa-mail-reply { - --fa: "\f3e5"; -} - -.fa-star-and-crescent { - --fa: "\f699"; -} - -.fa-house-fire { - --fa: "\e50c"; -} - -.fa-square-minus { - --fa: "\f146"; -} - -.fa-minus-square { - --fa: "\f146"; -} - -.fa-helicopter { - --fa: "\f533"; -} - -.fa-compass { - --fa: "\f14e"; -} - -.fa-square-caret-down { - --fa: "\f150"; -} - -.fa-caret-square-down { - --fa: "\f150"; -} - -.fa-file-circle-question { - --fa: "\e4ef"; -} - -.fa-laptop-code { - --fa: "\f5fc"; -} - -.fa-swatchbook { - --fa: "\f5c3"; -} - -.fa-prescription-bottle { - --fa: "\f485"; -} - -.fa-bars { - --fa: "\f0c9"; -} - -.fa-navicon { - --fa: "\f0c9"; -} - -.fa-people-group { - --fa: "\e533"; -} - -.fa-hourglass-end { - --fa: "\f253"; -} - -.fa-hourglass-3 { - --fa: "\f253"; -} - -.fa-heart-crack { - --fa: "\f7a9"; -} - -.fa-heart-broken { - --fa: "\f7a9"; -} - -.fa-square-up-right { - --fa: "\f360"; -} - -.fa-external-link-square-alt { - --fa: "\f360"; -} - -.fa-face-kiss-beam { - --fa: "\f597"; -} - -.fa-kiss-beam { - --fa: "\f597"; -} - -.fa-film { - --fa: "\f008"; -} - -.fa-ruler-horizontal { - --fa: "\f547"; -} - -.fa-people-robbery { - --fa: "\e536"; -} - -.fa-lightbulb { - --fa: "\f0eb"; -} - -.fa-caret-left { - --fa: "\f0d9"; -} - -.fa-circle-exclamation { - --fa: "\f06a"; -} - -.fa-exclamation-circle { - --fa: "\f06a"; -} - -.fa-school-circle-xmark { - --fa: "\e56d"; -} - -.fa-arrow-right-from-bracket { - --fa: "\f08b"; -} - -.fa-sign-out { - --fa: "\f08b"; -} - -.fa-circle-chevron-down { - --fa: "\f13a"; -} - -.fa-chevron-circle-down { - --fa: "\f13a"; -} - -.fa-unlock-keyhole { - --fa: "\f13e"; -} - -.fa-unlock-alt { - --fa: "\f13e"; -} - -.fa-cloud-showers-heavy { - --fa: "\f740"; -} - -.fa-headphones-simple { - --fa: "\f58f"; -} - -.fa-headphones-alt { - --fa: "\f58f"; -} - -.fa-sitemap { - --fa: "\f0e8"; -} - -.fa-circle-dollar-to-slot { - --fa: "\f4b9"; -} - -.fa-donate { - --fa: "\f4b9"; -} - -.fa-memory { - --fa: "\f538"; -} - -.fa-road-spikes { - --fa: "\e568"; -} - -.fa-fire-burner { - --fa: "\e4f1"; -} - -.fa-flag { - --fa: "\f024"; -} - -.fa-hanukiah { - --fa: "\f6e6"; -} - -.fa-feather { - --fa: "\f52d"; -} - -.fa-volume-low { - --fa: "\f027"; -} - -.fa-volume-down { - --fa: "\f027"; -} - -.fa-comment-slash { - --fa: "\f4b3"; -} - -.fa-cloud-sun-rain { - --fa: "\f743"; -} - -.fa-compress { - --fa: "\f066"; -} - -.fa-wheat-awn { - --fa: "\e2cd"; -} - -.fa-wheat-alt { - --fa: "\e2cd"; -} - -.fa-ankh { - --fa: "\f644"; -} - -.fa-hands-holding-child { - --fa: "\e4fa"; -} - -.fa-asterisk { - --fa: "\2a"; -} - -.fa-square-check { - --fa: "\f14a"; -} - -.fa-check-square { - --fa: "\f14a"; -} - -.fa-peseta-sign { - --fa: "\e221"; -} - -.fa-heading { - --fa: "\f1dc"; -} - -.fa-header { - --fa: "\f1dc"; -} - -.fa-ghost { - --fa: "\f6e2"; -} - -.fa-list { - --fa: "\f03a"; -} - -.fa-list-squares { - --fa: "\f03a"; -} - -.fa-square-phone-flip { - --fa: "\f87b"; -} - -.fa-phone-square-alt { - --fa: "\f87b"; -} - -.fa-cart-plus { - --fa: "\f217"; -} - -.fa-gamepad { - --fa: "\f11b"; -} - -.fa-circle-dot { - --fa: "\f192"; -} - -.fa-dot-circle { - --fa: "\f192"; -} - -.fa-face-dizzy { - --fa: "\f567"; -} - -.fa-dizzy { - --fa: "\f567"; -} - -.fa-egg { - --fa: "\f7fb"; -} - -.fa-house-medical-circle-xmark { - --fa: "\e513"; -} - -.fa-campground { - --fa: "\f6bb"; -} - -.fa-folder-plus { - --fa: "\f65e"; -} - -.fa-futbol { - --fa: "\f1e3"; -} - -.fa-futbol-ball { - --fa: "\f1e3"; -} - -.fa-soccer-ball { - --fa: "\f1e3"; -} - -.fa-paintbrush { - --fa: "\f1fc"; -} - -.fa-paint-brush { - --fa: "\f1fc"; -} - -.fa-lock { - --fa: "\f023"; -} - -.fa-gas-pump { - --fa: "\f52f"; -} - -.fa-hot-tub-person { - --fa: "\f593"; -} - -.fa-hot-tub { - --fa: "\f593"; -} - -.fa-map-location { - --fa: "\f59f"; -} - -.fa-map-marked { - --fa: "\f59f"; -} - -.fa-house-flood-water { - --fa: "\e50e"; -} - -.fa-tree { - --fa: "\f1bb"; -} - -.fa-bridge-lock { - --fa: "\e4cc"; -} - -.fa-sack-dollar { - --fa: "\f81d"; -} - -.fa-pen-to-square { - --fa: "\f044"; -} - -.fa-edit { - --fa: "\f044"; -} - -.fa-car-side { - --fa: "\f5e4"; -} - -.fa-share-nodes { - --fa: "\f1e0"; -} - -.fa-share-alt { - --fa: "\f1e0"; -} - -.fa-heart-circle-minus { - --fa: "\e4ff"; -} - -.fa-hourglass-half { - --fa: "\f252"; -} - -.fa-hourglass-2 { - --fa: "\f252"; -} - -.fa-microscope { - --fa: "\f610"; -} - -.fa-sink { - --fa: "\e06d"; -} - -.fa-bag-shopping { - --fa: "\f290"; -} - -.fa-shopping-bag { - --fa: "\f290"; -} - -.fa-arrow-down-z-a { - --fa: "\f881"; -} - -.fa-sort-alpha-desc { - --fa: "\f881"; -} - -.fa-sort-alpha-down-alt { - --fa: "\f881"; -} - -.fa-mitten { - --fa: "\f7b5"; -} - -.fa-person-rays { - --fa: "\e54d"; -} - -.fa-users { - --fa: "\f0c0"; -} - -.fa-eye-slash { - --fa: "\f070"; -} - -.fa-flask-vial { - --fa: "\e4f3"; -} - -.fa-hand { - --fa: "\f256"; -} - -.fa-hand-paper { - --fa: "\f256"; -} - -.fa-om { - --fa: "\f679"; -} - -.fa-worm { - --fa: "\e599"; -} - -.fa-house-circle-xmark { - --fa: "\e50b"; -} - -.fa-plug { - --fa: "\f1e6"; -} - -.fa-chevron-up { - --fa: "\f077"; -} - -.fa-hand-spock { - --fa: "\f259"; -} - -.fa-stopwatch { - --fa: "\f2f2"; -} - -.fa-face-kiss { - --fa: "\f596"; -} - -.fa-kiss { - --fa: "\f596"; -} - -.fa-bridge-circle-xmark { - --fa: "\e4cb"; -} - -.fa-face-grin-tongue { - --fa: "\f589"; -} - -.fa-grin-tongue { - --fa: "\f589"; -} - -.fa-chess-bishop { - --fa: "\f43a"; -} - -.fa-face-grin-wink { - --fa: "\f58c"; -} - -.fa-grin-wink { - --fa: "\f58c"; -} - -.fa-ear-deaf { - --fa: "\f2a4"; -} - -.fa-deaf { - --fa: "\f2a4"; -} - -.fa-deafness { - --fa: "\f2a4"; -} - -.fa-hard-of-hearing { - --fa: "\f2a4"; -} - -.fa-road-circle-check { - --fa: "\e564"; -} - -.fa-dice-five { - --fa: "\f523"; -} - -.fa-square-rss { - --fa: "\f143"; -} - -.fa-rss-square { - --fa: "\f143"; -} - -.fa-land-mine-on { - --fa: "\e51b"; -} - -.fa-i-cursor { - --fa: "\f246"; -} - -.fa-stamp { - --fa: "\f5bf"; -} - -.fa-stairs { - --fa: "\e289"; -} - -.fa-i { - --fa: "\49"; -} - -.fa-hryvnia-sign { - --fa: "\f6f2"; -} - -.fa-hryvnia { - --fa: "\f6f2"; -} - -.fa-pills { - --fa: "\f484"; -} - -.fa-face-grin-wide { - --fa: "\f581"; -} - -.fa-grin-alt { - --fa: "\f581"; -} - -.fa-tooth { - --fa: "\f5c9"; -} - -.fa-v { - --fa: "\56"; -} - -.fa-bangladeshi-taka-sign { - --fa: "\e2e6"; -} - -.fa-bicycle { - --fa: "\f206"; -} - -.fa-staff-snake { - --fa: "\e579"; -} - -.fa-rod-asclepius { - --fa: "\e579"; -} - -.fa-rod-snake { - --fa: "\e579"; -} - -.fa-staff-aesculapius { - --fa: "\e579"; -} - -.fa-head-side-cough-slash { - --fa: "\e062"; -} - -.fa-truck-medical { - --fa: "\f0f9"; -} - -.fa-ambulance { - --fa: "\f0f9"; -} - -.fa-wheat-awn-circle-exclamation { - --fa: "\e598"; -} - -.fa-snowman { - --fa: "\f7d0"; -} - -.fa-mortar-pestle { - --fa: "\f5a7"; -} - -.fa-road-barrier { - --fa: "\e562"; -} - -.fa-school { - --fa: "\f549"; -} - -.fa-igloo { - --fa: "\f7ae"; -} - -.fa-joint { - --fa: "\f595"; -} - -.fa-angle-right { - --fa: "\f105"; -} - -.fa-horse { - --fa: "\f6f0"; -} - -.fa-q { - --fa: "\51"; -} - -.fa-g { - --fa: "\47"; -} - -.fa-notes-medical { - --fa: "\f481"; -} - -.fa-temperature-half { - --fa: "\f2c9"; -} - -.fa-temperature-2 { - --fa: "\f2c9"; -} - -.fa-thermometer-2 { - --fa: "\f2c9"; -} - -.fa-thermometer-half { - --fa: "\f2c9"; -} - -.fa-dong-sign { - --fa: "\e169"; -} - -.fa-capsules { - --fa: "\f46b"; -} - -.fa-poo-storm { - --fa: "\f75a"; -} - -.fa-poo-bolt { - --fa: "\f75a"; -} - -.fa-face-frown-open { - --fa: "\f57a"; -} - -.fa-frown-open { - --fa: "\f57a"; -} - -.fa-hand-point-up { - --fa: "\f0a6"; -} - -.fa-money-bill { - --fa: "\f0d6"; -} - -.fa-bookmark { - --fa: "\f02e"; -} - -.fa-align-justify { - --fa: "\f039"; -} - -.fa-umbrella-beach { - --fa: "\f5ca"; -} - -.fa-helmet-un { - --fa: "\e503"; -} - -.fa-bullseye { - --fa: "\f140"; -} - -.fa-bacon { - --fa: "\f7e5"; -} - -.fa-hand-point-down { - --fa: "\f0a7"; -} - -.fa-arrow-up-from-bracket { - --fa: "\e09a"; -} - -.fa-folder { - --fa: "\f07b"; -} - -.fa-folder-blank { - --fa: "\f07b"; -} - -.fa-file-waveform { - --fa: "\f478"; -} - -.fa-file-medical-alt { - --fa: "\f478"; -} - -.fa-radiation { - --fa: "\f7b9"; -} - -.fa-chart-simple { - --fa: "\e473"; -} - -.fa-mars-stroke { - --fa: "\f229"; -} - -.fa-vial { - --fa: "\f492"; -} - -.fa-gauge { - --fa: "\f624"; -} - -.fa-dashboard { - --fa: "\f624"; -} - -.fa-gauge-med { - --fa: "\f624"; -} - -.fa-tachometer-alt-average { - --fa: "\f624"; -} - -.fa-wand-magic-sparkles { - --fa: "\e2ca"; -} - -.fa-magic-wand-sparkles { - --fa: "\e2ca"; -} - -.fa-e { - --fa: "\45"; -} - -.fa-pen-clip { - --fa: "\f305"; -} - -.fa-pen-alt { - --fa: "\f305"; -} - -.fa-bridge-circle-exclamation { - --fa: "\e4ca"; -} - -.fa-user { - --fa: "\f007"; -} - -.fa-school-circle-check { - --fa: "\e56b"; -} - -.fa-dumpster { - --fa: "\f793"; -} - -.fa-van-shuttle { - --fa: "\f5b6"; -} - -.fa-shuttle-van { - --fa: "\f5b6"; -} - -.fa-building-user { - --fa: "\e4da"; -} - -.fa-square-caret-left { - --fa: "\f191"; -} - -.fa-caret-square-left { - --fa: "\f191"; -} - -.fa-highlighter { - --fa: "\f591"; -} - -.fa-key { - --fa: "\f084"; -} - -.fa-bullhorn { - --fa: "\f0a1"; -} - -.fa-globe { - --fa: "\f0ac"; -} - -.fa-synagogue { - --fa: "\f69b"; -} - -.fa-person-half-dress { - --fa: "\e548"; -} - -.fa-road-bridge { - --fa: "\e563"; -} - -.fa-location-arrow { - --fa: "\f124"; -} - -.fa-c { - --fa: "\43"; -} - -.fa-tablet-button { - --fa: "\f10a"; -} - -.fa-building-lock { - --fa: "\e4d6"; -} - -.fa-pizza-slice { - --fa: "\f818"; -} - -.fa-money-bill-wave { - --fa: "\f53a"; -} - -.fa-chart-area { - --fa: "\f1fe"; -} - -.fa-area-chart { - --fa: "\f1fe"; -} - -.fa-house-flag { - --fa: "\e50d"; -} - -.fa-person-circle-minus { - --fa: "\e540"; -} - -.fa-ban { - --fa: "\f05e"; -} - -.fa-cancel { - --fa: "\f05e"; -} - -.fa-camera-rotate { - --fa: "\e0d8"; -} - -.fa-spray-can-sparkles { - --fa: "\f5d0"; -} - -.fa-air-freshener { - --fa: "\f5d0"; -} - -.fa-star { - --fa: "\f005"; -} - -.fa-repeat { - --fa: "\f363"; -} - -.fa-cross { - --fa: "\f654"; -} - -.fa-box { - --fa: "\f466"; -} - -.fa-venus-mars { - --fa: "\f228"; -} - -.fa-arrow-pointer { - --fa: "\f245"; -} - -.fa-mouse-pointer { - --fa: "\f245"; -} - -.fa-maximize { - --fa: "\f31e"; -} - -.fa-expand-arrows-alt { - --fa: "\f31e"; -} - -.fa-charging-station { - --fa: "\f5e7"; -} - -.fa-shapes { - --fa: "\f61f"; -} - -.fa-triangle-circle-square { - --fa: "\f61f"; -} - -.fa-shuffle { - --fa: "\f074"; -} - -.fa-random { - --fa: "\f074"; -} - -.fa-person-running { - --fa: "\f70c"; -} - -.fa-running { - --fa: "\f70c"; -} - -.fa-mobile-retro { - --fa: "\e527"; -} - -.fa-grip-lines-vertical { - --fa: "\f7a5"; -} - -.fa-spider { - --fa: "\f717"; -} - -.fa-hands-bound { - --fa: "\e4f9"; -} - -.fa-file-invoice-dollar { - --fa: "\f571"; -} - -.fa-plane-circle-exclamation { - --fa: "\e556"; -} - -.fa-x-ray { - --fa: "\f497"; -} - -.fa-spell-check { - --fa: "\f891"; -} - -.fa-slash { - --fa: "\f715"; -} - -.fa-computer-mouse { - --fa: "\f8cc"; -} - -.fa-mouse { - --fa: "\f8cc"; -} - -.fa-arrow-right-to-bracket { - --fa: "\f090"; -} - -.fa-sign-in { - --fa: "\f090"; -} - -.fa-shop-slash { - --fa: "\e070"; -} - -.fa-store-alt-slash { - --fa: "\e070"; -} - -.fa-server { - --fa: "\f233"; -} - -.fa-virus-covid-slash { - --fa: "\e4a9"; -} - -.fa-shop-lock { - --fa: "\e4a5"; -} - -.fa-hourglass-start { - --fa: "\f251"; -} - -.fa-hourglass-1 { - --fa: "\f251"; -} - -.fa-blender-phone { - --fa: "\f6b6"; -} - -.fa-building-wheat { - --fa: "\e4db"; -} - -.fa-person-breastfeeding { - --fa: "\e53a"; -} - -.fa-right-to-bracket { - --fa: "\f2f6"; -} - -.fa-sign-in-alt { - --fa: "\f2f6"; -} - -.fa-venus { - --fa: "\f221"; -} - -.fa-passport { - --fa: "\f5ab"; -} - -.fa-thumbtack-slash { - --fa: "\e68f"; -} - -.fa-thumb-tack-slash { - --fa: "\e68f"; -} - -.fa-heart-pulse { - --fa: "\f21e"; -} - -.fa-heartbeat { - --fa: "\f21e"; -} - -.fa-people-carry-box { - --fa: "\f4ce"; -} - -.fa-people-carry { - --fa: "\f4ce"; -} - -.fa-temperature-high { - --fa: "\f769"; -} - -.fa-microchip { - --fa: "\f2db"; -} - -.fa-crown { - --fa: "\f521"; -} - -.fa-weight-hanging { - --fa: "\f5cd"; -} - -.fa-xmarks-lines { - --fa: "\e59a"; -} - -.fa-file-prescription { - --fa: "\f572"; -} - -.fa-weight-scale { - --fa: "\f496"; -} - -.fa-weight { - --fa: "\f496"; -} - -.fa-user-group { - --fa: "\f500"; -} - -.fa-user-friends { - --fa: "\f500"; -} - -.fa-arrow-up-a-z { - --fa: "\f15e"; -} - -.fa-sort-alpha-up { - --fa: "\f15e"; -} - -.fa-chess-knight { - --fa: "\f441"; -} - -.fa-face-laugh-squint { - --fa: "\f59b"; -} - -.fa-laugh-squint { - --fa: "\f59b"; -} - -.fa-wheelchair { - --fa: "\f193"; -} - -.fa-circle-arrow-up { - --fa: "\f0aa"; -} - -.fa-arrow-circle-up { - --fa: "\f0aa"; -} - -.fa-toggle-on { - --fa: "\f205"; -} - -.fa-person-walking { - --fa: "\f554"; -} - -.fa-walking { - --fa: "\f554"; -} - -.fa-l { - --fa: "\4c"; -} - -.fa-fire { - --fa: "\f06d"; -} - -.fa-bed-pulse { - --fa: "\f487"; -} - -.fa-procedures { - --fa: "\f487"; -} - -.fa-shuttle-space { - --fa: "\f197"; -} - -.fa-space-shuttle { - --fa: "\f197"; -} - -.fa-face-laugh { - --fa: "\f599"; -} - -.fa-laugh { - --fa: "\f599"; -} - -.fa-folder-open { - --fa: "\f07c"; -} - -.fa-heart-circle-plus { - --fa: "\e500"; -} - -.fa-code-fork { - --fa: "\e13b"; -} - -.fa-city { - --fa: "\f64f"; -} - -.fa-microphone-lines { - --fa: "\f3c9"; -} - -.fa-microphone-alt { - --fa: "\f3c9"; -} - -.fa-pepper-hot { - --fa: "\f816"; -} - -.fa-unlock { - --fa: "\f09c"; -} - -.fa-colon-sign { - --fa: "\e140"; -} - -.fa-headset { - --fa: "\f590"; -} - -.fa-store-slash { - --fa: "\e071"; -} - -.fa-road-circle-xmark { - --fa: "\e566"; -} - -.fa-user-minus { - --fa: "\f503"; -} - -.fa-mars-stroke-up { - --fa: "\f22a"; -} - -.fa-mars-stroke-v { - --fa: "\f22a"; -} - -.fa-champagne-glasses { - --fa: "\f79f"; -} - -.fa-glass-cheers { - --fa: "\f79f"; -} - -.fa-clipboard { - --fa: "\f328"; -} - -.fa-house-circle-exclamation { - --fa: "\e50a"; -} - -.fa-file-arrow-up { - --fa: "\f574"; -} - -.fa-file-upload { - --fa: "\f574"; -} - -.fa-wifi { - --fa: "\f1eb"; -} - -.fa-wifi-3 { - --fa: "\f1eb"; -} - -.fa-wifi-strong { - --fa: "\f1eb"; -} - -.fa-bath { - --fa: "\f2cd"; -} - -.fa-bathtub { - --fa: "\f2cd"; -} - -.fa-underline { - --fa: "\f0cd"; -} - -.fa-user-pen { - --fa: "\f4ff"; -} - -.fa-user-edit { - --fa: "\f4ff"; -} - -.fa-signature { - --fa: "\f5b7"; -} - -.fa-stroopwafel { - --fa: "\f551"; -} - -.fa-bold { - --fa: "\f032"; -} - -.fa-anchor-lock { - --fa: "\e4ad"; -} - -.fa-building-ngo { - --fa: "\e4d7"; -} - -.fa-manat-sign { - --fa: "\e1d5"; -} - -.fa-not-equal { - --fa: "\f53e"; -} - -.fa-border-top-left { - --fa: "\f853"; -} - -.fa-border-style { - --fa: "\f853"; -} - -.fa-map-location-dot { - --fa: "\f5a0"; -} - -.fa-map-marked-alt { - --fa: "\f5a0"; -} - -.fa-jedi { - --fa: "\f669"; -} - -.fa-square-poll-vertical { - --fa: "\f681"; -} - -.fa-poll { - --fa: "\f681"; -} - -.fa-mug-hot { - --fa: "\f7b6"; -} - -.fa-car-battery { - --fa: "\f5df"; -} - -.fa-battery-car { - --fa: "\f5df"; -} - -.fa-gift { - --fa: "\f06b"; -} - -.fa-dice-two { - --fa: "\f528"; -} - -.fa-chess-queen { - --fa: "\f445"; -} - -.fa-glasses { - --fa: "\f530"; -} - -.fa-chess-board { - --fa: "\f43c"; -} - -.fa-building-circle-check { - --fa: "\e4d2"; -} - -.fa-person-chalkboard { - --fa: "\e53d"; -} - -.fa-mars-stroke-right { - --fa: "\f22b"; -} - -.fa-mars-stroke-h { - --fa: "\f22b"; -} - -.fa-hand-back-fist { - --fa: "\f255"; -} - -.fa-hand-rock { - --fa: "\f255"; -} - -.fa-square-caret-up { - --fa: "\f151"; -} - -.fa-caret-square-up { - --fa: "\f151"; -} - -.fa-cloud-showers-water { - --fa: "\e4e4"; -} - -.fa-chart-bar { - --fa: "\f080"; -} - -.fa-bar-chart { - --fa: "\f080"; -} - -.fa-hands-bubbles { - --fa: "\e05e"; -} - -.fa-hands-wash { - --fa: "\e05e"; -} - -.fa-less-than-equal { - --fa: "\f537"; -} - -.fa-train { - --fa: "\f238"; -} - -.fa-eye-low-vision { - --fa: "\f2a8"; -} - -.fa-low-vision { - --fa: "\f2a8"; -} - -.fa-crow { - --fa: "\f520"; -} - -.fa-sailboat { - --fa: "\e445"; -} - -.fa-window-restore { - --fa: "\f2d2"; -} - -.fa-square-plus { - --fa: "\f0fe"; -} - -.fa-plus-square { - --fa: "\f0fe"; -} - -.fa-torii-gate { - --fa: "\f6a1"; -} - -.fa-frog { - --fa: "\f52e"; -} - -.fa-bucket { - --fa: "\e4cf"; -} - -.fa-image { - --fa: "\f03e"; -} - -.fa-microphone { - --fa: "\f130"; -} - -.fa-cow { - --fa: "\f6c8"; -} - -.fa-caret-up { - --fa: "\f0d8"; -} - -.fa-screwdriver { - --fa: "\f54a"; -} - -.fa-folder-closed { - --fa: "\e185"; -} - -.fa-house-tsunami { - --fa: "\e515"; -} - -.fa-square-nfi { - --fa: "\e576"; -} - -.fa-arrow-up-from-ground-water { - --fa: "\e4b5"; -} - -.fa-martini-glass { - --fa: "\f57b"; -} - -.fa-glass-martini-alt { - --fa: "\f57b"; -} - -.fa-square-binary { - --fa: "\e69b"; -} - -.fa-rotate-left { - --fa: "\f2ea"; -} - -.fa-rotate-back { - --fa: "\f2ea"; -} - -.fa-rotate-backward { - --fa: "\f2ea"; -} - -.fa-undo-alt { - --fa: "\f2ea"; -} - -.fa-table-columns { - --fa: "\f0db"; -} - -.fa-columns { - --fa: "\f0db"; -} - -.fa-lemon { - --fa: "\f094"; -} - -.fa-head-side-mask { - --fa: "\e063"; -} - -.fa-handshake { - --fa: "\f2b5"; -} - -.fa-gem { - --fa: "\f3a5"; -} - -.fa-dolly { - --fa: "\f472"; -} - -.fa-dolly-box { - --fa: "\f472"; -} - -.fa-smoking { - --fa: "\f48d"; -} - -.fa-minimize { - --fa: "\f78c"; -} - -.fa-compress-arrows-alt { - --fa: "\f78c"; -} - -.fa-monument { - --fa: "\f5a6"; -} - -.fa-snowplow { - --fa: "\f7d2"; -} - -.fa-angles-right { - --fa: "\f101"; -} - -.fa-angle-double-right { - --fa: "\f101"; -} - -.fa-cannabis { - --fa: "\f55f"; -} - -.fa-circle-play { - --fa: "\f144"; -} - -.fa-play-circle { - --fa: "\f144"; -} - -.fa-tablets { - --fa: "\f490"; -} - -.fa-ethernet { - --fa: "\f796"; -} - -.fa-euro-sign { - --fa: "\f153"; -} - -.fa-eur { - --fa: "\f153"; -} - -.fa-euro { - --fa: "\f153"; -} - -.fa-chair { - --fa: "\f6c0"; -} - -.fa-circle-check { - --fa: "\f058"; -} - -.fa-check-circle { - --fa: "\f058"; -} - -.fa-circle-stop { - --fa: "\f28d"; -} - -.fa-stop-circle { - --fa: "\f28d"; -} - -.fa-compass-drafting { - --fa: "\f568"; -} - -.fa-drafting-compass { - --fa: "\f568"; -} - -.fa-plate-wheat { - --fa: "\e55a"; -} - -.fa-icicles { - --fa: "\f7ad"; -} - -.fa-person-shelter { - --fa: "\e54f"; -} - -.fa-neuter { - --fa: "\f22c"; -} - -.fa-id-badge { - --fa: "\f2c1"; -} - -.fa-marker { - --fa: "\f5a1"; -} - -.fa-face-laugh-beam { - --fa: "\f59a"; -} - -.fa-laugh-beam { - --fa: "\f59a"; -} - -.fa-helicopter-symbol { - --fa: "\e502"; -} - -.fa-universal-access { - --fa: "\f29a"; -} - -.fa-circle-chevron-up { - --fa: "\f139"; -} - -.fa-chevron-circle-up { - --fa: "\f139"; -} - -.fa-lari-sign { - --fa: "\e1c8"; -} - -.fa-volcano { - --fa: "\f770"; -} - -.fa-person-walking-dashed-line-arrow-right { - --fa: "\e553"; -} - -.fa-sterling-sign { - --fa: "\f154"; -} - -.fa-gbp { - --fa: "\f154"; -} - -.fa-pound-sign { - --fa: "\f154"; -} - -.fa-viruses { - --fa: "\e076"; -} - -.fa-square-person-confined { - --fa: "\e577"; -} - -.fa-user-tie { - --fa: "\f508"; -} - -.fa-arrow-down-long { - --fa: "\f175"; -} - -.fa-long-arrow-down { - --fa: "\f175"; -} - -.fa-tent-arrow-down-to-line { - --fa: "\e57e"; -} - -.fa-certificate { - --fa: "\f0a3"; -} - -.fa-reply-all { - --fa: "\f122"; -} - -.fa-mail-reply-all { - --fa: "\f122"; -} - -.fa-suitcase { - --fa: "\f0f2"; -} - -.fa-person-skating { - --fa: "\f7c5"; -} - -.fa-skating { - --fa: "\f7c5"; -} - -.fa-filter-circle-dollar { - --fa: "\f662"; -} - -.fa-funnel-dollar { - --fa: "\f662"; -} - -.fa-camera-retro { - --fa: "\f083"; -} - -.fa-circle-arrow-down { - --fa: "\f0ab"; -} - -.fa-arrow-circle-down { - --fa: "\f0ab"; -} - -.fa-file-import { - --fa: "\f56f"; -} - -.fa-arrow-right-to-file { - --fa: "\f56f"; -} - -.fa-square-arrow-up-right { - --fa: "\f14c"; -} - -.fa-external-link-square { - --fa: "\f14c"; -} - -.fa-box-open { - --fa: "\f49e"; -} - -.fa-scroll { - --fa: "\f70e"; -} - -.fa-spa { - --fa: "\f5bb"; -} - -.fa-location-pin-lock { - --fa: "\e51f"; -} - -.fa-pause { - --fa: "\f04c"; -} - -.fa-hill-avalanche { - --fa: "\e507"; -} - -.fa-temperature-empty { - --fa: "\f2cb"; -} - -.fa-temperature-0 { - --fa: "\f2cb"; -} - -.fa-thermometer-0 { - --fa: "\f2cb"; -} - -.fa-thermometer-empty { - --fa: "\f2cb"; -} - -.fa-bomb { - --fa: "\f1e2"; -} - -.fa-registered { - --fa: "\f25d"; -} - -.fa-address-card { - --fa: "\f2bb"; -} - -.fa-contact-card { - --fa: "\f2bb"; -} - -.fa-vcard { - --fa: "\f2bb"; -} - -.fa-scale-unbalanced-flip { - --fa: "\f516"; -} - -.fa-balance-scale-right { - --fa: "\f516"; -} - -.fa-subscript { - --fa: "\f12c"; -} - -.fa-diamond-turn-right { - --fa: "\f5eb"; -} - -.fa-directions { - --fa: "\f5eb"; -} - -.fa-burst { - --fa: "\e4dc"; -} - -.fa-house-laptop { - --fa: "\e066"; -} - -.fa-laptop-house { - --fa: "\e066"; -} - -.fa-face-tired { - --fa: "\f5c8"; -} - -.fa-tired { - --fa: "\f5c8"; -} - -.fa-money-bills { - --fa: "\e1f3"; -} - -.fa-smog { - --fa: "\f75f"; -} - -.fa-crutch { - --fa: "\f7f7"; -} - -.fa-cloud-arrow-up { - --fa: "\f0ee"; -} - -.fa-cloud-upload { - --fa: "\f0ee"; -} - -.fa-cloud-upload-alt { - --fa: "\f0ee"; -} - -.fa-palette { - --fa: "\f53f"; -} - -.fa-arrows-turn-right { - --fa: "\e4c0"; -} - -.fa-vest { - --fa: "\e085"; -} - -.fa-ferry { - --fa: "\e4ea"; -} - -.fa-arrows-down-to-people { - --fa: "\e4b9"; -} - -.fa-seedling { - --fa: "\f4d8"; -} - -.fa-sprout { - --fa: "\f4d8"; -} - -.fa-left-right { - --fa: "\f337"; -} - -.fa-arrows-alt-h { - --fa: "\f337"; -} - -.fa-boxes-packing { - --fa: "\e4c7"; -} - -.fa-circle-arrow-left { - --fa: "\f0a8"; -} - -.fa-arrow-circle-left { - --fa: "\f0a8"; -} - -.fa-group-arrows-rotate { - --fa: "\e4f6"; -} - -.fa-bowl-food { - --fa: "\e4c6"; -} - -.fa-candy-cane { - --fa: "\f786"; -} - -.fa-arrow-down-wide-short { - --fa: "\f160"; -} - -.fa-sort-amount-asc { - --fa: "\f160"; -} - -.fa-sort-amount-down { - --fa: "\f160"; -} - -.fa-cloud-bolt { - --fa: "\f76c"; -} - -.fa-thunderstorm { - --fa: "\f76c"; -} - -.fa-text-slash { - --fa: "\f87d"; -} - -.fa-remove-format { - --fa: "\f87d"; -} - -.fa-face-smile-wink { - --fa: "\f4da"; -} - -.fa-smile-wink { - --fa: "\f4da"; -} - -.fa-file-word { - --fa: "\f1c2"; -} - -.fa-file-powerpoint { - --fa: "\f1c4"; -} - -.fa-arrows-left-right { - --fa: "\f07e"; -} - -.fa-arrows-h { - --fa: "\f07e"; -} - -.fa-house-lock { - --fa: "\e510"; -} - -.fa-cloud-arrow-down { - --fa: "\f0ed"; -} - -.fa-cloud-download { - --fa: "\f0ed"; -} - -.fa-cloud-download-alt { - --fa: "\f0ed"; -} - -.fa-children { - --fa: "\e4e1"; -} - -.fa-chalkboard { - --fa: "\f51b"; -} - -.fa-blackboard { - --fa: "\f51b"; -} - -.fa-user-large-slash { - --fa: "\f4fa"; -} - -.fa-user-alt-slash { - --fa: "\f4fa"; -} - -.fa-envelope-open { - --fa: "\f2b6"; -} - -.fa-handshake-simple-slash { - --fa: "\e05f"; -} - -.fa-handshake-alt-slash { - --fa: "\e05f"; -} - -.fa-mattress-pillow { - --fa: "\e525"; -} - -.fa-guarani-sign { - --fa: "\e19a"; -} - -.fa-arrows-rotate { - --fa: "\f021"; -} - -.fa-refresh { - --fa: "\f021"; -} - -.fa-sync { - --fa: "\f021"; -} - -.fa-fire-extinguisher { - --fa: "\f134"; -} - -.fa-cruzeiro-sign { - --fa: "\e152"; -} - -.fa-greater-than-equal { - --fa: "\f532"; -} - -.fa-shield-halved { - --fa: "\f3ed"; -} - -.fa-shield-alt { - --fa: "\f3ed"; -} - -.fa-book-atlas { - --fa: "\f558"; -} - -.fa-atlas { - --fa: "\f558"; -} - -.fa-virus { - --fa: "\e074"; -} - -.fa-envelope-circle-check { - --fa: "\e4e8"; -} - -.fa-layer-group { - --fa: "\f5fd"; -} - -.fa-arrows-to-dot { - --fa: "\e4be"; -} - -.fa-archway { - --fa: "\f557"; -} - -.fa-heart-circle-check { - --fa: "\e4fd"; -} - -.fa-house-chimney-crack { - --fa: "\f6f1"; -} - -.fa-house-damage { - --fa: "\f6f1"; -} - -.fa-file-zipper { - --fa: "\f1c6"; -} - -.fa-file-archive { - --fa: "\f1c6"; -} - -.fa-square { - --fa: "\f0c8"; -} - -.fa-martini-glass-empty { - --fa: "\f000"; -} - -.fa-glass-martini { - --fa: "\f000"; -} - -.fa-couch { - --fa: "\f4b8"; -} - -.fa-cedi-sign { - --fa: "\e0df"; -} - -.fa-italic { - --fa: "\f033"; -} - -.fa-table-cells-column-lock { - --fa: "\e678"; -} - -.fa-church { - --fa: "\f51d"; -} - -.fa-comments-dollar { - --fa: "\f653"; -} - -.fa-democrat { - --fa: "\f747"; -} - -.fa-z { - --fa: "\5a"; -} - -.fa-person-skiing { - --fa: "\f7c9"; -} - -.fa-skiing { - --fa: "\f7c9"; -} - -.fa-road-lock { - --fa: "\e567"; -} - -.fa-a { - --fa: "\41"; -} - -.fa-temperature-arrow-down { - --fa: "\e03f"; -} - -.fa-temperature-down { - --fa: "\e03f"; -} - -.fa-feather-pointed { - --fa: "\f56b"; -} - -.fa-feather-alt { - --fa: "\f56b"; -} - -.fa-p { - --fa: "\50"; -} - -.fa-snowflake { - --fa: "\f2dc"; -} - -.fa-newspaper { - --fa: "\f1ea"; -} - -.fa-rectangle-ad { - --fa: "\f641"; -} - -.fa-ad { - --fa: "\f641"; -} - -.fa-circle-arrow-right { - --fa: "\f0a9"; -} - -.fa-arrow-circle-right { - --fa: "\f0a9"; -} - -.fa-filter-circle-xmark { - --fa: "\e17b"; -} - -.fa-locust { - --fa: "\e520"; -} - -.fa-sort { - --fa: "\f0dc"; -} - -.fa-unsorted { - --fa: "\f0dc"; -} - -.fa-list-ol { - --fa: "\f0cb"; -} - -.fa-list-1-2 { - --fa: "\f0cb"; -} - -.fa-list-numeric { - --fa: "\f0cb"; -} - -.fa-person-dress-burst { - --fa: "\e544"; -} - -.fa-money-check-dollar { - --fa: "\f53d"; -} - -.fa-money-check-alt { - --fa: "\f53d"; -} - -.fa-vector-square { - --fa: "\f5cb"; -} - -.fa-bread-slice { - --fa: "\f7ec"; -} - -.fa-language { - --fa: "\f1ab"; -} - -.fa-face-kiss-wink-heart { - --fa: "\f598"; -} - -.fa-kiss-wink-heart { - --fa: "\f598"; -} - -.fa-filter { - --fa: "\f0b0"; -} - -.fa-question { - --fa: "\3f"; -} - -.fa-file-signature { - --fa: "\f573"; -} - -.fa-up-down-left-right { - --fa: "\f0b2"; -} - -.fa-arrows-alt { - --fa: "\f0b2"; -} - -.fa-house-chimney-user { - --fa: "\e065"; -} - -.fa-hand-holding-heart { - --fa: "\f4be"; -} - -.fa-puzzle-piece { - --fa: "\f12e"; -} - -.fa-money-check { - --fa: "\f53c"; -} - -.fa-star-half-stroke { - --fa: "\f5c0"; -} - -.fa-star-half-alt { - --fa: "\f5c0"; -} - -.fa-code { - --fa: "\f121"; -} - -.fa-whiskey-glass { - --fa: "\f7a0"; -} - -.fa-glass-whiskey { - --fa: "\f7a0"; -} - -.fa-building-circle-exclamation { - --fa: "\e4d3"; -} - -.fa-magnifying-glass-chart { - --fa: "\e522"; -} - -.fa-arrow-up-right-from-square { - --fa: "\f08e"; -} - -.fa-external-link { - --fa: "\f08e"; -} - -.fa-cubes-stacked { - --fa: "\e4e6"; -} - -.fa-won-sign { - --fa: "\f159"; -} - -.fa-krw { - --fa: "\f159"; -} - -.fa-won { - --fa: "\f159"; -} - -.fa-virus-covid { - --fa: "\e4a8"; -} - -.fa-austral-sign { - --fa: "\e0a9"; -} - -.fa-f { - --fa: "\46"; -} - -.fa-leaf { - --fa: "\f06c"; -} - -.fa-road { - --fa: "\f018"; -} - -.fa-taxi { - --fa: "\f1ba"; -} - -.fa-cab { - --fa: "\f1ba"; -} - -.fa-person-circle-plus { - --fa: "\e541"; -} - -.fa-chart-pie { - --fa: "\f200"; -} - -.fa-pie-chart { - --fa: "\f200"; -} - -.fa-bolt-lightning { - --fa: "\e0b7"; -} - -.fa-sack-xmark { - --fa: "\e56a"; -} - -.fa-file-excel { - --fa: "\f1c3"; -} - -.fa-file-contract { - --fa: "\f56c"; -} - -.fa-fish-fins { - --fa: "\e4f2"; -} - -.fa-building-flag { - --fa: "\e4d5"; -} - -.fa-face-grin-beam { - --fa: "\f582"; -} - -.fa-grin-beam { - --fa: "\f582"; -} - -.fa-object-ungroup { - --fa: "\f248"; -} - -.fa-poop { - --fa: "\f619"; -} - -.fa-location-pin { - --fa: "\f041"; -} - -.fa-map-marker { - --fa: "\f041"; -} - -.fa-kaaba { - --fa: "\f66b"; -} - -.fa-toilet-paper { - --fa: "\f71e"; -} - -.fa-helmet-safety { - --fa: "\f807"; -} - -.fa-hard-hat { - --fa: "\f807"; -} - -.fa-hat-hard { - --fa: "\f807"; -} - -.fa-eject { - --fa: "\f052"; -} - -.fa-circle-right { - --fa: "\f35a"; -} - -.fa-arrow-alt-circle-right { - --fa: "\f35a"; -} - -.fa-plane-circle-check { - --fa: "\e555"; -} - -.fa-face-rolling-eyes { - --fa: "\f5a5"; -} - -.fa-meh-rolling-eyes { - --fa: "\f5a5"; -} - -.fa-object-group { - --fa: "\f247"; -} - -.fa-chart-line { - --fa: "\f201"; -} - -.fa-line-chart { - --fa: "\f201"; -} - -.fa-mask-ventilator { - --fa: "\e524"; -} - -.fa-arrow-right { - --fa: "\f061"; -} - -.fa-signs-post { - --fa: "\f277"; -} - -.fa-map-signs { - --fa: "\f277"; -} - -.fa-cash-register { - --fa: "\f788"; -} - -.fa-person-circle-question { - --fa: "\e542"; -} - -.fa-h { - --fa: "\48"; -} - -.fa-tarp { - --fa: "\e57b"; -} - -.fa-screwdriver-wrench { - --fa: "\f7d9"; -} - -.fa-tools { - --fa: "\f7d9"; -} - -.fa-arrows-to-eye { - --fa: "\e4bf"; -} - -.fa-plug-circle-bolt { - --fa: "\e55b"; -} - -.fa-heart { - --fa: "\f004"; -} - -.fa-mars-and-venus { - --fa: "\f224"; -} - -.fa-house-user { - --fa: "\e1b0"; -} - -.fa-home-user { - --fa: "\e1b0"; -} - -.fa-dumpster-fire { - --fa: "\f794"; -} - -.fa-house-crack { - --fa: "\e3b1"; -} - -.fa-martini-glass-citrus { - --fa: "\f561"; -} - -.fa-cocktail { - --fa: "\f561"; -} - -.fa-face-surprise { - --fa: "\f5c2"; -} - -.fa-surprise { - --fa: "\f5c2"; -} - -.fa-bottle-water { - --fa: "\e4c5"; -} - -.fa-circle-pause { - --fa: "\f28b"; -} - -.fa-pause-circle { - --fa: "\f28b"; -} - -.fa-toilet-paper-slash { - --fa: "\e072"; -} - -.fa-apple-whole { - --fa: "\f5d1"; -} - -.fa-apple-alt { - --fa: "\f5d1"; -} - -.fa-kitchen-set { - --fa: "\e51a"; -} - -.fa-r { - --fa: "\52"; -} - -.fa-temperature-quarter { - --fa: "\f2ca"; -} - -.fa-temperature-1 { - --fa: "\f2ca"; -} - -.fa-thermometer-1 { - --fa: "\f2ca"; -} - -.fa-thermometer-quarter { - --fa: "\f2ca"; -} - -.fa-cube { - --fa: "\f1b2"; -} - -.fa-bitcoin-sign { - --fa: "\e0b4"; -} - -.fa-shield-dog { - --fa: "\e573"; -} - -.fa-solar-panel { - --fa: "\f5ba"; -} - -.fa-lock-open { - --fa: "\f3c1"; -} - -.fa-elevator { - --fa: "\e16d"; -} - -.fa-money-bill-transfer { - --fa: "\e528"; -} - -.fa-money-bill-trend-up { - --fa: "\e529"; -} - -.fa-house-flood-water-circle-arrow-right { - --fa: "\e50f"; -} - -.fa-square-poll-horizontal { - --fa: "\f682"; -} - -.fa-poll-h { - --fa: "\f682"; -} - -.fa-circle { - --fa: "\f111"; -} - -.fa-backward-fast { - --fa: "\f049"; -} - -.fa-fast-backward { - --fa: "\f049"; -} - -.fa-recycle { - --fa: "\f1b8"; -} - -.fa-user-astronaut { - --fa: "\f4fb"; -} - -.fa-plane-slash { - --fa: "\e069"; -} - -.fa-trademark { - --fa: "\f25c"; -} - -.fa-basketball { - --fa: "\f434"; -} - -.fa-basketball-ball { - --fa: "\f434"; -} - -.fa-satellite-dish { - --fa: "\f7c0"; -} - -.fa-circle-up { - --fa: "\f35b"; -} - -.fa-arrow-alt-circle-up { - --fa: "\f35b"; -} - -.fa-mobile-screen-button { - --fa: "\f3cd"; -} - -.fa-mobile-alt { - --fa: "\f3cd"; -} - -.fa-volume-high { - --fa: "\f028"; -} - -.fa-volume-up { - --fa: "\f028"; -} - -.fa-users-rays { - --fa: "\e593"; -} - -.fa-wallet { - --fa: "\f555"; -} - -.fa-clipboard-check { - --fa: "\f46c"; -} - -.fa-file-audio { - --fa: "\f1c7"; -} - -.fa-burger { - --fa: "\f805"; -} - -.fa-hamburger { - --fa: "\f805"; -} - -.fa-wrench { - --fa: "\f0ad"; -} - -.fa-bugs { - --fa: "\e4d0"; -} - -.fa-rupee-sign { - --fa: "\f156"; -} - -.fa-rupee { - --fa: "\f156"; -} - -.fa-file-image { - --fa: "\f1c5"; -} - -.fa-circle-question { - --fa: "\f059"; -} - -.fa-question-circle { - --fa: "\f059"; -} - -.fa-plane-departure { - --fa: "\f5b0"; -} - -.fa-handshake-slash { - --fa: "\e060"; -} - -.fa-book-bookmark { - --fa: "\e0bb"; -} - -.fa-code-branch { - --fa: "\f126"; -} - -.fa-hat-cowboy { - --fa: "\f8c0"; -} - -.fa-bridge { - --fa: "\e4c8"; -} - -.fa-phone-flip { - --fa: "\f879"; -} - -.fa-phone-alt { - --fa: "\f879"; -} - -.fa-truck-front { - --fa: "\e2b7"; -} - -.fa-cat { - --fa: "\f6be"; -} - -.fa-anchor-circle-exclamation { - --fa: "\e4ab"; -} - -.fa-truck-field { - --fa: "\e58d"; -} - -.fa-route { - --fa: "\f4d7"; -} - -.fa-clipboard-question { - --fa: "\e4e3"; -} - -.fa-panorama { - --fa: "\e209"; -} - -.fa-comment-medical { - --fa: "\f7f5"; -} - -.fa-teeth-open { - --fa: "\f62f"; -} - -.fa-file-circle-minus { - --fa: "\e4ed"; -} - -.fa-tags { - --fa: "\f02c"; -} - -.fa-wine-glass { - --fa: "\f4e3"; -} - -.fa-forward-fast { - --fa: "\f050"; -} - -.fa-fast-forward { - --fa: "\f050"; -} - -.fa-face-meh-blank { - --fa: "\f5a4"; -} - -.fa-meh-blank { - --fa: "\f5a4"; -} - -.fa-square-parking { - --fa: "\f540"; -} - -.fa-parking { - --fa: "\f540"; -} - -.fa-house-signal { - --fa: "\e012"; -} - -.fa-bars-progress { - --fa: "\f828"; -} - -.fa-tasks-alt { - --fa: "\f828"; -} - -.fa-faucet-drip { - --fa: "\e006"; -} - -.fa-cart-flatbed { - --fa: "\f474"; -} - -.fa-dolly-flatbed { - --fa: "\f474"; -} - -.fa-ban-smoking { - --fa: "\f54d"; -} - -.fa-smoking-ban { - --fa: "\f54d"; -} - -.fa-terminal { - --fa: "\f120"; -} - -.fa-mobile-button { - --fa: "\f10b"; -} - -.fa-house-medical-flag { - --fa: "\e514"; -} - -.fa-basket-shopping { - --fa: "\f291"; -} - -.fa-shopping-basket { - --fa: "\f291"; -} - -.fa-tape { - --fa: "\f4db"; -} - -.fa-bus-simple { - --fa: "\f55e"; -} - -.fa-bus-alt { - --fa: "\f55e"; -} - -.fa-eye { - --fa: "\f06e"; -} - -.fa-face-sad-cry { - --fa: "\f5b3"; -} - -.fa-sad-cry { - --fa: "\f5b3"; -} - -.fa-audio-description { - --fa: "\f29e"; -} - -.fa-person-military-to-person { - --fa: "\e54c"; -} - -.fa-file-shield { - --fa: "\e4f0"; -} - -.fa-user-slash { - --fa: "\f506"; -} - -.fa-pen { - --fa: "\f304"; -} - -.fa-tower-observation { - --fa: "\e586"; -} - -.fa-file-code { - --fa: "\f1c9"; -} - -.fa-signal { - --fa: "\f012"; -} - -.fa-signal-5 { - --fa: "\f012"; -} - -.fa-signal-perfect { - --fa: "\f012"; -} - -.fa-bus { - --fa: "\f207"; -} - -.fa-heart-circle-xmark { - --fa: "\e501"; -} - -.fa-house-chimney { - --fa: "\e3af"; -} - -.fa-home-lg { - --fa: "\e3af"; -} - -.fa-window-maximize { - --fa: "\f2d0"; -} - -.fa-face-frown { - --fa: "\f119"; -} - -.fa-frown { - --fa: "\f119"; -} - -.fa-prescription { - --fa: "\f5b1"; -} - -.fa-shop { - --fa: "\f54f"; -} - -.fa-store-alt { - --fa: "\f54f"; -} - -.fa-floppy-disk { - --fa: "\f0c7"; -} - -.fa-save { - --fa: "\f0c7"; -} - -.fa-vihara { - --fa: "\f6a7"; -} - -.fa-scale-unbalanced { - --fa: "\f515"; -} - -.fa-balance-scale-left { - --fa: "\f515"; -} - -.fa-sort-up { - --fa: "\f0de"; -} - -.fa-sort-asc { - --fa: "\f0de"; -} - -.fa-comment-dots { - --fa: "\f4ad"; -} - -.fa-commenting { - --fa: "\f4ad"; -} - -.fa-plant-wilt { - --fa: "\e5aa"; -} - -.fa-diamond { - --fa: "\f219"; -} - -.fa-face-grin-squint { - --fa: "\f585"; -} - -.fa-grin-squint { - --fa: "\f585"; -} - -.fa-hand-holding-dollar { - --fa: "\f4c0"; -} - -.fa-hand-holding-usd { - --fa: "\f4c0"; -} - -.fa-chart-diagram { - --fa: "\e695"; -} - -.fa-bacterium { - --fa: "\e05a"; -} - -.fa-hand-pointer { - --fa: "\f25a"; -} - -.fa-drum-steelpan { - --fa: "\f56a"; -} - -.fa-hand-scissors { - --fa: "\f257"; -} - -.fa-hands-praying { - --fa: "\f684"; -} - -.fa-praying-hands { - --fa: "\f684"; -} - -.fa-arrow-rotate-right { - --fa: "\f01e"; -} - -.fa-arrow-right-rotate { - --fa: "\f01e"; -} - -.fa-arrow-rotate-forward { - --fa: "\f01e"; -} - -.fa-redo { - --fa: "\f01e"; -} - -.fa-biohazard { - --fa: "\f780"; -} - -.fa-location-crosshairs { - --fa: "\f601"; -} - -.fa-location { - --fa: "\f601"; -} - -.fa-mars-double { - --fa: "\f227"; -} - -.fa-child-dress { - --fa: "\e59c"; -} - -.fa-users-between-lines { - --fa: "\e591"; -} - -.fa-lungs-virus { - --fa: "\e067"; -} - -.fa-face-grin-tears { - --fa: "\f588"; -} - -.fa-grin-tears { - --fa: "\f588"; -} - -.fa-phone { - --fa: "\f095"; -} - -.fa-calendar-xmark { - --fa: "\f273"; -} - -.fa-calendar-times { - --fa: "\f273"; -} - -.fa-child-reaching { - --fa: "\e59d"; -} - -.fa-head-side-virus { - --fa: "\e064"; -} - -.fa-user-gear { - --fa: "\f4fe"; -} - -.fa-user-cog { - --fa: "\f4fe"; -} - -.fa-arrow-up-1-9 { - --fa: "\f163"; -} - -.fa-sort-numeric-up { - --fa: "\f163"; -} - -.fa-door-closed { - --fa: "\f52a"; -} - -.fa-shield-virus { - --fa: "\e06c"; -} - -.fa-dice-six { - --fa: "\f526"; -} - -.fa-mosquito-net { - --fa: "\e52c"; -} - -.fa-file-fragment { - --fa: "\e697"; -} - -.fa-bridge-water { - --fa: "\e4ce"; -} - -.fa-person-booth { - --fa: "\f756"; -} - -.fa-text-width { - --fa: "\f035"; -} - -.fa-hat-wizard { - --fa: "\f6e8"; -} - -.fa-pen-fancy { - --fa: "\f5ac"; -} - -.fa-person-digging { - --fa: "\f85e"; -} - -.fa-digging { - --fa: "\f85e"; -} - -.fa-trash { - --fa: "\f1f8"; -} - -.fa-gauge-simple { - --fa: "\f629"; -} - -.fa-gauge-simple-med { - --fa: "\f629"; -} - -.fa-tachometer-average { - --fa: "\f629"; -} - -.fa-book-medical { - --fa: "\f7e6"; -} - -.fa-poo { - --fa: "\f2fe"; -} - -.fa-quote-right { - --fa: "\f10e"; -} - -.fa-quote-right-alt { - --fa: "\f10e"; -} - -.fa-shirt { - --fa: "\f553"; -} - -.fa-t-shirt { - --fa: "\f553"; -} - -.fa-tshirt { - --fa: "\f553"; -} - -.fa-cubes { - --fa: "\f1b3"; -} - -.fa-divide { - --fa: "\f529"; -} - -.fa-tenge-sign { - --fa: "\f7d7"; -} - -.fa-tenge { - --fa: "\f7d7"; -} - -.fa-headphones { - --fa: "\f025"; -} - -.fa-hands-holding { - --fa: "\f4c2"; -} - -.fa-hands-clapping { - --fa: "\e1a8"; -} - -.fa-republican { - --fa: "\f75e"; -} - -.fa-arrow-left { - --fa: "\f060"; -} - -.fa-person-circle-xmark { - --fa: "\e543"; -} - -.fa-ruler { - --fa: "\f545"; -} - -.fa-align-left { - --fa: "\f036"; -} - -.fa-dice-d6 { - --fa: "\f6d1"; -} - -.fa-restroom { - --fa: "\f7bd"; -} - -.fa-j { - --fa: "\4a"; -} - -.fa-users-viewfinder { - --fa: "\e595"; -} - -.fa-file-video { - --fa: "\f1c8"; -} - -.fa-up-right-from-square { - --fa: "\f35d"; -} - -.fa-external-link-alt { - --fa: "\f35d"; -} - -.fa-table-cells { - --fa: "\f00a"; -} - -.fa-th { - --fa: "\f00a"; -} - -.fa-file-pdf { - --fa: "\f1c1"; -} - -.fa-book-bible { - --fa: "\f647"; -} - -.fa-bible { - --fa: "\f647"; -} - -.fa-o { - --fa: "\4f"; -} - -.fa-suitcase-medical { - --fa: "\f0fa"; -} - -.fa-medkit { - --fa: "\f0fa"; -} - -.fa-user-secret { - --fa: "\f21b"; -} - -.fa-otter { - --fa: "\f700"; -} - -.fa-person-dress { - --fa: "\f182"; -} - -.fa-female { - --fa: "\f182"; -} - -.fa-comment-dollar { - --fa: "\f651"; -} - -.fa-business-time { - --fa: "\f64a"; -} - -.fa-briefcase-clock { - --fa: "\f64a"; -} - -.fa-table-cells-large { - --fa: "\f009"; -} - -.fa-th-large { - --fa: "\f009"; -} - -.fa-book-tanakh { - --fa: "\f827"; -} - -.fa-tanakh { - --fa: "\f827"; -} - -.fa-phone-volume { - --fa: "\f2a0"; -} - -.fa-volume-control-phone { - --fa: "\f2a0"; -} - -.fa-hat-cowboy-side { - --fa: "\f8c1"; -} - -.fa-clipboard-user { - --fa: "\f7f3"; -} - -.fa-child { - --fa: "\f1ae"; -} - -.fa-lira-sign { - --fa: "\f195"; -} - -.fa-satellite { - --fa: "\f7bf"; -} - -.fa-plane-lock { - --fa: "\e558"; -} - -.fa-tag { - --fa: "\f02b"; -} - -.fa-comment { - --fa: "\f075"; -} - -.fa-cake-candles { - --fa: "\f1fd"; -} - -.fa-birthday-cake { - --fa: "\f1fd"; -} - -.fa-cake { - --fa: "\f1fd"; -} - -.fa-envelope { - --fa: "\f0e0"; -} - -.fa-angles-up { - --fa: "\f102"; -} - -.fa-angle-double-up { - --fa: "\f102"; -} - -.fa-paperclip { - --fa: "\f0c6"; -} - -.fa-arrow-right-to-city { - --fa: "\e4b3"; -} - -.fa-ribbon { - --fa: "\f4d6"; -} - -.fa-lungs { - --fa: "\f604"; -} - -.fa-arrow-up-9-1 { - --fa: "\f887"; -} - -.fa-sort-numeric-up-alt { - --fa: "\f887"; -} - -.fa-litecoin-sign { - --fa: "\e1d3"; -} - -.fa-border-none { - --fa: "\f850"; -} - -.fa-circle-nodes { - --fa: "\e4e2"; -} - -.fa-parachute-box { - --fa: "\f4cd"; -} - -.fa-indent { - --fa: "\f03c"; -} - -.fa-truck-field-un { - --fa: "\e58e"; -} - -.fa-hourglass { - --fa: "\f254"; -} - -.fa-hourglass-empty { - --fa: "\f254"; -} - -.fa-mountain { - --fa: "\f6fc"; -} - -.fa-user-doctor { - --fa: "\f0f0"; -} - -.fa-user-md { - --fa: "\f0f0"; -} - -.fa-circle-info { - --fa: "\f05a"; -} - -.fa-info-circle { - --fa: "\f05a"; -} - -.fa-cloud-meatball { - --fa: "\f73b"; -} - -.fa-camera { - --fa: "\f030"; -} - -.fa-camera-alt { - --fa: "\f030"; -} - -.fa-square-virus { - --fa: "\e578"; -} - -.fa-meteor { - --fa: "\f753"; -} - -.fa-car-on { - --fa: "\e4dd"; -} - -.fa-sleigh { - --fa: "\f7cc"; -} - -.fa-arrow-down-1-9 { - --fa: "\f162"; -} - -.fa-sort-numeric-asc { - --fa: "\f162"; -} - -.fa-sort-numeric-down { - --fa: "\f162"; -} - -.fa-hand-holding-droplet { - --fa: "\f4c1"; -} - -.fa-hand-holding-water { - --fa: "\f4c1"; -} - -.fa-water { - --fa: "\f773"; -} - -.fa-calendar-check { - --fa: "\f274"; -} - -.fa-braille { - --fa: "\f2a1"; -} - -.fa-prescription-bottle-medical { - --fa: "\f486"; -} - -.fa-prescription-bottle-alt { - --fa: "\f486"; -} - -.fa-landmark { - --fa: "\f66f"; -} - -.fa-truck { - --fa: "\f0d1"; -} - -.fa-crosshairs { - --fa: "\f05b"; -} - -.fa-person-cane { - --fa: "\e53c"; -} - -.fa-tent { - --fa: "\e57d"; -} - -.fa-vest-patches { - --fa: "\e086"; -} - -.fa-check-double { - --fa: "\f560"; -} - -.fa-arrow-down-a-z { - --fa: "\f15d"; -} - -.fa-sort-alpha-asc { - --fa: "\f15d"; -} - -.fa-sort-alpha-down { - --fa: "\f15d"; -} - -.fa-money-bill-wheat { - --fa: "\e52a"; -} - -.fa-cookie { - --fa: "\f563"; -} - -.fa-arrow-rotate-left { - --fa: "\f0e2"; -} - -.fa-arrow-left-rotate { - --fa: "\f0e2"; -} - -.fa-arrow-rotate-back { - --fa: "\f0e2"; -} - -.fa-arrow-rotate-backward { - --fa: "\f0e2"; -} - -.fa-undo { - --fa: "\f0e2"; -} - -.fa-hard-drive { - --fa: "\f0a0"; -} - -.fa-hdd { - --fa: "\f0a0"; -} - -.fa-face-grin-squint-tears { - --fa: "\f586"; -} - -.fa-grin-squint-tears { - --fa: "\f586"; -} - -.fa-dumbbell { - --fa: "\f44b"; -} - -.fa-rectangle-list { - --fa: "\f022"; -} - -.fa-list-alt { - --fa: "\f022"; -} - -.fa-tarp-droplet { - --fa: "\e57c"; -} - -.fa-house-medical-circle-check { - --fa: "\e511"; -} - -.fa-person-skiing-nordic { - --fa: "\f7ca"; -} - -.fa-skiing-nordic { - --fa: "\f7ca"; -} - -.fa-calendar-plus { - --fa: "\f271"; -} - -.fa-plane-arrival { - --fa: "\f5af"; -} - -.fa-circle-left { - --fa: "\f359"; -} - -.fa-arrow-alt-circle-left { - --fa: "\f359"; -} - -.fa-train-subway { - --fa: "\f239"; -} - -.fa-subway { - --fa: "\f239"; -} - -.fa-chart-gantt { - --fa: "\e0e4"; -} - -.fa-indian-rupee-sign { - --fa: "\e1bc"; -} - -.fa-indian-rupee { - --fa: "\e1bc"; -} - -.fa-inr { - --fa: "\e1bc"; -} - -.fa-crop-simple { - --fa: "\f565"; -} - -.fa-crop-alt { - --fa: "\f565"; -} - -.fa-money-bill-1 { - --fa: "\f3d1"; -} - -.fa-money-bill-alt { - --fa: "\f3d1"; -} - -.fa-left-long { - --fa: "\f30a"; -} - -.fa-long-arrow-alt-left { - --fa: "\f30a"; -} - -.fa-dna { - --fa: "\f471"; -} - -.fa-virus-slash { - --fa: "\e075"; -} - -.fa-minus { - --fa: "\f068"; -} - -.fa-subtract { - --fa: "\f068"; -} - -.fa-chess { - --fa: "\f439"; -} - -.fa-arrow-left-long { - --fa: "\f177"; -} - -.fa-long-arrow-left { - --fa: "\f177"; -} - -.fa-plug-circle-check { - --fa: "\e55c"; -} - -.fa-street-view { - --fa: "\f21d"; -} - -.fa-franc-sign { - --fa: "\e18f"; -} - -.fa-volume-off { - --fa: "\f026"; -} - -.fa-hands-asl-interpreting { - --fa: "\f2a3"; -} - -.fa-american-sign-language-interpreting { - --fa: "\f2a3"; -} - -.fa-asl-interpreting { - --fa: "\f2a3"; -} - -.fa-hands-american-sign-language-interpreting { - --fa: "\f2a3"; -} - -.fa-gear { - --fa: "\f013"; -} - -.fa-cog { - --fa: "\f013"; -} - -.fa-droplet-slash { - --fa: "\f5c7"; -} - -.fa-tint-slash { - --fa: "\f5c7"; -} - -.fa-mosque { - --fa: "\f678"; -} - -.fa-mosquito { - --fa: "\e52b"; -} - -.fa-star-of-david { - --fa: "\f69a"; -} - -.fa-person-military-rifle { - --fa: "\e54b"; -} - -.fa-cart-shopping { - --fa: "\f07a"; -} - -.fa-shopping-cart { - --fa: "\f07a"; -} - -.fa-vials { - --fa: "\f493"; -} - -.fa-plug-circle-plus { - --fa: "\e55f"; -} - -.fa-place-of-worship { - --fa: "\f67f"; -} - -.fa-grip-vertical { - --fa: "\f58e"; -} - -.fa-hexagon-nodes { - --fa: "\e699"; -} - -.fa-arrow-turn-up { - --fa: "\f148"; -} - -.fa-level-up { - --fa: "\f148"; -} - -.fa-u { - --fa: "\55"; -} - -.fa-square-root-variable { - --fa: "\f698"; -} - -.fa-square-root-alt { - --fa: "\f698"; -} - -.fa-clock { - --fa: "\f017"; -} - -.fa-clock-four { - --fa: "\f017"; -} - -.fa-backward-step { - --fa: "\f048"; -} - -.fa-step-backward { - --fa: "\f048"; -} - -.fa-pallet { - --fa: "\f482"; -} - -.fa-faucet { - --fa: "\e005"; -} - -.fa-baseball-bat-ball { - --fa: "\f432"; -} - -.fa-s { - --fa: "\53"; -} - -.fa-timeline { - --fa: "\e29c"; -} - -.fa-keyboard { - --fa: "\f11c"; -} - -.fa-caret-down { - --fa: "\f0d7"; -} - -.fa-house-chimney-medical { - --fa: "\f7f2"; -} - -.fa-clinic-medical { - --fa: "\f7f2"; -} - -.fa-temperature-three-quarters { - --fa: "\f2c8"; -} - -.fa-temperature-3 { - --fa: "\f2c8"; -} - -.fa-thermometer-3 { - --fa: "\f2c8"; -} - -.fa-thermometer-three-quarters { - --fa: "\f2c8"; -} - -.fa-mobile-screen { - --fa: "\f3cf"; -} - -.fa-mobile-android-alt { - --fa: "\f3cf"; -} - -.fa-plane-up { - --fa: "\e22d"; -} - -.fa-piggy-bank { - --fa: "\f4d3"; -} - -.fa-battery-half { - --fa: "\f242"; -} - -.fa-battery-3 { - --fa: "\f242"; -} - -.fa-mountain-city { - --fa: "\e52e"; -} - -.fa-coins { - --fa: "\f51e"; -} - -.fa-khanda { - --fa: "\f66d"; -} - -.fa-sliders { - --fa: "\f1de"; -} - -.fa-sliders-h { - --fa: "\f1de"; -} - -.fa-folder-tree { - --fa: "\f802"; -} - -.fa-network-wired { - --fa: "\f6ff"; -} - -.fa-map-pin { - --fa: "\f276"; -} - -.fa-hamsa { - --fa: "\f665"; -} - -.fa-cent-sign { - --fa: "\e3f5"; -} - -.fa-flask { - --fa: "\f0c3"; -} - -.fa-person-pregnant { - --fa: "\e31e"; -} - -.fa-wand-sparkles { - --fa: "\f72b"; -} - -.fa-ellipsis-vertical { - --fa: "\f142"; -} - -.fa-ellipsis-v { - --fa: "\f142"; -} - -.fa-ticket { - --fa: "\f145"; -} - -.fa-power-off { - --fa: "\f011"; -} - -.fa-right-long { - --fa: "\f30b"; -} - -.fa-long-arrow-alt-right { - --fa: "\f30b"; -} - -.fa-flag-usa { - --fa: "\f74d"; -} - -.fa-laptop-file { - --fa: "\e51d"; -} - -.fa-tty { - --fa: "\f1e4"; -} - -.fa-teletype { - --fa: "\f1e4"; -} - -.fa-diagram-next { - --fa: "\e476"; -} - -.fa-person-rifle { - --fa: "\e54e"; -} - -.fa-house-medical-circle-exclamation { - --fa: "\e512"; -} - -.fa-closed-captioning { - --fa: "\f20a"; -} - -.fa-person-hiking { - --fa: "\f6ec"; -} - -.fa-hiking { - --fa: "\f6ec"; -} - -.fa-venus-double { - --fa: "\f226"; -} - -.fa-images { - --fa: "\f302"; -} - -.fa-calculator { - --fa: "\f1ec"; -} - -.fa-people-pulling { - --fa: "\e535"; -} - -.fa-n { - --fa: "\4e"; -} - -.fa-cable-car { - --fa: "\f7da"; -} - -.fa-tram { - --fa: "\f7da"; -} - -.fa-cloud-rain { - --fa: "\f73d"; -} - -.fa-building-circle-xmark { - --fa: "\e4d4"; -} - -.fa-ship { - --fa: "\f21a"; -} - -.fa-arrows-down-to-line { - --fa: "\e4b8"; -} - -.fa-download { - --fa: "\f019"; -} - -.fa-face-grin { - --fa: "\f580"; -} - -.fa-grin { - --fa: "\f580"; -} - -.fa-delete-left { - --fa: "\f55a"; -} - -.fa-backspace { - --fa: "\f55a"; -} - -.fa-eye-dropper { - --fa: "\f1fb"; -} - -.fa-eye-dropper-empty { - --fa: "\f1fb"; -} - -.fa-eyedropper { - --fa: "\f1fb"; -} - -.fa-file-circle-check { - --fa: "\e5a0"; -} - -.fa-forward { - --fa: "\f04e"; -} - -.fa-mobile { - --fa: "\f3ce"; -} - -.fa-mobile-android { - --fa: "\f3ce"; -} - -.fa-mobile-phone { - --fa: "\f3ce"; -} - -.fa-face-meh { - --fa: "\f11a"; -} - -.fa-meh { - --fa: "\f11a"; -} - -.fa-align-center { - --fa: "\f037"; -} - -.fa-book-skull { - --fa: "\f6b7"; -} - -.fa-book-dead { - --fa: "\f6b7"; -} - -.fa-id-card { - --fa: "\f2c2"; -} - -.fa-drivers-license { - --fa: "\f2c2"; -} - -.fa-outdent { - --fa: "\f03b"; -} - -.fa-dedent { - --fa: "\f03b"; -} - -.fa-heart-circle-exclamation { - --fa: "\e4fe"; -} - -.fa-house { - --fa: "\f015"; -} - -.fa-home { - --fa: "\f015"; -} - -.fa-home-alt { - --fa: "\f015"; -} - -.fa-home-lg-alt { - --fa: "\f015"; -} - -.fa-calendar-week { - --fa: "\f784"; -} - -.fa-laptop-medical { - --fa: "\f812"; -} - -.fa-b { - --fa: "\42"; -} - -.fa-file-medical { - --fa: "\f477"; -} - -.fa-dice-one { - --fa: "\f525"; -} - -.fa-kiwi-bird { - --fa: "\f535"; -} - -.fa-arrow-right-arrow-left { - --fa: "\f0ec"; -} - -.fa-exchange { - --fa: "\f0ec"; -} - -.fa-rotate-right { - --fa: "\f2f9"; -} - -.fa-redo-alt { - --fa: "\f2f9"; -} - -.fa-rotate-forward { - --fa: "\f2f9"; -} - -.fa-utensils { - --fa: "\f2e7"; -} - -.fa-cutlery { - --fa: "\f2e7"; -} - -.fa-arrow-up-wide-short { - --fa: "\f161"; -} - -.fa-sort-amount-up { - --fa: "\f161"; -} - -.fa-mill-sign { - --fa: "\e1ed"; -} - -.fa-bowl-rice { - --fa: "\e2eb"; -} - -.fa-skull { - --fa: "\f54c"; -} - -.fa-tower-broadcast { - --fa: "\f519"; -} - -.fa-broadcast-tower { - --fa: "\f519"; -} - -.fa-truck-pickup { - --fa: "\f63c"; -} - -.fa-up-long { - --fa: "\f30c"; -} - -.fa-long-arrow-alt-up { - --fa: "\f30c"; -} - -.fa-stop { - --fa: "\f04d"; -} - -.fa-code-merge { - --fa: "\f387"; -} - -.fa-upload { - --fa: "\f093"; -} - -.fa-hurricane { - --fa: "\f751"; -} - -.fa-mound { - --fa: "\e52d"; -} - -.fa-toilet-portable { - --fa: "\e583"; -} - -.fa-compact-disc { - --fa: "\f51f"; -} - -.fa-file-arrow-down { - --fa: "\f56d"; -} - -.fa-file-download { - --fa: "\f56d"; -} - -.fa-caravan { - --fa: "\f8ff"; -} - -.fa-shield-cat { - --fa: "\e572"; -} - -.fa-bolt { - --fa: "\f0e7"; -} - -.fa-zap { - --fa: "\f0e7"; -} - -.fa-glass-water { - --fa: "\e4f4"; -} - -.fa-oil-well { - --fa: "\e532"; -} - -.fa-vault { - --fa: "\e2c5"; -} - -.fa-mars { - --fa: "\f222"; -} - -.fa-toilet { - --fa: "\f7d8"; -} - -.fa-plane-circle-xmark { - --fa: "\e557"; -} - -.fa-yen-sign { - --fa: "\f157"; -} - -.fa-cny { - --fa: "\f157"; -} - -.fa-jpy { - --fa: "\f157"; -} - -.fa-rmb { - --fa: "\f157"; -} - -.fa-yen { - --fa: "\f157"; -} - -.fa-ruble-sign { - --fa: "\f158"; -} - -.fa-rouble { - --fa: "\f158"; -} - -.fa-rub { - --fa: "\f158"; -} - -.fa-ruble { - --fa: "\f158"; -} - -.fa-sun { - --fa: "\f185"; -} - -.fa-guitar { - --fa: "\f7a6"; -} - -.fa-face-laugh-wink { - --fa: "\f59c"; -} - -.fa-laugh-wink { - --fa: "\f59c"; -} - -.fa-horse-head { - --fa: "\f7ab"; -} - -.fa-bore-hole { - --fa: "\e4c3"; -} - -.fa-industry { - --fa: "\f275"; -} - -.fa-circle-down { - --fa: "\f358"; -} - -.fa-arrow-alt-circle-down { - --fa: "\f358"; -} - -.fa-arrows-turn-to-dots { - --fa: "\e4c1"; -} - -.fa-florin-sign { - --fa: "\e184"; -} - -.fa-arrow-down-short-wide { - --fa: "\f884"; -} - -.fa-sort-amount-desc { - --fa: "\f884"; -} - -.fa-sort-amount-down-alt { - --fa: "\f884"; -} - -.fa-less-than { - --fa: "\3c"; -} - -.fa-angle-down { - --fa: "\f107"; -} - -.fa-car-tunnel { - --fa: "\e4de"; -} - -.fa-head-side-cough { - --fa: "\e061"; -} - -.fa-grip-lines { - --fa: "\f7a4"; -} - -.fa-thumbs-down { - --fa: "\f165"; -} - -.fa-user-lock { - --fa: "\f502"; -} - -.fa-arrow-right-long { - --fa: "\f178"; -} - -.fa-long-arrow-right { - --fa: "\f178"; -} - -.fa-anchor-circle-xmark { - --fa: "\e4ac"; -} - -.fa-ellipsis { - --fa: "\f141"; -} - -.fa-ellipsis-h { - --fa: "\f141"; -} - -.fa-chess-pawn { - --fa: "\f443"; -} - -.fa-kit-medical { - --fa: "\f479"; -} - -.fa-first-aid { - --fa: "\f479"; -} - -.fa-person-through-window { - --fa: "\e5a9"; -} - -.fa-toolbox { - --fa: "\f552"; -} - -.fa-hands-holding-circle { - --fa: "\e4fb"; -} - -.fa-bug { - --fa: "\f188"; -} - -.fa-credit-card { - --fa: "\f09d"; -} - -.fa-credit-card-alt { - --fa: "\f09d"; -} - -.fa-car { - --fa: "\f1b9"; -} - -.fa-automobile { - --fa: "\f1b9"; -} - -.fa-hand-holding-hand { - --fa: "\e4f7"; -} - -.fa-book-open-reader { - --fa: "\f5da"; -} - -.fa-book-reader { - --fa: "\f5da"; -} - -.fa-mountain-sun { - --fa: "\e52f"; -} - -.fa-arrows-left-right-to-line { - --fa: "\e4ba"; -} - -.fa-dice-d20 { - --fa: "\f6cf"; -} - -.fa-truck-droplet { - --fa: "\e58c"; -} - -.fa-file-circle-xmark { - --fa: "\e5a1"; -} - -.fa-temperature-arrow-up { - --fa: "\e040"; -} - -.fa-temperature-up { - --fa: "\e040"; -} - -.fa-medal { - --fa: "\f5a2"; -} - -.fa-bed { - --fa: "\f236"; -} - -.fa-square-h { - --fa: "\f0fd"; -} - -.fa-h-square { - --fa: "\f0fd"; -} - -.fa-podcast { - --fa: "\f2ce"; -} - -.fa-temperature-full { - --fa: "\f2c7"; -} - -.fa-temperature-4 { - --fa: "\f2c7"; -} - -.fa-thermometer-4 { - --fa: "\f2c7"; -} - -.fa-thermometer-full { - --fa: "\f2c7"; -} - -.fa-bell { - --fa: "\f0f3"; -} - -.fa-superscript { - --fa: "\f12b"; -} - -.fa-plug-circle-xmark { - --fa: "\e560"; -} - -.fa-star-of-life { - --fa: "\f621"; -} - -.fa-phone-slash { - --fa: "\f3dd"; -} - -.fa-paint-roller { - --fa: "\f5aa"; -} - -.fa-handshake-angle { - --fa: "\f4c4"; -} - -.fa-hands-helping { - --fa: "\f4c4"; -} - -.fa-location-dot { - --fa: "\f3c5"; -} - -.fa-map-marker-alt { - --fa: "\f3c5"; -} - -.fa-file { - --fa: "\f15b"; -} - -.fa-greater-than { - --fa: "\3e"; -} - -.fa-person-swimming { - --fa: "\f5c4"; -} - -.fa-swimmer { - --fa: "\f5c4"; -} - -.fa-arrow-down { - --fa: "\f063"; -} - -.fa-droplet { - --fa: "\f043"; -} - -.fa-tint { - --fa: "\f043"; -} - -.fa-eraser { - --fa: "\f12d"; -} - -.fa-earth-americas { - --fa: "\f57d"; -} - -.fa-earth { - --fa: "\f57d"; -} - -.fa-earth-america { - --fa: "\f57d"; -} - -.fa-globe-americas { - --fa: "\f57d"; -} - -.fa-person-burst { - --fa: "\e53b"; -} - -.fa-dove { - --fa: "\f4ba"; -} - -.fa-battery-empty { - --fa: "\f244"; -} - -.fa-battery-0 { - --fa: "\f244"; -} - -.fa-socks { - --fa: "\f696"; -} - -.fa-inbox { - --fa: "\f01c"; -} - -.fa-section { - --fa: "\e447"; -} - -.fa-gauge-high { - --fa: "\f625"; -} - -.fa-tachometer-alt { - --fa: "\f625"; -} - -.fa-tachometer-alt-fast { - --fa: "\f625"; -} - -.fa-envelope-open-text { - --fa: "\f658"; -} - -.fa-hospital { - --fa: "\f0f8"; -} - -.fa-hospital-alt { - --fa: "\f0f8"; -} - -.fa-hospital-wide { - --fa: "\f0f8"; -} - -.fa-wine-bottle { - --fa: "\f72f"; -} - -.fa-chess-rook { - --fa: "\f447"; -} - -.fa-bars-staggered { - --fa: "\f550"; -} - -.fa-reorder { - --fa: "\f550"; -} - -.fa-stream { - --fa: "\f550"; -} - -.fa-dharmachakra { - --fa: "\f655"; -} - -.fa-hotdog { - --fa: "\f80f"; -} - -.fa-person-walking-with-cane { - --fa: "\f29d"; -} - -.fa-blind { - --fa: "\f29d"; -} - -.fa-drum { - --fa: "\f569"; -} - -.fa-ice-cream { - --fa: "\f810"; -} - -.fa-heart-circle-bolt { - --fa: "\e4fc"; -} - -.fa-fax { - --fa: "\f1ac"; -} - -.fa-paragraph { - --fa: "\f1dd"; -} - -.fa-check-to-slot { - --fa: "\f772"; -} - -.fa-vote-yea { - --fa: "\f772"; -} - -.fa-star-half { - --fa: "\f089"; -} - -.fa-boxes-stacked { - --fa: "\f468"; -} - -.fa-boxes { - --fa: "\f468"; -} - -.fa-boxes-alt { - --fa: "\f468"; -} - -.fa-link { - --fa: "\f0c1"; -} - -.fa-chain { - --fa: "\f0c1"; -} - -.fa-ear-listen { - --fa: "\f2a2"; -} - -.fa-assistive-listening-systems { - --fa: "\f2a2"; -} - -.fa-tree-city { - --fa: "\e587"; -} - -.fa-play { - --fa: "\f04b"; -} - -.fa-font { - --fa: "\f031"; -} - -.fa-table-cells-row-lock { - --fa: "\e67a"; -} - -.fa-rupiah-sign { - --fa: "\e23d"; -} - -.fa-magnifying-glass { - --fa: "\f002"; -} - -.fa-search { - --fa: "\f002"; -} - -.fa-table-tennis-paddle-ball { - --fa: "\f45d"; -} - -.fa-ping-pong-paddle-ball { - --fa: "\f45d"; -} - -.fa-table-tennis { - --fa: "\f45d"; -} - -.fa-person-dots-from-line { - --fa: "\f470"; -} - -.fa-diagnoses { - --fa: "\f470"; -} - -.fa-trash-can-arrow-up { - --fa: "\f82a"; -} - -.fa-trash-restore-alt { - --fa: "\f82a"; -} - -.fa-naira-sign { - --fa: "\e1f6"; -} - -.fa-cart-arrow-down { - --fa: "\f218"; -} - -.fa-walkie-talkie { - --fa: "\f8ef"; -} - -.fa-file-pen { - --fa: "\f31c"; -} - -.fa-file-edit { - --fa: "\f31c"; -} - -.fa-receipt { - --fa: "\f543"; -} - -.fa-square-pen { - --fa: "\f14b"; -} - -.fa-pen-square { - --fa: "\f14b"; -} - -.fa-pencil-square { - --fa: "\f14b"; -} - -.fa-suitcase-rolling { - --fa: "\f5c1"; -} - -.fa-person-circle-exclamation { - --fa: "\e53f"; -} - -.fa-chevron-down { - --fa: "\f078"; -} - -.fa-battery-full { - --fa: "\f240"; -} - -.fa-battery { - --fa: "\f240"; -} - -.fa-battery-5 { - --fa: "\f240"; -} - -.fa-skull-crossbones { - --fa: "\f714"; -} - -.fa-code-compare { - --fa: "\e13a"; -} - -.fa-list-ul { - --fa: "\f0ca"; -} - -.fa-list-dots { - --fa: "\f0ca"; -} - -.fa-school-lock { - --fa: "\e56f"; -} - -.fa-tower-cell { - --fa: "\e585"; -} - -.fa-down-long { - --fa: "\f309"; -} - -.fa-long-arrow-alt-down { - --fa: "\f309"; -} - -.fa-ranking-star { - --fa: "\e561"; -} - -.fa-chess-king { - --fa: "\f43f"; -} - -.fa-person-harassing { - --fa: "\e549"; -} - -.fa-brazilian-real-sign { - --fa: "\e46c"; -} - -.fa-landmark-dome { - --fa: "\f752"; -} - -.fa-landmark-alt { - --fa: "\f752"; -} - -.fa-arrow-up { - --fa: "\f062"; -} - -.fa-tv { - --fa: "\f26c"; -} - -.fa-television { - --fa: "\f26c"; -} - -.fa-tv-alt { - --fa: "\f26c"; -} - -.fa-shrimp { - --fa: "\e448"; -} - -.fa-list-check { - --fa: "\f0ae"; -} - -.fa-tasks { - --fa: "\f0ae"; -} - -.fa-jug-detergent { - --fa: "\e519"; -} - -.fa-circle-user { - --fa: "\f2bd"; -} - -.fa-user-circle { - --fa: "\f2bd"; -} - -.fa-user-shield { - --fa: "\f505"; -} - -.fa-wind { - --fa: "\f72e"; -} - -.fa-car-burst { - --fa: "\f5e1"; -} - -.fa-car-crash { - --fa: "\f5e1"; -} - -.fa-y { - --fa: "\59"; -} - -.fa-person-snowboarding { - --fa: "\f7ce"; -} - -.fa-snowboarding { - --fa: "\f7ce"; -} - -.fa-truck-fast { - --fa: "\f48b"; -} - -.fa-shipping-fast { - --fa: "\f48b"; -} - -.fa-fish { - --fa: "\f578"; -} - -.fa-user-graduate { - --fa: "\f501"; -} - -.fa-circle-half-stroke { - --fa: "\f042"; -} - -.fa-adjust { - --fa: "\f042"; -} - -.fa-clapperboard { - --fa: "\e131"; -} - -.fa-circle-radiation { - --fa: "\f7ba"; -} - -.fa-radiation-alt { - --fa: "\f7ba"; -} - -.fa-baseball { - --fa: "\f433"; -} - -.fa-baseball-ball { - --fa: "\f433"; -} - -.fa-jet-fighter-up { - --fa: "\e518"; -} - -.fa-diagram-project { - --fa: "\f542"; -} - -.fa-project-diagram { - --fa: "\f542"; -} - -.fa-copy { - --fa: "\f0c5"; -} - -.fa-volume-xmark { - --fa: "\f6a9"; -} - -.fa-volume-mute { - --fa: "\f6a9"; -} - -.fa-volume-times { - --fa: "\f6a9"; -} - -.fa-hand-sparkles { - --fa: "\e05d"; -} - -.fa-grip { - --fa: "\f58d"; -} - -.fa-grip-horizontal { - --fa: "\f58d"; -} - -.fa-share-from-square { - --fa: "\f14d"; -} - -.fa-share-square { - --fa: "\f14d"; -} - -.fa-child-combatant { - --fa: "\e4e0"; -} - -.fa-child-rifle { - --fa: "\e4e0"; -} - -.fa-gun { - --fa: "\e19b"; -} - -.fa-square-phone { - --fa: "\f098"; -} - -.fa-phone-square { - --fa: "\f098"; -} - -.fa-plus { - --fa: "\2b"; -} - -.fa-add { - --fa: "\2b"; -} - -.fa-expand { - --fa: "\f065"; -} - -.fa-computer { - --fa: "\e4e5"; -} - -.fa-xmark { - --fa: "\f00d"; -} - -.fa-close { - --fa: "\f00d"; -} - -.fa-multiply { - --fa: "\f00d"; -} - -.fa-remove { - --fa: "\f00d"; -} - -.fa-times { - --fa: "\f00d"; -} - -.fa-arrows-up-down-left-right { - --fa: "\f047"; -} - -.fa-arrows { - --fa: "\f047"; -} - -.fa-chalkboard-user { - --fa: "\f51c"; -} - -.fa-chalkboard-teacher { - --fa: "\f51c"; -} - -.fa-peso-sign { - --fa: "\e222"; -} - -.fa-building-shield { - --fa: "\e4d8"; -} - -.fa-baby { - --fa: "\f77c"; -} - -.fa-users-line { - --fa: "\e592"; -} - -.fa-quote-left { - --fa: "\f10d"; -} - -.fa-quote-left-alt { - --fa: "\f10d"; -} - -.fa-tractor { - --fa: "\f722"; -} - -.fa-trash-arrow-up { - --fa: "\f829"; -} - -.fa-trash-restore { - --fa: "\f829"; -} - -.fa-arrow-down-up-lock { - --fa: "\e4b0"; -} - -.fa-lines-leaning { - --fa: "\e51e"; -} - -.fa-ruler-combined { - --fa: "\f546"; -} - -.fa-copyright { - --fa: "\f1f9"; -} - -.fa-equals { - --fa: "\3d"; -} - -.fa-blender { - --fa: "\f517"; -} - -.fa-teeth { - --fa: "\f62e"; -} - -.fa-shekel-sign { - --fa: "\f20b"; -} - -.fa-ils { - --fa: "\f20b"; -} - -.fa-shekel { - --fa: "\f20b"; -} - -.fa-sheqel { - --fa: "\f20b"; -} - -.fa-sheqel-sign { - --fa: "\f20b"; -} - -.fa-map { - --fa: "\f279"; -} - -.fa-rocket { - --fa: "\f135"; -} - -.fa-photo-film { - --fa: "\f87c"; -} - -.fa-photo-video { - --fa: "\f87c"; -} - -.fa-folder-minus { - --fa: "\f65d"; -} - -.fa-hexagon-nodes-bolt { - --fa: "\e69a"; -} - -.fa-store { - --fa: "\f54e"; -} - -.fa-arrow-trend-up { - --fa: "\e098"; -} - -.fa-plug-circle-minus { - --fa: "\e55e"; -} - -.fa-sign-hanging { - --fa: "\f4d9"; -} - -.fa-sign { - --fa: "\f4d9"; -} - -.fa-bezier-curve { - --fa: "\f55b"; -} - -.fa-bell-slash { - --fa: "\f1f6"; -} - -.fa-tablet { - --fa: "\f3fb"; -} - -.fa-tablet-android { - --fa: "\f3fb"; -} - -.fa-school-flag { - --fa: "\e56e"; -} - -.fa-fill { - --fa: "\f575"; -} - -.fa-angle-up { - --fa: "\f106"; -} - -.fa-drumstick-bite { - --fa: "\f6d7"; -} - -.fa-holly-berry { - --fa: "\f7aa"; -} - -.fa-chevron-left { - --fa: "\f053"; -} - -.fa-bacteria { - --fa: "\e059"; -} - -.fa-hand-lizard { - --fa: "\f258"; -} - -.fa-notdef { - --fa: "\e1fe"; -} - -.fa-disease { - --fa: "\f7fa"; -} - -.fa-briefcase-medical { - --fa: "\f469"; -} - -.fa-genderless { - --fa: "\f22d"; -} - -.fa-chevron-right { - --fa: "\f054"; -} - -.fa-retweet { - --fa: "\f079"; -} - -.fa-car-rear { - --fa: "\f5de"; -} - -.fa-car-alt { - --fa: "\f5de"; -} - -.fa-pump-soap { - --fa: "\e06b"; -} - -.fa-video-slash { - --fa: "\f4e2"; -} - -.fa-battery-quarter { - --fa: "\f243"; -} - -.fa-battery-2 { - --fa: "\f243"; -} - -.fa-radio { - --fa: "\f8d7"; -} - -.fa-baby-carriage { - --fa: "\f77d"; -} - -.fa-carriage-baby { - --fa: "\f77d"; -} - -.fa-traffic-light { - --fa: "\f637"; -} - -.fa-thermometer { - --fa: "\f491"; -} - -.fa-vr-cardboard { - --fa: "\f729"; -} - -.fa-hand-middle-finger { - --fa: "\f806"; -} - -.fa-percent { - --fa: "\25"; -} - -.fa-percentage { - --fa: "\25"; -} - -.fa-truck-moving { - --fa: "\f4df"; -} - -.fa-glass-water-droplet { - --fa: "\e4f5"; -} - -.fa-display { - --fa: "\e163"; -} - -.fa-face-smile { - --fa: "\f118"; -} - -.fa-smile { - --fa: "\f118"; -} - -.fa-thumbtack { - --fa: "\f08d"; -} - -.fa-thumb-tack { - --fa: "\f08d"; -} - -.fa-trophy { - --fa: "\f091"; -} - -.fa-person-praying { - --fa: "\f683"; -} - -.fa-pray { - --fa: "\f683"; -} - -.fa-hammer { - --fa: "\f6e3"; -} - -.fa-hand-peace { - --fa: "\f25b"; -} - -.fa-rotate { - --fa: "\f2f1"; -} - -.fa-sync-alt { - --fa: "\f2f1"; -} - -.fa-spinner { - --fa: "\f110"; -} - -.fa-robot { - --fa: "\f544"; -} - -.fa-peace { - --fa: "\f67c"; -} - -.fa-gears { - --fa: "\f085"; -} - -.fa-cogs { - --fa: "\f085"; -} - -.fa-warehouse { - --fa: "\f494"; -} - -.fa-arrow-up-right-dots { - --fa: "\e4b7"; -} - -.fa-splotch { - --fa: "\f5bc"; -} - -.fa-face-grin-hearts { - --fa: "\f584"; -} - -.fa-grin-hearts { - --fa: "\f584"; -} - -.fa-dice-four { - --fa: "\f524"; -} - -.fa-sim-card { - --fa: "\f7c4"; -} - -.fa-transgender { - --fa: "\f225"; -} - -.fa-transgender-alt { - --fa: "\f225"; -} - -.fa-mercury { - --fa: "\f223"; -} - -.fa-arrow-turn-down { - --fa: "\f149"; -} - -.fa-level-down { - --fa: "\f149"; -} - -.fa-person-falling-burst { - --fa: "\e547"; -} - -.fa-award { - --fa: "\f559"; -} - -.fa-ticket-simple { - --fa: "\f3ff"; -} - -.fa-ticket-alt { - --fa: "\f3ff"; -} - -.fa-building { - --fa: "\f1ad"; -} - -.fa-angles-left { - --fa: "\f100"; -} - -.fa-angle-double-left { - --fa: "\f100"; -} - -.fa-qrcode { - --fa: "\f029"; -} - -.fa-clock-rotate-left { - --fa: "\f1da"; -} - -.fa-history { - --fa: "\f1da"; -} - -.fa-face-grin-beam-sweat { - --fa: "\f583"; -} - -.fa-grin-beam-sweat { - --fa: "\f583"; -} - -.fa-file-export { - --fa: "\f56e"; -} - -.fa-arrow-right-from-file { - --fa: "\f56e"; -} - -.fa-shield { - --fa: "\f132"; -} - -.fa-shield-blank { - --fa: "\f132"; -} - -.fa-arrow-up-short-wide { - --fa: "\f885"; -} - -.fa-sort-amount-up-alt { - --fa: "\f885"; -} - -.fa-comment-nodes { - --fa: "\e696"; -} - -.fa-house-medical { - --fa: "\e3b2"; -} - -.fa-golf-ball-tee { - --fa: "\f450"; -} - -.fa-golf-ball { - --fa: "\f450"; -} - -.fa-circle-chevron-left { - --fa: "\f137"; -} - -.fa-chevron-circle-left { - --fa: "\f137"; -} - -.fa-house-chimney-window { - --fa: "\e00d"; -} - -.fa-pen-nib { - --fa: "\f5ad"; -} - -.fa-tent-arrow-turn-left { - --fa: "\e580"; -} - -.fa-tents { - --fa: "\e582"; -} - -.fa-wand-magic { - --fa: "\f0d0"; -} - -.fa-magic { - --fa: "\f0d0"; -} - -.fa-dog { - --fa: "\f6d3"; -} - -.fa-carrot { - --fa: "\f787"; -} - -.fa-moon { - --fa: "\f186"; -} - -.fa-wine-glass-empty { - --fa: "\f5ce"; -} - -.fa-wine-glass-alt { - --fa: "\f5ce"; -} - -.fa-cheese { - --fa: "\f7ef"; -} - -.fa-yin-yang { - --fa: "\f6ad"; -} - -.fa-music { - --fa: "\f001"; -} - -.fa-code-commit { - --fa: "\f386"; -} - -.fa-temperature-low { - --fa: "\f76b"; -} - -.fa-person-biking { - --fa: "\f84a"; -} - -.fa-biking { - --fa: "\f84a"; -} - -.fa-broom { - --fa: "\f51a"; -} - -.fa-shield-heart { - --fa: "\e574"; -} - -.fa-gopuram { - --fa: "\f664"; -} - -.fa-earth-oceania { - --fa: "\e47b"; -} - -.fa-globe-oceania { - --fa: "\e47b"; -} - -.fa-square-xmark { - --fa: "\f2d3"; -} - -.fa-times-square { - --fa: "\f2d3"; -} - -.fa-xmark-square { - --fa: "\f2d3"; -} - -.fa-hashtag { - --fa: "\23"; -} - -.fa-up-right-and-down-left-from-center { - --fa: "\f424"; -} - -.fa-expand-alt { - --fa: "\f424"; -} - -.fa-oil-can { - --fa: "\f613"; -} - -.fa-t { - --fa: "\54"; -} - -.fa-hippo { - --fa: "\f6ed"; -} - -.fa-chart-column { - --fa: "\e0e3"; -} - -.fa-infinity { - --fa: "\f534"; -} - -.fa-vial-circle-check { - --fa: "\e596"; -} - -.fa-person-arrow-down-to-line { - --fa: "\e538"; -} - -.fa-voicemail { - --fa: "\f897"; -} - -.fa-fan { - --fa: "\f863"; -} - -.fa-person-walking-luggage { - --fa: "\e554"; -} - -.fa-up-down { - --fa: "\f338"; -} - -.fa-arrows-alt-v { - --fa: "\f338"; -} - -.fa-cloud-moon-rain { - --fa: "\f73c"; -} - -.fa-calendar { - --fa: "\f133"; -} - -.fa-trailer { - --fa: "\e041"; -} - -.fa-bahai { - --fa: "\f666"; -} - -.fa-haykal { - --fa: "\f666"; -} - -.fa-sd-card { - --fa: "\f7c2"; -} - -.fa-dragon { - --fa: "\f6d5"; -} - -.fa-shoe-prints { - --fa: "\f54b"; -} - -.fa-circle-plus { - --fa: "\f055"; -} - -.fa-plus-circle { - --fa: "\f055"; -} - -.fa-face-grin-tongue-wink { - --fa: "\f58b"; -} - -.fa-grin-tongue-wink { - --fa: "\f58b"; -} - -.fa-hand-holding { - --fa: "\f4bd"; -} - -.fa-plug-circle-exclamation { - --fa: "\e55d"; -} - -.fa-link-slash { - --fa: "\f127"; -} - -.fa-chain-broken { - --fa: "\f127"; -} - -.fa-chain-slash { - --fa: "\f127"; -} - -.fa-unlink { - --fa: "\f127"; -} - -.fa-clone { - --fa: "\f24d"; -} - -.fa-person-walking-arrow-loop-left { - --fa: "\e551"; -} - -.fa-arrow-up-z-a { - --fa: "\f882"; -} - -.fa-sort-alpha-up-alt { - --fa: "\f882"; -} - -.fa-fire-flame-curved { - --fa: "\f7e4"; -} - -.fa-fire-alt { - --fa: "\f7e4"; -} - -.fa-tornado { - --fa: "\f76f"; -} - -.fa-file-circle-plus { - --fa: "\e494"; -} - -.fa-book-quran { - --fa: "\f687"; -} - -.fa-quran { - --fa: "\f687"; -} - -.fa-anchor { - --fa: "\f13d"; -} - -.fa-border-all { - --fa: "\f84c"; -} - -.fa-face-angry { - --fa: "\f556"; -} - -.fa-angry { - --fa: "\f556"; -} - -.fa-cookie-bite { - --fa: "\f564"; -} - -.fa-arrow-trend-down { - --fa: "\e097"; -} - -.fa-rss { - --fa: "\f09e"; -} - -.fa-feed { - --fa: "\f09e"; -} - -.fa-draw-polygon { - --fa: "\f5ee"; -} - -.fa-scale-balanced { - --fa: "\f24e"; -} - -.fa-balance-scale { - --fa: "\f24e"; -} - -.fa-gauge-simple-high { - --fa: "\f62a"; -} - -.fa-tachometer { - --fa: "\f62a"; -} - -.fa-tachometer-fast { - --fa: "\f62a"; -} - -.fa-shower { - --fa: "\f2cc"; -} - -.fa-desktop { - --fa: "\f390"; -} - -.fa-desktop-alt { - --fa: "\f390"; -} - -.fa-m { - --fa: "\4d"; -} - -.fa-table-list { - --fa: "\f00b"; -} - -.fa-th-list { - --fa: "\f00b"; -} - -.fa-comment-sms { - --fa: "\f7cd"; -} - -.fa-sms { - --fa: "\f7cd"; -} - -.fa-book { - --fa: "\f02d"; -} - -.fa-user-plus { - --fa: "\f234"; -} - -.fa-check { - --fa: "\f00c"; -} - -.fa-battery-three-quarters { - --fa: "\f241"; -} - -.fa-battery-4 { - --fa: "\f241"; -} - -.fa-house-circle-check { - --fa: "\e509"; -} - -.fa-angle-left { - --fa: "\f104"; -} - -.fa-diagram-successor { - --fa: "\e47a"; -} - -.fa-truck-arrow-right { - --fa: "\e58b"; -} - -.fa-arrows-split-up-and-left { - --fa: "\e4bc"; -} - -.fa-hand-fist { - --fa: "\f6de"; -} - -.fa-fist-raised { - --fa: "\f6de"; -} - -.fa-cloud-moon { - --fa: "\f6c3"; -} - -.fa-briefcase { - --fa: "\f0b1"; -} - -.fa-person-falling { - --fa: "\e546"; -} - -.fa-image-portrait { - --fa: "\f3e0"; -} - -.fa-portrait { - --fa: "\f3e0"; -} - -.fa-user-tag { - --fa: "\f507"; -} - -.fa-rug { - --fa: "\e569"; -} - -.fa-earth-europe { - --fa: "\f7a2"; -} - -.fa-globe-europe { - --fa: "\f7a2"; -} - -.fa-cart-flatbed-suitcase { - --fa: "\f59d"; -} - -.fa-luggage-cart { - --fa: "\f59d"; -} - -.fa-rectangle-xmark { - --fa: "\f410"; -} - -.fa-rectangle-times { - --fa: "\f410"; -} - -.fa-times-rectangle { - --fa: "\f410"; -} - -.fa-window-close { - --fa: "\f410"; -} - -.fa-baht-sign { - --fa: "\e0ac"; -} - -.fa-book-open { - --fa: "\f518"; -} - -.fa-book-journal-whills { - --fa: "\f66a"; -} - -.fa-journal-whills { - --fa: "\f66a"; -} - -.fa-handcuffs { - --fa: "\e4f8"; -} - -.fa-triangle-exclamation { - --fa: "\f071"; -} - -.fa-exclamation-triangle { - --fa: "\f071"; -} - -.fa-warning { - --fa: "\f071"; -} - -.fa-database { - --fa: "\f1c0"; -} - -.fa-share { - --fa: "\f064"; -} - -.fa-mail-forward { - --fa: "\f064"; -} - -.fa-bottle-droplet { - --fa: "\e4c4"; -} - -.fa-mask-face { - --fa: "\e1d7"; -} - -.fa-hill-rockslide { - --fa: "\e508"; -} - -.fa-right-left { - --fa: "\f362"; -} - -.fa-exchange-alt { - --fa: "\f362"; -} - -.fa-paper-plane { - --fa: "\f1d8"; -} - -.fa-road-circle-exclamation { - --fa: "\e565"; -} - -.fa-dungeon { - --fa: "\f6d9"; -} - -.fa-align-right { - --fa: "\f038"; -} - -.fa-money-bill-1-wave { - --fa: "\f53b"; -} - -.fa-money-bill-wave-alt { - --fa: "\f53b"; -} - -.fa-life-ring { - --fa: "\f1cd"; -} - -.fa-hands { - --fa: "\f2a7"; -} - -.fa-sign-language { - --fa: "\f2a7"; -} - -.fa-signing { - --fa: "\f2a7"; -} - -.fa-calendar-day { - --fa: "\f783"; -} - -.fa-water-ladder { - --fa: "\f5c5"; -} - -.fa-ladder-water { - --fa: "\f5c5"; -} - -.fa-swimming-pool { - --fa: "\f5c5"; -} - -.fa-arrows-up-down { - --fa: "\f07d"; -} - -.fa-arrows-v { - --fa: "\f07d"; -} - -.fa-face-grimace { - --fa: "\f57f"; -} - -.fa-grimace { - --fa: "\f57f"; -} - -.fa-wheelchair-move { - --fa: "\e2ce"; -} - -.fa-wheelchair-alt { - --fa: "\e2ce"; -} - -.fa-turn-down { - --fa: "\f3be"; -} - -.fa-level-down-alt { - --fa: "\f3be"; -} - -.fa-person-walking-arrow-right { - --fa: "\e552"; -} - -.fa-square-envelope { - --fa: "\f199"; -} - -.fa-envelope-square { - --fa: "\f199"; -} - -.fa-dice { - --fa: "\f522"; -} - -.fa-bowling-ball { - --fa: "\f436"; -} - -.fa-brain { - --fa: "\f5dc"; -} - -.fa-bandage { - --fa: "\f462"; -} - -.fa-band-aid { - --fa: "\f462"; -} - -.fa-calendar-minus { - --fa: "\f272"; -} - -.fa-circle-xmark { - --fa: "\f057"; -} - -.fa-times-circle { - --fa: "\f057"; -} - -.fa-xmark-circle { - --fa: "\f057"; -} - -.fa-gifts { - --fa: "\f79c"; -} - -.fa-hotel { - --fa: "\f594"; -} - -.fa-earth-asia { - --fa: "\f57e"; -} - -.fa-globe-asia { - --fa: "\f57e"; -} - -.fa-id-card-clip { - --fa: "\f47f"; -} - -.fa-id-card-alt { - --fa: "\f47f"; -} - -.fa-magnifying-glass-plus { - --fa: "\f00e"; -} - -.fa-search-plus { - --fa: "\f00e"; -} - -.fa-thumbs-up { - --fa: "\f164"; -} - -.fa-user-clock { - --fa: "\f4fd"; -} - -.fa-hand-dots { - --fa: "\f461"; -} - -.fa-allergies { - --fa: "\f461"; -} - -.fa-file-invoice { - --fa: "\f570"; -} - -.fa-window-minimize { - --fa: "\f2d1"; -} - -.fa-mug-saucer { - --fa: "\f0f4"; -} - -.fa-coffee { - --fa: "\f0f4"; -} - -.fa-brush { - --fa: "\f55d"; -} - -.fa-file-half-dashed { - --fa: "\e698"; -} - -.fa-mask { - --fa: "\f6fa"; -} - -.fa-magnifying-glass-minus { - --fa: "\f010"; -} - -.fa-search-minus { - --fa: "\f010"; -} - -.fa-ruler-vertical { - --fa: "\f548"; -} - -.fa-user-large { - --fa: "\f406"; -} - -.fa-user-alt { - --fa: "\f406"; -} - -.fa-train-tram { - --fa: "\e5b4"; -} - -.fa-user-nurse { - --fa: "\f82f"; -} - -.fa-syringe { - --fa: "\f48e"; -} - -.fa-cloud-sun { - --fa: "\f6c4"; -} - -.fa-stopwatch-20 { - --fa: "\e06f"; -} - -.fa-square-full { - --fa: "\f45c"; -} - -.fa-magnet { - --fa: "\f076"; -} - -.fa-jar { - --fa: "\e516"; -} - -.fa-note-sticky { - --fa: "\f249"; -} - -.fa-sticky-note { - --fa: "\f249"; -} - -.fa-bug-slash { - --fa: "\e490"; -} - -.fa-arrow-up-from-water-pump { - --fa: "\e4b6"; -} - -.fa-bone { - --fa: "\f5d7"; -} - -.fa-table-cells-row-unlock { - --fa: "\e691"; -} - -.fa-user-injured { - --fa: "\f728"; -} - -.fa-face-sad-tear { - --fa: "\f5b4"; -} - -.fa-sad-tear { - --fa: "\f5b4"; -} - -.fa-plane { - --fa: "\f072"; -} - -.fa-tent-arrows-down { - --fa: "\e581"; -} - -.fa-exclamation { - --fa: "\21"; -} - -.fa-arrows-spin { - --fa: "\e4bb"; -} - -.fa-print { - --fa: "\f02f"; -} - -.fa-turkish-lira-sign { - --fa: "\e2bb"; -} - -.fa-try { - --fa: "\e2bb"; -} - -.fa-turkish-lira { - --fa: "\e2bb"; -} - -.fa-dollar-sign { - --fa: "\24"; -} - -.fa-dollar { - --fa: "\24"; -} - -.fa-usd { - --fa: "\24"; -} - -.fa-x { - --fa: "\58"; -} - -.fa-magnifying-glass-dollar { - --fa: "\f688"; -} - -.fa-search-dollar { - --fa: "\f688"; -} - -.fa-users-gear { - --fa: "\f509"; -} - -.fa-users-cog { - --fa: "\f509"; -} - -.fa-person-military-pointing { - --fa: "\e54a"; -} - -.fa-building-columns { - --fa: "\f19c"; -} - -.fa-bank { - --fa: "\f19c"; -} - -.fa-institution { - --fa: "\f19c"; -} - -.fa-museum { - --fa: "\f19c"; -} - -.fa-university { - --fa: "\f19c"; -} - -.fa-umbrella { - --fa: "\f0e9"; -} - -.fa-trowel { - --fa: "\e589"; -} - -.fa-d { - --fa: "\44"; -} - -.fa-stapler { - --fa: "\e5af"; -} - -.fa-masks-theater { - --fa: "\f630"; -} - -.fa-theater-masks { - --fa: "\f630"; -} - -.fa-kip-sign { - --fa: "\e1c4"; -} - -.fa-hand-point-left { - --fa: "\f0a5"; -} - -.fa-handshake-simple { - --fa: "\f4c6"; -} - -.fa-handshake-alt { - --fa: "\f4c6"; -} - -.fa-jet-fighter { - --fa: "\f0fb"; -} - -.fa-fighter-jet { - --fa: "\f0fb"; -} - -.fa-square-share-nodes { - --fa: "\f1e1"; -} - -.fa-share-alt-square { - --fa: "\f1e1"; -} - -.fa-barcode { - --fa: "\f02a"; -} - -.fa-plus-minus { - --fa: "\e43c"; -} - -.fa-video { - --fa: "\f03d"; -} - -.fa-video-camera { - --fa: "\f03d"; -} - -.fa-graduation-cap { - --fa: "\f19d"; -} - -.fa-mortar-board { - --fa: "\f19d"; -} - -.fa-hand-holding-medical { - --fa: "\e05c"; -} - -.fa-person-circle-check { - --fa: "\e53e"; -} - -.fa-turn-up { - --fa: "\f3bf"; -} - -.fa-level-up-alt { - --fa: "\f3bf"; -} - -.sr-only, -.fa-sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} - -.sr-only-focusable:not(:focus), -.fa-sr-only-focusable:not(:focus) { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} diff --git a/apps/mobile/global.css b/apps/mobile/global.css deleted file mode 100644 index 83666a3..0000000 --- a/apps/mobile/global.css +++ /dev/null @@ -1,5 +0,0 @@ -@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"); - -body { - font-family: "Inter", sans-serif !important; -} diff --git a/apps/mobile/global.d.ts b/apps/mobile/global.d.ts deleted file mode 100644 index 53c72cf..0000000 --- a/apps/mobile/global.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -declare module 'react-native/Libraries/Core/ExceptionsManager' { - export function handleException(err: Error, isFatal: boolean): void; -} - -declare module 'react-native-safe-area-context/lib/commonjs' { - export const SafeAreaView: React.ComponentType; - export const SafeAreaProvider: React.ComponentType; - export const SafeAreaInsetsContext: React.Context; - export const SafeAreaFrameContext: React.Context; - export function useSafeAreaInsets(): { top: number; right: number; bottom: number; left: number }; - export function useSafeAreaFrame(): { x: number; y: number; width: number; height: number }; - export const initialWindowMetrics: any; -} - -declare module 'react-native-web-refresh-control' { - export const RefreshControl: React.ComponentType; -} - -declare module 'react-native-web/dist/exports/ScrollView' { - const ScrollView: React.ComponentType; - export default ScrollView; -} - -declare module '@anythingai/app/screens/launcher-menu' { - const LauncherMenuContainer: React.ComponentType; - export default LauncherMenuContainer; -} - -declare module 'lodash' { - export function merge(...args: T[]): T; -} - -declare module '*.css' {} diff --git a/apps/mobile/index.tsx b/apps/mobile/index.tsx deleted file mode 100644 index db6b7ae..0000000 --- a/apps/mobile/index.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import ExceptionsManager from "react-native/Libraries/Core/ExceptionsManager"; - -if (__DEV__) { - ExceptionsManager.handleException = (_error, _isFatal) => { - // no-op - }; -} - -import "react-native-url-polyfill/auto"; -import "./src/__create/polyfills"; -global.Buffer = require("buffer").Buffer; - -import "@expo/metro-runtime"; -import { AppRegistry, LogBox } from "react-native"; -import { initSentry } from "./__create/sentry"; -import { initTestFlightLogger } from "./__create/testflight-logger"; -import { renderRootComponent } from "expo-router/build/renderRootComponent"; -import App from "./entrypoint"; - -initSentry(); -initTestFlightLogger(); - -if (__DEV__ || process.env.EXPO_PUBLIC_CREATE_ENV === "DEVELOPMENT") { - LogBox.ignoreAllLogs(); - LogBox.uninstall(); - AppRegistry.setWrapperComponentProvider(() => ({ children }) => { - return <>{children}; - }); -} -renderRootComponent(App); diff --git a/apps/mobile/index.web.tsx b/apps/mobile/index.web.tsx deleted file mode 100644 index 671bfd9..0000000 --- a/apps/mobile/index.web.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import '@expo/metro-runtime'; -import { toPng } from 'html-to-image'; -import React, { useEffect } from 'react'; -import { renderRootComponent } from 'expo-router/build/renderRootComponent'; - -import { LoadSkiaWeb } from '@shopify/react-native-skia/lib/module/web'; -import CreateApp from './App'; -async function inlineGoogleFonts(): Promise { - // Find all elements that load Google Fonts CSS - const links = Array.from(document.querySelectorAll( - 'link[rel="stylesheet"][href*="fonts.googleapis.com"]' - )); - - for (const link of links) { - try { - const href = link.href; - const res = await fetch(href); - let cssText = await res.text(); - - // Ensure font URLs are absolute - cssText = cssText.replace(/url\(([^)]+)\)/g, (match, url) => { - const clean = url.replace(/["']/g, ""); - if (clean.startsWith("http")) { - return `url(${clean})`; - } - return `url(${new URL(clean, href).toString()})`; - }); - - // Inject