@sunggang/ui-lib 0.4.43 → 0.4.44

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.
@@ -456,14 +456,18 @@ var LiffContext = /*#__PURE__*/ React.createContext(undefined);
456
456
  var LiffProvider = function(param) {
457
457
  var children = param.children, liffId = param.liffId, _param_localStorageKey = param.localStorageKey, localStorageKey = _param_localStorageKey === void 0 ? "one-gobo-global-login" : _param_localStorageKey, checkTokenUrl = param.checkTokenUrl, loginUrl = param.loginUrl, accountLoginUrl = param.accountLoginUrl, memberInfoUrl = param.memberInfoUrl, _param_openInApp = param.openInApp, openInApp = _param_openInApp === void 0 ? false : _param_openInApp, _param_ignoreCheckAddFriend = param.ignoreCheckAddFriend, ignoreCheckAddFriend = _param_ignoreCheckAddFriend === void 0 ? false : _param_ignoreCheckAddFriend, _param_ignoreRoute = param.ignoreRoute, ignoreRoute = _param_ignoreRoute === void 0 ? false : _param_ignoreRoute, _param_loginByUser = param.loginByUser, loginByUser = _param_loginByUser === void 0 ? false : _param_loginByUser, _param_liffLogin = param.liffLogin, liffLogin = _param_liffLogin === void 0 ? false : _param_liffLogin, customerRedirectUrl = param.customerRedirectUrl, inviteCode = param.inviteCode, handleLoginError = param.handleLoginError;
458
458
  var _useState = _sliced_to_array(React.useState(null), 2), liffObject = _useState[0], setLiffObject = _useState[1];
459
- var _useState1 = _sliced_to_array(React.useState(""), 2), accessToken = _useState1[0], setAccessToken = _useState1[1];
460
- var _useState2 = _sliced_to_array(React.useState(null), 2), liffError = _useState2[0], setLiffError = _useState2[1];
461
- var _useState3 = _sliced_to_array(React.useState(null), 2), loginData = _useState3[0], setLoginData = _useState3[1];
462
- var _useState4 = _sliced_to_array(React.useState(null), 2), userInfo = _useState4[0], setUserInfo = _useState4[1];
463
- var _useState5 = _sliced_to_array(React.useState(null), 2), isFriendship = _useState5[0], setFriendship = _useState5[1];
464
- var _useState6 = _sliced_to_array(React.useState(null), 2), loginType = _useState6[0], setLoginType = _useState6[1];
459
+ var _useState1 = _sliced_to_array(React.useState(false), 2), liffInitialized = _useState1[0], setLiffInitialized = _useState1[1];
460
+ var _useState2 = _sliced_to_array(React.useState(""), 2), accessToken = _useState2[0], setAccessToken = _useState2[1];
461
+ var _useState3 = _sliced_to_array(React.useState(null), 2), liffError = _useState3[0], setLiffError = _useState3[1];
462
+ var _useState4 = _sliced_to_array(React.useState(null), 2), loginData = _useState4[0], setLoginData = _useState4[1];
463
+ var _useState5 = _sliced_to_array(React.useState(null), 2), userInfo = _useState5[0], setUserInfo = _useState5[1];
464
+ var _useState6 = _sliced_to_array(React.useState(null), 2), liffProfile = _useState6[0], setLiffProfile = _useState6[1];
465
+ var _useState7 = _sliced_to_array(React.useState(null), 2), isFriendship = _useState7[0], setFriendship = _useState7[1];
466
+ var _useState8 = _sliced_to_array(React.useState(null), 2), loginType = _useState8[0], setLoginType = _useState8[1];
465
467
  // userInfo 的 localStorage key
466
468
  var userInfoStorageKey = "".concat(localStorageKey, "-userInfo");
469
+ // liff profile 的 localStorage key
470
+ var liffProfileStorageKey = "".concat(localStorageKey, "-liffProfile");
467
471
  // 從 localStorage 載入 userInfo
468
472
  var loadUserInfoFromStorage = function() {
469
473
  try {
@@ -478,14 +482,40 @@ var LiffProvider = function(param) {
478
482
  }
479
483
  return null;
480
484
  };
485
+ // 從 localStorage 載入 LIFF profile
486
+ var loadLiffProfileFromStorage = function() {
487
+ try {
488
+ var stored = window.localStorage.getItem(liffProfileStorageKey);
489
+ if (stored) {
490
+ var parsed = JSON.parse(stored);
491
+ setLiffProfile(parsed);
492
+ return parsed;
493
+ }
494
+ } catch (err) {
495
+ console.error("載入 liffProfile 失敗:", err);
496
+ }
497
+ return null;
498
+ };
481
499
  // 儲存 userInfo 到 localStorage
482
- var saveUserInfoToStorage = function(info) {
500
+ var saveUserInfoToStorage = React.useCallback(function(info) {
483
501
  try {
484
502
  window.localStorage.setItem(userInfoStorageKey, JSON.stringify(info));
485
503
  } catch (err) {
486
504
  console.error("儲存 userInfo 失敗:", err);
487
505
  }
488
- };
506
+ }, [
507
+ userInfoStorageKey
508
+ ]);
509
+ // 儲存 LIFF profile 到 localStorage
510
+ var saveLiffProfileToStorage = React.useCallback(function(info) {
511
+ try {
512
+ window.localStorage.setItem(liffProfileStorageKey, JSON.stringify(info));
513
+ } catch (err) {
514
+ console.error("儲存 liffProfile 失敗:", err);
515
+ }
516
+ }, [
517
+ liffProfileStorageKey
518
+ ]);
489
519
  var fetchMemberInfo = function() {
490
520
  var _ref = _async_to_generator(function(token) {
491
521
  var response, err;
@@ -703,41 +733,37 @@ var LiffProvider = function(param) {
703
733
  // 初始化 LIFF
704
734
  var initializeLiff = function() {
705
735
  var _ref = _async_to_generator(function(isValid) {
706
- var customFetch, liff, originalFetch, lineToken, redirectUri, e, tempFriendship, friendship, friendFlag, error, err;
736
+ var _sdk_getAccessToken, _sdk_isLoggedIn, imported, sdk, lineToken, redirectUri, tempFriendship, friendship, friendFlag, error, err;
707
737
  return _ts_generator(this, function(_state) {
708
738
  switch(_state.label){
709
739
  case 0:
710
740
  _state.trys.push([
711
741
  0,
712
- 16,
742
+ 10,
713
743
  ,
714
- 17
744
+ 11
715
745
  ]);
716
- customFetch = // 自訂 fetch 函數,避免每次請求都改變 URL
717
- // eslint-disable-next-line no-inner-declarations
718
- function customFetch(url, options) {
719
- if (url.toString().startsWith("https://liffsdk.line-scdn.net/xlt/") && url.toString().endsWith(".json")) {
720
- url = "".concat(url, "?ts=").concat(Math.random());
721
- }
722
- return originalFetch(url, options);
723
- };
746
+ // 確保 LIFF 已初始化(只執行一次)
724
747
  return [
725
748
  4,
726
- Promise.resolve().then(function () { return require('./index.cjs3.js'); })
749
+ ensureLiffInitialized()
727
750
  ];
728
751
  case 1:
729
- liff = _state.sent().liff;
730
- originalFetch = window.fetch;
731
- window.fetch = customFetch;
732
- if (openInApp && !(liff === null || liff === void 0 ? void 0 : liff.isInClient()) && (liff === null || liff === void 0 ? void 0 : liff.getOS()) !== "web") window.location.href = "line://app/".concat(liffId);
733
- console.log("LIFF init succeeded.");
734
- setLiffObject(liff);
735
- lineToken = liff === null || liff === void 0 ? void 0 : liff.getAccessToken();
736
- // 未登入先進行登入(呼叫 login 後立即 return,避免後續執行 init)
737
- if (!liff.isLoggedIn()) {
752
+ _state.sent();
753
+ return [
754
+ 4,
755
+ Promise.resolve().then(function () { return require('./index.cjs3.js'); })
756
+ ];
757
+ case 2:
758
+ imported = _state.sent();
759
+ sdk = liffObject || imported.liff;
760
+ setLiffObject(sdk);
761
+ lineToken = sdk === null || sdk === void 0 ? void 0 : (_sdk_getAccessToken = sdk.getAccessToken) === null || _sdk_getAccessToken === void 0 ? void 0 : _sdk_getAccessToken.call(sdk);
762
+ // 未登入先進行登入(呼叫 login 後立即 return,避免後續執行)
763
+ if (!(sdk === null || sdk === void 0 ? void 0 : (_sdk_isLoggedIn = sdk.isLoggedIn) === null || _sdk_isLoggedIn === void 0 ? void 0 : _sdk_isLoggedIn.call(sdk))) {
738
764
  redirectUri = customerRedirectUrl || "".concat(window.location.href);
739
765
  if (liffLogin) {
740
- liff.login({
766
+ sdk.login({
741
767
  redirectUri: redirectUri
742
768
  });
743
769
  return [
@@ -747,105 +773,54 @@ var LiffProvider = function(param) {
747
773
  if (loginByUser || ignoreRoute) return [
748
774
  2
749
775
  ];
750
- liff.login({
776
+ sdk.login({
751
777
  redirectUri: redirectUri
752
778
  });
753
779
  return [
754
780
  2
755
781
  ];
756
782
  }
757
- if (!!liffId) return [
758
- 3,
759
- 2
760
- ];
761
- console.warn("liffId 未提供,跳過 liff.init()。");
762
- return [
763
- 3,
764
- 8
765
- ];
766
- case 2:
767
- if (!!liff.isLoggedIn()) return [
783
+ tempFriendship = null;
784
+ if (!lineToken) return [
768
785
  3,
769
- 7
786
+ 9
770
787
  ];
771
788
  _state.label = 3;
772
789
  case 3:
773
790
  _state.trys.push([
774
791
  3,
775
- 5,
776
- ,
777
- 6
778
- ]);
779
- return [
780
- 4,
781
- liff.init({
782
- liffId: liffId,
783
- withLoginOnExternalBrowser: false
784
- })
785
- ];
786
- case 4:
787
- _state.sent();
788
- return [
789
- 3,
790
- 6
791
- ];
792
- case 5:
793
- e = _state.sent();
794
- console.error("liff.init() 失敗:", e);
795
- return [
796
- 3,
797
- 6
798
- ];
799
- case 6:
800
- return [
801
- 3,
802
- 8
803
- ];
804
- case 7:
805
- console.log("LIFF 已登入,跳過 liff.init() 以避免重複的 verify/profile 呼叫。");
806
- _state.label = 8;
807
- case 8:
808
- tempFriendship = null;
809
- if (!lineToken) return [
810
- 3,
811
- 15
812
- ];
813
- _state.label = 9;
814
- case 9:
815
- _state.trys.push([
816
- 9,
817
- 12,
792
+ 6,
818
793
  ,
819
- 13
794
+ 7
820
795
  ]);
821
- if (!!liff.isLoggedIn()) return [
796
+ if (!(sdk.isLoggedIn && sdk.isLoggedIn())) return [
822
797
  3,
823
- 11
798
+ 5
824
799
  ];
825
800
  return [
826
801
  4,
827
- liff.getFriendship()
802
+ sdk.getFriendship()
828
803
  ];
829
- case 10:
804
+ case 4:
830
805
  friendship = _state.sent();
831
806
  friendFlag = friendship === null || friendship === void 0 ? void 0 : friendship.friendFlag;
832
807
  setFriendship(friendFlag);
833
808
  tempFriendship = friendFlag;
834
809
  console.log("isFriendship", friendFlag);
835
- _state.label = 11;
836
- case 11:
810
+ _state.label = 5;
811
+ case 5:
837
812
  return [
838
813
  3,
839
- 13
814
+ 7
840
815
  ];
841
- case 12:
816
+ case 6:
842
817
  error = _state.sent();
843
818
  console.error("Error in liff.getFriendship():", error);
844
819
  return [
845
820
  3,
846
- 13
821
+ 7
847
822
  ];
848
- case 13:
823
+ case 7:
849
824
  console.log("isValid", isValid);
850
825
  if (tempFriendship && isValid) return [
851
826
  2
@@ -854,23 +829,23 @@ var LiffProvider = function(param) {
854
829
  4,
855
830
  loginInit(lineToken)
856
831
  ];
857
- case 14:
832
+ case 8:
858
833
  _state.sent();
859
- _state.label = 15;
860
- case 15:
834
+ _state.label = 9;
835
+ case 9:
861
836
  return [
862
837
  3,
863
- 17
838
+ 11
864
839
  ];
865
- case 16:
840
+ case 10:
866
841
  err = _state.sent();
867
842
  setLiffError(err.toString());
868
843
  console.log("LIFF init failed.", err);
869
844
  return [
870
845
  3,
871
- 17
846
+ 11
872
847
  ];
873
- case 17:
848
+ case 11:
874
849
  return [
875
850
  2
876
851
  ];
@@ -881,6 +856,80 @@ var LiffProvider = function(param) {
881
856
  return _ref.apply(this, arguments);
882
857
  };
883
858
  }();
859
+ // 確保 LIFF init 只執行一次且在需要時才執行
860
+ var ensureLiffInitialized = React.useCallback(/*#__PURE__*/ _async_to_generator(function() {
861
+ var customFetch, liff, originalFetch, e;
862
+ return _ts_generator(this, function(_state) {
863
+ switch(_state.label){
864
+ case 0:
865
+ if (liffInitialized) return [
866
+ 2
867
+ ];
868
+ if (!liffId) {
869
+ console.warn("liffId 未提供,跳過 liff.init()。");
870
+ return [
871
+ 2
872
+ ];
873
+ }
874
+ _state.label = 1;
875
+ case 1:
876
+ _state.trys.push([
877
+ 1,
878
+ 4,
879
+ ,
880
+ 5
881
+ ]);
882
+ customFetch = // 自訂 fetch 函數,避免每次請求都改變 URL
883
+ // eslint-disable-next-line no-inner-declarations
884
+ function customFetch(url, options) {
885
+ if (url.toString().startsWith("https://liffsdk.line-scdn.net/xlt/") && url.toString().endsWith(".json")) {
886
+ url = "".concat(url, "?ts=").concat(Math.random());
887
+ }
888
+ return originalFetch(url, options);
889
+ };
890
+ return [
891
+ 4,
892
+ Promise.resolve().then(function () { return require('./index.cjs3.js'); })
893
+ ];
894
+ case 2:
895
+ liff = _state.sent().liff;
896
+ originalFetch = window.fetch;
897
+ window.fetch = customFetch;
898
+ if (openInApp && !(liff === null || liff === void 0 ? void 0 : liff.isInClient()) && (liff === null || liff === void 0 ? void 0 : liff.getOS()) !== "web") window.location.href = "line://app/".concat(liffId);
899
+ return [
900
+ 4,
901
+ liff.init({
902
+ liffId: liffId,
903
+ withLoginOnExternalBrowser: false
904
+ })
905
+ ];
906
+ case 3:
907
+ _state.sent();
908
+ setLiffObject(liff);
909
+ setLiffInitialized(true);
910
+ console.log("LIFF initialized.");
911
+ return [
912
+ 3,
913
+ 5
914
+ ];
915
+ case 4:
916
+ e = _state.sent();
917
+ console.error("ensureLiffInitialized failed:", e);
918
+ return [
919
+ 3,
920
+ 5
921
+ ];
922
+ case 5:
923
+ return [
924
+ 2
925
+ ];
926
+ }
927
+ });
928
+ }), [
929
+ liffInitialized,
930
+ liffId,
931
+ openInApp
932
+ ]);
884
933
  var accountLogin = function() {
885
934
  var _ref = _async_to_generator(function(username, password) {
886
935
  var response, token, tokenType, finalToken, err;
@@ -952,6 +1001,77 @@ var LiffProvider = function(param) {
952
1001
  return _ref.apply(this, arguments);
953
1002
  };
954
1003
  }();
1004
+ // 取得 LIFF profile(LIFF 的會員資料,與 API 的 member 分開處理)
1005
+ var getLiffProfile = React.useCallback(/*#__PURE__*/ _async_to_generator(function() {
1006
+ var sdk, imported, profile, err;
1007
+ return _ts_generator(this, function(_state) {
1008
+ switch(_state.label){
1009
+ case 0:
1010
+ _state.trys.push([
1011
+ 0,
1012
+ 5,
1013
+ ,
1014
+ 6
1015
+ ]);
1016
+ // 確保 LIFF 已初始化
1017
+ return [
1018
+ 4,
1019
+ ensureLiffInitialized()
1020
+ ];
1021
+ case 1:
1022
+ _state.sent();
1023
+ sdk = liffObject;
1024
+ if (!!sdk) return [
1025
+ 3,
1026
+ 3
1027
+ ];
1028
+ return [
1029
+ 4,
1030
+ Promise.resolve().then(function () { return require('./index.cjs3.js'); })
1031
+ ];
1032
+ case 2:
1033
+ imported = _state.sent();
1034
+ sdk = imported.liff;
1035
+ setLiffObject(sdk);
1036
+ _state.label = 3;
1037
+ case 3:
1038
+ if (!sdk || typeof sdk.isLoggedIn !== "function" || !sdk.isLoggedIn()) {
1039
+ console.warn("getLiffProfile: LIFF not initialized or user not logged in");
1040
+ return [
1041
+ 2,
1042
+ null
1043
+ ];
1044
+ }
1045
+ return [
1046
+ 4,
1047
+ sdk.getProfile()
1048
+ ];
1049
+ case 4:
1050
+ profile = _state.sent();
1051
+ setLiffProfile(profile);
1052
+ saveLiffProfileToStorage(profile);
1053
+ return [
1054
+ 2,
1055
+ profile
1056
+ ];
1057
+ case 5:
1058
+ err = _state.sent();
1059
+ console.error("取得 LIFF profile 失敗:", err);
1060
+ return [
1061
+ 2,
1062
+ null
1063
+ ];
1064
+ case 6:
1065
+ return [
1066
+ 2
1067
+ ];
1068
+ }
1069
+ });
1070
+ }), [
1071
+ liffObject,
1072
+ ensureLiffInitialized,
1073
+ saveLiffProfileToStorage
1074
+ ]);
955
1075
  var ensureLiffTokenValid = React.useCallback(/*#__PURE__*/ _async_to_generator(function() {
956
1076
  var _parsedStore_data, _parsedStore_state, jwtTokenValue, jwtToken, parsedStore, isValid, _tmp, err;
957
1077
  return _ts_generator(this, function(_state) {
@@ -1047,9 +1167,10 @@ var LiffProvider = function(param) {
1047
1167
  return trimmed.toLowerCase().startsWith("bearer ") ? trimmed : "Bearer ".concat(trimmed);
1048
1168
  };
1049
1169
  var searchParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
1050
- // 初始載入時從 localStorage 載入 userInfo
1170
+ // 初始載入時從 localStorage 載入 userInfo 與 LIFF profile
1051
1171
  React.useEffect(function() {
1052
1172
  loadUserInfoFromStorage();
1173
+ loadLiffProfileFromStorage();
1053
1174
  }, []);
1054
1175
  // 客戶端初始化 LIFF
1055
1176
  React.useEffect(function() {
@@ -1127,32 +1248,22 @@ var LiffProvider = function(param) {
1127
1248
  }();
1128
1249
  checkAndInitialize();
1129
1250
  }, []);
1130
- var contextValue = React.useMemo(function() {
1131
- return {
1132
- liffObject: liffObject,
1133
- loginData: loginData,
1134
- userInfo: userInfo,
1135
- accessToken: accessToken,
1136
- liffError: liffError,
1137
- initializeLiff: function() {
1138
- return initializeLiff(false);
1139
- },
1140
- isFriendship: isFriendship,
1141
- ensureLiffTokenValid: ensureLiffTokenValid,
1142
- accountLogin: accountLogin,
1143
- loginType: loginType
1144
- };
1145
- }, [
1146
- liffObject,
1147
- loginData,
1148
- userInfo,
1149
- accessToken,
1150
- liffError,
1151
- isFriendship,
1152
- ensureLiffTokenValid,
1153
- accountLogin,
1154
- loginType
1155
- ]);
1251
+ var contextValue = {
1252
+ liffObject: liffObject,
1253
+ loginData: loginData,
1254
+ userInfo: userInfo,
1255
+ accessToken: accessToken,
1256
+ liffError: liffError,
1257
+ initializeLiff: function() {
1258
+ return initializeLiff(false);
1259
+ },
1260
+ getLiffProfile: getLiffProfile,
1261
+ liffProfile: liffProfile,
1262
+ isFriendship: isFriendship,
1263
+ ensureLiffTokenValid: ensureLiffTokenValid,
1264
+ accountLogin: accountLogin,
1265
+ loginType: loginType
1266
+ };
1156
1267
  return /*#__PURE__*/ jsxRuntime.jsx(LiffContext.Provider, {
1157
1268
  value: contextValue,
1158
1269
  children: children
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useState, useCallback, useEffect, useMemo, useContext } from 'react';
2
+ import { createContext, useState, useCallback, useEffect, useContext } from 'react';
3
3
 
4
4
  function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
5
5
  try {
@@ -452,14 +452,18 @@ var LiffContext = /*#__PURE__*/ createContext(undefined);
452
452
  var LiffProvider = function(param) {
453
453
  var children = param.children, liffId = param.liffId, _param_localStorageKey = param.localStorageKey, localStorageKey = _param_localStorageKey === void 0 ? "one-gobo-global-login" : _param_localStorageKey, checkTokenUrl = param.checkTokenUrl, loginUrl = param.loginUrl, accountLoginUrl = param.accountLoginUrl, memberInfoUrl = param.memberInfoUrl, _param_openInApp = param.openInApp, openInApp = _param_openInApp === void 0 ? false : _param_openInApp, _param_ignoreCheckAddFriend = param.ignoreCheckAddFriend, ignoreCheckAddFriend = _param_ignoreCheckAddFriend === void 0 ? false : _param_ignoreCheckAddFriend, _param_ignoreRoute = param.ignoreRoute, ignoreRoute = _param_ignoreRoute === void 0 ? false : _param_ignoreRoute, _param_loginByUser = param.loginByUser, loginByUser = _param_loginByUser === void 0 ? false : _param_loginByUser, _param_liffLogin = param.liffLogin, liffLogin = _param_liffLogin === void 0 ? false : _param_liffLogin, customerRedirectUrl = param.customerRedirectUrl, inviteCode = param.inviteCode, handleLoginError = param.handleLoginError;
454
454
  var _useState = _sliced_to_array(useState(null), 2), liffObject = _useState[0], setLiffObject = _useState[1];
455
- var _useState1 = _sliced_to_array(useState(""), 2), accessToken = _useState1[0], setAccessToken = _useState1[1];
456
- var _useState2 = _sliced_to_array(useState(null), 2), liffError = _useState2[0], setLiffError = _useState2[1];
457
- var _useState3 = _sliced_to_array(useState(null), 2), loginData = _useState3[0], setLoginData = _useState3[1];
458
- var _useState4 = _sliced_to_array(useState(null), 2), userInfo = _useState4[0], setUserInfo = _useState4[1];
459
- var _useState5 = _sliced_to_array(useState(null), 2), isFriendship = _useState5[0], setFriendship = _useState5[1];
460
- var _useState6 = _sliced_to_array(useState(null), 2), loginType = _useState6[0], setLoginType = _useState6[1];
455
+ var _useState1 = _sliced_to_array(useState(false), 2), liffInitialized = _useState1[0], setLiffInitialized = _useState1[1];
456
+ var _useState2 = _sliced_to_array(useState(""), 2), accessToken = _useState2[0], setAccessToken = _useState2[1];
457
+ var _useState3 = _sliced_to_array(useState(null), 2), liffError = _useState3[0], setLiffError = _useState3[1];
458
+ var _useState4 = _sliced_to_array(useState(null), 2), loginData = _useState4[0], setLoginData = _useState4[1];
459
+ var _useState5 = _sliced_to_array(useState(null), 2), userInfo = _useState5[0], setUserInfo = _useState5[1];
460
+ var _useState6 = _sliced_to_array(useState(null), 2), liffProfile = _useState6[0], setLiffProfile = _useState6[1];
461
+ var _useState7 = _sliced_to_array(useState(null), 2), isFriendship = _useState7[0], setFriendship = _useState7[1];
462
+ var _useState8 = _sliced_to_array(useState(null), 2), loginType = _useState8[0], setLoginType = _useState8[1];
461
463
  // userInfo 的 localStorage key
462
464
  var userInfoStorageKey = "".concat(localStorageKey, "-userInfo");
465
+ // liff profile 的 localStorage key
466
+ var liffProfileStorageKey = "".concat(localStorageKey, "-liffProfile");
463
467
  // 從 localStorage 載入 userInfo
464
468
  var loadUserInfoFromStorage = function() {
465
469
  try {
@@ -474,14 +478,40 @@ var LiffProvider = function(param) {
474
478
  }
475
479
  return null;
476
480
  };
481
+ // 從 localStorage 載入 LIFF profile
482
+ var loadLiffProfileFromStorage = function() {
483
+ try {
484
+ var stored = window.localStorage.getItem(liffProfileStorageKey);
485
+ if (stored) {
486
+ var parsed = JSON.parse(stored);
487
+ setLiffProfile(parsed);
488
+ return parsed;
489
+ }
490
+ } catch (err) {
491
+ console.error("載入 liffProfile 失敗:", err);
492
+ }
493
+ return null;
494
+ };
477
495
  // 儲存 userInfo 到 localStorage
478
- var saveUserInfoToStorage = function(info) {
496
+ var saveUserInfoToStorage = useCallback(function(info) {
479
497
  try {
480
498
  window.localStorage.setItem(userInfoStorageKey, JSON.stringify(info));
481
499
  } catch (err) {
482
500
  console.error("儲存 userInfo 失敗:", err);
483
501
  }
484
- };
502
+ }, [
503
+ userInfoStorageKey
504
+ ]);
505
+ // 儲存 LIFF profile 到 localStorage
506
+ var saveLiffProfileToStorage = useCallback(function(info) {
507
+ try {
508
+ window.localStorage.setItem(liffProfileStorageKey, JSON.stringify(info));
509
+ } catch (err) {
510
+ console.error("儲存 liffProfile 失敗:", err);
511
+ }
512
+ }, [
513
+ liffProfileStorageKey
514
+ ]);
485
515
  var fetchMemberInfo = function() {
486
516
  var _ref = _async_to_generator(function(token) {
487
517
  var response, err;
@@ -699,41 +729,37 @@ var LiffProvider = function(param) {
699
729
  // 初始化 LIFF
700
730
  var initializeLiff = function() {
701
731
  var _ref = _async_to_generator(function(isValid) {
702
- var customFetch, liff, originalFetch, lineToken, redirectUri, e, tempFriendship, friendship, friendFlag, error, err;
732
+ var _sdk_getAccessToken, _sdk_isLoggedIn, imported, sdk, lineToken, redirectUri, tempFriendship, friendship, friendFlag, error, err;
703
733
  return _ts_generator(this, function(_state) {
704
734
  switch(_state.label){
705
735
  case 0:
706
736
  _state.trys.push([
707
737
  0,
708
- 16,
738
+ 10,
709
739
  ,
710
- 17
740
+ 11
711
741
  ]);
712
- customFetch = // 自訂 fetch 函數,避免每次請求都改變 URL
713
- // eslint-disable-next-line no-inner-declarations
714
- function customFetch(url, options) {
715
- if (url.toString().startsWith("https://liffsdk.line-scdn.net/xlt/") && url.toString().endsWith(".json")) {
716
- url = "".concat(url, "?ts=").concat(Math.random());
717
- }
718
- return originalFetch(url, options);
719
- };
742
+ // 確保 LIFF 已初始化(只執行一次)
720
743
  return [
721
744
  4,
722
- import('./index.esm3.js')
745
+ ensureLiffInitialized()
723
746
  ];
724
747
  case 1:
725
- liff = _state.sent().liff;
726
- originalFetch = window.fetch;
727
- window.fetch = customFetch;
728
- if (openInApp && !(liff === null || liff === void 0 ? void 0 : liff.isInClient()) && (liff === null || liff === void 0 ? void 0 : liff.getOS()) !== "web") window.location.href = "line://app/".concat(liffId);
729
- console.log("LIFF init succeeded.");
730
- setLiffObject(liff);
731
- lineToken = liff === null || liff === void 0 ? void 0 : liff.getAccessToken();
732
- // 未登入先進行登入(呼叫 login 後立即 return,避免後續執行 init)
733
- if (!liff.isLoggedIn()) {
748
+ _state.sent();
749
+ return [
750
+ 4,
751
+ import('./index.esm3.js')
752
+ ];
753
+ case 2:
754
+ imported = _state.sent();
755
+ sdk = liffObject || imported.liff;
756
+ setLiffObject(sdk);
757
+ lineToken = sdk === null || sdk === void 0 ? void 0 : (_sdk_getAccessToken = sdk.getAccessToken) === null || _sdk_getAccessToken === void 0 ? void 0 : _sdk_getAccessToken.call(sdk);
758
+ // 未登入先進行登入(呼叫 login 後立即 return,避免後續執行)
759
+ if (!(sdk === null || sdk === void 0 ? void 0 : (_sdk_isLoggedIn = sdk.isLoggedIn) === null || _sdk_isLoggedIn === void 0 ? void 0 : _sdk_isLoggedIn.call(sdk))) {
734
760
  redirectUri = customerRedirectUrl || "".concat(window.location.href);
735
761
  if (liffLogin) {
736
- liff.login({
762
+ sdk.login({
737
763
  redirectUri: redirectUri
738
764
  });
739
765
  return [
@@ -743,105 +769,54 @@ var LiffProvider = function(param) {
743
769
  if (loginByUser || ignoreRoute) return [
744
770
  2
745
771
  ];
746
- liff.login({
772
+ sdk.login({
747
773
  redirectUri: redirectUri
748
774
  });
749
775
  return [
750
776
  2
751
777
  ];
752
778
  }
753
- if (!!liffId) return [
754
- 3,
755
- 2
756
- ];
757
- console.warn("liffId 未提供,跳過 liff.init()。");
758
- return [
759
- 3,
760
- 8
761
- ];
762
- case 2:
763
- if (!!liff.isLoggedIn()) return [
779
+ tempFriendship = null;
780
+ if (!lineToken) return [
764
781
  3,
765
- 7
782
+ 9
766
783
  ];
767
784
  _state.label = 3;
768
785
  case 3:
769
786
  _state.trys.push([
770
787
  3,
771
- 5,
772
- ,
773
- 6
774
- ]);
775
- return [
776
- 4,
777
- liff.init({
778
- liffId: liffId,
779
- withLoginOnExternalBrowser: false
780
- })
781
- ];
782
- case 4:
783
- _state.sent();
784
- return [
785
- 3,
786
- 6
787
- ];
788
- case 5:
789
- e = _state.sent();
790
- console.error("liff.init() 失敗:", e);
791
- return [
792
- 3,
793
- 6
794
- ];
795
- case 6:
796
- return [
797
- 3,
798
- 8
799
- ];
800
- case 7:
801
- console.log("LIFF 已登入,跳過 liff.init() 以避免重複的 verify/profile 呼叫。");
802
- _state.label = 8;
803
- case 8:
804
- tempFriendship = null;
805
- if (!lineToken) return [
806
- 3,
807
- 15
808
- ];
809
- _state.label = 9;
810
- case 9:
811
- _state.trys.push([
812
- 9,
813
- 12,
788
+ 6,
814
789
  ,
815
- 13
790
+ 7
816
791
  ]);
817
- if (!!liff.isLoggedIn()) return [
792
+ if (!(sdk.isLoggedIn && sdk.isLoggedIn())) return [
818
793
  3,
819
- 11
794
+ 5
820
795
  ];
821
796
  return [
822
797
  4,
823
- liff.getFriendship()
798
+ sdk.getFriendship()
824
799
  ];
825
- case 10:
800
+ case 4:
826
801
  friendship = _state.sent();
827
802
  friendFlag = friendship === null || friendship === void 0 ? void 0 : friendship.friendFlag;
828
803
  setFriendship(friendFlag);
829
804
  tempFriendship = friendFlag;
830
805
  console.log("isFriendship", friendFlag);
831
- _state.label = 11;
832
- case 11:
806
+ _state.label = 5;
807
+ case 5:
833
808
  return [
834
809
  3,
835
- 13
810
+ 7
836
811
  ];
837
- case 12:
812
+ case 6:
838
813
  error = _state.sent();
839
814
  console.error("Error in liff.getFriendship():", error);
840
815
  return [
841
816
  3,
842
- 13
817
+ 7
843
818
  ];
844
- case 13:
819
+ case 7:
845
820
  console.log("isValid", isValid);
846
821
  if (tempFriendship && isValid) return [
847
822
  2
@@ -850,23 +825,23 @@ var LiffProvider = function(param) {
850
825
  4,
851
826
  loginInit(lineToken)
852
827
  ];
853
- case 14:
828
+ case 8:
854
829
  _state.sent();
855
- _state.label = 15;
856
- case 15:
830
+ _state.label = 9;
831
+ case 9:
857
832
  return [
858
833
  3,
859
- 17
834
+ 11
860
835
  ];
861
- case 16:
836
+ case 10:
862
837
  err = _state.sent();
863
838
  setLiffError(err.toString());
864
839
  console.log("LIFF init failed.", err);
865
840
  return [
866
841
  3,
867
- 17
842
+ 11
868
843
  ];
869
- case 17:
844
+ case 11:
870
845
  return [
871
846
  2
872
847
  ];
@@ -877,6 +852,80 @@ var LiffProvider = function(param) {
877
852
  return _ref.apply(this, arguments);
878
853
  };
879
854
  }();
855
+ // 確保 LIFF init 只執行一次且在需要時才執行
856
+ var ensureLiffInitialized = useCallback(/*#__PURE__*/ _async_to_generator(function() {
857
+ var customFetch, liff, originalFetch, e;
858
+ return _ts_generator(this, function(_state) {
859
+ switch(_state.label){
860
+ case 0:
861
+ if (liffInitialized) return [
862
+ 2
863
+ ];
864
+ if (!liffId) {
865
+ console.warn("liffId 未提供,跳過 liff.init()。");
866
+ return [
867
+ 2
868
+ ];
869
+ }
870
+ _state.label = 1;
871
+ case 1:
872
+ _state.trys.push([
873
+ 1,
874
+ 4,
875
+ ,
876
+ 5
877
+ ]);
878
+ customFetch = // 自訂 fetch 函數,避免每次請求都改變 URL
879
+ // eslint-disable-next-line no-inner-declarations
880
+ function customFetch(url, options) {
881
+ if (url.toString().startsWith("https://liffsdk.line-scdn.net/xlt/") && url.toString().endsWith(".json")) {
882
+ url = "".concat(url, "?ts=").concat(Math.random());
883
+ }
884
+ return originalFetch(url, options);
885
+ };
886
+ return [
887
+ 4,
888
+ import('./index.esm3.js')
889
+ ];
890
+ case 2:
891
+ liff = _state.sent().liff;
892
+ originalFetch = window.fetch;
893
+ window.fetch = customFetch;
894
+ if (openInApp && !(liff === null || liff === void 0 ? void 0 : liff.isInClient()) && (liff === null || liff === void 0 ? void 0 : liff.getOS()) !== "web") window.location.href = "line://app/".concat(liffId);
895
+ return [
896
+ 4,
897
+ liff.init({
898
+ liffId: liffId,
899
+ withLoginOnExternalBrowser: false
900
+ })
901
+ ];
902
+ case 3:
903
+ _state.sent();
904
+ setLiffObject(liff);
905
+ setLiffInitialized(true);
906
+ console.log("LIFF initialized.");
907
+ return [
908
+ 3,
909
+ 5
910
+ ];
911
+ case 4:
912
+ e = _state.sent();
913
+ console.error("ensureLiffInitialized failed:", e);
914
+ return [
915
+ 3,
916
+ 5
917
+ ];
918
+ case 5:
919
+ return [
920
+ 2
921
+ ];
922
+ }
923
+ });
924
+ }), [
925
+ liffInitialized,
926
+ liffId,
927
+ openInApp
928
+ ]);
880
929
  var accountLogin = function() {
881
930
  var _ref = _async_to_generator(function(username, password) {
882
931
  var response, token, tokenType, finalToken, err;
@@ -948,6 +997,77 @@ var LiffProvider = function(param) {
948
997
  return _ref.apply(this, arguments);
949
998
  };
950
999
  }();
1000
+ // 取得 LIFF profile(LIFF 的會員資料,與 API 的 member 分開處理)
1001
+ var getLiffProfile = useCallback(/*#__PURE__*/ _async_to_generator(function() {
1002
+ var sdk, imported, profile, err;
1003
+ return _ts_generator(this, function(_state) {
1004
+ switch(_state.label){
1005
+ case 0:
1006
+ _state.trys.push([
1007
+ 0,
1008
+ 5,
1009
+ ,
1010
+ 6
1011
+ ]);
1012
+ // 確保 LIFF 已初始化
1013
+ return [
1014
+ 4,
1015
+ ensureLiffInitialized()
1016
+ ];
1017
+ case 1:
1018
+ _state.sent();
1019
+ sdk = liffObject;
1020
+ if (!!sdk) return [
1021
+ 3,
1022
+ 3
1023
+ ];
1024
+ return [
1025
+ 4,
1026
+ import('./index.esm3.js')
1027
+ ];
1028
+ case 2:
1029
+ imported = _state.sent();
1030
+ sdk = imported.liff;
1031
+ setLiffObject(sdk);
1032
+ _state.label = 3;
1033
+ case 3:
1034
+ if (!sdk || typeof sdk.isLoggedIn !== "function" || !sdk.isLoggedIn()) {
1035
+ console.warn("getLiffProfile: LIFF not initialized or user not logged in");
1036
+ return [
1037
+ 2,
1038
+ null
1039
+ ];
1040
+ }
1041
+ return [
1042
+ 4,
1043
+ sdk.getProfile()
1044
+ ];
1045
+ case 4:
1046
+ profile = _state.sent();
1047
+ setLiffProfile(profile);
1048
+ saveLiffProfileToStorage(profile);
1049
+ return [
1050
+ 2,
1051
+ profile
1052
+ ];
1053
+ case 5:
1054
+ err = _state.sent();
1055
+ console.error("取得 LIFF profile 失敗:", err);
1056
+ return [
1057
+ 2,
1058
+ null
1059
+ ];
1060
+ case 6:
1061
+ return [
1062
+ 2
1063
+ ];
1064
+ }
1065
+ });
1066
+ }), [
1067
+ liffObject,
1068
+ ensureLiffInitialized,
1069
+ saveLiffProfileToStorage
1070
+ ]);
951
1071
  var ensureLiffTokenValid = useCallback(/*#__PURE__*/ _async_to_generator(function() {
952
1072
  var _parsedStore_data, _parsedStore_state, jwtTokenValue, jwtToken, parsedStore, isValid, _tmp, err;
953
1073
  return _ts_generator(this, function(_state) {
@@ -1043,9 +1163,10 @@ var LiffProvider = function(param) {
1043
1163
  return trimmed.toLowerCase().startsWith("bearer ") ? trimmed : "Bearer ".concat(trimmed);
1044
1164
  };
1045
1165
  var searchParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
1046
- // 初始載入時從 localStorage 載入 userInfo
1166
+ // 初始載入時從 localStorage 載入 userInfo 與 LIFF profile
1047
1167
  useEffect(function() {
1048
1168
  loadUserInfoFromStorage();
1169
+ loadLiffProfileFromStorage();
1049
1170
  }, []);
1050
1171
  // 客戶端初始化 LIFF
1051
1172
  useEffect(function() {
@@ -1123,32 +1244,22 @@ var LiffProvider = function(param) {
1123
1244
  }();
1124
1245
  checkAndInitialize();
1125
1246
  }, []);
1126
- var contextValue = useMemo(function() {
1127
- return {
1128
- liffObject: liffObject,
1129
- loginData: loginData,
1130
- userInfo: userInfo,
1131
- accessToken: accessToken,
1132
- liffError: liffError,
1133
- initializeLiff: function() {
1134
- return initializeLiff(false);
1135
- },
1136
- isFriendship: isFriendship,
1137
- ensureLiffTokenValid: ensureLiffTokenValid,
1138
- accountLogin: accountLogin,
1139
- loginType: loginType
1140
- };
1141
- }, [
1142
- liffObject,
1143
- loginData,
1144
- userInfo,
1145
- accessToken,
1146
- liffError,
1147
- isFriendship,
1148
- ensureLiffTokenValid,
1149
- accountLogin,
1150
- loginType
1151
- ]);
1247
+ var contextValue = {
1248
+ liffObject: liffObject,
1249
+ loginData: loginData,
1250
+ userInfo: userInfo,
1251
+ accessToken: accessToken,
1252
+ liffError: liffError,
1253
+ initializeLiff: function() {
1254
+ return initializeLiff(false);
1255
+ },
1256
+ getLiffProfile: getLiffProfile,
1257
+ liffProfile: liffProfile,
1258
+ isFriendship: isFriendship,
1259
+ ensureLiffTokenValid: ensureLiffTokenValid,
1260
+ accountLogin: accountLogin,
1261
+ loginType: loginType
1262
+ };
1152
1263
  return /*#__PURE__*/ jsx(LiffContext.Provider, {
1153
1264
  value: contextValue,
1154
1265
  children: children
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunggang/ui-lib",
3
- "version": "0.4.43",
3
+ "version": "0.4.44",
4
4
  "sideEffects": [
5
5
  "*.css",
6
6
  "./src/style.css",
@@ -3,9 +3,11 @@ type LiffContextType = {
3
3
  liffObject: any;
4
4
  loginData: any;
5
5
  userInfo?: any;
6
+ liffProfile?: any;
6
7
  accessToken: string;
7
8
  liffError: string | null;
8
9
  initializeLiff: () => Promise<void>;
10
+ getLiffProfile: () => Promise<any | null>;
9
11
  isFriendship: boolean | null;
10
12
  ensureLiffTokenValid: () => Promise<boolean>;
11
13
  loginType: string | null;