@sunggang/ui-lib 0.4.42 → 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, 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
- 12,
742
+ 10,
713
743
  ,
714
- 13
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,75 +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 (!!liff.isLoggedIn()) return [
758
- 3,
759
- 3
760
- ];
761
- return [
762
- 4,
763
- liff.init({
764
- liffId: liffId,
765
- withLoginOnExternalBrowser: false
766
- })
767
- ];
768
- case 2:
769
- _state.sent();
770
- return [
771
- 3,
772
- 4
773
- ];
774
- case 3:
775
- console.log("LIFF 已登入,跳過 liff.init() 以避免重複的 verify/profile 呼叫。");
776
- _state.label = 4;
777
- case 4:
778
783
  tempFriendship = null;
779
784
  if (!lineToken) return [
780
785
  3,
781
- 11
786
+ 9
782
787
  ];
783
- _state.label = 5;
784
- case 5:
788
+ _state.label = 3;
789
+ case 3:
785
790
  _state.trys.push([
786
- 5,
787
- 8,
791
+ 3,
792
+ 6,
788
793
  ,
789
- 9
794
+ 7
790
795
  ]);
791
- if (!!liff.isLoggedIn()) return [
796
+ if (!(sdk.isLoggedIn && sdk.isLoggedIn())) return [
792
797
  3,
793
- 7
798
+ 5
794
799
  ];
795
800
  return [
796
801
  4,
797
- liff.getFriendship()
802
+ sdk.getFriendship()
798
803
  ];
799
- case 6:
804
+ case 4:
800
805
  friendship = _state.sent();
801
806
  friendFlag = friendship === null || friendship === void 0 ? void 0 : friendship.friendFlag;
802
807
  setFriendship(friendFlag);
803
808
  tempFriendship = friendFlag;
804
809
  console.log("isFriendship", friendFlag);
805
- _state.label = 7;
806
- case 7:
810
+ _state.label = 5;
811
+ case 5:
807
812
  return [
808
813
  3,
809
- 9
814
+ 7
810
815
  ];
811
- case 8:
816
+ case 6:
812
817
  error = _state.sent();
813
818
  console.error("Error in liff.getFriendship():", error);
814
819
  return [
815
820
  3,
816
- 9
821
+ 7
817
822
  ];
818
- case 9:
823
+ case 7:
819
824
  console.log("isValid", isValid);
820
825
  if (tempFriendship && isValid) return [
821
826
  2
@@ -824,23 +829,23 @@ var LiffProvider = function(param) {
824
829
  4,
825
830
  loginInit(lineToken)
826
831
  ];
827
- case 10:
832
+ case 8:
828
833
  _state.sent();
829
- _state.label = 11;
830
- case 11:
834
+ _state.label = 9;
835
+ case 9:
831
836
  return [
832
837
  3,
833
- 13
838
+ 11
834
839
  ];
835
- case 12:
840
+ case 10:
836
841
  err = _state.sent();
837
842
  setLiffError(err.toString());
838
843
  console.log("LIFF init failed.", err);
839
844
  return [
840
845
  3,
841
- 13
846
+ 11
842
847
  ];
843
- case 13:
848
+ case 11:
844
849
  return [
845
850
  2
846
851
  ];
@@ -851,6 +856,80 @@ var LiffProvider = function(param) {
851
856
  return _ref.apply(this, arguments);
852
857
  };
853
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
+ ]);
854
933
  var accountLogin = function() {
855
934
  var _ref = _async_to_generator(function(username, password) {
856
935
  var response, token, tokenType, finalToken, err;
@@ -922,6 +1001,77 @@ var LiffProvider = function(param) {
922
1001
  return _ref.apply(this, arguments);
923
1002
  };
924
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
+ ]);
925
1075
  var ensureLiffTokenValid = React.useCallback(/*#__PURE__*/ _async_to_generator(function() {
926
1076
  var _parsedStore_data, _parsedStore_state, jwtTokenValue, jwtToken, parsedStore, isValid, _tmp, err;
927
1077
  return _ts_generator(this, function(_state) {
@@ -1017,9 +1167,10 @@ var LiffProvider = function(param) {
1017
1167
  return trimmed.toLowerCase().startsWith("bearer ") ? trimmed : "Bearer ".concat(trimmed);
1018
1168
  };
1019
1169
  var searchParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
1020
- // 初始載入時從 localStorage 載入 userInfo
1170
+ // 初始載入時從 localStorage 載入 userInfo 與 LIFF profile
1021
1171
  React.useEffect(function() {
1022
1172
  loadUserInfoFromStorage();
1173
+ loadLiffProfileFromStorage();
1023
1174
  }, []);
1024
1175
  // 客戶端初始化 LIFF
1025
1176
  React.useEffect(function() {
@@ -1097,32 +1248,22 @@ var LiffProvider = function(param) {
1097
1248
  }();
1098
1249
  checkAndInitialize();
1099
1250
  }, []);
1100
- var contextValue = React.useMemo(function() {
1101
- return {
1102
- liffObject: liffObject,
1103
- loginData: loginData,
1104
- userInfo: userInfo,
1105
- accessToken: accessToken,
1106
- liffError: liffError,
1107
- initializeLiff: function() {
1108
- return initializeLiff(false);
1109
- },
1110
- isFriendship: isFriendship,
1111
- ensureLiffTokenValid: ensureLiffTokenValid,
1112
- accountLogin: accountLogin,
1113
- loginType: loginType
1114
- };
1115
- }, [
1116
- liffObject,
1117
- loginData,
1118
- userInfo,
1119
- accessToken,
1120
- liffError,
1121
- isFriendship,
1122
- ensureLiffTokenValid,
1123
- accountLogin,
1124
- loginType
1125
- ]);
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
+ };
1126
1267
  return /*#__PURE__*/ jsxRuntime.jsx(LiffContext.Provider, {
1127
1268
  value: contextValue,
1128
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, 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
- 12,
738
+ 10,
709
739
  ,
710
- 13
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,75 +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 (!!liff.isLoggedIn()) return [
754
- 3,
755
- 3
756
- ];
757
- return [
758
- 4,
759
- liff.init({
760
- liffId: liffId,
761
- withLoginOnExternalBrowser: false
762
- })
763
- ];
764
- case 2:
765
- _state.sent();
766
- return [
767
- 3,
768
- 4
769
- ];
770
- case 3:
771
- console.log("LIFF 已登入,跳過 liff.init() 以避免重複的 verify/profile 呼叫。");
772
- _state.label = 4;
773
- case 4:
774
779
  tempFriendship = null;
775
780
  if (!lineToken) return [
776
781
  3,
777
- 11
782
+ 9
778
783
  ];
779
- _state.label = 5;
780
- case 5:
784
+ _state.label = 3;
785
+ case 3:
781
786
  _state.trys.push([
782
- 5,
783
- 8,
787
+ 3,
788
+ 6,
784
789
  ,
785
- 9
790
+ 7
786
791
  ]);
787
- if (!!liff.isLoggedIn()) return [
792
+ if (!(sdk.isLoggedIn && sdk.isLoggedIn())) return [
788
793
  3,
789
- 7
794
+ 5
790
795
  ];
791
796
  return [
792
797
  4,
793
- liff.getFriendship()
798
+ sdk.getFriendship()
794
799
  ];
795
- case 6:
800
+ case 4:
796
801
  friendship = _state.sent();
797
802
  friendFlag = friendship === null || friendship === void 0 ? void 0 : friendship.friendFlag;
798
803
  setFriendship(friendFlag);
799
804
  tempFriendship = friendFlag;
800
805
  console.log("isFriendship", friendFlag);
801
- _state.label = 7;
802
- case 7:
806
+ _state.label = 5;
807
+ case 5:
803
808
  return [
804
809
  3,
805
- 9
810
+ 7
806
811
  ];
807
- case 8:
812
+ case 6:
808
813
  error = _state.sent();
809
814
  console.error("Error in liff.getFriendship():", error);
810
815
  return [
811
816
  3,
812
- 9
817
+ 7
813
818
  ];
814
- case 9:
819
+ case 7:
815
820
  console.log("isValid", isValid);
816
821
  if (tempFriendship && isValid) return [
817
822
  2
@@ -820,23 +825,23 @@ var LiffProvider = function(param) {
820
825
  4,
821
826
  loginInit(lineToken)
822
827
  ];
823
- case 10:
828
+ case 8:
824
829
  _state.sent();
825
- _state.label = 11;
826
- case 11:
830
+ _state.label = 9;
831
+ case 9:
827
832
  return [
828
833
  3,
829
- 13
834
+ 11
830
835
  ];
831
- case 12:
836
+ case 10:
832
837
  err = _state.sent();
833
838
  setLiffError(err.toString());
834
839
  console.log("LIFF init failed.", err);
835
840
  return [
836
841
  3,
837
- 13
842
+ 11
838
843
  ];
839
- case 13:
844
+ case 11:
840
845
  return [
841
846
  2
842
847
  ];
@@ -847,6 +852,80 @@ var LiffProvider = function(param) {
847
852
  return _ref.apply(this, arguments);
848
853
  };
849
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
+ ]);
850
929
  var accountLogin = function() {
851
930
  var _ref = _async_to_generator(function(username, password) {
852
931
  var response, token, tokenType, finalToken, err;
@@ -918,6 +997,77 @@ var LiffProvider = function(param) {
918
997
  return _ref.apply(this, arguments);
919
998
  };
920
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
+ ]);
921
1071
  var ensureLiffTokenValid = useCallback(/*#__PURE__*/ _async_to_generator(function() {
922
1072
  var _parsedStore_data, _parsedStore_state, jwtTokenValue, jwtToken, parsedStore, isValid, _tmp, err;
923
1073
  return _ts_generator(this, function(_state) {
@@ -1013,9 +1163,10 @@ var LiffProvider = function(param) {
1013
1163
  return trimmed.toLowerCase().startsWith("bearer ") ? trimmed : "Bearer ".concat(trimmed);
1014
1164
  };
1015
1165
  var searchParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
1016
- // 初始載入時從 localStorage 載入 userInfo
1166
+ // 初始載入時從 localStorage 載入 userInfo 與 LIFF profile
1017
1167
  useEffect(function() {
1018
1168
  loadUserInfoFromStorage();
1169
+ loadLiffProfileFromStorage();
1019
1170
  }, []);
1020
1171
  // 客戶端初始化 LIFF
1021
1172
  useEffect(function() {
@@ -1093,32 +1244,22 @@ var LiffProvider = function(param) {
1093
1244
  }();
1094
1245
  checkAndInitialize();
1095
1246
  }, []);
1096
- var contextValue = useMemo(function() {
1097
- return {
1098
- liffObject: liffObject,
1099
- loginData: loginData,
1100
- userInfo: userInfo,
1101
- accessToken: accessToken,
1102
- liffError: liffError,
1103
- initializeLiff: function() {
1104
- return initializeLiff(false);
1105
- },
1106
- isFriendship: isFriendship,
1107
- ensureLiffTokenValid: ensureLiffTokenValid,
1108
- accountLogin: accountLogin,
1109
- loginType: loginType
1110
- };
1111
- }, [
1112
- liffObject,
1113
- loginData,
1114
- userInfo,
1115
- accessToken,
1116
- liffError,
1117
- isFriendship,
1118
- ensureLiffTokenValid,
1119
- accountLogin,
1120
- loginType
1121
- ]);
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
+ };
1122
1263
  return /*#__PURE__*/ jsx(LiffContext.Provider, {
1123
1264
  value: contextValue,
1124
1265
  children: children
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunggang/ui-lib",
3
- "version": "0.4.42",
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;