| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- import { View, Text, Image } from "@tarojs/components";
- import './index_time.scss';
- import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
- import { getCommon, getDot } from "@/features/trackTimeDuration/hooks/RingData";
- import Rings, { RingCommon, BgRing, TargetRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings";
- import { useEffect, useState } from "react";
- import DeviceInfo from 'react-native-device-info';
- import dayjs from "dayjs";
- import moment from 'moment-timezone'
- import Modal from "@/components/layout/Modal.weapp";
- import { getResources, loginAnonymous, place, systemVersion } from "./services/net";
- import Taro, { useDidShow } from "@tarojs/taro";
- import { useTranslation } from "react-i18next";
- import 'dayjs/locale/zh-cn';
- import 'dayjs/locale/en';
- import momentT from 'moment';
- import { getTimezone, getTimezoneName, kIsAndroid } from "@/utils/tools";
- import { AppState, Linking, SafeAreaView } from "react-native";
- import { method } from "lodash";
- import { AtActivityIndicator } from "taro-ui";
- import showAlert from "@/components/basic/Alert";
- // import 'moment/locale/en';
- let showUpdate = false;
- let LinearGradient, useActionSheet, useNavigation
- if (process.env.TARO_ENV == 'rn') {
- LinearGradient = require('react-native-linear-gradient').default
- useActionSheet = require('@expo/react-native-action-sheet').useActionSheet
- useNavigation = require("@react-navigation/native").useNavigation
- }
- export default function IndexTimePage() {
- let navigation;
- if (useNavigation) {
- navigation = useNavigation()
- }
- const [count, setCount] = useState(0)
- const [showLanguage, setShowLanguage] = useState(false)
- const [isEn, setIsEn] = useState(true)
- const [showDst, setShowDst] = useState(false)
- const [current, setCurrent] = useState<any>(null)
- const [loading, setLoading] = useState(false)
- const [resources, setResources] = useState<any>([])
- const { t, i18n } = useTranslation()
- useEffect(() => {
- getLanguage();
- getResources().then(res => {
- setResources(res)
- })
- AppState.addEventListener('change', handleAppStateChange);
- login()
- setInterval(() => {
- setCount(t => t + 1)
- const now = new Date()
- const seconds = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds()
- if (current && current.time && current.time.timezone.use_dst) {
- if (current.time_changes && current.time_changes.length > 1) {
- const date = new Date(current.time_changes[1].timestamp)
- const seconds2 = date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds()
- if (seconds == seconds2) {
- refresh()
- }
- }
- }
- }, 1000)
- }, [])
- function login() {
- loginAnonymous(kIsAndroid ? DeviceInfo.getAndroidIdSync() : DeviceInfo.getDeviceId()).then(res => {
- global.token = (res as any).token
- Taro.setStorage({
- key: 'token',
- data: (res as any).token
- })
- checkVersionUpdate()
- }).catch(e => {
- console.log('login error', e)
- })
- }
- useDidShow(() => {
- checkVersionUpdate()
- })
- const handleAppStateChange = (nextAppState) => {
- console.log(nextAppState)
- if (nextAppState != 'active') {
- return
- }
- if (nextAppState == 'active') {
- console.log('active')
- refresh()
- }
- };
- async function checkVersionUpdate() {
- systemVersion('time').then(res => {
- if ((res as any).result == 'UPDATE' && !showUpdate) {
- showUpdate = true
- showAlert({
- title: (res as any).title,
- content: (res as any).description,
- showCancel: true,
- confirmText: 'Update',
- confirm: () => {
- Linking.openURL((res as any).download_url)
- }
- })
- }
- else if ((res as any).result == 'FORCE_UPDATE') {
- showAlert({
- title: (res as any).title,
- content: (res as any).description,
- showCancel: false,
- confirmText: 'Update',
- confirm: () => {
- Linking.openURL((res as any).download_url)
- }
- })
- }
- })
- }
- function refresh() {
- if (current) {
- chooseLocation({
- lat: current.geo.lat,
- lng: current.geo.lng
- }, 'QUERY')
- }
- }
- async function getLanguage() {
- var strLocation = await getStorage('lastLocation')
- if (strLocation) {
- setCurrent(JSON.parse(strLocation))
- }
- var language = await getStorage('language') || 'en'
- global.language = language;
- i18n.changeLanguage(language)
- setIsEn(language == 'en')
- dayjs.locale(language == 'en' ? 'en' : 'zh-cn');
- require('moment/locale/en-gb')
- require('moment/locale/zh-cn')
- momentT.locale(language == 'en' ? 'en-gb' : 'zh-cn')
- moment.defineLocale(language == 'en' ? 'en-gb' : 'zh-cn', (momentT.localeData() as any)._config)
- moment.locale(language == 'en' ? 'en-gb' : 'zh-cn')
- var token = await getStorage('token') || ''
- global.token = token
- refresh()
- // moment.locale(language == 'en' ? 'en' : 'zh-cn');
- }
- async function getStorage(key: string) {
- try {
- const res = await Taro.getStorage({ key });
- return res.data;
- } catch {
- return '';
- }
- }
- function changeLanguage(isEnglish: boolean) {
- global.language = isEnglish ? 'en' : 'zh';
- i18n.changeLanguage(isEnglish ? 'en' : 'zh')
- setIsEn(isEnglish)
- Taro.setStorage({ key: 'language', data: isEnglish ? 'en' : 'zh' })
- setShowLanguage(false)
- dayjs.locale(isEnglish ? 'en' : 'zh-cn');
- require('moment/locale/en-gb')
- require('moment/locale/zh-cn')
- momentT.locale(isEnglish ? 'en-gb' : 'zh-cn')
- moment.defineLocale(isEnglish ? 'en-gb' : 'zh-cn', (momentT.localeData() as any)._config)
- moment.locale(isEnglish ? 'en-gb' : 'zh-cn')
- // moment.locale(isEnglish ? 'en' : 'zh-cn');
- if (current) {
- chooseLocation({
- lat: current.geo.lat,
- lng: current.geo.lng
- }, 'QUERY')
- }
- }
- async function goMap() {
- if (loading) {
- return;
- }
- const zoom = await getStorage('zoom') || 8
- jumpPage('', 'map', navigation, {
- source: 'time_of_day',
- zoom: zoom,
- lat: current ? current.geo.lat : null,
- lng: current ? current.geo.lng : null,
- chooseLocation: chooseLocation
- })
- }
- function goRecords() {
- if (loading) {
- return;
- }
- if (!current) {
- return
- }
- jumpPage('', 'MyPlaces', navigation, {
- clearLocation: clearLocation,
- changeLocation: changeLocation
- })
- }
- function showPrivacy() {
- const resource = resources.filter((item: any) => {
- const code = isEn ? "time_privacy_en" : "time_privacy_cn"
- return item.code == code
- })
- if (!resource || resource.length == 0) {
- Taro.showToast({
- title: 'Not found.',
- icon: 'none'
- })
- return
- }
- jumpPage('/pages/common/H5?title=User Agreement&url=' + resource[0].url, 'H5', navigation, {
- title: resource[0].name,
- url: resource[0].url
- })
- }
- function chooseLocation(res: any, method: string) {
- if (res.lng < -180) {
- res.lng += 360
- }
- if (res.lng > 180) {
- res.lng -= 360
- }
- if (res.lat > 90) {
- res.lat -= 90
- }
- if (res.lat < -90) {
- res.lat += 90
- }
- setLoading(true)
- place(res.lat, res.lng, method).then(res => {
- console.log(res)
- setCurrent((res as any).location)
- saveLocation((res as any).location)
- setLoading(false)
- }).catch(e => {
- console.log(e)
- setLoading(false)
- })
- }
- async function saveLocation(location: any) {
- Taro.setStorage({ key: 'lastLocation', data: JSON.stringify(location) })
- var locations = await getStorage('locations')
- var list: any = []
- var isFind = false;
- if (locations) {
- list = JSON.parse(locations)
- }
- list.map(item => {
- if (item.geo.lat == location.geo.lat && item.geo.lng == location.geo.lng) {
- isFind = true
- }
- })
- if (!isFind) {
- list.push(location)
- }
- Taro.setStorage({ key: 'locations', data: JSON.stringify(list) })
- }
- function clearLocation() {
- Taro.clearStorage()
- setCurrent(null)
- }
- function changeLocation(location) {
- setCurrent(location)
- Taro.setStorage({ key: 'lastLocation', data: JSON.stringify(location) })
- chooseLocation({
- lat: location.geo.lat,
- lng: location.geo.lng
- }, 'SWITCH')
- }
- function getLocation() {
- if (current.geo) {
- if (current.geo.city) {
- return current.geo.city
- }
- if (current.geo.country) {
- return current.geo.country
- }
- return `${Math.abs(parseInt(current.geo.lat))}°${parseInt(current.geo.lat) < 0 ? 'S' : 'N'} ${Math.abs(parseInt(current.geo.lng))}°${parseInt(current.geo.lng) < 0 ? 'W' : 'E'}`
- }
- return t('time_of_day.index.unknown')
- }
- function getTimezone1() {
- if (current.time && current.time.timezone) {
- return current.time.timezone.offset_id + ' · ' + current.time.timezone.name
- }
- return ''
- }
- const common: RingCommon = {
- useCase: 'ChooseScenario',
- radius: 115,
- lineWidth: 26,
- isFast: true,
- status: 'WAIT_FOR_START'
- }
- const bgRing: BgRing = {
- color: '#EAE9E9'
- }
- function getArc() {
- var hour = new Date().getHours()
- var minute = new Date().getMinutes()
- var second = new Date().getSeconds()
- if (current) {
- var strHour = moment().tz(current.time.timezone.id).format('H')
- hour = parseInt(strHour)
- var strMin = moment().tz(current.time.timezone.id).format('m')
- minute = parseInt(strMin)
- var strSecond = moment().tz(current.time.timezone.id).format('s')
- second = parseInt(strSecond)
- }
- return (hour * 3600 + minute * 60 + second) / (24 * 3600) * 2 * Math.PI
- }
- function ring() {
- var offset = 0
- var hour = new Date().getHours()
- var minute = new Date().getMinutes()
- if (current) {
- var strHour = moment().tz(current.time.timezone.id).format('H')
- hour = parseInt(strHour)
- var strMin = moment().tz(current.time.timezone.id).format('m')
- minute = parseInt(strMin)
- }
- if (hour != new Date().getHours() || minute != new Date().getMinutes()) {
- offset = hour * 60 + minute - new Date().getHours() * 60 - new Date().getMinutes()
- }
- const currentDot: CurrentDot = {
- color: '#CACACA',
- lineWidth: 10,
- borderColor: '#fff',
- offset: offset,
- whiteIcon: true
- }
- const targetRing: TargetRing = {
- color: '#CACACA',
- startArc: -Math.PI / 2,
- durationArc: getArc()
- }
- return <Rings common={common} bgRing={bgRing} targetRing={targetRing} currentDot={currentDot} canvasId={'smal11l'} />
- }
- function languageModalContent() {
- return <View className="modal_bg">
- <View className="language_content">
- <View className="language_item" onClick={() => changeLanguage(isEn ? true : false)}>
- <Text className="language_text">{isEn ? 'English' : '中文'}</Text>
- <Image className="check" src={require('@assets/index_time/check.png')} />
- </View>
- <View className="line" />
- <View className="language_item" onClick={() => changeLanguage(isEn ? false : true)}>
- <Text className="language_text">{!isEn ? 'English' : '中文'}</Text>
- </View>
- </View>
- </View>
- }
- function formatTime(format: string, timestamp?: number) {
- // var moment = require('moment-timezone');
- if (current) {
- if (timestamp) {
- return moment(timestamp).tz(current.time.timezone.id).format(format)
- }
- return moment().tz(current.time.timezone.id).format(format)
- }
- return dayjs().format(format)
- }
- function dstTitle(index: number) {
- if (index == 0) {
- return t('time_of_day.index.last_change')
- }
- return t('time_of_day.index.next_change')
- }
- function dstDesc(item: any, index: number) {
- if (index == 0) {
- if (item.new_dst > 0) {
- return t('time_of_day.index.summer_started')
- }
- return t('time_of_day.index.winter_started')
- }
- if (item.new_dst > 0) {
- return t('time_of_day.index.summer_starts')
- }
- return t('time_of_day.index.winter_starts')
- }
- function isNight() {
- var hour = new Date().getHours()
- if (current) {
- var strHour = moment().tz(current.time.timezone.id).format('H')
- hour = parseInt(strHour)
- }
- if (hour >= 18 || hour < 6) {
- return true
- }
- return false
- }
- function dstModalContent() {
- return <View className="modal_bg">
- {
- current.time_changes.map((item, index) => {
- return <View className="dst_content" key={index}>
- <View className="dst_item">
- <View className="dst_card">
- <Text className="month">{formatTime('MMMM', item.timestamp)}</Text>
- <Text className="day">{formatTime('D', item.timestamp)}</Text>
- <Text className="week">{formatTime('dddd', item.timestamp)}</Text>
- <Text className="year">{formatTime('YYYY', item.timestamp)}</Text>
- </View>
- </View>
- <View style={{ flex: 1 }}>
- <Text className="dst_title">{item.title}</Text>
- <Text className="dst_desc" style={{ marginBottom: 10 }}>{item.subtitle}</Text>
- {
- item.descriptions.map((desc, j) => {
- return <Text className="dst_note" key={j * 100}>· {desc}</Text>
- })
- }
- </View>
- </View>
- })
- }
- </View>
- }
- function detail() {
- return <View className="page_container">
- <View style={{ position: 'relative' }}>
- {
- ring()
- }
- <View className="ring_center">
- <Image className="sun" src={isNight() ? require('@assets/index_time/moon.png') : require('@assets/index_time/sun.png')} />
- <Text className="time">{formatTime('HH:mm:ss')}</Text>
- <Text className="date1">{global.language == 'en' ? formatTime('dddd, MMM D') : formatTime('MMMD日 dddd')}</Text>
- </View>
- </View>
- <View className="location">
- {
- loading && <View style={{ display: 'flex', overflow: 'hidden', height: 20, marginRight: 5 }}><AtActivityIndicator color="#CACACA" /></View>
- }
- {
- loading && <Text className="location_text">{t('time_of_day.index.updating')}</Text>
- }
- {
- !loading && <Image className="location_icon" src={require('@assets/index_time/pin.png')} />
- }
- {
- !loading && <Text className="location_text">{current ? getLocation() : t('time_of_day.index.unknown')}</Text>
- }
- </View>
- <View style={{ flexDirection: 'row', marginTop: 10, alignItems: 'center', opacity: loading ? 0 : 1 }} onClick={() => {
- if (current && current.time && current.time.timezone.use_dst) {
- setShowDst(true)
- }
- }}>
- <Text className="timezone">{current ? getTimezone1() : getTimezone()}</Text>
- {
- current && current.time && current.time.timezone.use_dst && <Image className="location_icon" src={require('@assets/index_time/arrow_right.png')} />
- }
- </View>
- <View className="btn_bg2" style={{ opacity: loading ? 0.4 : 1 }} onClick={goMap} onLongClick={goRecords} onLongPress={goRecords} onLongTap={goRecords}>
- <Image className="btn_img_bg" src={require('@assets/index_time/btn_bg.png')} />
- <View className="btn_text_bg">
- <Text className="btn_text">{!current ? t('time_of_day.index.pick_location') : t('time_of_day.index.change_location')}</Text>
- </View>
- {
- current && <Image className="more" onClick={goRecords} src={require('@assets/index_time/more.png')} />
- }
- </View>
- {/* <View className="btn_bg" onClick={goMap} onLongClick={goRecords} onLongPress={goRecords} onLongTap={goRecords}>
- <Text className="btn_text">{!current ? t('time_of_day.index.pick_location') : t('time_of_day.index.change_location')}</Text>
- {
- current && <Image className="more" onClick={goRecords} src={require('@assets/index_time/more.png')} />
- }
- </View> */}
- <View className="footer" >
- <Text className="footer_text">{t('time_of_day.index.version')}</Text>
- <Text className="footer_text" onClick={showPrivacy} style={{ paddingLeft: 20, paddingRight: 20 }}>{t('time_of_day.index.privacy')}</Text>
- <Text className="footer_text" onClick={() => setShowLanguage(true)}>{isEn ? 'English' : '中文'}</Text>
- <Image className="footer_icon" src={require('@assets/index_time/arrow.png')} onClick={() => setShowLanguage(true)} />
- </View>
- {
- showLanguage && <Modal
- testInfo={null}
- themeIsWhite={true}
- dismiss={() => {
- setShowLanguage(false)
- }}
- confirm={() => { }}>
- {
- languageModalContent()
- }
- </Modal>
- }
- {
- showDst && <Modal
- testInfo={null}
- themeIsWhite={true}
- dismiss={() => {
- setShowDst(false)
- }}
- confirm={() => { }}>
- {
- dstModalContent()
- }
- </Modal>
- }
- </View>
- }
- return detail()
- }
|