ClockMain.tsx 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. import { View, Text, Image, ScrollView, PageContainer, Swiper, SwiperItem, Switch } from "@tarojs/components";
  2. import Tabbar from "@/components/navigation/TabBar";
  3. import IndexItem from '@/features/trackTimeDuration/components/IndexItem';
  4. import Rings from "@/features/trackTimeDuration/components/Rings";
  5. import './Clock.scss'
  6. import { useDispatch, useSelector } from "react-redux";
  7. import { useDidHide, useDidShow, usePageScroll, useReady, useShareAppMessage } from "@tarojs/taro";
  8. import Taro from "@tarojs/taro";
  9. import { getInfoSuccess } from "@/store/user";
  10. import { clockHome, clockSummaryRecords, clockSummaryStats, getClockRecords, getClocks, getPlans } from "@/services/trackTimeDuration";
  11. import { updateScenario } from "@/store/time";
  12. import { setConfigs } from "@/store/common";
  13. import { setScenario, setStep } from "@/store/scenario";
  14. import { useEffect, useRef, useState } from "react";
  15. import { IconPlus, IconRadioCheck, IconRadioCross } from "@/components/basic/Icons";
  16. import { ColorType } from "@/context/themes/color";
  17. import { bigRingRadius, getBgRing, getCommon, getDot, getSchedule, ringWidth, smallRingRadius } from "@/features/trackTimeDuration/hooks/RingData";
  18. import { RealRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings";
  19. import IndexConsole from "@/features/trackTimeDuration/components/IndexConsole";
  20. import Modal from '@/components/layout/Modal.weapp'
  21. import { compareVersion, getTimezone, getTimezoneId, getTimezoneName, kIsIOS, rpxToPx } from "@/utils/tools";
  22. import RecordFastSleep from "@/features/trackTimeDuration/components/RecordFastSleep";
  23. import WeekCalendar from "@/features/trackTimeDuration/components/WeekCalendar";
  24. import { useTranslation } from "react-i18next";
  25. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  26. import Layout from "@/components/layout/layout";
  27. import { ModalType, NaviBarTitleShowType, TemplateType } from "@/utils/types";
  28. import ClockHeader from "@/features/trackTimeDuration/components/ClockHeader";
  29. import DurationPicker from "@/features/trackTimeDuration/components/DurationPicker";
  30. import SegmentPop from "@/features/trackTimeDuration/components/SegmentPop";
  31. import Box from "@/components/layout/Box";
  32. import DayNightCard from "@/features/daynight/DayNightCard";
  33. import StageSelector from "@/features/trackTimeDuration/components/StageSelector";
  34. import { ChooseScenarioBtn } from "@/features/common/SpecBtns";
  35. import { clearNightStore, showNight } from "@/store/night";
  36. import { showDay } from "@/store/day";
  37. import { clientInfo, staticResources, systemVersion } from "@/services/common";
  38. import { changeFastDuration, changeSleepDuration, setCurrentRecord, setSchedule } from "@/store/ring";
  39. import { checkAuthorized } from "@/utils/check_authorized";
  40. import { AtActivityIndicator } from "taro-ui";
  41. import Tooltip from "@/components/view/Tooltip";
  42. import AllRings from "@/features/daynight/AllRings";
  43. import Streaks from "@/features/trackTimeDuration/components/Streaks";
  44. import dayjs from 'dayjs'
  45. import DayNightSwiper from "@/features/daynight/DayNightSwiper";
  46. import showAlert from "@/components/basic/Alert";
  47. import { APP_VERSION, WX_VERSION } from "@/services/http/api";
  48. import { wxPubFollow } from "@/services/permission";
  49. import { repeat } from "lodash";
  50. import { setWXFollow } from "@/store/permission";
  51. import Discovery from "@/features/trackTimeDuration/components/Discovery";
  52. import NoData from "@/components/view/NoData";
  53. import { getLocalPush } from "@/features/trackTimeDuration/actions/TrackTimeActions";
  54. import { TimeFormatter } from "@/utils/time_format";
  55. import { userAccess } from "@/services/user";
  56. const utc = require('dayjs/plugin/utc')
  57. const timezone = require('dayjs/plugin/timezone')
  58. dayjs.extend(utc)
  59. dayjs.extend(timezone)
  60. let GradientText
  61. let useNavigation;
  62. let timer
  63. let pauseTimer = false;
  64. let AppState;
  65. let needScroll = false;
  66. let showUpdate = false;
  67. let Linking;
  68. let PushNotification;
  69. let checkNotification, uploadPermissions, NativeAppEventEmitter;
  70. let messaging;
  71. if (process.env.TARO_ENV == 'rn') {
  72. messaging = require('@react-native-firebase/messaging').default
  73. PushNotification = require('react-native-push-notification')
  74. Linking = require('react-native').Linking;
  75. AppState = require("react-native").AppState
  76. NativeAppEventEmitter = require("react-native").NativeAppEventEmitter
  77. GradientText = require('@/components/basic/GradientText').default
  78. useNavigation = require("@react-navigation/native").useNavigation
  79. checkNotification = require('@/utils/native_permission_check').checkNotification;
  80. uploadPermissions = require('@/utils/native_permission_check').uploadPermissions;
  81. }
  82. const defaultValue = `[{"scenario":{"name":"FAST_SLEEP","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"},"sleep":{"start_time":"22:00","end_time":"07:00"}}},"current_record":{"scenario":"FAST_SLEEP","status":"WAIT_FOR_START","fast":{"status":"WAIT_FOR_START","target_start_time":1710514800000,"target_end_time":1710576000000},"sleep":{"status":"WAIT_FOR_START","target_start_time":1710540000000,"target_end_time":1710572400000}},"wx_pub_followed":false,"time_input_schema":{"min":60,"max":1380,"step":5},"theme_color":{"fast":"#00FFFF","sleep":"#8183FF"}},{"scenarios":[{"name":"FAST","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"}}},{"name":"SLEEP","count":0,"schedule":{"sleep":{"start_time":"22:00","end_time":"07:00"}}},{"name":"FAST_SLEEP","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"},"sleep":{"start_time":"22:00","end_time":"07:00"}}}],"select_count":0,"theme_color":{"fast":"#00FFFF","sleep":"#8183FF"}}]`
  83. let fcmUnsubscribe: any = null;
  84. export default function Page() {
  85. const dispatch = useDispatch();
  86. global.dispatch = dispatch;
  87. let navigation;
  88. if (useNavigation) {
  89. navigation = useNavigation()
  90. }
  91. const { t } = useTranslation()
  92. const user = useSelector((state: any) => state.user);
  93. const time = useSelector((state: any) => state.time);
  94. const [count, setCount] = useState(0)
  95. const [homeData, setHomeData] = useState(null)
  96. const [loaded, setLoaded] = useState(false)
  97. const [showErrorPage, setErrorPage] = useState(false)
  98. const [showModal, setShowModal] = useState(false)
  99. const [modalDetail, setModalDetail] = useState<any>(null)
  100. const [showModal2, setShowModal2] = useState(false)
  101. const [modalDetail2, setModalDetail2] = useState<any>(null)
  102. const [debugInfo, setDebugInfo] = useState(null)
  103. const [needShowAddTip, setNeedShowAddTip] = useState(false)
  104. const [showTip, setShowTip] = useState(false)
  105. const [records, setRecords] = useState([])
  106. const [showEatCalendar, setShowEatCalendar] = useState(false)
  107. const [schedules, setSchedules] = useState<any>(null)
  108. const permission = useSelector((state: any) => state.permission);
  109. const common = useSelector((state: any) => state.common);
  110. const [access, setAccess] = useState<any>(null)
  111. const [buildVersion,setBuildVersion] = useState('')
  112. const scrollRef = useRef(null);
  113. const nightStore = useSelector((state: any) => state.night);
  114. if (process.env.TARO_ENV == 'weapp') {
  115. useShareAppMessage((e) => {
  116. return {
  117. title: t('feature.track_time_duration.common.share_title'),
  118. path: 'pages/clock/Clock'
  119. }
  120. })
  121. }
  122. useEffect(() => {
  123. console.log(new Date().toString());
  124. dispatch(staticResources() as any);
  125. pauseTimer = false;
  126. mainTimer()
  127. if (process.env.TARO_ENV == 'rn') {
  128. NativeAppEventEmitter.addListener('openNotificationSetting', (data) => {
  129. jumpPage('/pages/account/ChooseAuth', 'NotificationSetting', navigation)
  130. })
  131. }
  132. }, [])
  133. function mainTimer() {
  134. if (timer) {
  135. clearInterval(timer)
  136. timer = null
  137. }
  138. timer = setInterval(() => {
  139. var now = new Date()
  140. if (now.getDay() == 0 && now.getHours() == 12 && now.getMinutes() == 0 && now.getSeconds() == 0) {
  141. if (global.refrehWeekly) {
  142. global.refrehWeekly()
  143. }
  144. }
  145. if (global.pauseIndexTimer || pauseTimer) {
  146. return
  147. }
  148. setCount((prevCounter) => prevCounter + 1)
  149. }, 1000)
  150. }
  151. useEffect(() => {
  152. if (process.env.TARO_ENV == 'rn') {
  153. AppState.addEventListener('change', handleAppStateChange);
  154. }
  155. }, [])
  156. useEffect(() => {
  157. getCheckData()
  158. if (user.isLogin) {
  159. uploadUserClient();
  160. checkAuthorized();
  161. //检查用户是否添加过小程序
  162. checkAddToMini();
  163. wxPubFollow({ force_refresh: true }).then(res => {
  164. dispatch(setWXFollow((res as any).wx_pub_followed));
  165. })
  166. if (process.env.TARO_ENV == 'rn') {
  167. if (kIsIOS) {
  168. var Jto = require('react-native').NativeModules.NativeBridge;
  169. Jto.getNotificationAuthStatus()
  170. // Jto.rnPageLoaded()
  171. NativeAppEventEmitter.addListener('notificationResult', (data) => {
  172. console.log('notification auth result', data)
  173. global.notification = data;
  174. uploadPermissions()
  175. })
  176. }
  177. // uploadPermissions()
  178. // JPush.isNotificationEnabled((res) => {
  179. // if (res) {
  180. // const test = require('@/utils/push').default
  181. // test()
  182. // }
  183. // })
  184. checkVersionUpdate()
  185. }
  186. }
  187. else {
  188. dispatch(clearNightStore());
  189. }
  190. }, [user.isLogin])
  191. useReady(async () => {
  192. const userData = await getStorage('userData');
  193. if (userData) {
  194. dispatch(getInfoSuccess(JSON.parse(userData as string)) as any);
  195. getHistory()
  196. }
  197. })
  198. async function checkVersionUpdate() {
  199. if (!user.isLogin) {
  200. return
  201. }
  202. if (process.env.TARO_ENV == 'rn') {
  203. systemVersion().then(res => {
  204. if ((res as any).result == 'UPDATE' && !showUpdate) {
  205. showUpdate = true
  206. showAlert({
  207. title: (res as any).title,
  208. content: (res as any).description,
  209. showCancel: true,
  210. confirmText: 'Update',
  211. confirm: () => {
  212. Linking.openURL((res as any).download_url)
  213. }
  214. })
  215. }
  216. else if ((res as any).result == 'FORCE_UPDATE') {
  217. showAlert({
  218. title: (res as any).title,
  219. content: (res as any).description,
  220. showCancel: false,
  221. confirmText: 'Update',
  222. confirm: () => {
  223. Linking.openURL((res as any).download_url)
  224. }
  225. })
  226. }
  227. })
  228. return;
  229. }
  230. const showAlert1 = await getStorage('121alert') || false;
  231. if (!showAlert1) {
  232. showAlert({
  233. title: '重要更新提示',
  234. content: '🔥 连续打卡天数现根据结束日期统计;\n 🪐 断食与睡眠升级为高级功能。\n连续打卡的老用户仍可继续使用。\n更多高级功能如『进食窗口』显示、『社区排行』等敬请期待!',
  235. showCancel: false,
  236. confirmText: '我知道了'
  237. })
  238. }
  239. Taro.setStorage({ key: '121alert', data: true })
  240. }
  241. function checkAddToMini() {
  242. if (process.env.TARO_ENV == 'weapp') {
  243. const version = Taro.getAppBaseInfo().SDKVersion
  244. if (compareVersion(version, '2.30.3') >= 0) {
  245. wx.checkIsAddedToMyMiniProgram({
  246. success: (res) => {
  247. if (!res.added) {
  248. setNeedShowAddTip(true)
  249. }
  250. },
  251. fail: (e) => {
  252. }
  253. });
  254. }
  255. }
  256. }
  257. useDidShow(() => {
  258. if (process.env.TARO_ENV == 'weapp') {
  259. checkTimeZone()
  260. }
  261. else {
  262. if (!kIsIOS) {
  263. updateNotificationStatus()
  264. }
  265. }
  266. setCount(pre => pre + 1)
  267. //resume timer
  268. pauseTimer = false
  269. if (user.isLogin) {
  270. if (global.refreshRecent) {
  271. global.refreshRecent()
  272. }
  273. }
  274. setTimeout(() => {
  275. checkVersionUpdate();
  276. updateNotificationStatus();
  277. }, 1000)
  278. })
  279. usePageScroll((e) => {
  280. if (e.scrollTop > 70) {
  281. setShowTip(true)
  282. }
  283. else {
  284. setShowTip(false)
  285. }
  286. })
  287. useDidHide(() => {
  288. //pause timer
  289. pauseTimer = true
  290. })
  291. global.refreshIndex = () => {
  292. setCount((prevCounter) => prevCounter + 1)
  293. }
  294. const handleAppStateChange = (nextAppState) => {
  295. console.log(nextAppState)
  296. if (nextAppState != 'active') {
  297. return
  298. }
  299. if (nextAppState == 'active') {
  300. checkTimeZone()
  301. updateNotificationStatus()
  302. mainTimer()
  303. }
  304. };
  305. function updateNotificationStatus() {
  306. if (process.env.TARO_ENV == 'rn') {
  307. if (user.isLogin) {
  308. if (kIsIOS) {
  309. var Jto = require('react-native').NativeModules.NativeBridge;
  310. Jto.getNotificationAuthStatus()
  311. }
  312. else {
  313. uploadPermissions()
  314. }
  315. }
  316. // JPush.setBadge({
  317. // badge: 0,
  318. // appBadge: 0
  319. // })
  320. }
  321. }
  322. function checkTimeZone() {
  323. getLocalPush()
  324. setCount((prevCounter) => prevCounter + 1)
  325. var timeZoneFormatted = getTimezone()
  326. Taro.getStorage({
  327. key: 'last_tz',
  328. success: function (res) {
  329. if (res.data && res.data != timeZoneFormatted) {
  330. if (global.refrehWeekly) {
  331. global.refrehWeekly()
  332. }
  333. global.indexPageRefresh()
  334. // if (global.refreshNight){
  335. // global.refreshNight()
  336. // }
  337. // if (global.refreshDay){
  338. // global.refreshDay()
  339. // }
  340. // if (global.currentStatus != 'WAIT_FOR_START') {
  341. showAlert({
  342. title: t('feature.track_time_duration.change_tz_alert.title'),
  343. content: t('feature.track_time_duration.change_tz_alert.content', { tz: timeZoneFormatted }),
  344. showCancel: false,
  345. confirmText: t('feature.track_time_duration.change_tz_alert.confirm'),
  346. })
  347. // }
  348. }
  349. },
  350. complete: function () {
  351. Taro.setStorage({ key: 'last_tz', data: timeZoneFormatted })
  352. }
  353. })
  354. }
  355. function uploadUserClient() {
  356. var systemInfo = Taro.getSystemInfoSync();
  357. console.log(systemInfo)
  358. var language: any = systemInfo.language
  359. if (process.env.TARO_ENV == 'rn') {
  360. var NativeModules = require('react-native').NativeModules;
  361. var DeviceInfo = require('react-native-device-info').default
  362. console.log('jslfspodgfsdfopgs',DeviceInfo.getBuildNumber())
  363. setBuildVersion(DeviceInfo.getBuildNumber())
  364. if (kIsIOS) {
  365. // language = NativeModules.SettingsManager.settings.AppleLocale
  366. // languageList = NativeModules.SettingsManager.settings.AppleLanguages
  367. language = {
  368. AppleLocale: NativeModules.SettingsManager.settings.AppleLocale,
  369. AppleLanguages: NativeModules.SettingsManager.settings.AppleLanguages,
  370. NSLanguages: NativeModules.SettingsManager.settings.NSLanguages
  371. }
  372. }
  373. else {
  374. language = NativeModules.I18nManager.localeIdentifier
  375. }
  376. // iOS:
  377. // var locale = NativeModules.SettingsManager.settings.AppleLocale ||
  378. // NativeModules.SettingsManager.settings.AppleLanguages[0] // "fr_FR"
  379. // showAlert({
  380. // title: 'locale',
  381. // content: JSON.stringify(NativeModules.SettingsManager.settings)
  382. // })
  383. // Android:
  384. // locale = NativeModules.I18nManager.localeIdentifier // "fr_FR"
  385. }
  386. var timeZoneFormatted = getTimezone()
  387. var timeZoneId = ''
  388. var timeZoneName = ''
  389. if (kIsIOS) {
  390. timeZoneId = getTimezoneId()
  391. timeZoneName = getTimezoneName()
  392. }
  393. else {
  394. timeZoneId = getTimezoneId()
  395. timeZoneName = getTimezoneName()
  396. }
  397. var clientInfoParams = {
  398. client: {
  399. client_type: process.env.TARO_ENV == 'weapp' ? 'MP' : 'APP',
  400. client_version: process.env.TARO_ENV == 'weapp' ? WX_VERSION : APP_VERSION,//Taro.getAccountInfoSync().miniProgram.version : '1.0',//'1.0'
  401. wx_version: process.env.TARO_ENV == 'weapp' ? systemInfo.version : '_'
  402. },
  403. meta: {
  404. language: language,
  405. timezone: {
  406. gmt: timeZoneFormatted,
  407. id: timeZoneId,
  408. name: timeZoneName
  409. },
  410. },
  411. device: {
  412. brand: systemInfo.brand,
  413. model: systemInfo.model,
  414. platform: systemInfo.platform,
  415. system: systemInfo.system
  416. },
  417. }
  418. if (process.env.TARO_ENV == 'weapp') {
  419. (clientInfoParams as any).perm = {
  420. wxmp: {
  421. wifi_enabled: systemInfo.wifiEnabled,
  422. location_authorized: systemInfo.locationAuthorized,
  423. location_enabled: systemInfo.locationEnabled
  424. }
  425. }
  426. }
  427. clientInfo(clientInfoParams)
  428. }
  429. function getCheckData() {
  430. Promise.all([getClocks(), getPlans()]).then((list) => {
  431. setErrorPage(false)
  432. setCheckData(list)
  433. if (needScroll) {
  434. needScroll = false
  435. if (process.env.TARO_ENV == 'weapp') {
  436. setTimeout(() => {
  437. Taro.createSelectorQuery().select('#latest').boundingClientRect((rect) => {
  438. Taro.pageScrollTo({
  439. scrollTop: (rect as any).top,
  440. duration: 150
  441. })
  442. }).exec()
  443. }, 100)
  444. }
  445. else {
  446. // (scrollRef.current as any).scrollTo({ y: rpxToPx(400), animated: true })
  447. }
  448. }
  449. if (process.env.TARO_ENV == 'rn' && user.isLogin) {
  450. if (kIsIOS) {
  451. var Jto = require('react-native').NativeModules.NativeBridge;
  452. Jto.rnPageLoaded()
  453. }
  454. else {
  455. var Jto = require('react-native').NativeModules.NativeBridge;
  456. Jto.rnPageLoaded()
  457. }
  458. }
  459. setLoaded(true)
  460. }).catch((e) => {
  461. setErrorPage(true)
  462. var list = JSON.parse(defaultValue)
  463. setCheckData(list)
  464. needScroll = false
  465. setLoaded(true)
  466. })
  467. if (user.isLogin) {
  468. getHistory()
  469. userAccess().then(res => {
  470. console.log('useraccess', res)
  471. setAccess(res)
  472. })
  473. }
  474. }
  475. global.refreshAccess = (res) => {
  476. setAccess(res)
  477. }
  478. function setCheckData(list: any) {
  479. setHomeData(list[0])
  480. setSchedules(list[1].scenarios)
  481. global.homeData = list[0]
  482. global.currentStatus = list[0].current_record.status;
  483. var array = list[1].scenarios
  484. var schedule: any = null
  485. array.map(item => {
  486. if (item.name == 'FAST_SLEEP') {
  487. schedule = item.schedule;
  488. schedule.sleep.prev_input = item.prev_input;
  489. schedule.sleep.valid = item.valid;
  490. }
  491. })
  492. if (user.isLogin) {
  493. dispatch(updateScenario(list[0].current_record))
  494. dispatch(setConfigs(list[0].time_input_schema));
  495. dispatch(setScenario(list[0].scenario));
  496. global.scenario = list[0].scenario.name;
  497. }
  498. dispatch(setCurrentRecord(list[0].current_record))
  499. dispatch(setSchedule(schedule))
  500. // setLoaded(true)
  501. }
  502. function getHistory() {
  503. if (user.isLogin)
  504. getClockRecords({
  505. page: 1,
  506. limit: 1,
  507. // part_completed: true
  508. completed: true
  509. }).then(res => {
  510. setRecords((res as any).data)
  511. })
  512. }
  513. global.indexPageRefresh = () => {
  514. if (global.refreshStreaks) {
  515. global.refreshStreaks()
  516. }
  517. getCheckData()
  518. if (global.swiperDayNightRefresh) {
  519. global.swiperDayNightRefresh()
  520. }
  521. if (global.refrehWeekly){
  522. global.refrehWeekly()
  523. }
  524. }
  525. global.showIndexModal = (isShow: boolean, detail: any, debugNode?: any) => {
  526. global.showModal = isShow
  527. setDebugInfo(debugNode)
  528. setShowModal(isShow)
  529. setModalDetail(detail)
  530. }
  531. global.showIndexModal2 = (isShow: boolean, detail: any) => {
  532. setDebugInfo(null)
  533. global.showModal = isShow
  534. setShowModal2(isShow)
  535. setModalDetail2(detail)
  536. }
  537. global.changeTargetDuration = (duration: number, isFast: boolean) => {
  538. var obj = JSON.parse(JSON.stringify(homeData))
  539. var record = obj.current_record
  540. if (isFast) {
  541. record.fast.target_end_time = record.fast.target_start_time + duration * 60 * 1000
  542. }
  543. else {
  544. record.sleep.target_end_time = record.sleep.target_start_time + duration * 60 * 1000
  545. }
  546. setHomeData(obj)
  547. }
  548. global.updateFastSleepData = (data: any, schedule?: any) => {
  549. if (data.id == (homeData as any).current_record.id) {
  550. var obj = JSON.parse(JSON.stringify(homeData))
  551. obj.current_record = data
  552. if (schedule) {
  553. obj.scenario.schedule = schedule
  554. }
  555. setHomeData(obj)
  556. }
  557. switch (data.scenario) {
  558. case 'FAST':
  559. if (data.status == 'WAIT_FOR_START') {
  560. dispatch(changeFastDuration(data.fast.target_end_time - data.fast.target_start_time))
  561. }
  562. break;
  563. case 'SLEEP':
  564. if (data.status == 'WAIT_FOR_START') {
  565. dispatch(changeSleepDuration(data.sleep.target_end_time - data.sleep.target_start_time))
  566. }
  567. break;
  568. case 'FAST_SLEEP':
  569. if (data.status == 'WAIT_FOR_START') {
  570. dispatch(changeFastDuration(data.fast.target_end_time - data.fast.target_start_time))
  571. }
  572. else if (data.status == 'ONGOING1') {
  573. dispatch(changeSleepDuration(data.sleep.target_end_time - data.sleep.target_start_time))
  574. }
  575. break;
  576. }
  577. }
  578. global.popScheduleAlert = (scenario, startTime) => {
  579. if (process.env.TARO_ENV == 'weapp') {
  580. if (permission.wxPubFollow) {
  581. }
  582. else {
  583. showAlert({
  584. title: t('feature.track_time_duration.reminders.schedule_title'),
  585. content: scenario.name == 'FAST' ?
  586. t('feature.track_time_duration.reminders.schedule_fast_content', { time: startTime }) :
  587. t('feature.track_time_duration.reminders.schedule_sleep_content', { time: startTime }),
  588. cancelText: t('feature.track_time_duration.reminders.later'),
  589. confirmText: t('feature.track_time_duration.reminders.open'),
  590. showCancel: true,
  591. confirm: () => {
  592. followWxPub()
  593. }
  594. })
  595. }
  596. }
  597. else {
  598. PushNotification.checkPermissions((res) => {
  599. //允许授权
  600. if ((kIsIOS && res.authorizationStatus == 2) || (!kIsIOS && res.alert)) {
  601. }
  602. else {
  603. showAlert({
  604. title: t('feature.track_time_duration.reminders.schedule_title'),
  605. content: scenario.name == 'FAST' ?
  606. t('feature.track_time_duration.reminders.schedule_fast_content', { time: startTime }) :
  607. t('feature.track_time_duration.reminders.schedule_sleep_content', { time: startTime }),
  608. cancelText: t('feature.track_time_duration.reminders.later'),
  609. confirmText: t('feature.track_time_duration.reminders.open'),
  610. showCancel: true,
  611. confirm: () => {
  612. checkNotification()
  613. // Linking.openURL('app-settings:notifications')
  614. }
  615. })
  616. }
  617. })
  618. }
  619. }
  620. global.popMixScheduleAlert = (time1, time2) => {
  621. if (process.env.TARO_ENV == 'weapp') {
  622. if (permission.wxPubFollow) {
  623. }
  624. else {
  625. showAlert({
  626. title: t('feature.track_time_duration.reminders.schedule_title'),
  627. content:
  628. t('feature.track_time_duration.reminders.schedule_mix_content'),
  629. cancelText: t('feature.track_time_duration.reminders.later'),
  630. confirmText: t('feature.track_time_duration.reminders.open'),
  631. showCancel: true,
  632. confirm: () => {
  633. followWxPub()
  634. }
  635. })
  636. }
  637. }
  638. else {
  639. PushNotification.checkPermissions((res) => {
  640. //允许授权
  641. if ((kIsIOS && res.authorizationStatus == 2) || (!kIsIOS && res.alert)) {
  642. }
  643. else {
  644. showAlert({
  645. title: t('feature.track_time_duration.reminders.schedule_title'),
  646. content:
  647. t('feature.track_time_duration.reminders.schedule_mix_content'),
  648. cancelText: t('feature.track_time_duration.reminders.later'),
  649. confirmText: t('feature.track_time_duration.reminders.open'),
  650. showCancel: true,
  651. confirm: () => {
  652. checkNotification()
  653. // Linking.openURL('app-settings:notifications')
  654. }
  655. })
  656. }
  657. })
  658. }
  659. }
  660. function followWxPub() {
  661. const resource = common.resources.filter((item: any) => {
  662. return item.code == 'follow_wx_pub'
  663. })
  664. jumpPage('/pages/common/H5?title=fast16cc 关注服务号&url=' + resource[0].url)
  665. }
  666. function modalContent() {
  667. if (showModal || showModal2) {
  668. return <Modal
  669. testInfo={debugInfo}
  670. dismiss={() => {
  671. setDebugInfo(null)
  672. setShowModal(false);
  673. setShowModal2(false);
  674. global.pauseIndexTimer = false
  675. }}
  676. confirm={() => { }}>
  677. {
  678. showModal ? modalDetail : modalDetail2
  679. }
  680. </Modal>
  681. }
  682. return <View />
  683. }
  684. async function getStorage(key: string) {
  685. try {
  686. const res = await Taro.getStorage({ key });
  687. return res.data;
  688. } catch {
  689. return '';
  690. }
  691. }
  692. function more() {
  693. jumpPage('/pages/common/RecordsHistory?type=time&title=time', 'RecordsHistory', navigation, {
  694. type: 'time',
  695. title: 'time'
  696. })
  697. }
  698. function tapLogin() {
  699. if (!user.isLogin) {
  700. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
  701. }
  702. }
  703. function headerView() {
  704. return <ClockHeader homeData={homeData} />
  705. }
  706. global.scrollToLatest = () => {
  707. needScroll = true;
  708. }
  709. var timestamp = new Date().getTime()
  710. function goSetting() {
  711. if (process.env.TARO_ENV == 'weapp') {
  712. Taro.navigateTo({
  713. url: '/pages/notification/setting'
  714. })
  715. }
  716. else {
  717. jumpPage('/pages/account/ChooseAuth', 'NotificationSetting', navigation)
  718. }
  719. }
  720. function eatCalendarContent() {
  721. return <View style={{ display: 'flex', flexDirection: 'column' }}>
  722. <View className="index_section">
  723. <Text className="index_section_title">{t('feature.track_time_duration.weekly.title')}</Text>
  724. </View>
  725. <WeekCalendar isFastSleep={false} />
  726. <View className="vip_calendar" style={{ marginBottom: 40 }} onClick={() => setShowEatCalendar(false)}>
  727. <Text style={{ color: '#fff' }}>{t('feature.track_time_duration.weekly.back')}</Text>
  728. </View>
  729. </View>
  730. }
  731. function render() {
  732. var smallTitle = ''
  733. const weekday = TimeFormatter.getDayOfWeek(new Date().getDay(), true);
  734. const date = global.language == 'en' ? dayjs().format('MMMM DD') : dayjs().format('M月D日 ')
  735. smallTitle = global.language == 'en' ? (weekday + ', ' + date) : (date + weekday);
  736. if (!loaded) {
  737. return <Layout type={TemplateType.customHeader} header={headerView()} title={smallTitle} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
  738. <View style={{ width: rpxToPx(750), height: rpxToPx(900), display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
  739. <AtActivityIndicator size={40} color="#fff" />
  740. {
  741. process.env.TARO_ENV == 'weapp' && <Tabbar index={0} />
  742. }
  743. </View>
  744. </Layout>
  745. }
  746. return <Layout type={TemplateType.customHeader} header={headerView()} title={smallTitle} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
  747. <View className="index_container">
  748. {
  749. needShowAddTip && showTip && <Tooltip title="添加到我的小程序" closeTip={() => { setNeedShowAddTip(false) }} />
  750. }
  751. <Text className="count">{count}</Text>
  752. <Box>
  753. <View>
  754. <IndexItem type="FAST_SLEEP" data={homeData} time={timestamp} showStage={false} />
  755. {
  756. user.isLogin ? <IndexConsole record={homeData} count={count} access={access} /> : <StageSelector />
  757. }
  758. </View>
  759. </Box>
  760. {/*
  761. <Text style={{color:'#fff',fontSize:30}} onClick={goSetting}>notification setting</Text> */}
  762. {
  763. user.isLogin && records && records.length > 0 && <View className="index_section" style={{ marginTop: -rpxToPx(25 - 12), marginBottom: -rpxToPx(20) }}>
  764. <Text className="index_section_title">{t('feature.track_time_duration.record_fast_sleep.header.latest_record')}</Text>
  765. {
  766. process.env.TARO_ENV == 'weapp' && <Text className="fast_sleep_more index_more" onClick={more}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</Text>
  767. }
  768. {
  769. process.env.TARO_ENV == 'rn' && <View onClick={more}>
  770. <GradientText style={{ fontSize: rpxToPx(32), fontWeight: 'bold', color: 'black' }}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</GradientText>
  771. </View>
  772. }
  773. </View>
  774. }
  775. {
  776. user.isLogin && records && records.length == 0 && <View style={{ marginTop: -rpxToPx(25) }} />
  777. }
  778. {
  779. user.isLogin && records && records.length > 0 && <View id="latest" className="fast_sleep_item_bg">
  780. <RecordFastSleep data={records[0]} type='record' index={-20000} />
  781. </View>
  782. }
  783. {
  784. loaded && !user.isLogin && <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', marginTop: rpxToPx(36) }}>
  785. <ChooseScenarioBtn title={t('feature.auth.login.login_now')} background={ColorType.fast} onClick={tapLogin} />
  786. </View>
  787. }
  788. {
  789. showErrorPage && <NoData refresh={() => { getCheckData() }} />
  790. }
  791. {
  792. user.isLogin && <Streaks count={count} />
  793. }
  794. {
  795. user.isLogin && !showErrorPage && <View style={{ display: 'flex', flexDirection: 'column' }}>
  796. <View className="index_section">
  797. <Text className="index_section_title">{t('feature.track_time_duration.weekly.title')}</Text>
  798. </View>
  799. <WeekCalendar isFastSleep={true} />
  800. <View className="vip_calendar" onClick={() => setShowEatCalendar(true)}>
  801. <Text className="eat_calendar_text">{t('feature.track_time_duration.weekly.show_eating_window')}</Text>
  802. </View>
  803. </View>
  804. }
  805. {
  806. showEatCalendar && <Modal
  807. testInfo={null}
  808. dismiss={() => {
  809. setShowEatCalendar(false)
  810. }}
  811. confirm={() => { }}>
  812. {
  813. eatCalendarContent()
  814. }
  815. </Modal>
  816. }
  817. {
  818. user.isLogin && !showErrorPage && <View className="index_section" style={{ height: rpxToPx(120), marginTop: rpxToPx(40) }}>
  819. <Text className="index_main_title">{t('feature.pro.for_pro')}</Text>
  820. </View>
  821. }
  822. {
  823. user.isLogin && !showErrorPage && <View className="index_section" style={{ marginBottom: -rpxToPx(10), marginTop: -rpxToPx(40) }}>
  824. <Text className="index_section_title">{t('feature.day_night.group_title')}</Text>
  825. </View>
  826. }
  827. {
  828. user.isLogin && !showErrorPage && <DayNightSwiper count={count} schedule={schedules} homeData={homeData} />
  829. }
  830. {
  831. user.isLogin && (process.env.TARO_ENV == 'weapp') && <View className="index_section">
  832. <Text className="index_section_title">{t('page.explore.title')}</Text>
  833. </View>
  834. }
  835. {
  836. user.isLogin && (process.env.TARO_ENV == 'weapp') && <Discovery />
  837. }
  838. {
  839. modalContent()
  840. }
  841. {
  842. homeData && <SegmentPop data={homeData} />
  843. }
  844. {
  845. homeData && <DurationPicker record={(homeData as any).current_record} />
  846. }
  847. {
  848. user.isLogin && user.test_user && homeData && access && <View style={{ display: 'flex', flexDirection: 'column' }}>
  849. <Text style={{ color: '#fff', fontSize: 15 }}>member status:{access && access.member && access.member.status}</Text>
  850. {
  851. access && access.member && access.member.status=='MEMBER' &&
  852. <Text style={{ color: '#fff', fontSize: 15 }}>会员过期时间:{dayjs(access.member.expire).format('YYYY-MM-DD HH:mm:ss')}</Text>
  853. }
  854. {
  855. access && access.member && access.member.status=='MEMBER' &&
  856. <Text style={{ color: '#fff', fontSize: 15 }}>会员过期倒计时:{TimeFormatter.countdown(access.member.expire)}</Text>
  857. }
  858. <Text style={{ color: '#fff', fontSize: 15 }}>current status:{access.fast_sleep.current.qualification.status}</Text>
  859. <Text style={{ color: '#fff', fontSize: 15 }}>previous status:{access.fast_sleep.previous.qualification.status}</Text>
  860. <Text style={{ color: '#fff', fontSize: 15 }}>trigger event:{access.fast_sleep.current.qualification.trigger_event}</Text>
  861. <Text style={{ color: '#fff', fontSize: 15 }}>lost_access_total:{access.fast_sleep.current.qualification.condition.lost_access_total}</Text>
  862. <Text style={{ color: '#fff', fontSize: 15 }}>streak_fast_min_required:{access.fast_sleep.current.qualification.condition.streak_fast_min_required}</Text>
  863. {
  864. process.env.TARO_ENV=='rn' && <Text style={{ color: '#fff', fontSize: 15 }}>App build version:{buildVersion}</Text>
  865. }
  866. </View>
  867. }
  868. {
  869. process.env.TARO_ENV == 'weapp' && <View style={{ height: 100 }} />
  870. }
  871. <Tabbar index={0} />
  872. </View>
  873. </Layout>
  874. }
  875. return render()
  876. }