@nakamura-123/pages 1.0.0 → 1.0.2

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.
@@ -37,8 +37,9 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.isCheckRequired = exports.coinCheckFnc = void 0;
40
- var lib_1 = require("@nakamura-123/lib");
41
40
  var toolkit_1 = require("@reduxjs/toolkit");
41
+ // import { initConnection } from "expo-iap";
42
+ var lib_1 = require("@nakamura-123/lib");
42
43
  var CoinFnc_1 = require("./CoinFnc");
43
44
  var stores_1 = require("@nakamura-123/stores");
44
45
  // 00.メイン関数
@@ -1,7 +1,7 @@
1
1
  import RNIap, { ProductPurchase, Purchase } from "expo-iap";
2
2
  import { Storage } from "@nakamura-123/types";
3
- export declare const initializeIAP: (paymentItems: string[] | undefined, setProducts: (products: RNIap.Product[]) => void, setLoading: (loading: boolean) => void) => Promise<void>;
4
- export declare const handlePurchase: (productId: string, dispatch: (action: any) => void) => Promise<ProductPurchase | null>;
3
+ export declare const initializeIAP: (paymentItems: string[] | undefined, setProducts?: (products: RNIap.Product[]) => void, setLoading?: (loading: boolean) => void) => Promise<void>;
4
+ export declare const handlePurchase: (productId: string) => Promise<ProductPurchase | null>;
5
5
  export declare const restorePurchases: (dispatch: (action: any) => void, isAlert?: boolean) => Promise<Storage.Receipt[] | null>;
6
6
  export declare const updateAllFreeState: (receipt: Storage.Receipt | null) => (dispatch: any, getState: any) => void;
7
- export declare const getAndroidPurchaseState: (purchase: Purchase) => "paid" | "canceled" | "waiting";
7
+ export declare const getAndroidPurchaseState: (purchase: Purchase) => "paid" | "canceled" | "wait";
@@ -60,7 +60,7 @@ var initializeIAP = function (paymentItems, setProducts, setLoading) { return __
60
60
  case 2:
61
61
  productList = _a.sent();
62
62
  console.log("Product List: ", productList);
63
- setProducts(productList);
63
+ setProducts && setProducts(productList);
64
64
  return [3 /*break*/, 4];
65
65
  case 3:
66
66
  console.warn("No SKUs provided.");
@@ -71,7 +71,7 @@ var initializeIAP = function (paymentItems, setProducts, setLoading) { return __
71
71
  console.warn("IAP Initialization Error: ", err_1);
72
72
  return [3 /*break*/, 7];
73
73
  case 6:
74
- setLoading(false);
74
+ setLoading && setLoading(false);
75
75
  return [7 /*endfinally*/];
76
76
  case 7: return [2 /*return*/];
77
77
  }
@@ -79,7 +79,7 @@ var initializeIAP = function (paymentItems, setProducts, setLoading) { return __
79
79
  }); };
80
80
  exports.initializeIAP = initializeIAP;
81
81
  // 11. 購入処理
82
- var handlePurchase = function (productId, dispatch) { return __awaiter(void 0, void 0, void 0, function () {
82
+ var handlePurchase = function (productId) { return __awaiter(void 0, void 0, void 0, function () {
83
83
  var purchase, receipt, isValid, err_2;
84
84
  return __generator(this, function (_a) {
85
85
  switch (_a.label) {
@@ -95,25 +95,18 @@ var handlePurchase = function (productId, dispatch) { return __awaiter(void 0, v
95
95
  purchase = purchase[0];
96
96
  // 購入データの検証
97
97
  if (!purchase) {
98
- // dispatch(pushCoinWarn({ title: "購入応答がありません", log: purchase }));
99
98
  throw new Error("無効な購入応答");
100
99
  }
101
100
  receipt = purchase.transactionReceipt || purchase.purchaseToken;
102
101
  if (!receipt) {
103
- // dispatch(
104
- // pushCoinWarn({ title: "レシートが取得できません", log: purchase })
105
- // );
106
102
  throw new Error("レシートデータが無効です");
107
103
  }
108
104
  isValid = (0, ReceiptFnc_1.validatePurchaseClientSide)(receipt, react_native_1.Platform.OS);
109
105
  if (!isValid) {
110
- // dispatch(
111
- // pushCoinWarn({ title: "購入検証に失敗しました", log: purchase })
112
- // );
113
106
  throw new Error("購入検証に失敗しました");
114
107
  }
115
108
  if (!(react_native_1.Platform.OS === "android" &&
116
- (0, exports.getAndroidPurchaseState)(purchase) === "waiting")) return [3 /*break*/, 2];
109
+ (0, exports.getAndroidPurchaseState)(purchase) === "wait")) return [3 /*break*/, 2];
117
110
  alert("手続きが完了しました。支払いが完了したら、このページにある「以前購入した方はこちらから復元」をタップしてください。");
118
111
  return [3 /*break*/, 4];
119
112
  case 2: return [4 /*yield*/, (0, expo_iap_1.finishTransaction)({ purchase: purchase, isConsumable: false })];
@@ -142,11 +135,10 @@ var restorePurchases = function (dispatch, isAlert) { return __awaiter(void 0, v
142
135
  switch (_a.label) {
143
136
  case 0:
144
137
  _a.trys.push([0, 8, , 9]);
145
- console.log("restorePurchases");
138
+ console.log("restorePurchases復元中:");
146
139
  return [4 /*yield*/, (0, expo_iap_1.getAvailablePurchases)()];
147
140
  case 1:
148
141
  purchases = _a.sent();
149
- // const purchases: Purchase[] = await getAvailablePurchases();
150
142
  console.log("purchases", purchases);
151
143
  receipts = [];
152
144
  _i = 0, purchases_1 = purchases;
@@ -218,21 +210,19 @@ var getAndroidPurchaseState = function (purchase) {
218
210
  return "paid";
219
211
  }
220
212
  switch (purchase.purchaseStateAndroid) {
221
- case 0:
222
- return "paid";
223
213
  case 1:
224
- return "canceled";
214
+ return "paid";
225
215
  case 2:
226
- return "waiting";
216
+ return "wait";
227
217
  default:
228
- return "paid";
218
+ return "canceled";
229
219
  }
230
220
  };
231
221
  exports.getAndroidPurchaseState = getAndroidPurchaseState;
232
222
  // 94. Androidの後払いアイテムの承認をするか否か
233
223
  var checkIsAcknowledgedAndroid = function (purchase) {
234
224
  if (purchase.platform === "ios")
235
- return true; // iOSでは常に承認済み
225
+ return false; // iOSでは常に未承認(finishは自動で行われる)
236
226
  return ((0, exports.getAndroidPurchaseState)(purchase) === "paid" &&
237
227
  !purchase.isAcknowledgedAndroid);
238
228
  };
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validatePurchaseClientSide = exports.unifyReceipt = void 0;
4
4
  // 01. レシートの形式を統一
5
5
  var unifyReceipt = function (receipt) {
6
- var os = receipt.platform === "ios" ? "ios" : "android";
6
+ console.log("Unifying receipt:", receipt);
7
7
  if (receipt.platform === "android")
8
8
  return {
9
9
  transactionId: receipt.transactionId || "",
10
10
  productId: receipt.productId,
11
11
  transactionDate: Number(receipt.transactionDate),
12
12
  receipt: receipt.purchaseToken || "",
13
- isPaid: receipt.purchaseStateAndroid === 0,
13
+ isPaid: receipt.purchaseStateAndroid === 1,
14
14
  };
15
15
  else
16
16
  return {
@@ -31,28 +31,34 @@ var validatePurchaseClientSide = function (receipt, platform) {
31
31
  return false;
32
32
  }
33
33
  // 2. プラットフォーム特有のチェック
34
- if (platform === "android") {
35
- // Android特有のチェック(例: レシートがJSON形式でない場合など)
36
- try {
37
- var parsedReceipt = JSON.parse(receipt);
38
- if (!parsedReceipt.purchaseToken ||
39
- typeof parsedReceipt.purchaseToken !== "string") {
40
- console.error("購入データが無効です: purchaseTokenがありません");
41
- return false;
42
- }
43
- }
44
- catch (_a) {
45
- console.error("購入データが無効です: レシートの形式が不正です (JSONである必要があります)");
46
- return false;
47
- }
48
- }
49
- if (platform === "ios") {
50
- // iOS特有のチェック
51
- if (!/^[A-Za-z0-9+/=]+$/.test(receipt)) {
52
- console.error("購入データが無効です: レシートがBase64形式ではありません");
53
- return false;
54
- }
55
- }
34
+ // if (platform === "android") {
35
+ // // Android特有のチェック(例: レシートがJSON形式でない場合など)
36
+ // try {
37
+ // const parsedReceipt = JSON.parse(receipt);
38
+ // if (
39
+ // !parsedReceipt.purchaseToken ||
40
+ // typeof parsedReceipt.purchaseToken !== "string"
41
+ // ) {
42
+ // console.error("購入データが無効です: purchaseTokenがありません");
43
+ // return false;
44
+ // }
45
+ // } catch {
46
+ // console.error(
47
+ // "購入データが無効です: レシートの形式が不正です (JSONである必要があります)"
48
+ // );
49
+ // return false;
50
+ // }
51
+ // }
52
+ // iOSは、もうこの形式ではなくJSON形式なので、これは当てはまらない。
53
+ // if (platform === "ios") {
54
+ // // iOS特有のチェック
55
+ // if (!/^[A-Za-z0-9+/=]+$/.test(receipt)) {
56
+ // console.error(
57
+ // "購入データが無効です: レシートがBase64形式ではありません"
58
+ // );
59
+ // return false;
60
+ // }
61
+ // }
56
62
  console.log("クライアントサイドの簡易検証が成功しました");
57
63
  return true;
58
64
  }
@@ -12,6 +12,7 @@ var WaitingPayBanner = function (_a) {
12
12
  var currentPage = _a.currentPage;
13
13
  var msg = currentPage === "home" ? homeMsg : coinMsg;
14
14
  var allFreeState = (0, react_redux_1.useSelector)(function (state) { return state.setting.payment.allFreeState; });
15
+ console.log(allFreeState);
15
16
  if (allFreeState !== "wait")
16
17
  return null;
17
18
  return <common_1.ModalBanner bannerMsg={msg}/>;
@@ -25,14 +25,11 @@ var useConfirmExit = function (navigation) {
25
25
  showExitConfirmation(function () { return navigation.goBack(); }, onSaveProgress, removeSave);
26
26
  return true; // デフォルトの戻る挙動を無効化
27
27
  };
28
- // ここがポイント:subscription を受け取る
29
- var subscription = react_native_1.BackHandler.addEventListener("hardwareBackPress", onBackPress);
30
- // cleanup で subscription.remove() を呼ぶ
28
+ react_native_1.BackHandler.addEventListener("hardwareBackPress", onBackPress);
31
29
  return function () {
32
- subscription.remove();
30
+ return react_native_1.BackHandler.removeEventListener("hardwareBackPress", onBackPress);
33
31
  };
34
- }, [navigation, onSaveProgress, removeSave]) // 依存を入れて stale 回避
35
- );
32
+ }, []));
36
33
  };
37
34
  exports.useConfirmExit = useConfirmExit;
38
35
  // 確認ダイアログを表示する関数
@@ -98,7 +98,7 @@ var CoinPage = function (_a) {
98
98
  _a.label = 1;
99
99
  case 1:
100
100
  _a.trys.push([1, 6, 7, 8]);
101
- return [4 /*yield*/, (0, CoinFnc_1.handlePurchase)(productId, dispatch)];
101
+ return [4 /*yield*/, (0, CoinFnc_1.handlePurchase)(productId)];
102
102
  case 2:
103
103
  purchase = _a.sent();
104
104
  if (!purchase) {
@@ -3,7 +3,6 @@ import { Home, Nav } from "@nakamura-123/types";
3
3
  interface Prop {
4
4
  menuLists: Home.MenuListItem[];
5
5
  navigation: Nav.NavigationProp<"Home">;
6
- t: (key: string) => string;
7
6
  }
8
7
  declare const HomePage: React.FC<Prop>;
9
8
  export default HomePage;
@@ -67,6 +67,7 @@ var react_native_1 = require("react-native");
67
67
  var realm_1 = __importDefault(require("realm"));
68
68
  var react_redux_1 = require("react-redux");
69
69
  var react_2 = require("@realm/react");
70
+ var react_i18next_1 = require("react-i18next");
70
71
  var i18next_1 = __importDefault(require("i18next"));
71
72
  var common_1 = require("@nakamura-123/common");
72
73
  var stores_1 = require("@nakamura-123/stores");
@@ -87,26 +88,22 @@ var MenuRectangle = function (_a) {
87
88
  };
88
89
  var LOAD_OLD_MSG = " 旧システムのデータ引き継ぎを実施いたします。ふせんデータや模擬試験の成績など、可能な限りデータを移行いたしますが、仕様上一部移行ができない項目があります。あらかじめご了承ください。\n\n なお、引き継ぎをキャンセルされた場合でも、設定ページより再度操作を行うことが可能です。";
89
90
  var HomePage = function (_a) {
90
- var menuLists = _a.menuLists, navigation = _a.navigation, t = _a.t;
91
+ var menuLists = _a.menuLists, navigation = _a.navigation;
91
92
  var dispatch = (0, react_redux_1.useDispatch)();
92
93
  var DailyLogDB = (0, react_2.useQuery)(db_1.DailyLogSchema);
93
94
  // ここは、データの引き継ぎを行うための処理です。
94
95
  var realm = (0, react_2.useRealm)();
95
- // const { t } = useTranslation();
96
+ var t = (0, react_i18next_1.useTranslation)().t;
96
97
  var showLoadOldData = (0, react_redux_1.useSelector)(function (state) { return state.setting.guide.loadOldData; });
97
98
  var settingAsyncLoaded = (0, react_redux_1.useSelector)(function (state) { return state.setting.asyncLoaded; });
98
99
  var oldInfo = (0, react_redux_1.useSelector)(function (state) { return state.app.appSetting.oldInfo; });
99
100
  var isJLPT = (0, react_redux_1.useSelector)(function (state) { return state.app.appSetting.setting.appSystem; }) === "JLPT";
100
- // let language = useSelector((state: RootState) => state.setting.language);
101
- // language = isJLPT ? language : "ja"; // JLPTの時は、jaにする。
101
+ var language = (0, react_redux_1.useSelector)(function (state) { return state.setting.language; });
102
+ language = isJLPT ? language : "ja"; // JLPTの時は、jaにする。
102
103
  (0, react_1.useEffect)(function () {
103
- console.log("18next");
104
- console.log(i18next_1.default);
105
- console.log("t");
106
- console.log(t("home.updateMsg"));
107
104
  if (!settingAsyncLoaded)
108
105
  return;
109
- // i18next.changeLanguage(language); // 言語を切り替える
106
+ i18next_1.default.changeLanguage(language); // 言語を切り替える
110
107
  if (!showLoadOldData)
111
108
  return;
112
109
  dispatch({ type: "setting/guideStateFalse", payload: "loadOldData" });
@@ -22,12 +22,49 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __generator = (this && this.__generator) || function (thisArg, body) {
35
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
36
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
37
+ function verb(n) { return function (v) { return step([n, v]); }; }
38
+ function step(op) {
39
+ if (f) throw new TypeError("Generator is already executing.");
40
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
41
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
42
+ if (y = 0, t) op = [op[0] & 2, t.value];
43
+ switch (op[0]) {
44
+ case 0: case 1: t = op; break;
45
+ case 4: _.label++; return { value: op[1], done: false };
46
+ case 5: _.label++; y = op[1]; op = [0]; continue;
47
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
48
+ default:
49
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
50
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
51
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
52
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
53
+ if (t[2]) _.ops.pop();
54
+ _.trys.pop(); continue;
55
+ }
56
+ op = body.call(thisArg, _);
57
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
58
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
59
+ }
60
+ };
25
61
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
62
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
63
  };
28
64
  Object.defineProperty(exports, "__esModule", { value: true });
29
65
  var react_1 = __importStar(require("react"));
30
66
  var react_native_1 = require("react-native");
67
+ var expo_iap_1 = require("expo-iap");
31
68
  var common_1 = require("@nakamura-123/common");
32
69
  var CharaCard_1 = __importDefault(require("../component/Result/CharaCard"));
33
70
  var LessonTitle_1 = __importDefault(require("../component/Result/LessonTitle"));
@@ -39,6 +76,7 @@ var CoinCheck_1 = require("../component/Coin/CoinCheck");
39
76
  var lib_1 = require("@nakamura-123/lib");
40
77
  var react_i18next_1 = require("react-i18next");
41
78
  var AdCard_1 = __importDefault(require("../component/Result/AdCard"));
79
+ var CoinFnc_1 = require("../component/Coin/CoinFnc");
42
80
  var ResultPage = function (_a) {
43
81
  var navigation = _a.navigation;
44
82
  var dispatch = (0, react_redux_1.useDispatch)();
@@ -47,15 +85,61 @@ var ResultPage = function (_a) {
47
85
  var _b = (0, react_redux_1.useSelector)(function (state) { return state.setting.payment; }), allFreeState = _b.allFreeState, lastCheckedDate = _b.lastCheckedDate;
48
86
  var isJLPT = (0, react_redux_1.useSelector)(function (state) { return state.app.appSetting.setting.appSystem; }) === "JLPT";
49
87
  var isCompletelyFree = (0, react_redux_1.useSelector)(function (state) { var _a; return (_a = state.app.appSetting.setting) === null || _a === void 0 ? void 0 : _a.payment.isCompletelyFree; }) || false;
88
+ var items = allFreeId ? [allFreeId] : [];
50
89
  (0, react_1.useEffect)(function () {
51
- var isCheckRequir = (0, CoinCheck_1.isCheckRequired)(allFreeState, lastCheckedDate, isCompletelyFree);
52
- if (isCheckRequir) {
53
- // 最終チェック日を更新・成功しようがしまいが、1日1回以上やらないようにする.
54
- var todayStr = lib_1.timeFnc.getTodayString();
55
- dispatch({ type: "setting/updateLastCheckedDate", payload: todayStr });
56
- // ここで復元処理を行う
57
- dispatch((0, CoinCheck_1.coinCheckFnc)(allFreeId));
58
- }
90
+ var cancelled = false;
91
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
92
+ var need, todayStr, e_1, _a;
93
+ return __generator(this, function (_b) {
94
+ switch (_b.label) {
95
+ case 0:
96
+ need = (0, CoinCheck_1.isCheckRequired)(allFreeState, lastCheckedDate, isCompletelyFree);
97
+ console.log("Check required:", need);
98
+ if (!need)
99
+ return [2 /*return*/];
100
+ _b.label = 1;
101
+ case 1:
102
+ _b.trys.push([1, 5, 6, 10]);
103
+ todayStr = lib_1.timeFnc.getTodayString();
104
+ dispatch({ type: "setting/updateLastCheckedDate", payload: todayStr });
105
+ // 3) 接続
106
+ // --- expo-iap ---
107
+ return [4 /*yield*/, (0, CoinFnc_1.initializeIAP)(items)];
108
+ case 2:
109
+ // 3) 接続
110
+ // --- expo-iap ---
111
+ _b.sent();
112
+ return [4 /*yield*/, new Promise(function (r) { return setTimeout(r, 5000); })];
113
+ case 3:
114
+ _b.sent(); // 少し待つ
115
+ // 4) チェック本体(復元や検証)
116
+ return [4 /*yield*/, dispatch((0, CoinCheck_1.coinCheckFnc)(allFreeId))];
117
+ case 4:
118
+ // 4) チェック本体(復元や検証)
119
+ _b.sent();
120
+ return [3 /*break*/, 10];
121
+ case 5:
122
+ e_1 = _b.sent();
123
+ console.warn("IAP check failed:", e_1);
124
+ return [3 /*break*/, 10];
125
+ case 6:
126
+ _b.trys.push([6, 8, , 9]);
127
+ return [4 /*yield*/, (0, expo_iap_1.endConnection)()];
128
+ case 7:
129
+ _b.sent();
130
+ return [3 /*break*/, 9];
131
+ case 8:
132
+ _a = _b.sent();
133
+ return [3 /*break*/, 9];
134
+ case 9: return [7 /*endfinally*/];
135
+ case 10: return [2 /*return*/];
136
+ }
137
+ });
138
+ }); })();
139
+ return function () {
140
+ cancelled = true;
141
+ };
142
+ // 依存は必要最小限。チェック条件が変わった時だけ再評価されるように。
59
143
  }, []);
60
144
  var scoreInfo = (0, quizHook_1.useScoreInfo)();
61
145
  return (<react_native_1.View style={styles.page}>
@@ -68,6 +152,13 @@ var ResultPage = function (_a) {
68
152
  <common_1.MiniIconBtn onPress={function () { return navigation.goBack(); }} icon="arrow-left" title={t("quiz.resultBtn.back")} color="blue" outerStyle={styles.miniBtnOuter}/>
69
153
  </react_native_1.View>
70
154
  <QuizFlatList_1.default navigation={navigation}/>
155
+ {/* <Button
156
+ title={"チェック"}
157
+ onPress={async () => {
158
+ const purchases = await getAvailablePurchases();
159
+ console.log("getAvailablePurchases", purchases);
160
+ }}
161
+ /> */}
71
162
  </react_native_1.View>);
72
163
  };
73
164
  var styles = react_native_1.StyleSheet.create({