commit d5d9c77fafe6930567a9e48dbfedb355555f6f35
parent 64d9bdfe425ba34a65c05d70854a639b62b0efa2
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Fri, 14 Feb 2025 06:29:52 +0000
utils: add browser utils, edit app utils
Diffstat:
7 files changed, 147 insertions(+), 39 deletions(-)
diff --git a/utils/src/app/lib.ts b/utils/src/app/lib.ts
@@ -10,16 +10,6 @@ type ConfigWindow = {
}
};
-/*
-{
- xs: 0,
- sm: 640,
- md: 768,
- lg: 1024,
- xl: 1280,
- "2xl": 1536
- };
-*/
export const cfg_app: ConfigWindow = {
layout: {
ios0: {
@@ -30,11 +20,15 @@ export const cfg_app: ConfigWindow = {
h: 750,
w: 350,
},
- webm0: {
+ web0: {
h: 600,
w: 300,
},
- webm1: {
+ web_ios0: {
+ h: 600,
+ w: 300,
+ },
+ web_ios1: {
h: 750,
w: 800,
},
diff --git a/utils/src/app/styles.ts b/utils/src/app/styles.ts
@@ -29,8 +29,11 @@ export const loading_style_map: Map<LoadingDimension, { dim_1: number; gl_2: num
export const toast_layout_map: Map<AppLayoutKey, string> = new Map([
[`ios0`, `pt-8`],
[`ios1`, `pt-16`],
- [`webm0`, `pt-8`],
- [`webm1`, `pt-16`],
+ [`web_mobile`, `pt-8`],
+ [`web_desktop`, `pt-16`],
+ [`web_ios0`, `pt-8`],
+ [`web_ios1`, `pt-16`],
+ [`web0`, `pt-8`],
]);
export const toast_style_map: Map<IToastKind, { inner: string; outer: string }> = new Map([
diff --git a/utils/src/app/types/app.ts b/utils/src/app/types/app.ts
@@ -6,15 +6,16 @@ export type AppConfigType = `farmer` | `personal`
export type AppLayoutKeyIOS = `ios0` | `ios1`;
export type AppLayoutKeyWeb = `web_mobile` | `web_desktop`;
-export type AppLayoutKeyWebPwa = `webm0` | `webm1`;
+export type AppLayoutKeyWebPwa = `web_ios0` | `web_ios1` | `web0`;
export type AppLayoutKey = AppLayoutKeyIOS | AppLayoutKeyWeb | AppLayoutKeyWebPwa;
export type AppLayoutIOS<T extends string> = `${T}_${AppLayoutKeyIOS}`;
export type AppLayoutWeb<T extends string> = `${T}_${AppLayoutKeyWeb}`;
-export type AppLayoutWebPwa<T extends string> = `${T}_${AppLayoutKeyWeb}`;
+export type AppLayoutWebPwa<T extends string> = `${T}_${AppLayoutKeyWebPwa}`;
export type AppLayoutKeyHeight =
+ | `lo_view_main`
| `lo_bottom_button`
| `nav_tabs`
| `nav_page_header`
@@ -30,7 +31,7 @@ export type AppHeightsResponsiveWebPwa = AppLayoutWebPwa<AppLayoutKeyHeight>;
export type AppWidthsResponsiveIOS = AppLayoutIOS<AppLayoutKeyWidth>;
export type AppWidthsResponsiveWeb = AppLayoutWeb<AppLayoutKeyWidth>;
-export type AppWidthsResponsiveWebPwa = AppLayoutWebPwa<AppLayoutKeyHeight>;
+export type AppWidthsResponsiveWebPwa = AppLayoutWebPwa<AppLayoutKeyWidth>;
export type CallbackPromiseFigureResult<Ti, Tr> = (value: Ti) => Promise<Tr | undefined>;
export type CallbackPromiseFull<Ti, Tr> = (value: Ti) => Promise<Tr>;
diff --git a/utils/src/app/types/resolve.ts b/utils/src/app/types/resolve.ts
@@ -8,14 +8,14 @@ export type ResolveEnumPayment_Period = 'biweekly' | 'hourly' | 'monthly' | 'wee
export type ResolveEnumPayment_Status = 'confirmed' | 'pending';
export type ResolveEnumQuantity_Unit = 'g' | 'kg' | 'lb' | 'ton';
export type ResolveEnumWorker_Type = 'contractor' | 'laborer';
-export type ResolveAccountInfo = { id: string, created_at: string, updated_at: string, role: ResolveEnumAccount_Role, username: string, auth_ref: { credential: ResolveEnumAuth_Credential, email: { id: string, created_at: string, updated_at: string, address: string } }, profiles?: Array<{ id: string, created_at: string, updated_at: string, name: string, display_name?: string | null, primary: boolean, about?: string | null, emails: Array<{ id: string, created_at: string, updated_at: string, address: string }>, profile_photos?: Array<{ id: string, created_at: string, updated_at: string, primary: boolean, title?: string | null, description?: string | null, media_image: { id: string, created_at: string, updated_at: string, url: string } }> | null, nostr_keys: Array<{ id: string, created_at: string, updated_at: string, public_key: string }> }> | null, farms?: Array<{ id: string, created_at: string, updated_at: string, name: string, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } }, farm_products?: Array<{ id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }> | null, farm_lots?: Array<{ id: string, created_at: string, updated_at: string, name?: string | null, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } }, farm_lot_products?: Array<{ id: string, created_at: string, updated_at: string, area_planted?: number | null, area_planted_unit: ResolveEnumArea_Unit, date_planted?: string | null, days_to_maturity?: number | null, farm_product: { id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }, farm_trade_products?: Array<{ id: string, created_at: string, updated_at: string, title: string, description: string, process?: string | null, trade_product_prices?: Array<{ id: string, created_at: string, updated_at: string, amount: number, currency: string, quantity_amount?: number | null, quantity_unit: ResolveEnumQuantity_Unit, quantity_label?: string | null }> | null, trade_product_quantitys?: Array<{ id: string, created_at: string, updated_at: string, amount?: number | null, unit: ResolveEnumQuantity_Unit, label?: string | null }> | null }> | null, farm_lot_harvests?: Array<{ id: string, created_at: string, updated_at: string, quantity_harvested: number, quantity_harvested_unit: ResolveEnumQuantity_Unit }> | null }> | null }> | null }> | null };
+export type ResolveAccountInfo = { id: string, created_at: string, updated_at: string, role: ResolveEnumAccount_Role, username: string, auth_ref: { credential: ResolveEnumAuth_Credential, email: { id: string, created_at: string, updated_at: string, address: string } }, profiles?: Array<{ id: string, created_at: string, updated_at: string, name: string, display_name?: string | null, primary: boolean, about?: string | null, emails: Array<{ id: string, created_at: string, updated_at: string, address: string }>, profile_photos?: Array<{ id: string, created_at: string, updated_at: string, primary: boolean, title?: string | null, description?: string | null, media_image: { id: string, created_at: string, updated_at: string, url: string } }> | null, nostr_keys: Array<{ id: string, created_at: string, updated_at: string, public_key: string }> }> | null, farms?: Array<{ id: string, created_at: string, updated_at: string, name: string, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation?: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } } | null, farm_products?: Array<{ id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }> | null, farm_lots?: Array<{ id: string, created_at: string, updated_at: string, name?: string | null, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } }, farm_lot_products?: Array<{ id: string, created_at: string, updated_at: string, area_planted?: number | null, area_planted_unit: ResolveEnumArea_Unit, date_planted?: string | null, days_to_maturity?: number | null, farm_product: { id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }, farm_trade_products?: Array<{ id: string, created_at: string, updated_at: string, title: string, description: string, process?: string | null, trade_product_prices?: Array<{ id: string, created_at: string, updated_at: string, amount: number, currency: string, quantity_amount?: number | null, quantity_unit: ResolveEnumQuantity_Unit, quantity_label?: string | null }> | null, trade_product_quantitys?: Array<{ id: string, created_at: string, updated_at: string, amount?: number | null, unit: ResolveEnumQuantity_Unit, label?: string | null }> | null }> | null, farm_lot_harvests?: Array<{ id: string, created_at: string, updated_at: string, quantity_harvested: number, quantity_harvested_unit: ResolveEnumQuantity_Unit }> | null }> | null }> | null }> | null };
export type ResolveAuthRefInfo = { credential: ResolveEnumAuth_Credential, email: { id: string, created_at: string, updated_at: string, address: string } };
export type ResolveEmailInfo = { id: string, created_at: string, updated_at: string, address: string };
export type ResolveProfileInfo = { id: string, created_at: string, updated_at: string, name: string, display_name?: string | null, primary: boolean, about?: string | null, emails: Array<{ id: string, created_at: string, updated_at: string, address: string }>, profile_photos?: Array<{ id: string, created_at: string, updated_at: string, primary: boolean, title?: string | null, description?: string | null, media_image: { id: string, created_at: string, updated_at: string, url: string } }> | null, nostr_keys: Array<{ id: string, created_at: string, updated_at: string, public_key: string }> };
export type ResolveProfilePhotoInfo = { id: string, created_at: string, updated_at: string, primary: boolean, title?: string | null, description?: string | null, media_image: { id: string, created_at: string, updated_at: string, url: string } };
export type ResolveMediaImageInfo = { id: string, created_at: string, updated_at: string, url: string };
export type ResolveNostrKeyInfo = { id: string, created_at: string, updated_at: string, public_key: string };
-export type ResolveFarmInfo = { id: string, created_at: string, updated_at: string, name: string, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } }, farm_products?: Array<{ id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }> | null, farm_lots?: Array<{ id: string, created_at: string, updated_at: string, name?: string | null, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } }, farm_lot_products?: Array<{ id: string, created_at: string, updated_at: string, area_planted?: number | null, area_planted_unit: ResolveEnumArea_Unit, date_planted?: string | null, days_to_maturity?: number | null, farm_product: { id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }, farm_trade_products?: Array<{ id: string, created_at: string, updated_at: string, title: string, description: string, process?: string | null, trade_product_prices?: Array<{ id: string, created_at: string, updated_at: string, amount: number, currency: string, quantity_amount?: number | null, quantity_unit: ResolveEnumQuantity_Unit, quantity_label?: string | null }> | null, trade_product_quantitys?: Array<{ id: string, created_at: string, updated_at: string, amount?: number | null, unit: ResolveEnumQuantity_Unit, label?: string | null }> | null }> | null, farm_lot_harvests?: Array<{ id: string, created_at: string, updated_at: string, quantity_harvested: number, quantity_harvested_unit: ResolveEnumQuantity_Unit }> | null }> | null }> | null };
+export type ResolveFarmInfo = { id: string, created_at: string, updated_at: string, name: string, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation?: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } } | null, farm_products?: Array<{ id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }> | null, farm_lots?: Array<{ id: string, created_at: string, updated_at: string, name?: string | null, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } }, farm_lot_products?: Array<{ id: string, created_at: string, updated_at: string, area_planted?: number | null, area_planted_unit: ResolveEnumArea_Unit, date_planted?: string | null, days_to_maturity?: number | null, farm_product: { id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }, farm_trade_products?: Array<{ id: string, created_at: string, updated_at: string, title: string, description: string, process?: string | null, trade_product_prices?: Array<{ id: string, created_at: string, updated_at: string, amount: number, currency: string, quantity_amount?: number | null, quantity_unit: ResolveEnumQuantity_Unit, quantity_label?: string | null }> | null, trade_product_quantitys?: Array<{ id: string, created_at: string, updated_at: string, amount?: number | null, unit: ResolveEnumQuantity_Unit, label?: string | null }> | null }> | null, farm_lot_harvests?: Array<{ id: string, created_at: string, updated_at: string, quantity_harvested: number, quantity_harvested_unit: ResolveEnumQuantity_Unit }> | null }> | null }> | null };
export type ResolveGeolocationInfo = { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } };
export type ResolveAddressInfo = { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string };
export type ResolveFarmLotInfo = { id: string, created_at: string, updated_at: string, name?: string | null, area?: number | null, area_unit: ResolveEnumArea_Unit, geolocation: { id: string, created_at: string, updated_at: string, point: { type: string, coordinates: Array<number> }, polygon?: { type: string, coordinates: Array<Array<Array<number>>> } | null, address: { id: string, created_at: string, updated_at: string, primary: string, admin: string, country: string } }, farm_lot_products?: Array<{ id: string, created_at: string, updated_at: string, area_planted?: number | null, area_planted_unit: ResolveEnumArea_Unit, date_planted?: string | null, days_to_maturity?: number | null, farm_product: { id: string, created_at: string, updated_at: string, name: string, farm_lot_products?: Array<{ id: string }> | null }, farm_trade_products?: Array<{ id: string, created_at: string, updated_at: string, title: string, description: string, process?: string | null, trade_product_prices?: Array<{ id: string, created_at: string, updated_at: string, amount: number, currency: string, quantity_amount?: number | null, quantity_unit: ResolveEnumQuantity_Unit, quantity_label?: string | null }> | null, trade_product_quantitys?: Array<{ id: string, created_at: string, updated_at: string, amount?: number | null, unit: ResolveEnumQuantity_Unit, label?: string | null }> | null }> | null, farm_lot_harvests?: Array<{ id: string, created_at: string, updated_at: string, quantity_harvested: number, quantity_harvested_unit: ResolveEnumQuantity_Unit }> | null }> | null };
diff --git a/utils/src/app/util.ts b/utils/src/app/util.ts
@@ -4,51 +4,68 @@ export const fmt_cl = (classes?: string): string => {
return classes ? classes : ``;
};
-export const get_layout = (val: string | false): AppLayoutKey => {
- switch (val) {
- case `ios0`:
- case `ios1`:
- case `webm0`:
- case `webm1`:
- case `web_mobile`:
- case `web_desktop`:
- return val;
- default:
- return `ios0`;
- };
+export const get_layout = (val?: string): AppLayoutKey | undefined => {
+ const lo_ios = get_ios_layout(val);
+ if (lo_ios) return lo_ios;
+ const lo_web = get_web_layout(val);
+ if (lo_web) return lo_web;
+ const lo_web_pwa = get_web_pwa_layout(val);
+ if (lo_web_pwa) return lo_web_pwa;
+ return undefined;
};
-export const get_ios_layout = (val: string | false): AppLayoutKeyIOS => {
+export const get_layout_default = (val?: string): AppLayoutKey => {
+ const res = get_layout(val);
+ return res || `web0`;
+};
+
+export const get_ios_layout = (val?: string): AppLayoutKeyIOS | undefined => {
switch (val) {
case `ios0`:
case `ios1`:
return val;
default:
- return `ios0`;
+ return undefined;
};
};
-export const get_web_layout = (val: string | false): AppLayoutKeyWeb => {
+export const get_ios_layout_default = (val?: string): AppLayoutKeyIOS => {
+ const res = get_ios_layout(val);
+ return res || `ios0`;
+};
+
+export const get_web_layout = (val?: string): AppLayoutKeyWeb | undefined => {
switch (val) {
case `web_mobile`:
case `web_desktop`:
return val;
default:
- return `web_desktop`;
+ return undefined;
};
};
+export const get_web_layout_default = (val?: string): AppLayoutKeyWeb => {
+ const res = get_web_layout(val);
+ return res || `web_desktop`;
+};
+
-export const get_web_pwa_layout = (val: string | false): AppLayoutKeyWebPwa => {
+export const get_web_pwa_layout = (val?: string): AppLayoutKeyWebPwa | undefined => {
switch (val) {
- case `webm0`:
- case `webm1`:
+ case `web_ios0`:
+ case `web_ios1`:
+ case `web0`:
return val;
default:
- return `webm0`;
+ return undefined;
};
};
+export const get_web_pwa_layout_default = (val?: string): AppLayoutKeyWebPwa => {
+ const res = get_web_pwa_layout(val);
+ return res || `web0`;
+};
+
export const parse_layer = (layer?: number, layer_default?: ThemeLayer): ThemeLayer => {
switch (layer) {
case 0:
diff --git a/utils/src/browser.ts b/utils/src/browser.ts
@@ -0,0 +1,92 @@
+export type BrowserPlatformInfo = {
+ os: string;
+ browser: string;
+ version: string;
+};
+
+const remove_excess_mozilla_and_version = /^mozilla\/\d\.\d\W/;
+const browser_pattern = /(\w+)\/(\d+\.\d+(?:\.\d+)?(?:\.\d+)?)/g;
+const engine_and_version_pattern = /^(ver|cri|gec)/;
+const brand_list = ['chrome', 'opera', 'safari', 'edge', 'firefox'];
+
+const mobiles: Record<string, RegExp> = {
+ iphone: /iphone/,
+ ipad: /ipad|macintosh/,
+ android: /android/
+};
+
+const desktops: Record<string, RegExp> = {
+ windows: /win/,
+ mac: /macintosh/,
+ linux: /linux/
+};
+
+const parse_user_agent_string = (ua_string: string): BrowserPlatformInfo => {
+ const ua = ua_string.toLowerCase().replace(remove_excess_mozilla_and_version, '');
+
+ const mobile_os = Object.keys(mobiles).find(
+ (key) => mobiles[key].test(ua) && navigator.maxTouchPoints >= 1
+ );
+ const desktop_os = Object.keys(desktops).find((key) => desktops[key].test(ua));
+ const os = mobile_os || desktop_os || '';
+
+ const browser_matches = ua.match(browser_pattern);
+ const version_regex = /version\/(\d+(\.\d+)*)/;
+ const safari_version_match = ua.match(version_regex);
+ const safari_version = Array.isArray(safari_version_match) ? safari_version_match[1] : null;
+
+ const browser_offset =
+ browser_matches && browser_matches.length > 2 && !engine_and_version_pattern.test(browser_matches[1])
+ ? 1
+ : 0;
+ const browser_result =
+ browser_matches && browser_matches[browser_matches.length - 1 - browser_offset].split('/');
+ const browser = browser_result ? browser_result[0] : '';
+ const version = safari_version || (browser_result ? browser_result[1] : '');
+
+ return { os, browser, version };
+};
+
+export const browser_platform = (): BrowserPlatformInfo | undefined => {
+ if (typeof navigator !== 'undefined') {
+ if ('userAgentData' in navigator && navigator.userAgentData) {
+ const ua_data = navigator.userAgentData as {
+ platform: string;
+ brands: { brand: string; version: string }[];
+ };
+ const os = ua_data.platform.toLowerCase();
+ let browser = '';
+ let version = '';
+
+ if (Array.isArray(ua_data.brands)) {
+ for (const { brand, version: brand_version } of ua_data.brands) {
+ const lower_brand = brand.toLowerCase();
+ if (brand_list.some((b) => lower_brand.includes(b))) {
+ browser = lower_brand;
+ version = brand_version;
+ break;
+ }
+ }
+ }
+
+ if (!browser && navigator.userAgent) {
+ return parse_user_agent_string(navigator.userAgent);
+ }
+ return { os, browser, version };
+ }
+
+ if (navigator.userAgent) {
+ return parse_user_agent_string(navigator.userAgent);
+ }
+
+ const nav_platform = navigator.platform;
+ if (!nav_platform) return undefined;
+ return {
+ os: nav_platform,
+ browser: '',
+ version: ''
+ };
+ }
+
+ return undefined;
+};
diff --git a/utils/src/index.ts b/utils/src/index.ts
@@ -19,6 +19,7 @@ export * from "./app/util/resolve.js"
export * from "./app/util/search.js"
export * from "./app/util.js"
export * from "./app/validation/view.js"
+export * from "./browser.js"
export * from "./client/database.js"
export * from "./client/datastore.js"
export * from "./client/geo.js"