ClockMain.tsx 34 KB

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