index_time.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. import { View, Text, Image } from "@tarojs/components";
  2. import './index_time.scss';
  3. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  4. import { getCommon, getDot } from "@/features/trackTimeDuration/hooks/RingData";
  5. import Rings, { RingCommon, BgRing,TargetRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings";
  6. import { useEffect, useState } from "react";
  7. import DeviceInfo from 'react-native-device-info';
  8. import dayjs from "dayjs";
  9. import moment from 'moment-timezone'
  10. import Modal from "@/components/layout/Modal.weapp";
  11. import { loginAnonymous, place } from "./services/net";
  12. import Taro from "@tarojs/taro";
  13. import { useTranslation } from "react-i18next";
  14. import 'dayjs/locale/zh-cn';
  15. import 'dayjs/locale/en';
  16. let LinearGradient, useActionSheet, useNavigation
  17. if (process.env.TARO_ENV == 'rn') {
  18. LinearGradient = require('react-native-linear-gradient').default
  19. useActionSheet = require('@expo/react-native-action-sheet').useActionSheet
  20. useNavigation = require("@react-navigation/native").useNavigation
  21. }
  22. export default function IndexTimePage() {
  23. let navigation;
  24. if (useNavigation) {
  25. navigation = useNavigation()
  26. }
  27. const [count, setCount] = useState(0)
  28. const [showLanguage, setShowLanguage] = useState(false)
  29. const [isEn, setIsEn] = useState(true)
  30. const [showDst, setShowDst] = useState(false)
  31. const [current, setCurrent] = useState<any>(null)
  32. const { t, i18n } = useTranslation()
  33. useEffect(() => {
  34. getLanguage();
  35. login()
  36. setInterval(() => {
  37. setCount(t => t + 1)
  38. }, 1000)
  39. }, [])
  40. async function getLanguage() {
  41. var language = await getStorage('language') || 'en'
  42. global.language = language;
  43. i18n.changeLanguage(language)
  44. setIsEn(language == 'en')
  45. dayjs.locale(language == 'en' ? 'en' : 'zh-cn');
  46. moment.locale(language == 'en' ? 'en' : 'zh-cn');
  47. }
  48. async function getStorage(key: string) {
  49. try {
  50. const res = await Taro.getStorage({ key });
  51. return res.data;
  52. } catch {
  53. return '';
  54. }
  55. }
  56. function changeLanguage(isEnglish: boolean) {
  57. global.language = isEnglish ? 'en' : 'zh';
  58. i18n.changeLanguage(isEnglish ? 'en' : 'zh')
  59. setIsEn(isEnglish)
  60. Taro.setStorage({ key: 'language', data: isEnglish ? 'en' : 'zh' })
  61. setShowLanguage(false)
  62. dayjs.locale(isEnglish ? 'en' : 'zh-cn');
  63. moment.locale(isEnglish ? 'en' : 'zh-cn');
  64. if (current) {
  65. chooseLocation({
  66. lat: current.geo.lat,
  67. lng: current.geo.lng
  68. })
  69. }
  70. }
  71. function login() {
  72. loginAnonymous(DeviceInfo.getDeviceSync()).then(res => {
  73. console.log('login success', res)
  74. }).catch(e => {
  75. console.log('login error', e)
  76. })
  77. }
  78. function goMap() {
  79. jumpPage('', 'map', navigation, { source: 'time_of_day', chooseLocation: chooseLocation })
  80. }
  81. function chooseLocation(res: any) {
  82. place(res.lat, res.lng).then(res => {
  83. console.log(res)
  84. setCurrent((res as any).location)
  85. saveLocation((res as any).location)
  86. }).catch(e => {
  87. console.log(e)
  88. })
  89. }
  90. function saveLocation(location: any) {
  91. }
  92. function getLocation() {
  93. if (current.geo) {
  94. if (current.geo.city) {
  95. return current.geo.city
  96. }
  97. if (current.geo.country) {
  98. return current.geo.country
  99. }
  100. }
  101. return t('time_of_day.index.unknown')
  102. }
  103. function getTimezone() {
  104. if (current.time && current.time.timezone) {
  105. return current.time.timezone.abbrev + ' · ' + current.time.timezone.name
  106. }
  107. return ''
  108. }
  109. const common: RingCommon = {
  110. useCase: 'ChooseScenario',
  111. radius: 115,
  112. lineWidth: 26,
  113. isFast: true,
  114. status: 'WAIT_FOR_START'
  115. }
  116. const bgRing: BgRing = {
  117. color: '#EAE9E9'
  118. }
  119. function getArc(){
  120. var hour = new Date().getHours()
  121. var minute = new Date().getMinutes()
  122. var second = new Date().getSeconds()
  123. if (current) {
  124. var strHour = moment().tz(current.time.timezone.id).format('H')
  125. hour = parseInt(strHour)
  126. var strMin = moment().tz(current.time.timezone.id).format('m')
  127. minute = parseInt(strMin)
  128. var strSecond = moment().tz(current.time.timezone.id).format('s')
  129. second = parseInt(strSecond)
  130. }
  131. return (hour*3600+minute*60+second)/(24*3600)*2*Math.PI
  132. }
  133. function ring() {
  134. const currentDot: CurrentDot = {
  135. color: '#CACACA',
  136. lineWidth: 10,
  137. borderColor: '#ffffff',
  138. offset: 0
  139. }
  140. const targetRing: TargetRing = {
  141. color: '#CACACA',
  142. startArc: -Math.PI/2,
  143. durationArc: getArc()
  144. }
  145. return <Rings common={common} bgRing={bgRing} targetRing={targetRing} currentDot={currentDot} canvasId={'smal11l'} />
  146. }
  147. function languageModalContent() {
  148. return <View className="modal_bg">
  149. <View className="language_content">
  150. <View className="language_item" onClick={() => changeLanguage(true)}>
  151. <Text className="language_text">English</Text>
  152. {
  153. isEn && <Image className="check" src={require('@assets/index_time/check.png')} />
  154. }
  155. </View>
  156. <View className="line" />
  157. <View className="language_item" onClick={() => changeLanguage(false)}>
  158. <Text className="language_text">中文</Text>
  159. {
  160. !isEn && <Image className="check" src={require('@assets/index_time/check.png')} />
  161. }
  162. </View>
  163. </View>
  164. </View>
  165. }
  166. function formatTime(format: string, timestamp?: number) {
  167. // var moment = require('moment-timezone');
  168. if (current) {
  169. if (timestamp) {
  170. return dayjs(timestamp).tz(current.time.timezone.id).format(format)
  171. }
  172. return dayjs().tz(current.time.timezone.id).format(format)
  173. }
  174. return dayjs().format(format)
  175. }
  176. function dstTitle(index: number) {
  177. if (index == 0) {
  178. return t('time_of_day.index.last_change')
  179. }
  180. return t('time_of_day.index.next_change')
  181. }
  182. function dstDesc(item: any, index: number) {
  183. if (index == 0) {
  184. if (item.new_dst > 0) {
  185. return t('time_of_day.index.summer_started')
  186. }
  187. return t('time_of_day.index.winter_started')
  188. }
  189. if (item.new_dst > 0) {
  190. return t('time_of_day.index.summer_starts')
  191. }
  192. return t('time_of_day.index.winter_starts')
  193. }
  194. function dstNote(item: any) {
  195. var str = moment(item.timestamp).tz(current.time.timezone.id).format('YYYY-MM-DDTHH:mm:ss')
  196. var str2 = moment(item.timestamp - 1).tz(current.time.timezone.id).format('YYYY-MM-DDTHH:mm:ss')
  197. console.log(str, str2)
  198. debugger
  199. return 'Time was set forward 1 hour from 02:00 to 03:00.\nTime zone changed to UTC-7, Pacific Daylight Time (PDT).'
  200. }
  201. function isNight() {
  202. var hour = new Date().getHours()
  203. if (current) {
  204. var strHour = moment().tz(current.time.timezone.id).format('H')
  205. hour = parseInt(strHour)
  206. }
  207. if (hour >= 18 || hour < 6) {
  208. return true
  209. }
  210. return false
  211. }
  212. function dstModalContent() {
  213. return <View className="modal_bg">
  214. {
  215. current.time_changes.map((item, index) => {
  216. return <View className="dst_content" key={index}>
  217. <View className="dst_item">
  218. <View className="dst_card">
  219. <Text className="month">{formatTime('MMMM', item.timestamp)}</Text>
  220. <Text className="day">{formatTime('D', item.timestamp)}</Text>
  221. <Text className="week">{formatTime('dddd', item.timestamp)}</Text>
  222. <Text className="year">{formatTime('YYYY', item.timestamp)}</Text>
  223. </View>
  224. </View>
  225. <View style={{ flex: 1 }}>
  226. <Text className="dst_title">{dstTitle(index)}</Text>
  227. <Text className="dst_desc">{dstDesc(item, index)}</Text>
  228. <Text className="dst_note">{dstNote(item)}</Text>
  229. </View>
  230. </View>
  231. })
  232. }
  233. </View>
  234. }
  235. return <View className="page_container">
  236. <View style={{ position: 'relative' }}>
  237. {
  238. ring()
  239. }
  240. <View className="ring_center">
  241. <Image className="sun" src={isNight() ? require('@assets/index_time/moon.png') : require('@assets/index_time/sun.png')} />
  242. <Text className="time">{formatTime('HH:mm:ss')}</Text>
  243. <Text className="date">{global.language == 'en' ? formatTime('dddd, MMM DD') : formatTime('MMMD dddd')}</Text>
  244. </View>
  245. </View>
  246. <View className="location">
  247. <Image className="location_icon" src={require('@assets/index_time/pin.png')} />
  248. <Text className="location_text">{current ? getLocation() : t('time_of_day.index.unknown')}</Text>
  249. </View>
  250. <View style={{ flexDirection: 'row', marginTop: 10, alignItems: 'center' }} onClick={() => {
  251. if (current && current.time && current.time.timezone.use_dst) {
  252. setShowDst(true)
  253. }
  254. }}>
  255. <Text className="timezone">{current ? getTimezone() : 'UTC+8'}</Text>
  256. {
  257. current && current.time && current.time.timezone.use_dst && <Image className="location_icon" src={require('@assets/index_time/arrow_right.png')} />
  258. }
  259. </View>
  260. <View className="btn_bg" onClick={goMap}>
  261. <Text className="btn_text">{t('time_of_day.index.pick_location')}</Text>
  262. <Image className="more" src={require('@assets/index_time/more.png')} />
  263. </View>
  264. <View className="footer" onClick={() => setShowLanguage(true)}>
  265. <Text className="footer_text">{isEn ? 'English' : '中文'}</Text>
  266. <Image className="footer_icon" src={require('@assets/index_time/arrow.png')} />
  267. </View>
  268. {
  269. showLanguage && <Modal
  270. testInfo={null}
  271. themeIsWhite={true}
  272. dismiss={() => {
  273. setShowLanguage(false)
  274. }}
  275. confirm={() => { }}>
  276. {
  277. languageModalContent()
  278. }
  279. </Modal>
  280. }
  281. {
  282. showDst && <Modal
  283. testInfo={null}
  284. themeIsWhite={true}
  285. dismiss={() => {
  286. setShowDst(false)
  287. }}
  288. confirm={() => { }}>
  289. {
  290. dstModalContent()
  291. }
  292. </Modal>
  293. }
  294. </View>
  295. }