import { observable , runInAction , action } from 'mobx' ; import Taro from '@tarojs/taro' ; import { ChangeEvent } from 'react' ; import debounce from 'lodash.debounce' ; import { convertCelsiusFahrenheit , convertKmMiles , convertMillibarsInches , } from '../utils/convert' ; import { setLoadingToast , setToast } from '../utils/toast' ; import httpClient from '../utils/https' ; import { defaultPhotoUrl , toastTxt } from '../constants/constants' ; import { Meta , Weather } from '../types/weather' ; import Region from '../types/region' ; interface WeatherRes { requestID : string ; weatherResult : { meta : Meta ; weathers : Weather [ ] ; } ; } interface RegionRes { regionList : Region [ ] ; } class WeatherStore { construtor ( ) { this . getRegion = debounce ( this . getRegion , 150 ) ; } @ observable . deep public weatherData : Weather = { location : { countryName : '' , displayName : '' , } , observation : { conditionDescription : 'Sunny' , conditionCode : 32 , localTime : { timestamp : '' , } , observationTime : { hour : 0 , weekday : 0 , } , precipitationProbability : 0 , temperature : { now : 0 , high : 0 , low : 0 , feelsLike : 0 , } , visibility : 0 , uvIndex : 1 , uvDescription : 'low' , humidity : 100 , dayPartTexts : [ ] , windSpeed : 0 , windDirectionCode : 'South South East' , barometricPressure : 0 , } , precipitations : [ { timeSlot : 'MORNING' , probability : 0 , } , { timeSlot : 'AFTERNOON' , probability : 0 , } , { timeSlot : 'EVENING' , probability : 0 , } , { timeSlot : 'NIGHT' , probability : 0 , } , ] , sunAndMoon : { sunrise : 0 , sunset : 0 , moonPhase : 1 , } , forecasts : { daily : [ ] , hourly : [ ] , } , photos : [ { ownerName : '' , resolutions : [ ] , } , ] , } ; @ observable . deep public metaData : Meta = { conditionMap : { } , skycode : { 32 : 'clear_day' , } , } ; @ observable public curWoeid = '' ; @ observable public curCountryName = '--' ; @ observable public curCityName = '--' ; @ observable public isFahrenheit = false ; @ observable public systemLanguage = 'en-US' ; @ observable public backgroudImageUrl = defaultPhotoUrl ; @ observable public widthBackgroudImageUrl = '' ; @ observable public showModal = false ; @ observable public showSearch = false ; @ observable public isSearching = false ; @ observable public regionList : Region [ ] = [ ] ; @ action public handleTemperatureTypeChange = ( type ) => { this . isFahrenheit = type ; const observation = this . weatherData . observation ; const forecasts = this . weatherData . forecasts ; observation . temperature . feelsLike = convertCelsiusFahrenheit ( this . isFahrenheit , observation . temperature . feelsLike ) ; observation . temperature . now = convertCelsiusFahrenheit ( this . isFahrenheit , observation . temperature . now ) ; observation . temperature . low = convertCelsiusFahrenheit ( this . isFahrenheit , observation . temperature . low ) ; observation . temperature . high = convertCelsiusFahrenheit ( this . isFahrenheit , observation . temperature . high ) ; observation . visibility = convertKmMiles ( this . isFahrenheit , observation . visibility ) ; observation . windSpeed = convertKmMiles ( this . isFahrenheit , observation . windSpeed ) ; observation . barometricPressure = convertMillibarsInches ( this . isFahrenheit , observation . barometricPressure ) ; forecasts . daily . forEach ( value => { value . temperature . low = convertCelsiusFahrenheit ( this . isFahrenheit , value . temperature . low ) ; value . temperature . high = convertCelsiusFahrenheit ( this . isFahrenheit , value . temperature . high ) ; } ) ; forecasts . hourly . forEach ( value => { value . temperature . now = convertCelsiusFahrenheit ( this . isFahrenheit , value . temperature . now ) ; } ) ; } ; @ action public showSearchDialog = ( ) => { this . getStorage ( ) ; this . showSearch = true ; } ; @ action public hideSearchDialog = ( ) => { this . showSearch = false ; setTimeout ( ( ) => { this . isSearching = false ; } , 350 ) ; } ; @ action public handleInputTextChange = ( e ) => { this . isSearching = true ; this . getRegion ( e . target . value ) ; } ; @ action public handleSelectRegionChange = ( woeid , qualifiedName ) => { Taro . setStorage ( { key : woeid . toString ( ) , data : qualifiedName , } ) . then ( ( ) => { this . getWeatherById ( woeid ) ; } ) ; } ; @ action public deleteHistoryItemByWoeid = ( woeid ) => { Taro . removeStorage ( { key : woeid . toString ( ) , } ) . then ( ( ) => { setToast ( toastTxt . deleteHistorySuccess , 'success' ) ; this . getStorage ( ) ; } ) ; } ; public getWeatherById = async ( woeid ) => { setLoadingToast ( true , toastTxt . weatherLoading ) ; try { const res = await httpClient ( 'getWeatherById' , { woeid , lang : this . systemLanguage , } ) ; runInAction ( ( ) => { this . curWoeid = woeid ; this . isFahrenheit = true ; const weatherResult = ( res as WeatherRes ) . weatherResult ; this . weatherData = weatherResult . weathers [ 0 ] ; this . metaData = weatherResult . meta ; this . curCountryName = this . weatherData . location . countryName ; this . curCityName = this . weatherData . location . displayName ; this . backgroudImageUrl = this . weatherData . photos [ 0 ] . resolutions [ 0 ] . url ; this . widthBackgroudImageUrl = this . weatherData . photos [ 0 ] . resolutions [ 1 ] . url ; setLoadingToast ( false ) ; this . handleTemperatureTypeChange ( false ) ; } ) ; } catch ( e ) { setToast ( toastTxt . deleteHistoryFail ) ; Taro . vibrateLong ( ) ; } finally { Taro . stopPullDownRefresh ( ) ; } } ; public getWoeid = async ( lat , lon , lang = this . systemLanguage ) => { setLoadingToast ( true , toastTxt . locationLoading ) ; try { const res = await httpClient ( 'getWoeid' , { lat , lon , lang , } ) ; runInAction ( ( ) => { const location = JSON . parse ( res as any ) . location ; this . curCountryName = location . country ; this . curCityName = location . region ; this . getWeatherById ( location . woeid ) ; } ) ; } catch ( e ) { setLoadingToast ( false ) ; setToast ( toastTxt . cityFail ) ; } } ; public getRegion = async ( text ) => { try { const res = await httpClient ( 'getRegion' , { region : encodeURI ( text ) , } ) ; runInAction ( ( ) => { if ( ( res as RegionRes ) . regionList ) { this . regionList = ( res as RegionRes ) . regionList ; } } ) ; } catch ( e ) { setToast ( toastTxt . cityFail ) ; } } ; public getStorage = ( ) => { this . regionList = [ ] ; Taro . getStorageInfo ( ) . then ( res => { ; ( res as any ) . keys . forEach ( key => Taro . getStorage ( { key , } ) . then ( data => { this . regionList . push ( { woeid : parseInt ( key , 10 ) , qualifiedName : data . data , } ) ; } ) ) ; } ) ; } ; public getSetting = ( ) => { Taro . getSetting ( ) . then ( res => { if ( ! res . authSetting [ 'scope.userLocation' ] ) { this . showModal = true ; } else { this . showModal = false ; this . getPosition ( ) ; setToast ( toastTxt . coordinatesFail ) ; } } ) ; } ; public getPosition = ( ) => { if ( this . showSearch ) { this . showSearch = false ; } setLoadingToast ( true , toastTxt . coordinatesLoading ) ; Taro . getLocation ( { type : 'gcj02' , } ) . then ( res => { const lat = res . latitude ; const lon = res . longitude ; this . getWoeid ( lat , lon ) ; } ) . catch ( ( ) => { setLoadingToast ( false ) ; this . getSetting ( ) ; } ) ; } ; public getLanguage = ( ) => { Taro . getSystemInfo ( ) . then ( res => { this . systemLanguage = res . language ; this . getPosition ( ) ; } ) . catch ( ( ) => { setToast ( toastTxt . languageFail ) ; } ) ; } ; } const weatherStore = new WeatherStore ( ) ; export default weatherStore ;