@akanjs/next 0.0.52 → 0.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bootCsr.js ADDED
@@ -0,0 +1,138 @@
1
+ "use client";
2
+ import { device, initAuth, storage } from "@akanjs/client";
3
+ import {
4
+ csrContext,
5
+ DEFAULT_BOTTOM_INSET,
6
+ DEFAULT_TOP_INSET,
7
+ defaultPageState
8
+ } from "@akanjs/client";
9
+ import { Logger } from "@akanjs/common";
10
+ import React from "react";
11
+ import * as ReactDOM from "react-dom/client";
12
+ import { useCsrValues } from "./useCsrValues";
13
+ const supportLanguages = ["en", "ko"];
14
+ const bootCsr = async (context, rootPath, entryPath = "/route") => {
15
+ const [, jwt] = await Promise.all([device.init({ supportLanguages }), storage.getItem("jwt")]);
16
+ if (jwt)
17
+ initAuth({ jwt });
18
+ Logger.verbose(`Set default language: ${device.lang}`);
19
+ const pages = {};
20
+ await Promise.all(
21
+ Object.entries(context).map(async ([key, value]) => {
22
+ pages[key] = await value();
23
+ })
24
+ );
25
+ const getPageState = (csrConfig) => {
26
+ const { transition, safeArea, topInset, bottomInset, gesture, cache } = csrConfig ?? {};
27
+ const pageState = {
28
+ transition: transition ?? "none",
29
+ topSafeArea: safeArea === false ? 0 : device.topSafeArea,
30
+ bottomSafeArea: safeArea === false ? 0 : device.bottomSafeArea,
31
+ // topSafeArea: safeArea === false || device.info.platform === "android" ? 0 : device.topSafeArea,
32
+ // bottomSafeArea: safeArea === false || device.info.platform === "android" ? 0 : device.bottomSafeArea,
33
+ topInset: topInset === true ? DEFAULT_TOP_INSET : topInset === false ? 0 : topInset ?? 0,
34
+ bottomInset: bottomInset === true ? DEFAULT_BOTTOM_INSET : bottomInset === false ? 0 : bottomInset ?? 0,
35
+ gesture: gesture ?? true,
36
+ cache: cache ?? false
37
+ };
38
+ return pageState;
39
+ };
40
+ const routeMap = /* @__PURE__ */ new Map();
41
+ routeMap.set("/", { path: "/", children: /* @__PURE__ */ new Map() });
42
+ for (const filePath of Object.keys(pages)) {
43
+ const fileName = /\.\/(.*)\.tsx$/.exec(filePath)?.[1];
44
+ if (!fileName)
45
+ continue;
46
+ const fileType = fileName.endsWith("page") ? "page" : fileName.endsWith("layout") ? "layout" : null;
47
+ if (!fileType)
48
+ continue;
49
+ const pathSegments = [
50
+ "/",
51
+ ...fileName.split("/").slice(0, -1).map((segment) => `/${segment.replace(/\[(.*?)\]/g, ":$1")}`)
52
+ ];
53
+ const targetRouteMap = pathSegments.slice(0, -1).reduce((rMap, path) => {
54
+ if (!rMap.has(path))
55
+ rMap.set(path, { path, children: /* @__PURE__ */ new Map() });
56
+ return rMap.get(path)?.children;
57
+ }, routeMap);
58
+ if (!targetRouteMap)
59
+ continue;
60
+ const targetPath = pathSegments[pathSegments.length - 1];
61
+ targetRouteMap.set(targetPath, {
62
+ // action: pages[path]?.action,
63
+ // ErrorBoundary: pages[path]?.ErrorBoundary,
64
+ ...targetRouteMap.get(targetPath) ?? { path: targetPath, children: /* @__PURE__ */ new Map() },
65
+ ...fileType === "layout" ? { Layout: pages[filePath].default } : {
66
+ Page: pages[filePath].default,
67
+ pageState: getPageState(pages[filePath].default.csrConfig),
68
+ csrConfig: pages[filePath].default.csrConfig
69
+ }
70
+ });
71
+ }
72
+ const pathname = window.location.pathname;
73
+ const initialPath = device.lang + entryPath;
74
+ window.document.body.style.overflow = "hidden";
75
+ const getPathRoutes = (route, parentRootLayouts = [], parentLayouts = [], parentPaths = []) => {
76
+ const parentPath = parentPaths.filter((path2) => path2 !== "/").join("");
77
+ const currentPathSegment = /^\/\(.*\)$/.test(route.path) ? "" : route.path;
78
+ const isRoot = ["/", "/:lang"].includes(parentPath + currentPathSegment) && parentRootLayouts.length < 2;
79
+ const path = parentPath + currentPathSegment;
80
+ const pathSegments = [...parentPaths, ...currentPathSegment ? [currentPathSegment] : []];
81
+ const RootLayouts = [...parentRootLayouts, ...isRoot && route.Layout ? [route.Layout] : []];
82
+ const Layouts = [...parentLayouts, ...!isRoot && route.Layout ? [route.Layout] : []];
83
+ return [
84
+ ...route.Page ? [
85
+ {
86
+ path,
87
+ pathSegments,
88
+ Page: route.Page,
89
+ RootLayouts,
90
+ Layouts,
91
+ pageState: route.pageState ?? defaultPageState
92
+ }
93
+ ] : [],
94
+ ...route.children.size ? [...route.children.values()].flatMap((child) => getPathRoutes(child, RootLayouts, Layouts, pathSegments)) : []
95
+ ];
96
+ };
97
+ const rootRoute = routeMap.get("/");
98
+ if (!rootRoute)
99
+ throw new Error("No root route");
100
+ const pathRoutes = getPathRoutes(rootRoute);
101
+ const routeGuide = { pathSegment: "/", children: {} };
102
+ pathRoutes.forEach((pathRoute) => {
103
+ const pathSegments = pathRoute.pathSegments.slice(1);
104
+ pathSegments.reduce((routeGuide2, pathSegment, index) => {
105
+ const child = routeGuide2.children[pathSegment];
106
+ routeGuide2.children[pathSegment] = {
107
+ ...child ?? {},
108
+ pathSegment,
109
+ ...index === pathSegments.length - 1 ? { pathRoute } : {},
110
+ children: child?.children ?? {}
111
+ };
112
+ return routeGuide2.children[pathSegment];
113
+ }, routeGuide);
114
+ });
115
+ const RouterProvider = () => {
116
+ const csrValues = useCsrValues(routeGuide, pathRoutes);
117
+ const { location } = csrValues;
118
+ return /* @__PURE__ */ React.createElement(csrContext.Provider, { value: csrValues }, location.pathRoute.RootLayouts.reduceRight(
119
+ (children, Layout) => {
120
+ return /* @__PURE__ */ React.createElement(Layout, { params: location.params, searchParams: location.searchParams }, children);
121
+ },
122
+ /* @__PURE__ */ React.createElement(React.Fragment, null)
123
+ ));
124
+ };
125
+ if (pathname !== `/${initialPath}`) {
126
+ window.location.replace(initialPath);
127
+ return;
128
+ } else {
129
+ const el = document.getElementById("root");
130
+ if (!el)
131
+ throw new Error("No root element");
132
+ const root = ReactDOM.createRoot(el);
133
+ root.render(/* @__PURE__ */ React.createElement(RouterProvider, null));
134
+ }
135
+ };
136
+ export {
137
+ bootCsr
138
+ };
@@ -2,15 +2,14 @@ import { logo } from "@akanjs/base";
2
2
  import { Logger } from "@akanjs/common";
3
3
  import { match as matchLocale } from "@formatjs/intl-localematcher";
4
4
  import Negotiator from "negotiator";
5
- import { NextRequest, NextResponse } from "next/server";
6
-
5
+ import { NextResponse } from "next/server";
7
6
  const i18n = { defaultLocale: "en", locales: ["en", "ko"] };
8
7
  const basePaths = process.env.basePaths ? process.env.basePaths.split(",") : [];
9
-
10
- function getLocale(request: NextRequest): string | undefined {
11
- if (!request.headers.get("accept-language")) return i18n.defaultLocale;
12
- const negotiatorHeaders: Record<string, string> = {};
13
- request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));
8
+ function getLocale(request) {
9
+ if (!request.headers.get("accept-language"))
10
+ return i18n.defaultLocale;
11
+ const negotiatorHeaders = {};
12
+ request.headers.forEach((value, key) => negotiatorHeaders[key] = value);
14
13
  try {
15
14
  const languages = new Negotiator({ headers: negotiatorHeaders }).languages();
16
15
  return matchLocale(languages, i18n.locales, i18n.defaultLocale);
@@ -18,12 +17,12 @@ function getLocale(request: NextRequest): string | undefined {
18
17
  return i18n.defaultLocale;
19
18
  }
20
19
  }
21
- export const createNextMiddleware = () => {
20
+ const createNextMiddleware = () => {
22
21
  Logger.rawLog(logo, "console");
23
- const middleware = (request: NextRequest) => {
22
+ const middleware = (request) => {
24
23
  const pathname = request.nextUrl.pathname;
25
24
  const pathnameIsMissingLocale = i18n.locales.every(
26
- (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
25
+ (locale2) => !pathname.startsWith(`/${locale2}/`) && pathname !== `/${locale2}`
27
26
  );
28
27
  if (pathnameIsMissingLocale)
29
28
  return NextResponse.redirect(
@@ -37,9 +36,14 @@ export const createNextMiddleware = () => {
37
36
  const searchParamJwt = searchParams.get("jwt");
38
37
  headers.set("x-locale", locale);
39
38
  headers.set("x-path", "/" + splits.slice(2).join("/"));
40
- if (basePath) headers.set("x-base-path", basePath);
41
- if (searchParamJwt) headers.set("jwt", searchParamJwt);
39
+ if (basePath)
40
+ headers.set("x-base-path", basePath);
41
+ if (searchParamJwt)
42
+ headers.set("jwt", searchParamJwt);
42
43
  return NextResponse.next({ request: { headers } });
43
44
  };
44
45
  return middleware;
45
46
  };
47
+ export {
48
+ createNextMiddleware
49
+ };
@@ -0,0 +1,15 @@
1
+ const createRobotPage = (clientHttpUri, config) => {
2
+ return {
3
+ ...config ?? {},
4
+ rules: {
5
+ userAgent: "*",
6
+ allow: "/",
7
+ disallow: "/admin/",
8
+ ...config?.rules ?? {}
9
+ },
10
+ sitemap: `${clientHttpUri}/sitemap.xml`
11
+ };
12
+ };
13
+ export {
14
+ createRobotPage
15
+ };
@@ -0,0 +1,7 @@
1
+ const lastModified = /* @__PURE__ */ new Date();
2
+ const createSitemapPage = (clientHttpUri, paths) => {
3
+ return paths.map((path) => ({ url: `${clientHttpUri}${path}`, lastModified }));
4
+ };
5
+ export {
6
+ createSitemapPage
7
+ };
package/index.js ADDED
@@ -0,0 +1,41 @@
1
+ import { useFetch } from "./useFetch";
2
+ import { lazy } from "./lazy";
3
+ import { makePageProto } from "./makePageProto";
4
+ import { useDebounce } from "./useDebounce";
5
+ import { useInterval } from "./useInterval";
6
+ import { bootCsr } from "./bootCsr";
7
+ import { useCamera } from "./useCamera";
8
+ import { useContact } from "./useContact";
9
+ import { usePushNoti } from "./usePushNoti";
10
+ import { useGeoLocation } from "./useGeoLocation";
11
+ import { useCodepush } from "./useCodepush";
12
+ import { usePurchase } from "./usePurchase";
13
+ import { useCsrValues } from "./useCsrValues";
14
+ import { createRobotPage } from "./createRobotPage";
15
+ import { createSitemapPage } from "./createSitemapPage";
16
+ import { createNextMiddleware } from "./createNextMiddleware";
17
+ //! PageAgent csr에서 말썽 일으킨다
18
+ import { useThrottle } from "./useThrottle";
19
+ import { useHistory } from "./useHistory";
20
+ import { useLocation } from "./useLocation";
21
+ export {
22
+ bootCsr,
23
+ createNextMiddleware,
24
+ createRobotPage,
25
+ createSitemapPage,
26
+ lazy,
27
+ makePageProto,
28
+ useCamera,
29
+ useCodepush,
30
+ useContact,
31
+ useCsrValues,
32
+ useDebounce,
33
+ useFetch,
34
+ useGeoLocation,
35
+ useHistory,
36
+ useInterval,
37
+ useLocation,
38
+ usePurchase,
39
+ usePushNoti,
40
+ useThrottle
41
+ };
package/lazy.js ADDED
@@ -0,0 +1,6 @@
1
+ //! next build를 위해서 lint 무시
2
+ import dynamic from "next/dynamic";
3
+ const lazy = (loader, option) => dynamic(loader, { ...option ?? {} });
4
+ export {
5
+ lazy
6
+ };
@@ -0,0 +1,114 @@
1
+ import { baseClientEnv } from "@akanjs/base";
2
+ import { getHeader } from "@akanjs/client";
3
+ import { Logger, pathGet } from "@akanjs/common";
4
+ const getPageInfo = () => {
5
+ if (baseClientEnv.side !== "server") {
6
+ return {
7
+ locale: window.location.pathname.split("/")[1] ?? "en",
8
+ path: "/" + window.location.pathname.split("/").slice(2).join("/")
9
+ };
10
+ }
11
+ const locale = getHeader("x-locale") ?? "en";
12
+ const path = getHeader("x-path") ?? "/";
13
+ return { locale, path };
14
+ };
15
+ const langIdx = { en: 0, ko: 1, zhChs: 2, zhCht: 3 };
16
+ const dictionary = {};
17
+ const translator = (lang, key, param) => {
18
+ const idx = langIdx[lang];
19
+ try {
20
+ const msg = pathGet(key, dictionary)?.[idx];
21
+ if (!msg) {
22
+ Logger.error(`No translation for ${key}`);
23
+ return key;
24
+ }
25
+ return param ? msg.replace(/{([^}]+)}/g, (_, key2) => param[key2]) : msg;
26
+ } catch (e) {
27
+ return key;
28
+ }
29
+ };
30
+ translator.rich = (lang, key, param) => {
31
+ const idx = langIdx[lang];
32
+ const msg = pathGet(key, dictionary)?.[idx];
33
+ if (!msg) {
34
+ Logger.error(`No translation for ${key}`);
35
+ return key;
36
+ }
37
+ return param ? msg.replace(/{([^}]+)}/g, (_, key2) => param[key2]) : msg;
38
+ };
39
+ const makePageProto = (locales) => {
40
+ locales.forEach((locale) => {
41
+ Object.keys(locale).forEach((key) => dictionary[key] = Object.assign(dictionary[key] ?? {}, locale[key]));
42
+ });
43
+ return () => {
44
+ const { locale, path } = getPageInfo();
45
+ const lang = locale;
46
+ const l = (key, param) => translator(lang, key, param);
47
+ l.rich = (key, param) => /* @__PURE__ */ React.createElement(
48
+ "span",
49
+ {
50
+ dangerouslySetInnerHTML: {
51
+ __html: translator.rich(lang, key, {
52
+ ...param,
53
+ // strong: (chunks: string) => `<b>${chunks}</b>`,
54
+ // "bg-primary": (chunks: string) => `<span className="bg-primary text-base-100">${chunks}</span>`,
55
+ // primary: (chunks: string) => `<span className="bg-base-100 text-primary">${chunks}</span>`,
56
+ br: `<br />`
57
+ })
58
+ }
59
+ }
60
+ );
61
+ l.field = (model, field) => {
62
+ const key = `${model}.${field}`;
63
+ return l(key);
64
+ };
65
+ l.desc = (model, field) => {
66
+ const key = `${model}.desc-${field}`;
67
+ return l(key);
68
+ };
69
+ l.enum = (model, field, value) => {
70
+ const key = `${model}.enum-${field}-${value}`;
71
+ return l(key);
72
+ };
73
+ l.enumdesc = (model, field, value) => {
74
+ const key = `${model}.enumdesc-${field}-${value}`;
75
+ return l(key);
76
+ };
77
+ l.api = (model, endpoint) => {
78
+ const key = `${model}.api-${endpoint}`;
79
+ return l(key);
80
+ };
81
+ l.apidesc = (model, endpoint) => {
82
+ const key = `${model}.apidesc-${endpoint}`;
83
+ return l(key);
84
+ };
85
+ l.arg = (model, endpoint, arg) => {
86
+ const key = `${model}.arg-${endpoint}-${arg}`;
87
+ return l(key);
88
+ };
89
+ l.argdesc = (model, endpoint, arg) => {
90
+ const key = `${model}.argdesc-${endpoint}-${arg}`;
91
+ return l(key);
92
+ };
93
+ l.qry = (model, queryKey) => {
94
+ const key = `${model}.qry-${queryKey}`;
95
+ return l(key);
96
+ };
97
+ l.qrydesc = (model, queryKey) => {
98
+ const key = `${model}.qrydesc-${queryKey}`;
99
+ return l(key);
100
+ };
101
+ l.qarg = (model, queryKey, arg) => {
102
+ const key = `${model}.qarg-${queryKey}-${arg}`;
103
+ return l(key);
104
+ };
105
+ l.qargdesc = (model, queryKey, arg) => {
106
+ const key = `${model}.qargdesc-${queryKey}-${arg}`;
107
+ return l(key);
108
+ };
109
+ return { path, l, lang };
110
+ };
111
+ };
112
+ export {
113
+ makePageProto
114
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@akanjs/next",
3
- "version": "0.0.52",
4
- "type": "commonjs",
3
+ "version": "0.0.54",
4
+ "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -14,23 +14,5 @@
14
14
  "engines": {
15
15
  "node": ">=22"
16
16
  },
17
- "dependencies": {
18
- "@capacitor-community/contacts": "^6.1.1",
19
- "@capacitor-community/fcm": "^7.1.1",
20
- "@capacitor/app": "^7.0.1",
21
- "@capacitor/camera": "^7.0.1",
22
- "@capacitor/device": "^7.0.1",
23
- "@capacitor/geolocation": "^7.1.2",
24
- "@capacitor/push-notifications": "^7.0.1",
25
- "@capgo/capacitor-updater": "^7.0.50",
26
- "@formatjs/intl-localematcher": "^0.5.10",
27
- "@react-spring/web": "^9.7.5",
28
- "@use-gesture/react": "^10.3.1",
29
- "axios": "^1.7.9",
30
- "cordova-plugin-purchase": "^13.12.1",
31
- "negotiator": "^1.0.0",
32
- "next": "^15.3.2",
33
- "react": "^18.3.1",
34
- "react-dom": "^18.3.1"
35
- }
17
+ "dependencies": {}
36
18
  }
package/types.js ADDED
File without changes
@@ -1,19 +1,10 @@
1
1
  "use client";
2
2
  import { device } from "@akanjs/client";
3
- import { Camera, CameraResultType, CameraSource, PermissionStatus } from "@capacitor/camera";
3
+ import { Camera, CameraResultType, CameraSource } from "@capacitor/camera";
4
4
  import { useEffect, useState } from "react";
5
-
6
- export const useCamera = () => {
7
- const [permissions, setPermissions] = useState<PermissionStatus>({ camera: "prompt", photos: "prompt" });
8
-
9
- /**
10
- * 최초로 킬 경우 권한은 prompt 상태이다.
11
- * prompt 상태일 경우 권한을 요청한다.
12
- * 권한이 denied 상태일 경우 설정으로 이동한다.
13
- * 이후 state의 permission을 업데이트해야한다.
14
- *
15
- */
16
- const checkPermission = async (type: "photos" | "camera" | "all") => {
5
+ const useCamera = () => {
6
+ const [permissions, setPermissions] = useState({ camera: "prompt", photos: "prompt" });
7
+ const checkPermission = async (type) => {
17
8
  try {
18
9
  if (type === "photos") {
19
10
  if (permissions.photos === "prompt") {
@@ -33,27 +24,18 @@ export const useCamera = () => {
33
24
  }
34
25
  } else {
35
26
  if (permissions.camera === "prompt" || permissions.photos === "prompt") {
36
- const permissions = await Camera.requestPermissions();
37
- setPermissions(permissions);
27
+ const permissions2 = await Camera.requestPermissions();
28
+ setPermissions(permissions2);
38
29
  } else if (permissions.camera === "denied" || permissions.photos === "denied") {
39
30
  location.assign("app-settings:");
40
31
  return;
41
32
  }
42
33
  }
43
34
  } catch (e) {
44
- //
45
35
  }
46
36
  };
47
-
48
- const getPhoto = async (src: "prompt" | "camera" | "photos" = "prompt") => {
49
- const source =
50
- device.info.platform !== "web"
51
- ? src === "prompt"
52
- ? CameraSource.Prompt
53
- : src === "camera"
54
- ? CameraSource.Camera
55
- : CameraSource.Photos
56
- : CameraSource.Photos;
37
+ const getPhoto = async (src = "prompt") => {
38
+ const source = device.info.platform !== "web" ? src === "prompt" ? CameraSource.Prompt : src === "camera" ? CameraSource.Camera : CameraSource.Photos : CameraSource.Photos;
57
39
  const permission = src === "prompt" ? "all" : src === "camera" ? "camera" : "photos";
58
40
  void checkPermission(permission);
59
41
  try {
@@ -62,33 +44,34 @@ export const useCamera = () => {
62
44
  source,
63
45
  allowEditing: false,
64
46
  resultType: CameraResultType.DataUrl,
65
- promptLabelHeader: "프로필 사진을 올려주세요",
66
- promptLabelPhoto: "앨범에서 선택하기",
67
- promptLabelPicture: "사진 찍기",
68
- promptLabelCancel: "취소",
47
+ promptLabelHeader: "\uD504\uB85C\uD544 \uC0AC\uC9C4\uC744 \uC62C\uB824\uC8FC\uC138\uC694",
48
+ promptLabelPhoto: "\uC568\uBC94\uC5D0\uC11C \uC120\uD0DD\uD558\uAE30",
49
+ promptLabelPicture: "\uC0AC\uC9C4 \uCC0D\uAE30",
50
+ promptLabelCancel: "\uCDE8\uC18C"
69
51
  });
70
52
  return photo;
71
53
  } catch (e) {
72
- if (e === "User cancelled photos app") return;
54
+ if (e === "User cancelled photos app")
55
+ return;
73
56
  }
74
57
  };
75
-
76
58
  const pickImage = async () => {
77
59
  void checkPermission("photos");
78
60
  const photo = await Camera.pickImages({
79
- quality: 90,
61
+ quality: 90
80
62
  });
81
-
82
63
  return photo;
83
64
  };
84
-
85
65
  useEffect(() => {
86
66
  void (async () => {
87
67
  if (device.info.platform !== "web") {
88
- const permissions = await Camera.checkPermissions();
89
- setPermissions(permissions);
68
+ const permissions2 = await Camera.checkPermissions();
69
+ setPermissions(permissions2);
90
70
  }
91
71
  })();
92
72
  }, []);
93
73
  return { permissions, getPhoto, pickImage, checkPermission };
94
74
  };
75
+ export {
76
+ useCamera
77
+ };
package/useCodepush.js ADDED
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import { mergeVersion, splitVersion } from "@akanjs/common";
3
+ import { App } from "@capacitor/app";
4
+ import { Device } from "@capacitor/device";
5
+ import { CapacitorUpdater } from "@capgo/capacitor-updater";
6
+ import axios from "axios";
7
+ import { useState } from "react";
8
+ const useCodepush = ({ serverUrl, branch }) => {
9
+ const [update, setUpdate] = useState(false);
10
+ const [version, setVersion] = useState("");
11
+ const initialize = async () => {
12
+ await CapacitorUpdater.notifyAppReady();
13
+ };
14
+ const checkNewRelease = async () => {
15
+ const info = await Device.getInfo();
16
+ const app = await App.getInfo();
17
+ const pluginVersion = await CapacitorUpdater.getPluginVersion();
18
+ const { deviceId } = await CapacitorUpdater.getDeviceId();
19
+ const { bundle: version2, native } = await CapacitorUpdater.current();
20
+ const builtInversion = await CapacitorUpdater.getBuiltinVersion();
21
+ const appId = app.id;
22
+ const platform = info.platform;
23
+ window.alert(
24
+ `getBuildinVersion:${builtInversion.version}
25
+ current.bundle:${version2.version}
26
+ currennt.native:${native}`
27
+ );
28
+ const { major, minor, patch } = splitVersion(version2.version === "builtin" ? app.version : version2.version);
29
+ const appName = process.env.NEXT_PUBLIC_APP_NAME ?? "";
30
+ const appInfo = {
31
+ appId,
32
+ appName,
33
+ deviceId,
34
+ platform,
35
+ branch,
36
+ isEmulator: info.isVirtual,
37
+ major: parseInt(major),
38
+ minor: parseInt(minor),
39
+ patch: parseInt(patch),
40
+ buildNum: app.build,
41
+ //앱내 빌드시 버전 횟수 모르면 고한테 물어보기
42
+ versionOs: info.osVersion
43
+ };
44
+ const url = serverUrl.replace("lu", "akasys");
45
+ const release = (await axios.post(`${url}/release/codepush`, {
46
+ data: { ...appInfo }
47
+ })).data;
48
+ if (!release)
49
+ return;
50
+ const file = (await axios.get(`${url}/file/file/${release.appBuild}`)).data;
51
+ return { release, bundleFile: file };
52
+ };
53
+ const codepush = async () => {
54
+ const isNewRelease = await checkNewRelease();
55
+ if (!isNewRelease)
56
+ return;
57
+ const { release, bundleFile } = isNewRelease;
58
+ setUpdate(true);
59
+ const bundle = await CapacitorUpdater.download({
60
+ url: bundleFile.url,
61
+ version: mergeVersion(release.major, release.minor, release.patch)
62
+ });
63
+ await CapacitorUpdater.set(bundle);
64
+ };
65
+ const getVersion = async () => {
66
+ return await CapacitorUpdater.getBuiltinVersion();
67
+ };
68
+ const statManager = async () => {
69
+ };
70
+ return { update, version, initialize, checkNewRelease, codepush, statManager };
71
+ };
72
+ export {
73
+ useCodepush
74
+ };
@@ -1,18 +1,9 @@
1
1
  "use client";
2
2
  import { device } from "@akanjs/client";
3
- import { Contacts, PermissionStatus } from "@capacitor-community/contacts";
3
+ import { Contacts } from "@capacitor-community/contacts";
4
4
  import { useEffect, useState } from "react";
5
-
6
- export const useContact = () => {
7
- const [permissions, setPermissions] = useState<PermissionStatus>({ contacts: "prompt" });
8
-
9
- /**
10
- * 최초로 킬 경우 권한은 prompt 상태이다.
11
- * prompt 상태일 경우 권한을 요청한다.
12
- * 권한이 denied 상태일 경우 설정으로 이동한다.
13
- * 이후 state의 permission을 업데이트해야한다.
14
- *
15
- */
5
+ const useContact = () => {
6
+ const [permissions, setPermissions] = useState({ contacts: "prompt" });
16
7
  const checkPermission = async () => {
17
8
  try {
18
9
  if (permissions.contacts === "prompt") {
@@ -23,23 +14,23 @@ export const useContact = () => {
23
14
  return;
24
15
  }
25
16
  } catch (e) {
26
- //
27
17
  }
28
18
  };
29
-
30
19
  const getContacts = async () => {
31
20
  await checkPermission();
32
21
  const { contacts } = await Contacts.getContacts({ projection: { name: true, phones: true } });
33
22
  return contacts;
34
23
  };
35
-
36
24
  useEffect(() => {
37
25
  void (async () => {
38
- if (device.info.platform === "web") return;
39
- const permissions = await Contacts.checkPermissions();
40
- setPermissions(permissions);
26
+ if (device.info.platform === "web")
27
+ return;
28
+ const permissions2 = await Contacts.checkPermissions();
29
+ setPermissions(permissions2);
41
30
  })();
42
31
  }, []);
43
-
44
32
  return { permissions, getContacts, checkPermission };
45
33
  };
34
+ export {
35
+ useContact
36
+ };