151 行
4.8 KiB
TypeScript
151 行
4.8 KiB
TypeScript
const WECOM_WEBVIEW_PATTERN = /(wxwork|wecom|wechatwork)/i;
|
|
const ENTERPRISE_IM_PATTERN = /(wxwork|wecom|wechatwork|dingtalk|aliapp\(dingtalk\))/i;
|
|
|
|
export function canUseWindow() {
|
|
return typeof window !== "undefined";
|
|
}
|
|
|
|
export function matchesMedia(query: string) {
|
|
return canUseWindow() && typeof window.matchMedia === "function" && window.matchMedia(query).matches;
|
|
}
|
|
|
|
export function readUserAgent() {
|
|
return canUseWindow() ? window.navigator.userAgent : "";
|
|
}
|
|
|
|
export function isWecomWebView(userAgent = readUserAgent()) {
|
|
return WECOM_WEBVIEW_PATTERN.test(userAgent);
|
|
}
|
|
|
|
export function isEnterpriseMessengerContainer(userAgent = readUserAgent()) {
|
|
return ENTERPRISE_IM_PATTERN.test(userAgent);
|
|
}
|
|
|
|
export function isTouchSmallScreen() {
|
|
if (!canUseWindow()) {
|
|
return false;
|
|
}
|
|
|
|
return window.navigator.maxTouchPoints > 0 && matchesMedia("(max-width: 768px)");
|
|
}
|
|
|
|
export function shouldPreferMobileWorkplace() {
|
|
return isEnterpriseMessengerContainer() || isTouchSmallScreen();
|
|
}
|
|
|
|
export function resolveDefaultWorkspacePath() {
|
|
return shouldPreferMobileWorkplace() ? "/mobile" : "/portal";
|
|
}
|
|
|
|
function encodeSegment(value: string) {
|
|
return encodeURIComponent(value);
|
|
}
|
|
|
|
export function resolveMobileEquivalentPath(pathname: string, search = "") {
|
|
const normalizedPath = pathname.replace(/\/+$/, "") || "/";
|
|
const searchParams = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
|
|
|
|
if (normalizedPath === "/" || normalizedPath === "/portal" || normalizedPath === "/dashboard") {
|
|
return "/mobile";
|
|
}
|
|
|
|
if (normalizedPath === "/notifications") {
|
|
return "/mobile/notifications";
|
|
}
|
|
|
|
if (normalizedPath === "/settings/profile") {
|
|
return "/mobile/profile";
|
|
}
|
|
|
|
if (normalizedPath === "/reimbursements" || normalizedPath === "/reimbursements/dashboard") {
|
|
return "/mobile/reimbursements";
|
|
}
|
|
|
|
const reimbursementPrintMatch = normalizedPath.match(/^\/reimbursements\/([^/]+)\/print$/);
|
|
if (reimbursementPrintMatch?.[1]) {
|
|
return `/mobile/reimbursements/${encodeSegment(reimbursementPrintMatch[1])}`;
|
|
}
|
|
|
|
const reimbursementDetailMatch = normalizedPath.match(/^\/reimbursements\/([^/]+)$/);
|
|
if (reimbursementDetailMatch?.[1]) {
|
|
return `/mobile/reimbursements/${encodeSegment(reimbursementDetailMatch[1])}`;
|
|
}
|
|
|
|
if (normalizedPath === "/leave-requests") {
|
|
const leaveRequestId = searchParams.get("highlight") ?? searchParams.get("id") ?? searchParams.get("requestId");
|
|
if (leaveRequestId) {
|
|
return `/mobile/leave/${encodeSegment(leaveRequestId)}`;
|
|
}
|
|
const action = searchParams.get("action") ?? searchParams.get("view");
|
|
if (action === "create" || action === "form") {
|
|
return "/mobile/leave?view=form";
|
|
}
|
|
return "/mobile/leave";
|
|
}
|
|
|
|
if (normalizedPath === "/invoice-pool") {
|
|
return "/mobile/capture";
|
|
}
|
|
|
|
if (normalizedPath === "/attendance") {
|
|
return "/mobile/attendance";
|
|
}
|
|
|
|
const workflowTaskMatch = normalizedPath.match(/^\/workflow\/tasks\/([^/]+)$/);
|
|
if (workflowTaskMatch?.[1]) {
|
|
return `/mobile/approvals/${encodeSegment(workflowTaskMatch[1])}`;
|
|
}
|
|
|
|
if (normalizedPath === "/workflow/tasks") {
|
|
return "/mobile/approvals";
|
|
}
|
|
|
|
if (normalizedPath === "/assets" || normalizedPath.startsWith("/assets/") || normalizedPath === "/inventory-checks") {
|
|
return "/mobile/assets/scan";
|
|
}
|
|
|
|
if (
|
|
normalizedPath.startsWith("/system") ||
|
|
normalizedPath.startsWith("/people") ||
|
|
normalizedPath.startsWith("/organization") ||
|
|
normalizedPath.startsWith("/payroll") ||
|
|
normalizedPath.startsWith("/performance")
|
|
) {
|
|
return "/mobile/me";
|
|
}
|
|
|
|
if (
|
|
normalizedPath.startsWith("/projects") ||
|
|
normalizedPath.startsWith("/contracts-registry") ||
|
|
normalizedPath.startsWith("/travel-requests") ||
|
|
normalizedPath.startsWith("/ap-operations") ||
|
|
normalizedPath.startsWith("/weekly-reports") ||
|
|
normalizedPath.startsWith("/todos") ||
|
|
normalizedPath.startsWith("/team") ||
|
|
normalizedPath.startsWith("/budgets") ||
|
|
normalizedPath.startsWith("/announcements") ||
|
|
normalizedPath.startsWith("/delegations")
|
|
) {
|
|
return "/mobile";
|
|
}
|
|
|
|
if (normalizedPath === "/payment-batches") {
|
|
return `/mobile/payment-batches${search}`;
|
|
}
|
|
|
|
if (normalizedPath === "/purchase-requests") {
|
|
const purchaseRequestId = searchParams.get("highlight") ?? searchParams.get("id") ?? searchParams.get("requestId");
|
|
if (purchaseRequestId) {
|
|
return `/mobile/purchase-requests/${encodeSegment(purchaseRequestId)}`;
|
|
}
|
|
return "/mobile/purchase-requests";
|
|
}
|
|
|
|
const purchaseRequestDetailMatch = normalizedPath.match(/^\/purchase-requests\/([^/]+)$/);
|
|
if (purchaseRequestDetailMatch?.[1]) {
|
|
return `/mobile/purchase-requests/${encodeSegment(purchaseRequestDetailMatch[1])}`;
|
|
}
|
|
|
|
return search ? `${pathname}${search}` : pathname;
|
|
}
|