@norcy/react-native-toolkit 0.1.32 → 0.1.33

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.
@@ -4,9 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.initToolkitConfig = exports.ToolkitConfig = exports.Tool = void 0;
7
+ var _cameraroll = _interopRequireDefault(require("@react-native-community/cameraroll"));
7
8
  var _react = require("react");
8
9
  var _reactNative = require("react-native");
9
10
  var _reactNativeSimpleToast = _interopRequireDefault(require("react-native-simple-toast"));
11
+ var _rnFetchBlob = _interopRequireDefault(require("rn-fetch-blob"));
10
12
  var _ReportUtil = require("./ReportUtil");
11
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
14
  let ToolkitConfig = exports.ToolkitConfig = void 0;
@@ -23,6 +25,15 @@ const _jsonify = target => {
23
25
  if (Array.isArray(target)) return target.map(_jsonify);
24
26
  return target;
25
27
  };
28
+ const _hasAndroidWritePermission = async () => {
29
+ const permission = _reactNative.PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;
30
+ const hasPermission = await _reactNative.PermissionsAndroid.check(permission);
31
+ if (hasPermission) {
32
+ return true;
33
+ }
34
+ const status = await _reactNative.PermissionsAndroid.request(permission);
35
+ return status === 'granted';
36
+ };
26
37
  const Tool = exports.Tool = {
27
38
  sleep: delay => new Promise(resolve => setTimeout(resolve, delay)),
28
39
  formatDate(date, fmt) {
@@ -148,6 +159,67 @@ const Tool = exports.Tool = {
148
159
  if (!__DEV__) {
149
160
  await fetch(ToolkitConfig.PushDeerUrl + encodeURIComponent(text));
150
161
  }
162
+ },
163
+ savePicture: async (url, albumName) => {
164
+ console.log('savePicture', url);
165
+
166
+ // 检查权限
167
+ if (_reactNative.Platform.OS === 'android' && !(await _hasAndroidWritePermission())) {
168
+ return {
169
+ errorCode: -1
170
+ };
171
+ }
172
+
173
+ // iOS 或本地图片直接保存
174
+ if (_reactNative.Platform.OS === 'ios' || !Tool.isRemoteURL(url)) {
175
+ try {
176
+ await _cameraroll.default.save(url, {
177
+ type: 'photo',
178
+ album: albumName !== null && albumName !== void 0 ? albumName : ToolkitConfig.AppName
179
+ });
180
+ return {
181
+ errorCode: 0
182
+ };
183
+ } catch (error) {
184
+ console.error(error);
185
+ return {
186
+ errorCode: -2,
187
+ errMsg: JSON.stringify(error)
188
+ };
189
+ }
190
+ }
191
+
192
+ // 安卓远程图片需要下载
193
+ const extension = Tool.get_url_extension(url);
194
+ try {
195
+ const res = await _rnFetchBlob.default.config({
196
+ fileCache: true,
197
+ appendExt: extension
198
+ }).fetch('GET', url, {});
199
+ // the temp file path
200
+ console.log('The file saved to ', res.path());
201
+ try {
202
+ await _cameraroll.default.save('file://' + res.path(), {
203
+ type: 'photo',
204
+ album: albumName
205
+ });
206
+ return {
207
+ errorCode: 0
208
+ };
209
+ } catch (e1) {
210
+ console.error(e1 + '\n' + res.path());
211
+ return {
212
+ errorCode: -3,
213
+ errMsg: JSON.stringify(e1)
214
+ };
215
+ }
216
+ } catch (error) {
217
+ console.error(error);
218
+ return {
219
+ errorCode: -4,
220
+ errMsg: JSON.stringify(error)
221
+ };
222
+ }
151
223
  }
152
224
  };
153
225
  //# sourceMappingURL=Tool.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_reactNative","_reactNativeSimpleToast","_interopRequireDefault","_ReportUtil","obj","__esModule","default","ToolkitConfig","exports","initToolkitConfig","config","_isPlainObject","target","toString","Object","getPrototypeOf","prototype","_jsonify","toJSON","Array","isArray","map","Tool","sleep","delay","Promise","resolve","setTimeout","formatDate","date","fmt","o","getMonth","getDate","getHours","getMinutes","getSeconds","Math","floor","getMilliseconds","test","replace","RegExp","$1","getFullYear","substr","length","k","jsonify","keys","reduce","result","key","isChinese","value","isRemoteURL","str","startsWith","get_url_extension","url","_url$split$","split","pop","trim","generateObjectId","timestamp","Date","getTime","random","toLowerCase","humanFileSize","bytes","si","arguments","undefined","dp","thresh","abs","units","u","r","round","toFixed","useForceUpdate","setValue","useState","showToast","toast","Toast","showWithGravity","SHORT","CENTER","goAppStoreReview","ReportUtil","report","Platform","OS","Linking","canOpenURL","then","supported","openURL","iOSReviewUrl","NativeModules","CheckPackageInstallation","isPackageInstalled","isInstalled","goToMarket","AndroidPackageName","AndroidStoreScheme","goUpgrade","iOSStoreScheme","AppWebsite","notifyMe","text","__DEV__","fetch","PushDeerUrl","encodeURIComponent"],"sources":["Tool.ts"],"sourcesContent":["import { useState } from 'react';\nimport { Linking, NativeModules, Platform } from 'react-native';\nimport Toast from 'react-native-simple-toast';\nimport { ReportUtil } from './ReportUtil';\n\nexport interface ToolkitConfigType {\n iOSStoreUrl: string;\n AndroidStoreUrl: string;\n iOSStoreScheme: string;\n AndroidStoreScheme: string;\n iOSReviewUrl: string;\n AndroidPackageName: string;\n\n AppWebsite: string;\n\n PolicyUrl: string;\n TermsUrl: string;\n\n PushDeerUrl: string;\n\n RC_API_KEY: string;\n RC_ENTITLEMENT_ID: string;\n WeChatPayServer: string;\n WeiXinId: string;\n WeiXinSecret: string;\n}\n\nexport let ToolkitConfig: ToolkitConfigType;\n\nexport const initToolkitConfig = (config: ToolkitConfigType) => {\n ToolkitConfig = config;\n};\n\nconst _isPlainObject = (target: any) => {\n return (\n target &&\n target.toString() === '[object Object]' &&\n Object.getPrototypeOf(target) === Object.prototype\n );\n};\n\nconst _jsonify = (target: any): any => {\n if (target && typeof target.toJSON === 'function') return target.toJSON();\n // map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一次提供的函数后的返回值\n if (Array.isArray(target)) return target.map(_jsonify);\n return target;\n};\n\nexport const Tool = {\n sleep: (delay: number) =>\n new Promise((resolve) => setTimeout(resolve, delay)),\n\n formatDate(date: Date, fmt: string): string {\n fmt = fmt ? fmt : 'yyyy-MM-dd';\n var o: { [key: string]: number } = {\n 'M+': date.getMonth() + 1, //月份\n 'd+': date.getDate(), //日\n 'h+': date.getHours(), //小时\n 'm+': date.getMinutes(), //分\n 's+': date.getSeconds(), //秒\n 'q+': Math.floor((date.getMonth() + 3) / 3), //季度\n 'S': date.getMilliseconds(), //毫秒\n };\n\n // 获取年份\n if (/(y+)/i.test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (date.getFullYear() + '').substr(4 - RegExp.$1.length)\n );\n }\n\n for (var k in o) {\n if (new RegExp('(' + k + ')', 'i').test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (RegExp.$1.length === 1\n ? o[k]\n : ('00' + o[k]).substr(('' + o[k]).length)\n ).toString()\n );\n }\n }\n return fmt;\n },\n\n jsonify: (target: any) =>\n _isPlainObject(target)\n ? Object.keys(target).reduce(\n (result, key) => ({\n ...result,\n [key]: _jsonify(target[key]),\n }),\n {}\n )\n : _jsonify(target),\n\n isChinese: (value: string) => {\n return /[\\u4E00-\\u9FA5]+/g.test(value);\n },\n\n isRemoteURL: (str: string) => {\n return str.startsWith('http');\n },\n\n get_url_extension: (url: string) => {\n return url.split(/[#?]/)[0]?.split('.')?.pop()?.trim();\n },\n\n generateObjectId: () => {\n var timestamp = ((new Date().getTime() / 1000) | 0).toString(16); // eslint-disable-line no-bitwise\n return (\n timestamp +\n 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {\n return ((Math.random() * 16) | 0).toString(16).toLowerCase(); // eslint-disable-line no-bitwise\n })\n );\n },\n\n /**\n * Format bytes as human-readable text.\n *\n * @param bytes Number of bytes.\n * @param si True to use metric (SI) units, aka powers of 1000. False to use\n * binary (IEC), aka powers of 1024.\n * @param dp Number of decimal places to display.\n *\n * @return Formatted string.\n */\n humanFileSize: (bytes: number, si = false, dp = 1) => {\n const thresh = si ? 1000 : 1024;\n\n if (Math.abs(bytes) < thresh) {\n return bytes + ' B';\n }\n\n const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n let u = -1;\n const r = 10 ** dp;\n\n do {\n bytes /= thresh;\n ++u;\n } while (\n Math.round(Math.abs(bytes) * r) / r >= thresh &&\n u < units.length - 1\n );\n\n return bytes.toFixed(dp) + ' ' + units[u];\n },\n\n useForceUpdate: () => {\n const [, setValue] = useState(0);\n return () => setValue((value) => value + 1);\n },\n\n showToast: (toast: string) => {\n Toast.showWithGravity(toast, Toast.SHORT, Toast.CENTER);\n },\n\n goAppStoreReview: () => {\n ReportUtil.report('StoreReview');\n if (Platform.OS === 'ios') {\n Linking.canOpenURL('itms-apps://').then((supported) => {\n if (supported) {\n Linking.openURL(ToolkitConfig.iOSReviewUrl);\n }\n });\n } else {\n if (NativeModules.CheckPackageInstallation) {\n NativeModules.CheckPackageInstallation.isPackageInstalled(\n 'com.coolapk.market',\n (isInstalled: boolean) => {\n if (isInstalled) {\n if (NativeModules.CheckPackageInstallation.goToMarket) {\n NativeModules.CheckPackageInstallation.goToMarket(\n ToolkitConfig.AndroidPackageName,\n 'com.coolapk.market',\n 'com.coolapk.market.activity.AppViewActivity'\n );\n } else {\n Tool.showToast('请用酷安市场打开');\n Linking.openURL(ToolkitConfig.AndroidStoreScheme);\n }\n } else {\n Tool.showToast('需要先安装酷安市场');\n }\n }\n );\n }\n }\n },\n\n goUpgrade: () => {\n if (Platform.OS === 'ios') {\n Linking.canOpenURL('itms-apps://').then((supported) => {\n if (supported) {\n Linking.openURL(ToolkitConfig.iOSStoreScheme);\n }\n });\n } else {\n Linking.openURL(ToolkitConfig.AppWebsite);\n }\n },\n\n notifyMe: async (text: string) => {\n if (!__DEV__) {\n await fetch(ToolkitConfig.PushDeerUrl + encodeURIComponent(text));\n }\n },\n};\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,uBAAA,GAAAC,sBAAA,CAAAH,OAAA;AACA,IAAAI,WAAA,GAAAJ,OAAA;AAA0C,SAAAG,uBAAAE,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAwBnC,IAAIG,aAAgC,GAAAC,OAAA,CAAAD,aAAA;AAEpC,MAAME,iBAAiB,GAAIC,MAAyB,IAAK;EAC9DF,OAAA,CAAAD,aAAA,GAAAA,aAAa,GAAGG,MAAM;AACxB,CAAC;AAACF,OAAA,CAAAC,iBAAA,GAAAA,iBAAA;AAEF,MAAME,cAAc,GAAIC,MAAW,IAAK;EACtC,OACEA,MAAM,IACNA,MAAM,CAACC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,IACvCC,MAAM,CAACC,cAAc,CAACH,MAAM,CAAC,KAAKE,MAAM,CAACE,SAAS;AAEtD,CAAC;AAED,MAAMC,QAAQ,GAAIL,MAAW,IAAU;EACrC,IAAIA,MAAM,IAAI,OAAOA,MAAM,CAACM,MAAM,KAAK,UAAU,EAAE,OAAON,MAAM,CAACM,MAAM,CAAC,CAAC;EACzE;EACA,IAAIC,KAAK,CAACC,OAAO,CAACR,MAAM,CAAC,EAAE,OAAOA,MAAM,CAACS,GAAG,CAACJ,QAAQ,CAAC;EACtD,OAAOL,MAAM;AACf,CAAC;AAEM,MAAMU,IAAI,GAAAd,OAAA,CAAAc,IAAA,GAAG;EAClBC,KAAK,EAAGC,KAAa,IACnB,IAAIC,OAAO,CAAEC,OAAO,IAAKC,UAAU,CAACD,OAAO,EAAEF,KAAK,CAAC,CAAC;EAEtDI,UAAUA,CAACC,IAAU,EAAEC,GAAW,EAAU;IAC1CA,GAAG,GAAGA,GAAG,GAAGA,GAAG,GAAG,YAAY;IAC9B,IAAIC,CAA4B,GAAG;MACjC,IAAI,EAAEF,IAAI,CAACG,QAAQ,CAAC,CAAC,GAAG,CAAC;MAAE;MAC3B,IAAI,EAAEH,IAAI,CAACI,OAAO,CAAC,CAAC;MAAE;MACtB,IAAI,EAAEJ,IAAI,CAACK,QAAQ,CAAC,CAAC;MAAE;MACvB,IAAI,EAAEL,IAAI,CAACM,UAAU,CAAC,CAAC;MAAE;MACzB,IAAI,EAAEN,IAAI,CAACO,UAAU,CAAC,CAAC;MAAE;MACzB,IAAI,EAAEC,IAAI,CAACC,KAAK,CAAC,CAACT,IAAI,CAACG,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;MAAE;MAC7C,GAAG,EAAEH,IAAI,CAACU,eAAe,CAAC,CAAC,CAAE;IAC/B,CAAC;;IAED;IACA,IAAI,OAAO,CAACC,IAAI,CAACV,GAAG,CAAC,EAAE;MACrBA,GAAG,GAAGA,GAAG,CAACW,OAAO,CACfC,MAAM,CAACC,EAAE,EACT,CAACd,IAAI,CAACe,WAAW,CAAC,CAAC,GAAG,EAAE,EAAEC,MAAM,CAAC,CAAC,GAAGH,MAAM,CAACC,EAAE,CAACG,MAAM,CACvD,CAAC;IACH;IAEA,KAAK,IAAIC,CAAC,IAAIhB,CAAC,EAAE;MACf,IAAI,IAAIW,MAAM,CAAC,GAAG,GAAGK,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,CAACP,IAAI,CAACV,GAAG,CAAC,EAAE;QAC5CA,GAAG,GAAGA,GAAG,CAACW,OAAO,CACfC,MAAM,CAACC,EAAE,EACT,CAACD,MAAM,CAACC,EAAE,CAACG,MAAM,KAAK,CAAC,GACnBf,CAAC,CAACgB,CAAC,CAAC,GACJ,CAAC,IAAI,GAAGhB,CAAC,CAACgB,CAAC,CAAC,EAAEF,MAAM,CAAC,CAAC,EAAE,GAAGd,CAAC,CAACgB,CAAC,CAAC,EAAED,MAAM,CAAC,EAC1CjC,QAAQ,CAAC,CACb,CAAC;MACH;IACF;IACA,OAAOiB,GAAG;EACZ,CAAC;EAEDkB,OAAO,EAAGpC,MAAW,IACnBD,cAAc,CAACC,MAAM,CAAC,GAClBE,MAAM,CAACmC,IAAI,CAACrC,MAAM,CAAC,CAACsC,MAAM,CACxB,CAACC,MAAM,EAAEC,GAAG,MAAM;IAChB,GAAGD,MAAM;IACT,CAACC,GAAG,GAAGnC,QAAQ,CAACL,MAAM,CAACwC,GAAG,CAAC;EAC7B,CAAC,CAAC,EACF,CAAC,CACH,CAAC,GACDnC,QAAQ,CAACL,MAAM,CAAC;EAEtByC,SAAS,EAAGC,KAAa,IAAK;IAC5B,OAAO,mBAAmB,CAACd,IAAI,CAACc,KAAK,CAAC;EACxC,CAAC;EAEDC,WAAW,EAAGC,GAAW,IAAK;IAC5B,OAAOA,GAAG,CAACC,UAAU,CAAC,MAAM,CAAC;EAC/B,CAAC;EAEDC,iBAAiB,EAAGC,GAAW,IAAK;IAAA,IAAAC,WAAA;IAClC,QAAAA,WAAA,GAAOD,GAAG,CAACE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,cAAAD,WAAA,gBAAAA,WAAA,GAApBA,WAAA,CAAsBC,KAAK,CAAC,GAAG,CAAC,cAAAD,WAAA,gBAAAA,WAAA,GAAhCA,WAAA,CAAkCE,GAAG,CAAC,CAAC,cAAAF,WAAA,uBAAvCA,WAAA,CAAyCG,IAAI,CAAC,CAAC;EACxD,CAAC;EAEDC,gBAAgB,EAAEA,CAAA,KAAM;IACtB,IAAIC,SAAS,GAAG,CAAE,IAAIC,IAAI,CAAC,CAAC,CAACC,OAAO,CAAC,CAAC,GAAG,IAAI,GAAI,CAAC,EAAEtD,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,OACEoD,SAAS,GACT,kBAAkB,CAACxB,OAAO,CAAC,MAAM,EAAE,YAAY;MAC7C,OAAO,CAAEJ,IAAI,CAAC+B,MAAM,CAAC,CAAC,GAAG,EAAE,GAAI,CAAC,EAAEvD,QAAQ,CAAC,EAAE,CAAC,CAACwD,WAAW,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC;EAEN,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,aAAa,EAAE,SAAAA,CAACC,KAAa,EAAyB;IAAA,IAAvBC,EAAE,GAAAC,SAAA,CAAA3B,MAAA,QAAA2B,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,KAAK;IAAA,IAAEE,EAAE,GAAAF,SAAA,CAAA3B,MAAA,QAAA2B,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,CAAC;IAC/C,MAAMG,MAAM,GAAGJ,EAAE,GAAG,IAAI,GAAG,IAAI;IAE/B,IAAInC,IAAI,CAACwC,GAAG,CAACN,KAAK,CAAC,GAAGK,MAAM,EAAE;MAC5B,OAAOL,KAAK,GAAG,IAAI;IACrB;IAEA,MAAMO,KAAK,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;IAC9D,IAAIC,CAAC,GAAG,CAAC,CAAC;IACV,MAAMC,CAAC,GAAG,EAAE,IAAIL,EAAE;IAElB,GAAG;MACDJ,KAAK,IAAIK,MAAM;MACf,EAAEG,CAAC;IACL,CAAC,QACC1C,IAAI,CAAC4C,KAAK,CAAC5C,IAAI,CAACwC,GAAG,CAACN,KAAK,CAAC,GAAGS,CAAC,CAAC,GAAGA,CAAC,IAAIJ,MAAM,IAC7CG,CAAC,GAAGD,KAAK,CAAChC,MAAM,GAAG,CAAC;IAGtB,OAAOyB,KAAK,CAACW,OAAO,CAACP,EAAE,CAAC,GAAG,GAAG,GAAGG,KAAK,CAACC,CAAC,CAAC;EAC3C,CAAC;EAEDI,cAAc,EAAEA,CAAA,KAAM;IACpB,MAAM,GAAGC,QAAQ,CAAC,GAAG,IAAAC,eAAQ,EAAC,CAAC,CAAC;IAChC,OAAO,MAAMD,QAAQ,CAAE9B,KAAK,IAAKA,KAAK,GAAG,CAAC,CAAC;EAC7C,CAAC;EAEDgC,SAAS,EAAGC,KAAa,IAAK;IAC5BC,+BAAK,CAACC,eAAe,CAACF,KAAK,EAAEC,+BAAK,CAACE,KAAK,EAAEF,+BAAK,CAACG,MAAM,CAAC;EACzD,CAAC;EAEDC,gBAAgB,EAAEA,CAAA,KAAM;IACtBC,sBAAU,CAACC,MAAM,CAAC,aAAa,CAAC;IAChC,IAAIC,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzBC,oBAAO,CAACC,UAAU,CAAC,cAAc,CAAC,CAACC,IAAI,CAAEC,SAAS,IAAK;QACrD,IAAIA,SAAS,EAAE;UACbH,oBAAO,CAACI,OAAO,CAAC9F,aAAa,CAAC+F,YAAY,CAAC;QAC7C;MACF,CAAC,CAAC;IACJ,CAAC,MAAM;MACL,IAAIC,0BAAa,CAACC,wBAAwB,EAAE;QAC1CD,0BAAa,CAACC,wBAAwB,CAACC,kBAAkB,CACvD,oBAAoB,EACnBC,WAAoB,IAAK;UACxB,IAAIA,WAAW,EAAE;YACf,IAAIH,0BAAa,CAACC,wBAAwB,CAACG,UAAU,EAAE;cACrDJ,0BAAa,CAACC,wBAAwB,CAACG,UAAU,CAC/CpG,aAAa,CAACqG,kBAAkB,EAChC,oBAAoB,EACpB,6CACF,CAAC;YACH,CAAC,MAAM;cACLtF,IAAI,CAACgE,SAAS,CAAC,UAAU,CAAC;cAC1BW,oBAAO,CAACI,OAAO,CAAC9F,aAAa,CAACsG,kBAAkB,CAAC;YACnD;UACF,CAAC,MAAM;YACLvF,IAAI,CAACgE,SAAS,CAAC,WAAW,CAAC;UAC7B;QACF,CACF,CAAC;MACH;IACF;EACF,CAAC;EAEDwB,SAAS,EAAEA,CAAA,KAAM;IACf,IAAIf,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzBC,oBAAO,CAACC,UAAU,CAAC,cAAc,CAAC,CAACC,IAAI,CAAEC,SAAS,IAAK;QACrD,IAAIA,SAAS,EAAE;UACbH,oBAAO,CAACI,OAAO,CAAC9F,aAAa,CAACwG,cAAc,CAAC;QAC/C;MACF,CAAC,CAAC;IACJ,CAAC,MAAM;MACLd,oBAAO,CAACI,OAAO,CAAC9F,aAAa,CAACyG,UAAU,CAAC;IAC3C;EACF,CAAC;EAEDC,QAAQ,EAAE,MAAOC,IAAY,IAAK;IAChC,IAAI,CAACC,OAAO,EAAE;MACZ,MAAMC,KAAK,CAAC7G,aAAa,CAAC8G,WAAW,GAAGC,kBAAkB,CAACJ,IAAI,CAAC,CAAC;IACnE;EACF;AACF,CAAC"}
1
+ {"version":3,"names":["_cameraroll","_interopRequireDefault","require","_react","_reactNative","_reactNativeSimpleToast","_rnFetchBlob","_ReportUtil","obj","__esModule","default","ToolkitConfig","exports","initToolkitConfig","config","_isPlainObject","target","toString","Object","getPrototypeOf","prototype","_jsonify","toJSON","Array","isArray","map","_hasAndroidWritePermission","permission","PermissionsAndroid","PERMISSIONS","WRITE_EXTERNAL_STORAGE","hasPermission","check","status","request","Tool","sleep","delay","Promise","resolve","setTimeout","formatDate","date","fmt","o","getMonth","getDate","getHours","getMinutes","getSeconds","Math","floor","getMilliseconds","test","replace","RegExp","$1","getFullYear","substr","length","k","jsonify","keys","reduce","result","key","isChinese","value","isRemoteURL","str","startsWith","get_url_extension","url","_url$split$","split","pop","trim","generateObjectId","timestamp","Date","getTime","random","toLowerCase","humanFileSize","bytes","si","arguments","undefined","dp","thresh","abs","units","u","r","round","toFixed","useForceUpdate","setValue","useState","showToast","toast","Toast","showWithGravity","SHORT","CENTER","goAppStoreReview","ReportUtil","report","Platform","OS","Linking","canOpenURL","then","supported","openURL","iOSReviewUrl","NativeModules","CheckPackageInstallation","isPackageInstalled","isInstalled","goToMarket","AndroidPackageName","AndroidStoreScheme","goUpgrade","iOSStoreScheme","AppWebsite","notifyMe","text","__DEV__","fetch","PushDeerUrl","encodeURIComponent","savePicture","albumName","console","log","errorCode","CameraRoll","save","type","album","AppName","error","errMsg","JSON","stringify","extension","res","RNFetchBlob","fileCache","appendExt","path","e1"],"sources":["Tool.ts"],"sourcesContent":["import CameraRoll from '@react-native-community/cameraroll';\nimport { useState } from 'react';\nimport {\n Linking,\n NativeModules,\n PermissionsAndroid,\n Platform,\n} from 'react-native';\nimport Toast from 'react-native-simple-toast';\nimport RNFetchBlob from 'rn-fetch-blob';\nimport { ReportUtil } from './ReportUtil';\n\nexport interface ToolkitConfigType {\n iOSStoreUrl: string;\n AndroidStoreUrl: string;\n iOSStoreScheme: string;\n AndroidStoreScheme: string;\n iOSReviewUrl: string;\n AndroidPackageName: string;\n\n AppName: string;\n AppWebsite: string;\n\n PolicyUrl: string;\n TermsUrl: string;\n\n PushDeerUrl: string;\n\n RC_API_KEY: string;\n RC_ENTITLEMENT_ID: string;\n WeChatPayServer: string;\n WeiXinId: string;\n WeiXinSecret: string;\n}\n\nexport let ToolkitConfig: ToolkitConfigType;\n\nexport const initToolkitConfig = (config: ToolkitConfigType) => {\n ToolkitConfig = config;\n};\n\nconst _isPlainObject = (target: any) => {\n return (\n target &&\n target.toString() === '[object Object]' &&\n Object.getPrototypeOf(target) === Object.prototype\n );\n};\n\nconst _jsonify = (target: any): any => {\n if (target && typeof target.toJSON === 'function') return target.toJSON();\n // map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一次提供的函数后的返回值\n if (Array.isArray(target)) return target.map(_jsonify);\n return target;\n};\n\nconst _hasAndroidWritePermission = async () => {\n const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;\n\n const hasPermission = await PermissionsAndroid.check(permission);\n if (hasPermission) {\n return true;\n }\n\n const status = await PermissionsAndroid.request(permission);\n return status === 'granted';\n};\n\nexport const Tool = {\n sleep: (delay: number) =>\n new Promise((resolve) => setTimeout(resolve, delay)),\n\n formatDate(date: Date, fmt: string): string {\n fmt = fmt ? fmt : 'yyyy-MM-dd';\n var o: { [key: string]: number } = {\n 'M+': date.getMonth() + 1, //月份\n 'd+': date.getDate(), //日\n 'h+': date.getHours(), //小时\n 'm+': date.getMinutes(), //分\n 's+': date.getSeconds(), //秒\n 'q+': Math.floor((date.getMonth() + 3) / 3), //季度\n 'S': date.getMilliseconds(), //毫秒\n };\n\n // 获取年份\n if (/(y+)/i.test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (date.getFullYear() + '').substr(4 - RegExp.$1.length)\n );\n }\n\n for (var k in o) {\n if (new RegExp('(' + k + ')', 'i').test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (RegExp.$1.length === 1\n ? o[k]\n : ('00' + o[k]).substr(('' + o[k]).length)\n ).toString()\n );\n }\n }\n return fmt;\n },\n\n jsonify: (target: any) =>\n _isPlainObject(target)\n ? Object.keys(target).reduce(\n (result, key) => ({\n ...result,\n [key]: _jsonify(target[key]),\n }),\n {}\n )\n : _jsonify(target),\n\n isChinese: (value: string) => {\n return /[\\u4E00-\\u9FA5]+/g.test(value);\n },\n\n isRemoteURL: (str: string) => {\n return str.startsWith('http');\n },\n\n get_url_extension: (url: string) => {\n return url.split(/[#?]/)[0]?.split('.')?.pop()?.trim();\n },\n\n generateObjectId: () => {\n var timestamp = ((new Date().getTime() / 1000) | 0).toString(16); // eslint-disable-line no-bitwise\n return (\n timestamp +\n 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {\n return ((Math.random() * 16) | 0).toString(16).toLowerCase(); // eslint-disable-line no-bitwise\n })\n );\n },\n\n /**\n * Format bytes as human-readable text.\n *\n * @param bytes Number of bytes.\n * @param si True to use metric (SI) units, aka powers of 1000. False to use\n * binary (IEC), aka powers of 1024.\n * @param dp Number of decimal places to display.\n *\n * @return Formatted string.\n */\n humanFileSize: (bytes: number, si = false, dp = 1) => {\n const thresh = si ? 1000 : 1024;\n\n if (Math.abs(bytes) < thresh) {\n return bytes + ' B';\n }\n\n const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n let u = -1;\n const r = 10 ** dp;\n\n do {\n bytes /= thresh;\n ++u;\n } while (\n Math.round(Math.abs(bytes) * r) / r >= thresh &&\n u < units.length - 1\n );\n\n return bytes.toFixed(dp) + ' ' + units[u];\n },\n\n useForceUpdate: () => {\n const [, setValue] = useState(0);\n return () => setValue((value) => value + 1);\n },\n\n showToast: (toast: string) => {\n Toast.showWithGravity(toast, Toast.SHORT, Toast.CENTER);\n },\n\n goAppStoreReview: () => {\n ReportUtil.report('StoreReview');\n if (Platform.OS === 'ios') {\n Linking.canOpenURL('itms-apps://').then((supported) => {\n if (supported) {\n Linking.openURL(ToolkitConfig.iOSReviewUrl);\n }\n });\n } else {\n if (NativeModules.CheckPackageInstallation) {\n NativeModules.CheckPackageInstallation.isPackageInstalled(\n 'com.coolapk.market',\n (isInstalled: boolean) => {\n if (isInstalled) {\n if (NativeModules.CheckPackageInstallation.goToMarket) {\n NativeModules.CheckPackageInstallation.goToMarket(\n ToolkitConfig.AndroidPackageName,\n 'com.coolapk.market',\n 'com.coolapk.market.activity.AppViewActivity'\n );\n } else {\n Tool.showToast('请用酷安市场打开');\n Linking.openURL(ToolkitConfig.AndroidStoreScheme);\n }\n } else {\n Tool.showToast('需要先安装酷安市场');\n }\n }\n );\n }\n }\n },\n\n goUpgrade: () => {\n if (Platform.OS === 'ios') {\n Linking.canOpenURL('itms-apps://').then((supported) => {\n if (supported) {\n Linking.openURL(ToolkitConfig.iOSStoreScheme);\n }\n });\n } else {\n Linking.openURL(ToolkitConfig.AppWebsite);\n }\n },\n\n notifyMe: async (text: string) => {\n if (!__DEV__) {\n await fetch(ToolkitConfig.PushDeerUrl + encodeURIComponent(text));\n }\n },\n\n savePicture: async (url: string, albumName?: string) => {\n console.log('savePicture', url);\n\n // 检查权限\n if (Platform.OS === 'android' && !(await _hasAndroidWritePermission())) {\n return { errorCode: -1 };\n }\n\n // iOS 或本地图片直接保存\n if (Platform.OS === 'ios' || !Tool.isRemoteURL(url)) {\n try {\n await CameraRoll.save(url, {\n type: 'photo',\n album: albumName ?? ToolkitConfig.AppName,\n });\n return { errorCode: 0 };\n } catch (error: any) {\n console.error(error);\n return { errorCode: -2, errMsg: JSON.stringify(error) };\n }\n }\n\n // 安卓远程图片需要下载\n const extension = Tool.get_url_extension(url);\n try {\n const res = await RNFetchBlob.config({\n fileCache: true,\n appendExt: extension,\n }).fetch('GET', url, {});\n // the temp file path\n console.log('The file saved to ', res.path());\n try {\n await CameraRoll.save('file://' + res.path(), {\n type: 'photo',\n album: albumName,\n });\n return { errorCode: 0 };\n } catch (e1) {\n console.error(e1 + '\\n' + res.path());\n return { errorCode: -3, errMsg: JSON.stringify(e1) };\n }\n } catch (error) {\n console.error(error);\n return { errorCode: -4, errMsg: JSON.stringify(error) };\n }\n },\n};\n"],"mappings":";;;;;;AAAA,IAAAA,WAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,YAAA,GAAAF,OAAA;AAMA,IAAAG,uBAAA,GAAAJ,sBAAA,CAAAC,OAAA;AACA,IAAAI,YAAA,GAAAL,sBAAA,CAAAC,OAAA;AACA,IAAAK,WAAA,GAAAL,OAAA;AAA0C,SAAAD,uBAAAO,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAyBnC,IAAIG,aAAgC,GAAAC,OAAA,CAAAD,aAAA;AAEpC,MAAME,iBAAiB,GAAIC,MAAyB,IAAK;EAC9DF,OAAA,CAAAD,aAAA,GAAAA,aAAa,GAAGG,MAAM;AACxB,CAAC;AAACF,OAAA,CAAAC,iBAAA,GAAAA,iBAAA;AAEF,MAAME,cAAc,GAAIC,MAAW,IAAK;EACtC,OACEA,MAAM,IACNA,MAAM,CAACC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,IACvCC,MAAM,CAACC,cAAc,CAACH,MAAM,CAAC,KAAKE,MAAM,CAACE,SAAS;AAEtD,CAAC;AAED,MAAMC,QAAQ,GAAIL,MAAW,IAAU;EACrC,IAAIA,MAAM,IAAI,OAAOA,MAAM,CAACM,MAAM,KAAK,UAAU,EAAE,OAAON,MAAM,CAACM,MAAM,CAAC,CAAC;EACzE;EACA,IAAIC,KAAK,CAACC,OAAO,CAACR,MAAM,CAAC,EAAE,OAAOA,MAAM,CAACS,GAAG,CAACJ,QAAQ,CAAC;EACtD,OAAOL,MAAM;AACf,CAAC;AAED,MAAMU,0BAA0B,GAAG,MAAAA,CAAA,KAAY;EAC7C,MAAMC,UAAU,GAAGC,+BAAkB,CAACC,WAAW,CAACC,sBAAsB;EAExE,MAAMC,aAAa,GAAG,MAAMH,+BAAkB,CAACI,KAAK,CAACL,UAAU,CAAC;EAChE,IAAII,aAAa,EAAE;IACjB,OAAO,IAAI;EACb;EAEA,MAAME,MAAM,GAAG,MAAML,+BAAkB,CAACM,OAAO,CAACP,UAAU,CAAC;EAC3D,OAAOM,MAAM,KAAK,SAAS;AAC7B,CAAC;AAEM,MAAME,IAAI,GAAAvB,OAAA,CAAAuB,IAAA,GAAG;EAClBC,KAAK,EAAGC,KAAa,IACnB,IAAIC,OAAO,CAAEC,OAAO,IAAKC,UAAU,CAACD,OAAO,EAAEF,KAAK,CAAC,CAAC;EAEtDI,UAAUA,CAACC,IAAU,EAAEC,GAAW,EAAU;IAC1CA,GAAG,GAAGA,GAAG,GAAGA,GAAG,GAAG,YAAY;IAC9B,IAAIC,CAA4B,GAAG;MACjC,IAAI,EAAEF,IAAI,CAACG,QAAQ,CAAC,CAAC,GAAG,CAAC;MAAE;MAC3B,IAAI,EAAEH,IAAI,CAACI,OAAO,CAAC,CAAC;MAAE;MACtB,IAAI,EAAEJ,IAAI,CAACK,QAAQ,CAAC,CAAC;MAAE;MACvB,IAAI,EAAEL,IAAI,CAACM,UAAU,CAAC,CAAC;MAAE;MACzB,IAAI,EAAEN,IAAI,CAACO,UAAU,CAAC,CAAC;MAAE;MACzB,IAAI,EAAEC,IAAI,CAACC,KAAK,CAAC,CAACT,IAAI,CAACG,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;MAAE;MAC7C,GAAG,EAAEH,IAAI,CAACU,eAAe,CAAC,CAAC,CAAE;IAC/B,CAAC;;IAED;IACA,IAAI,OAAO,CAACC,IAAI,CAACV,GAAG,CAAC,EAAE;MACrBA,GAAG,GAAGA,GAAG,CAACW,OAAO,CACfC,MAAM,CAACC,EAAE,EACT,CAACd,IAAI,CAACe,WAAW,CAAC,CAAC,GAAG,EAAE,EAAEC,MAAM,CAAC,CAAC,GAAGH,MAAM,CAACC,EAAE,CAACG,MAAM,CACvD,CAAC;IACH;IAEA,KAAK,IAAIC,CAAC,IAAIhB,CAAC,EAAE;MACf,IAAI,IAAIW,MAAM,CAAC,GAAG,GAAGK,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,CAACP,IAAI,CAACV,GAAG,CAAC,EAAE;QAC5CA,GAAG,GAAGA,GAAG,CAACW,OAAO,CACfC,MAAM,CAACC,EAAE,EACT,CAACD,MAAM,CAACC,EAAE,CAACG,MAAM,KAAK,CAAC,GACnBf,CAAC,CAACgB,CAAC,CAAC,GACJ,CAAC,IAAI,GAAGhB,CAAC,CAACgB,CAAC,CAAC,EAAEF,MAAM,CAAC,CAAC,EAAE,GAAGd,CAAC,CAACgB,CAAC,CAAC,EAAED,MAAM,CAAC,EAC1C1C,QAAQ,CAAC,CACb,CAAC;MACH;IACF;IACA,OAAO0B,GAAG;EACZ,CAAC;EAEDkB,OAAO,EAAG7C,MAAW,IACnBD,cAAc,CAACC,MAAM,CAAC,GAClBE,MAAM,CAAC4C,IAAI,CAAC9C,MAAM,CAAC,CAAC+C,MAAM,CACxB,CAACC,MAAM,EAAEC,GAAG,MAAM;IAChB,GAAGD,MAAM;IACT,CAACC,GAAG,GAAG5C,QAAQ,CAACL,MAAM,CAACiD,GAAG,CAAC;EAC7B,CAAC,CAAC,EACF,CAAC,CACH,CAAC,GACD5C,QAAQ,CAACL,MAAM,CAAC;EAEtBkD,SAAS,EAAGC,KAAa,IAAK;IAC5B,OAAO,mBAAmB,CAACd,IAAI,CAACc,KAAK,CAAC;EACxC,CAAC;EAEDC,WAAW,EAAGC,GAAW,IAAK;IAC5B,OAAOA,GAAG,CAACC,UAAU,CAAC,MAAM,CAAC;EAC/B,CAAC;EAEDC,iBAAiB,EAAGC,GAAW,IAAK;IAAA,IAAAC,WAAA;IAClC,QAAAA,WAAA,GAAOD,GAAG,CAACE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,cAAAD,WAAA,gBAAAA,WAAA,GAApBA,WAAA,CAAsBC,KAAK,CAAC,GAAG,CAAC,cAAAD,WAAA,gBAAAA,WAAA,GAAhCA,WAAA,CAAkCE,GAAG,CAAC,CAAC,cAAAF,WAAA,uBAAvCA,WAAA,CAAyCG,IAAI,CAAC,CAAC;EACxD,CAAC;EAEDC,gBAAgB,EAAEA,CAAA,KAAM;IACtB,IAAIC,SAAS,GAAG,CAAE,IAAIC,IAAI,CAAC,CAAC,CAACC,OAAO,CAAC,CAAC,GAAG,IAAI,GAAI,CAAC,EAAE/D,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,OACE6D,SAAS,GACT,kBAAkB,CAACxB,OAAO,CAAC,MAAM,EAAE,YAAY;MAC7C,OAAO,CAAEJ,IAAI,CAAC+B,MAAM,CAAC,CAAC,GAAG,EAAE,GAAI,CAAC,EAAEhE,QAAQ,CAAC,EAAE,CAAC,CAACiE,WAAW,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC;EAEN,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,aAAa,EAAE,SAAAA,CAACC,KAAa,EAAyB;IAAA,IAAvBC,EAAE,GAAAC,SAAA,CAAA3B,MAAA,QAAA2B,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,KAAK;IAAA,IAAEE,EAAE,GAAAF,SAAA,CAAA3B,MAAA,QAAA2B,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,CAAC;IAC/C,MAAMG,MAAM,GAAGJ,EAAE,GAAG,IAAI,GAAG,IAAI;IAE/B,IAAInC,IAAI,CAACwC,GAAG,CAACN,KAAK,CAAC,GAAGK,MAAM,EAAE;MAC5B,OAAOL,KAAK,GAAG,IAAI;IACrB;IAEA,MAAMO,KAAK,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;IAC9D,IAAIC,CAAC,GAAG,CAAC,CAAC;IACV,MAAMC,CAAC,GAAG,EAAE,IAAIL,EAAE;IAElB,GAAG;MACDJ,KAAK,IAAIK,MAAM;MACf,EAAEG,CAAC;IACL,CAAC,QACC1C,IAAI,CAAC4C,KAAK,CAAC5C,IAAI,CAACwC,GAAG,CAACN,KAAK,CAAC,GAAGS,CAAC,CAAC,GAAGA,CAAC,IAAIJ,MAAM,IAC7CG,CAAC,GAAGD,KAAK,CAAChC,MAAM,GAAG,CAAC;IAGtB,OAAOyB,KAAK,CAACW,OAAO,CAACP,EAAE,CAAC,GAAG,GAAG,GAAGG,KAAK,CAACC,CAAC,CAAC;EAC3C,CAAC;EAEDI,cAAc,EAAEA,CAAA,KAAM;IACpB,MAAM,GAAGC,QAAQ,CAAC,GAAG,IAAAC,eAAQ,EAAC,CAAC,CAAC;IAChC,OAAO,MAAMD,QAAQ,CAAE9B,KAAK,IAAKA,KAAK,GAAG,CAAC,CAAC;EAC7C,CAAC;EAEDgC,SAAS,EAAGC,KAAa,IAAK;IAC5BC,+BAAK,CAACC,eAAe,CAACF,KAAK,EAAEC,+BAAK,CAACE,KAAK,EAAEF,+BAAK,CAACG,MAAM,CAAC;EACzD,CAAC;EAEDC,gBAAgB,EAAEA,CAAA,KAAM;IACtBC,sBAAU,CAACC,MAAM,CAAC,aAAa,CAAC;IAChC,IAAIC,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzBC,oBAAO,CAACC,UAAU,CAAC,cAAc,CAAC,CAACC,IAAI,CAAEC,SAAS,IAAK;QACrD,IAAIA,SAAS,EAAE;UACbH,oBAAO,CAACI,OAAO,CAACvG,aAAa,CAACwG,YAAY,CAAC;QAC7C;MACF,CAAC,CAAC;IACJ,CAAC,MAAM;MACL,IAAIC,0BAAa,CAACC,wBAAwB,EAAE;QAC1CD,0BAAa,CAACC,wBAAwB,CAACC,kBAAkB,CACvD,oBAAoB,EACnBC,WAAoB,IAAK;UACxB,IAAIA,WAAW,EAAE;YACf,IAAIH,0BAAa,CAACC,wBAAwB,CAACG,UAAU,EAAE;cACrDJ,0BAAa,CAACC,wBAAwB,CAACG,UAAU,CAC/C7G,aAAa,CAAC8G,kBAAkB,EAChC,oBAAoB,EACpB,6CACF,CAAC;YACH,CAAC,MAAM;cACLtF,IAAI,CAACgE,SAAS,CAAC,UAAU,CAAC;cAC1BW,oBAAO,CAACI,OAAO,CAACvG,aAAa,CAAC+G,kBAAkB,CAAC;YACnD;UACF,CAAC,MAAM;YACLvF,IAAI,CAACgE,SAAS,CAAC,WAAW,CAAC;UAC7B;QACF,CACF,CAAC;MACH;IACF;EACF,CAAC;EAEDwB,SAAS,EAAEA,CAAA,KAAM;IACf,IAAIf,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzBC,oBAAO,CAACC,UAAU,CAAC,cAAc,CAAC,CAACC,IAAI,CAAEC,SAAS,IAAK;QACrD,IAAIA,SAAS,EAAE;UACbH,oBAAO,CAACI,OAAO,CAACvG,aAAa,CAACiH,cAAc,CAAC;QAC/C;MACF,CAAC,CAAC;IACJ,CAAC,MAAM;MACLd,oBAAO,CAACI,OAAO,CAACvG,aAAa,CAACkH,UAAU,CAAC;IAC3C;EACF,CAAC;EAEDC,QAAQ,EAAE,MAAOC,IAAY,IAAK;IAChC,IAAI,CAACC,OAAO,EAAE;MACZ,MAAMC,KAAK,CAACtH,aAAa,CAACuH,WAAW,GAAGC,kBAAkB,CAACJ,IAAI,CAAC,CAAC;IACnE;EACF,CAAC;EAEDK,WAAW,EAAE,MAAAA,CAAO5D,GAAW,EAAE6D,SAAkB,KAAK;IACtDC,OAAO,CAACC,GAAG,CAAC,aAAa,EAAE/D,GAAG,CAAC;;IAE/B;IACA,IAAIoC,qBAAQ,CAACC,EAAE,KAAK,SAAS,IAAI,EAAE,MAAMnF,0BAA0B,CAAC,CAAC,CAAC,EAAE;MACtE,OAAO;QAAE8G,SAAS,EAAE,CAAC;MAAE,CAAC;IAC1B;;IAEA;IACA,IAAI5B,qBAAQ,CAACC,EAAE,KAAK,KAAK,IAAI,CAAC1E,IAAI,CAACiC,WAAW,CAACI,GAAG,CAAC,EAAE;MACnD,IAAI;QACF,MAAMiE,mBAAU,CAACC,IAAI,CAAClE,GAAG,EAAE;UACzBmE,IAAI,EAAE,OAAO;UACbC,KAAK,EAAEP,SAAS,aAATA,SAAS,cAATA,SAAS,GAAI1H,aAAa,CAACkI;QACpC,CAAC,CAAC;QACF,OAAO;UAAEL,SAAS,EAAE;QAAE,CAAC;MACzB,CAAC,CAAC,OAAOM,KAAU,EAAE;QACnBR,OAAO,CAACQ,KAAK,CAACA,KAAK,CAAC;QACpB,OAAO;UAAEN,SAAS,EAAE,CAAC,CAAC;UAAEO,MAAM,EAAEC,IAAI,CAACC,SAAS,CAACH,KAAK;QAAE,CAAC;MACzD;IACF;;IAEA;IACA,MAAMI,SAAS,GAAG/G,IAAI,CAACoC,iBAAiB,CAACC,GAAG,CAAC;IAC7C,IAAI;MACF,MAAM2E,GAAG,GAAG,MAAMC,oBAAW,CAACtI,MAAM,CAAC;QACnCuI,SAAS,EAAE,IAAI;QACfC,SAAS,EAAEJ;MACb,CAAC,CAAC,CAACjB,KAAK,CAAC,KAAK,EAAEzD,GAAG,EAAE,CAAC,CAAC,CAAC;MACxB;MACA8D,OAAO,CAACC,GAAG,CAAC,oBAAoB,EAAEY,GAAG,CAACI,IAAI,CAAC,CAAC,CAAC;MAC7C,IAAI;QACF,MAAMd,mBAAU,CAACC,IAAI,CAAC,SAAS,GAAGS,GAAG,CAACI,IAAI,CAAC,CAAC,EAAE;UAC5CZ,IAAI,EAAE,OAAO;UACbC,KAAK,EAAEP;QACT,CAAC,CAAC;QACF,OAAO;UAAEG,SAAS,EAAE;QAAE,CAAC;MACzB,CAAC,CAAC,OAAOgB,EAAE,EAAE;QACXlB,OAAO,CAACQ,KAAK,CAACU,EAAE,GAAG,IAAI,GAAGL,GAAG,CAACI,IAAI,CAAC,CAAC,CAAC;QACrC,OAAO;UAAEf,SAAS,EAAE,CAAC,CAAC;UAAEO,MAAM,EAAEC,IAAI,CAACC,SAAS,CAACO,EAAE;QAAE,CAAC;MACtD;IACF,CAAC,CAAC,OAAOV,KAAK,EAAE;MACdR,OAAO,CAACQ,KAAK,CAACA,KAAK,CAAC;MACpB,OAAO;QAAEN,SAAS,EAAE,CAAC,CAAC;QAAEO,MAAM,EAAEC,IAAI,CAACC,SAAS,CAACH,KAAK;MAAE,CAAC;IACzD;EACF;AACF,CAAC"}
@@ -1,6 +1,8 @@
1
+ import CameraRoll from '@react-native-community/cameraroll';
1
2
  import { useState } from 'react';
2
- import { Linking, NativeModules, Platform } from 'react-native';
3
+ import { Linking, NativeModules, PermissionsAndroid, Platform } from 'react-native';
3
4
  import Toast from 'react-native-simple-toast';
5
+ import RNFetchBlob from 'rn-fetch-blob';
4
6
  import { ReportUtil } from './ReportUtil';
5
7
  export let ToolkitConfig;
6
8
  export const initToolkitConfig = config => {
@@ -15,6 +17,15 @@ const _jsonify = target => {
15
17
  if (Array.isArray(target)) return target.map(_jsonify);
16
18
  return target;
17
19
  };
20
+ const _hasAndroidWritePermission = async () => {
21
+ const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;
22
+ const hasPermission = await PermissionsAndroid.check(permission);
23
+ if (hasPermission) {
24
+ return true;
25
+ }
26
+ const status = await PermissionsAndroid.request(permission);
27
+ return status === 'granted';
28
+ };
18
29
  export const Tool = {
19
30
  sleep: delay => new Promise(resolve => setTimeout(resolve, delay)),
20
31
  formatDate(date, fmt) {
@@ -140,6 +151,67 @@ export const Tool = {
140
151
  if (!__DEV__) {
141
152
  await fetch(ToolkitConfig.PushDeerUrl + encodeURIComponent(text));
142
153
  }
154
+ },
155
+ savePicture: async (url, albumName) => {
156
+ console.log('savePicture', url);
157
+
158
+ // 检查权限
159
+ if (Platform.OS === 'android' && !(await _hasAndroidWritePermission())) {
160
+ return {
161
+ errorCode: -1
162
+ };
163
+ }
164
+
165
+ // iOS 或本地图片直接保存
166
+ if (Platform.OS === 'ios' || !Tool.isRemoteURL(url)) {
167
+ try {
168
+ await CameraRoll.save(url, {
169
+ type: 'photo',
170
+ album: albumName !== null && albumName !== void 0 ? albumName : ToolkitConfig.AppName
171
+ });
172
+ return {
173
+ errorCode: 0
174
+ };
175
+ } catch (error) {
176
+ console.error(error);
177
+ return {
178
+ errorCode: -2,
179
+ errMsg: JSON.stringify(error)
180
+ };
181
+ }
182
+ }
183
+
184
+ // 安卓远程图片需要下载
185
+ const extension = Tool.get_url_extension(url);
186
+ try {
187
+ const res = await RNFetchBlob.config({
188
+ fileCache: true,
189
+ appendExt: extension
190
+ }).fetch('GET', url, {});
191
+ // the temp file path
192
+ console.log('The file saved to ', res.path());
193
+ try {
194
+ await CameraRoll.save('file://' + res.path(), {
195
+ type: 'photo',
196
+ album: albumName
197
+ });
198
+ return {
199
+ errorCode: 0
200
+ };
201
+ } catch (e1) {
202
+ console.error(e1 + '\n' + res.path());
203
+ return {
204
+ errorCode: -3,
205
+ errMsg: JSON.stringify(e1)
206
+ };
207
+ }
208
+ } catch (error) {
209
+ console.error(error);
210
+ return {
211
+ errorCode: -4,
212
+ errMsg: JSON.stringify(error)
213
+ };
214
+ }
143
215
  }
144
216
  };
145
217
  //# sourceMappingURL=Tool.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useState","Linking","NativeModules","Platform","Toast","ReportUtil","ToolkitConfig","initToolkitConfig","config","_isPlainObject","target","toString","Object","getPrototypeOf","prototype","_jsonify","toJSON","Array","isArray","map","Tool","sleep","delay","Promise","resolve","setTimeout","formatDate","date","fmt","o","getMonth","getDate","getHours","getMinutes","getSeconds","Math","floor","getMilliseconds","test","replace","RegExp","$1","getFullYear","substr","length","k","jsonify","keys","reduce","result","key","isChinese","value","isRemoteURL","str","startsWith","get_url_extension","url","_url$split$","split","pop","trim","generateObjectId","timestamp","Date","getTime","random","toLowerCase","humanFileSize","bytes","si","arguments","undefined","dp","thresh","abs","units","u","r","round","toFixed","useForceUpdate","setValue","showToast","toast","showWithGravity","SHORT","CENTER","goAppStoreReview","report","OS","canOpenURL","then","supported","openURL","iOSReviewUrl","CheckPackageInstallation","isPackageInstalled","isInstalled","goToMarket","AndroidPackageName","AndroidStoreScheme","goUpgrade","iOSStoreScheme","AppWebsite","notifyMe","text","__DEV__","fetch","PushDeerUrl","encodeURIComponent"],"sources":["Tool.ts"],"sourcesContent":["import { useState } from 'react';\nimport { Linking, NativeModules, Platform } from 'react-native';\nimport Toast from 'react-native-simple-toast';\nimport { ReportUtil } from './ReportUtil';\n\nexport interface ToolkitConfigType {\n iOSStoreUrl: string;\n AndroidStoreUrl: string;\n iOSStoreScheme: string;\n AndroidStoreScheme: string;\n iOSReviewUrl: string;\n AndroidPackageName: string;\n\n AppWebsite: string;\n\n PolicyUrl: string;\n TermsUrl: string;\n\n PushDeerUrl: string;\n\n RC_API_KEY: string;\n RC_ENTITLEMENT_ID: string;\n WeChatPayServer: string;\n WeiXinId: string;\n WeiXinSecret: string;\n}\n\nexport let ToolkitConfig: ToolkitConfigType;\n\nexport const initToolkitConfig = (config: ToolkitConfigType) => {\n ToolkitConfig = config;\n};\n\nconst _isPlainObject = (target: any) => {\n return (\n target &&\n target.toString() === '[object Object]' &&\n Object.getPrototypeOf(target) === Object.prototype\n );\n};\n\nconst _jsonify = (target: any): any => {\n if (target && typeof target.toJSON === 'function') return target.toJSON();\n // map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一次提供的函数后的返回值\n if (Array.isArray(target)) return target.map(_jsonify);\n return target;\n};\n\nexport const Tool = {\n sleep: (delay: number) =>\n new Promise((resolve) => setTimeout(resolve, delay)),\n\n formatDate(date: Date, fmt: string): string {\n fmt = fmt ? fmt : 'yyyy-MM-dd';\n var o: { [key: string]: number } = {\n 'M+': date.getMonth() + 1, //月份\n 'd+': date.getDate(), //日\n 'h+': date.getHours(), //小时\n 'm+': date.getMinutes(), //分\n 's+': date.getSeconds(), //秒\n 'q+': Math.floor((date.getMonth() + 3) / 3), //季度\n 'S': date.getMilliseconds(), //毫秒\n };\n\n // 获取年份\n if (/(y+)/i.test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (date.getFullYear() + '').substr(4 - RegExp.$1.length)\n );\n }\n\n for (var k in o) {\n if (new RegExp('(' + k + ')', 'i').test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (RegExp.$1.length === 1\n ? o[k]\n : ('00' + o[k]).substr(('' + o[k]).length)\n ).toString()\n );\n }\n }\n return fmt;\n },\n\n jsonify: (target: any) =>\n _isPlainObject(target)\n ? Object.keys(target).reduce(\n (result, key) => ({\n ...result,\n [key]: _jsonify(target[key]),\n }),\n {}\n )\n : _jsonify(target),\n\n isChinese: (value: string) => {\n return /[\\u4E00-\\u9FA5]+/g.test(value);\n },\n\n isRemoteURL: (str: string) => {\n return str.startsWith('http');\n },\n\n get_url_extension: (url: string) => {\n return url.split(/[#?]/)[0]?.split('.')?.pop()?.trim();\n },\n\n generateObjectId: () => {\n var timestamp = ((new Date().getTime() / 1000) | 0).toString(16); // eslint-disable-line no-bitwise\n return (\n timestamp +\n 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {\n return ((Math.random() * 16) | 0).toString(16).toLowerCase(); // eslint-disable-line no-bitwise\n })\n );\n },\n\n /**\n * Format bytes as human-readable text.\n *\n * @param bytes Number of bytes.\n * @param si True to use metric (SI) units, aka powers of 1000. False to use\n * binary (IEC), aka powers of 1024.\n * @param dp Number of decimal places to display.\n *\n * @return Formatted string.\n */\n humanFileSize: (bytes: number, si = false, dp = 1) => {\n const thresh = si ? 1000 : 1024;\n\n if (Math.abs(bytes) < thresh) {\n return bytes + ' B';\n }\n\n const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n let u = -1;\n const r = 10 ** dp;\n\n do {\n bytes /= thresh;\n ++u;\n } while (\n Math.round(Math.abs(bytes) * r) / r >= thresh &&\n u < units.length - 1\n );\n\n return bytes.toFixed(dp) + ' ' + units[u];\n },\n\n useForceUpdate: () => {\n const [, setValue] = useState(0);\n return () => setValue((value) => value + 1);\n },\n\n showToast: (toast: string) => {\n Toast.showWithGravity(toast, Toast.SHORT, Toast.CENTER);\n },\n\n goAppStoreReview: () => {\n ReportUtil.report('StoreReview');\n if (Platform.OS === 'ios') {\n Linking.canOpenURL('itms-apps://').then((supported) => {\n if (supported) {\n Linking.openURL(ToolkitConfig.iOSReviewUrl);\n }\n });\n } else {\n if (NativeModules.CheckPackageInstallation) {\n NativeModules.CheckPackageInstallation.isPackageInstalled(\n 'com.coolapk.market',\n (isInstalled: boolean) => {\n if (isInstalled) {\n if (NativeModules.CheckPackageInstallation.goToMarket) {\n NativeModules.CheckPackageInstallation.goToMarket(\n ToolkitConfig.AndroidPackageName,\n 'com.coolapk.market',\n 'com.coolapk.market.activity.AppViewActivity'\n );\n } else {\n Tool.showToast('请用酷安市场打开');\n Linking.openURL(ToolkitConfig.AndroidStoreScheme);\n }\n } else {\n Tool.showToast('需要先安装酷安市场');\n }\n }\n );\n }\n }\n },\n\n goUpgrade: () => {\n if (Platform.OS === 'ios') {\n Linking.canOpenURL('itms-apps://').then((supported) => {\n if (supported) {\n Linking.openURL(ToolkitConfig.iOSStoreScheme);\n }\n });\n } else {\n Linking.openURL(ToolkitConfig.AppWebsite);\n }\n },\n\n notifyMe: async (text: string) => {\n if (!__DEV__) {\n await fetch(ToolkitConfig.PushDeerUrl + encodeURIComponent(text));\n }\n },\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["CameraRoll","useState","Linking","NativeModules","PermissionsAndroid","Platform","Toast","RNFetchBlob","ReportUtil","ToolkitConfig","initToolkitConfig","config","_isPlainObject","target","toString","Object","getPrototypeOf","prototype","_jsonify","toJSON","Array","isArray","map","_hasAndroidWritePermission","permission","PERMISSIONS","WRITE_EXTERNAL_STORAGE","hasPermission","check","status","request","Tool","sleep","delay","Promise","resolve","setTimeout","formatDate","date","fmt","o","getMonth","getDate","getHours","getMinutes","getSeconds","Math","floor","getMilliseconds","test","replace","RegExp","$1","getFullYear","substr","length","k","jsonify","keys","reduce","result","key","isChinese","value","isRemoteURL","str","startsWith","get_url_extension","url","_url$split$","split","pop","trim","generateObjectId","timestamp","Date","getTime","random","toLowerCase","humanFileSize","bytes","si","arguments","undefined","dp","thresh","abs","units","u","r","round","toFixed","useForceUpdate","setValue","showToast","toast","showWithGravity","SHORT","CENTER","goAppStoreReview","report","OS","canOpenURL","then","supported","openURL","iOSReviewUrl","CheckPackageInstallation","isPackageInstalled","isInstalled","goToMarket","AndroidPackageName","AndroidStoreScheme","goUpgrade","iOSStoreScheme","AppWebsite","notifyMe","text","__DEV__","fetch","PushDeerUrl","encodeURIComponent","savePicture","albumName","console","log","errorCode","save","type","album","AppName","error","errMsg","JSON","stringify","extension","res","fileCache","appendExt","path","e1"],"sources":["Tool.ts"],"sourcesContent":["import CameraRoll from '@react-native-community/cameraroll';\nimport { useState } from 'react';\nimport {\n Linking,\n NativeModules,\n PermissionsAndroid,\n Platform,\n} from 'react-native';\nimport Toast from 'react-native-simple-toast';\nimport RNFetchBlob from 'rn-fetch-blob';\nimport { ReportUtil } from './ReportUtil';\n\nexport interface ToolkitConfigType {\n iOSStoreUrl: string;\n AndroidStoreUrl: string;\n iOSStoreScheme: string;\n AndroidStoreScheme: string;\n iOSReviewUrl: string;\n AndroidPackageName: string;\n\n AppName: string;\n AppWebsite: string;\n\n PolicyUrl: string;\n TermsUrl: string;\n\n PushDeerUrl: string;\n\n RC_API_KEY: string;\n RC_ENTITLEMENT_ID: string;\n WeChatPayServer: string;\n WeiXinId: string;\n WeiXinSecret: string;\n}\n\nexport let ToolkitConfig: ToolkitConfigType;\n\nexport const initToolkitConfig = (config: ToolkitConfigType) => {\n ToolkitConfig = config;\n};\n\nconst _isPlainObject = (target: any) => {\n return (\n target &&\n target.toString() === '[object Object]' &&\n Object.getPrototypeOf(target) === Object.prototype\n );\n};\n\nconst _jsonify = (target: any): any => {\n if (target && typeof target.toJSON === 'function') return target.toJSON();\n // map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一次提供的函数后的返回值\n if (Array.isArray(target)) return target.map(_jsonify);\n return target;\n};\n\nconst _hasAndroidWritePermission = async () => {\n const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;\n\n const hasPermission = await PermissionsAndroid.check(permission);\n if (hasPermission) {\n return true;\n }\n\n const status = await PermissionsAndroid.request(permission);\n return status === 'granted';\n};\n\nexport const Tool = {\n sleep: (delay: number) =>\n new Promise((resolve) => setTimeout(resolve, delay)),\n\n formatDate(date: Date, fmt: string): string {\n fmt = fmt ? fmt : 'yyyy-MM-dd';\n var o: { [key: string]: number } = {\n 'M+': date.getMonth() + 1, //月份\n 'd+': date.getDate(), //日\n 'h+': date.getHours(), //小时\n 'm+': date.getMinutes(), //分\n 's+': date.getSeconds(), //秒\n 'q+': Math.floor((date.getMonth() + 3) / 3), //季度\n 'S': date.getMilliseconds(), //毫秒\n };\n\n // 获取年份\n if (/(y+)/i.test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (date.getFullYear() + '').substr(4 - RegExp.$1.length)\n );\n }\n\n for (var k in o) {\n if (new RegExp('(' + k + ')', 'i').test(fmt)) {\n fmt = fmt.replace(\n RegExp.$1,\n (RegExp.$1.length === 1\n ? o[k]\n : ('00' + o[k]).substr(('' + o[k]).length)\n ).toString()\n );\n }\n }\n return fmt;\n },\n\n jsonify: (target: any) =>\n _isPlainObject(target)\n ? Object.keys(target).reduce(\n (result, key) => ({\n ...result,\n [key]: _jsonify(target[key]),\n }),\n {}\n )\n : _jsonify(target),\n\n isChinese: (value: string) => {\n return /[\\u4E00-\\u9FA5]+/g.test(value);\n },\n\n isRemoteURL: (str: string) => {\n return str.startsWith('http');\n },\n\n get_url_extension: (url: string) => {\n return url.split(/[#?]/)[0]?.split('.')?.pop()?.trim();\n },\n\n generateObjectId: () => {\n var timestamp = ((new Date().getTime() / 1000) | 0).toString(16); // eslint-disable-line no-bitwise\n return (\n timestamp +\n 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {\n return ((Math.random() * 16) | 0).toString(16).toLowerCase(); // eslint-disable-line no-bitwise\n })\n );\n },\n\n /**\n * Format bytes as human-readable text.\n *\n * @param bytes Number of bytes.\n * @param si True to use metric (SI) units, aka powers of 1000. False to use\n * binary (IEC), aka powers of 1024.\n * @param dp Number of decimal places to display.\n *\n * @return Formatted string.\n */\n humanFileSize: (bytes: number, si = false, dp = 1) => {\n const thresh = si ? 1000 : 1024;\n\n if (Math.abs(bytes) < thresh) {\n return bytes + ' B';\n }\n\n const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n let u = -1;\n const r = 10 ** dp;\n\n do {\n bytes /= thresh;\n ++u;\n } while (\n Math.round(Math.abs(bytes) * r) / r >= thresh &&\n u < units.length - 1\n );\n\n return bytes.toFixed(dp) + ' ' + units[u];\n },\n\n useForceUpdate: () => {\n const [, setValue] = useState(0);\n return () => setValue((value) => value + 1);\n },\n\n showToast: (toast: string) => {\n Toast.showWithGravity(toast, Toast.SHORT, Toast.CENTER);\n },\n\n goAppStoreReview: () => {\n ReportUtil.report('StoreReview');\n if (Platform.OS === 'ios') {\n Linking.canOpenURL('itms-apps://').then((supported) => {\n if (supported) {\n Linking.openURL(ToolkitConfig.iOSReviewUrl);\n }\n });\n } else {\n if (NativeModules.CheckPackageInstallation) {\n NativeModules.CheckPackageInstallation.isPackageInstalled(\n 'com.coolapk.market',\n (isInstalled: boolean) => {\n if (isInstalled) {\n if (NativeModules.CheckPackageInstallation.goToMarket) {\n NativeModules.CheckPackageInstallation.goToMarket(\n ToolkitConfig.AndroidPackageName,\n 'com.coolapk.market',\n 'com.coolapk.market.activity.AppViewActivity'\n );\n } else {\n Tool.showToast('请用酷安市场打开');\n Linking.openURL(ToolkitConfig.AndroidStoreScheme);\n }\n } else {\n Tool.showToast('需要先安装酷安市场');\n }\n }\n );\n }\n }\n },\n\n goUpgrade: () => {\n if (Platform.OS === 'ios') {\n Linking.canOpenURL('itms-apps://').then((supported) => {\n if (supported) {\n Linking.openURL(ToolkitConfig.iOSStoreScheme);\n }\n });\n } else {\n Linking.openURL(ToolkitConfig.AppWebsite);\n }\n },\n\n notifyMe: async (text: string) => {\n if (!__DEV__) {\n await fetch(ToolkitConfig.PushDeerUrl + encodeURIComponent(text));\n }\n },\n\n savePicture: async (url: string, albumName?: string) => {\n console.log('savePicture', url);\n\n // 检查权限\n if (Platform.OS === 'android' && !(await _hasAndroidWritePermission())) {\n return { errorCode: -1 };\n }\n\n // iOS 或本地图片直接保存\n if (Platform.OS === 'ios' || !Tool.isRemoteURL(url)) {\n try {\n await CameraRoll.save(url, {\n type: 'photo',\n album: albumName ?? ToolkitConfig.AppName,\n });\n return { errorCode: 0 };\n } catch (error: any) {\n console.error(error);\n return { errorCode: -2, errMsg: JSON.stringify(error) };\n }\n }\n\n // 安卓远程图片需要下载\n const extension = Tool.get_url_extension(url);\n try {\n const res = await RNFetchBlob.config({\n fileCache: true,\n appendExt: extension,\n }).fetch('GET', url, {});\n // the temp file path\n console.log('The file saved to ', res.path());\n try {\n await CameraRoll.save('file://' + res.path(), {\n type: 'photo',\n album: albumName,\n });\n return { errorCode: 0 };\n } catch (e1) {\n console.error(e1 + '\\n' + res.path());\n return { errorCode: -3, errMsg: JSON.stringify(e1) };\n }\n } catch (error) {\n console.error(error);\n return { errorCode: -4, errMsg: JSON.stringify(error) };\n }\n },\n};\n"],"mappings":"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"}
@@ -5,6 +5,7 @@ export interface ToolkitConfigType {
5
5
  AndroidStoreScheme: string;
6
6
  iOSReviewUrl: string;
7
7
  AndroidPackageName: string;
8
+ AppName: string;
8
9
  AppWebsite: string;
9
10
  PolicyUrl: string;
10
11
  TermsUrl: string;
@@ -41,4 +42,11 @@ export declare const Tool: {
41
42
  goAppStoreReview: () => void;
42
43
  goUpgrade: () => void;
43
44
  notifyMe: (text: string) => Promise<void>;
45
+ savePicture: (url: string, albumName?: string) => Promise<{
46
+ errorCode: number;
47
+ errMsg?: undefined;
48
+ } | {
49
+ errorCode: number;
50
+ errMsg: string;
51
+ }>;
44
52
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@norcy/react-native-toolkit",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "description": "My Toolkit",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -74,7 +74,9 @@
74
74
  "@react-navigation/bottom-tabs": "^5.9.2",
75
75
  "@react-navigation/native": "^5.7.5",
76
76
  "@react-navigation/stack": "^5.9.2",
77
- "react-navigation": "^4.4.2"
77
+ "react-navigation": "^4.4.2",
78
+ "@react-native-community/cameraroll": "^4.0.4",
79
+ "rn-fetch-blob": "^0.12.0"
78
80
  },
79
81
  "peerDependencies": {
80
82
  "react": "*",
@@ -91,7 +93,9 @@
91
93
  "@react-navigation/bottom-tabs": "*",
92
94
  "@react-navigation/native": "*",
93
95
  "@react-navigation/stack": "*",
94
- "react-navigation": "*"
96
+ "react-navigation": "*",
97
+ "@react-native-community/cameraroll": "*",
98
+ "rn-fetch-blob": "*"
95
99
  },
96
100
  "jest": {
97
101
  "preset": "react-native",
package/src/Tool.ts CHANGED
@@ -1,6 +1,13 @@
1
+ import CameraRoll from '@react-native-community/cameraroll';
1
2
  import { useState } from 'react';
2
- import { Linking, NativeModules, Platform } from 'react-native';
3
+ import {
4
+ Linking,
5
+ NativeModules,
6
+ PermissionsAndroid,
7
+ Platform,
8
+ } from 'react-native';
3
9
  import Toast from 'react-native-simple-toast';
10
+ import RNFetchBlob from 'rn-fetch-blob';
4
11
  import { ReportUtil } from './ReportUtil';
5
12
 
6
13
  export interface ToolkitConfigType {
@@ -11,6 +18,7 @@ export interface ToolkitConfigType {
11
18
  iOSReviewUrl: string;
12
19
  AndroidPackageName: string;
13
20
 
21
+ AppName: string;
14
22
  AppWebsite: string;
15
23
 
16
24
  PolicyUrl: string;
@@ -46,6 +54,18 @@ const _jsonify = (target: any): any => {
46
54
  return target;
47
55
  };
48
56
 
57
+ const _hasAndroidWritePermission = async () => {
58
+ const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;
59
+
60
+ const hasPermission = await PermissionsAndroid.check(permission);
61
+ if (hasPermission) {
62
+ return true;
63
+ }
64
+
65
+ const status = await PermissionsAndroid.request(permission);
66
+ return status === 'granted';
67
+ };
68
+
49
69
  export const Tool = {
50
70
  sleep: (delay: number) =>
51
71
  new Promise((resolve) => setTimeout(resolve, delay)),
@@ -208,4 +228,51 @@ export const Tool = {
208
228
  await fetch(ToolkitConfig.PushDeerUrl + encodeURIComponent(text));
209
229
  }
210
230
  },
231
+
232
+ savePicture: async (url: string, albumName?: string) => {
233
+ console.log('savePicture', url);
234
+
235
+ // 检查权限
236
+ if (Platform.OS === 'android' && !(await _hasAndroidWritePermission())) {
237
+ return { errorCode: -1 };
238
+ }
239
+
240
+ // iOS 或本地图片直接保存
241
+ if (Platform.OS === 'ios' || !Tool.isRemoteURL(url)) {
242
+ try {
243
+ await CameraRoll.save(url, {
244
+ type: 'photo',
245
+ album: albumName ?? ToolkitConfig.AppName,
246
+ });
247
+ return { errorCode: 0 };
248
+ } catch (error: any) {
249
+ console.error(error);
250
+ return { errorCode: -2, errMsg: JSON.stringify(error) };
251
+ }
252
+ }
253
+
254
+ // 安卓远程图片需要下载
255
+ const extension = Tool.get_url_extension(url);
256
+ try {
257
+ const res = await RNFetchBlob.config({
258
+ fileCache: true,
259
+ appendExt: extension,
260
+ }).fetch('GET', url, {});
261
+ // the temp file path
262
+ console.log('The file saved to ', res.path());
263
+ try {
264
+ await CameraRoll.save('file://' + res.path(), {
265
+ type: 'photo',
266
+ album: albumName,
267
+ });
268
+ return { errorCode: 0 };
269
+ } catch (e1) {
270
+ console.error(e1 + '\n' + res.path());
271
+ return { errorCode: -3, errMsg: JSON.stringify(e1) };
272
+ }
273
+ } catch (error) {
274
+ console.error(error);
275
+ return { errorCode: -4, errMsg: JSON.stringify(error) };
276
+ }
277
+ },
211
278
  };