/* * Copyright 2015. Appsi Mobile * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.appsimobile.appsii.module.home; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; import android.os.AsyncTask; import android.support.annotation.Nullable; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.Time; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; import android.widget.PopupMenu; import android.widget.TextView; import com.appsimobile.appsii.AccountHelper; import com.appsimobile.appsii.BitmapUtils; import com.appsimobile.appsii.R; import com.appsimobile.appsii.dagger.AppInjector; import com.appsimobile.appsii.module.home.config.HomeItemConfiguration; import com.appsimobile.appsii.module.home.config.HomeItemConfigurationHelper; import com.appsimobile.appsii.module.weather.ImageDownloadHelper; import com.appsimobile.appsii.module.weather.WeatherActivity; import com.appsimobile.appsii.module.weather.WeatherLoadingService; import com.appsimobile.appsii.module.weather.WeatherUtils; import com.appsimobile.appsii.module.weather.loader.WeatherData; import com.appsimobile.appsii.preference.PreferenceHelper; import com.appsimobile.paintjob.PaintJob; import java.io.File; import java.util.TimeZone; import javax.inject.Inject; /** * Created by nick on 22/01/15. */ public abstract class AbsWeatherViewHolder extends AbsHomeViewHolder implements HomeItemConfigurationHelper.ConfigurationListener, View.OnClickListener, PopupMenu.OnMenuItemClickListener { static final Time sTime = new Time(); final boolean mShowsWallpaper; final View mOverflow; /** * This is null when {@link #mShowsWallpaper} is false */ @Nullable final ImageView mCellBackground; @Inject HomeItemConfiguration mConfigurationHelper; @Inject SharedPreferences mSharedPreferences; @Inject BitmapUtils mBitmapUtils; @Inject WeatherUtils mWeatherUtils; HomeItem mHomeItem; AsyncTask<Void, Void, WeatherData> mLoaderTask; BroadcastReceiver mReceiver; OnWeatherCellClickListener mOnWeatherCellClickListener; @Inject PreferenceHelper mPreferenceHelper; String mBackgroundLoadedForWoeid; WeatherData mWeatherData; PaintJob mPaintJob; @Inject AccountHelper mAccountHelper; public AbsWeatherViewHolder(HomeViewWrapper view, boolean showsWallpaper) { super(view); AppInjector.inject(this); mShowsWallpaper = showsWallpaper; mOverflow = view.findViewById(R.id.overflow); mCellBackground = (ImageView) view.findViewById(R.id.weather_location_background); mOverflow.setOnClickListener(this); if (showsWallpaper && mCellBackground == null) { throw new IllegalStateException("Expected wallpaper view"); } view.setOnClickListener(this); } public void setOnWeatherCellClickListener( OnWeatherCellClickListener onWeatherCellClickListener) { mOnWeatherCellClickListener = onWeatherCellClickListener; } @Override void bind(HomeItem item, int heightPx) { mHomeItem = item; applySuggestedHeight(heightPx); } @Override public void onAllowLoads() { mConfigurationHelper.addConfigurationListener(this); mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { updateConfiguration(); } }; IntentFilter intentFilter = new IntentFilter(WeatherLoadingService.ACTION_WEATHER_UPDATED); itemView.getContext().registerReceiver(mReceiver, intentFilter); updateConfiguration(); } @Override public void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (mWeatherData != null) { applyBackgroundImageIfNeeded(mWeatherData.woeid); } } @Override public void onDisallowLoads() { mConfigurationHelper.removeConfigurationListener(this); itemView.getContext().unregisterReceiver(mReceiver); if (mLoaderTask != null) { mLoaderTask.cancel(true); } } @Override public void onDetached(boolean allowLoads) { super.onDetached(allowLoads); if (mCellBackground != null) { mCellBackground.setImageDrawable(null); } if (mPaintJob != null) { mPaintJob.cancel(); } } @Override public boolean onInterceptTouchEvent(MotionEvent e) { return false; } @Override public boolean onTouchEvent(MotionEvent e) { return false; } void updateConfiguration() { long cellId = mHomeItem.mId; String woeid = mConfigurationHelper.getProperty( cellId, WeatherFragment.PREFERENCE_WEATHER_WOEID, null); if (woeid == null) { long lastUpdateMillis = mSharedPreferences.getLong(WeatherLoadingService.PREFERENCE_LAST_UPDATED_MILLIS, 0); long elapsed = System.currentTimeMillis() - lastUpdateMillis; if (elapsed < DateUtils.DAY_IN_MILLIS) { woeid = mSharedPreferences.getString( WeatherLoadingService.PREFERENCE_LAST_KNOWN_WOEID, null); } } if (woeid == null) { woeid = mPreferenceHelper.getDefaultLocationWoeId(); } if (woeid != null) { startLoadWeatherData(woeid); } else { onNoWeatherDataAvailable(); } if (WeatherLoadingService.hasTimeoutExpired(mSharedPreferences)) { mAccountHelper.requestSync(); } } void startLoadWeatherData(final String woeid) { final Context context = itemView.getContext(); if (mLoaderTask != null) { mLoaderTask.cancel(true); } mLoaderTask = new AsyncTask<Void, Void, WeatherData>() { @Override protected WeatherData doInBackground(Void... params) { return mWeatherUtils.getWeatherData(context, woeid); } @Override protected void onPostExecute(WeatherData weatherData) { mWeatherData = weatherData; if (weatherData == null) { onNoWeatherDataAvailable(); } else { onWeatherDataReady(weatherData); applyBackgroundImageIfNeeded(weatherData.woeid); } } }; mLoaderTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } abstract void onNoWeatherDataAvailable(); abstract void onWeatherDataReady(WeatherData weatherData); public void applyBackgroundImageIfNeeded(String woeid) { if (!mShowsWallpaper) return; if (mCellBackground == null) return; if (TextUtils.equals(woeid, mBackgroundLoadedForWoeid)) { return; } if (mPaintJob != null) { mPaintJob.cancel(); } mCellBackground.setImageDrawable(null); int w = (int) (itemView.getWidth() * 1.5f); int h = (int) (itemView.getHeight() * 1.5f); PaintJob.Builder builder = PaintJob.newBuilder(itemView, new BackgroundLoader( itemView.getContext(), mWeatherUtils, woeid, w, h, 10, true, mBitmapUtils)); builder.setBitmapCallback(new PaintJob.BitmapCallback() { @Override public void onBitmapLoaded(Bitmap bitmap, boolean immediate) { if (bitmap == null) { mCellBackground.setImageDrawable(null); return; } Drawable tmp = new ColorDrawable(Color.TRANSPARENT); Drawable drawable = new BitmapDrawable(itemView.getResources(), bitmap); TransitionDrawable d = new TransitionDrawable(new Drawable[]{ tmp, drawable }); mCellBackground.setImageDrawable(d); d.startTransition(150); d.setCrossFadeEnabled(true); } }); configurePaintJob(builder); PaintJob paintJob = builder.build(); paintJob.execute(150); mPaintJob = paintJob; } protected void configurePaintJob(PaintJob.Builder paintJob) { } @Override public boolean onMenuItemClick(MenuItem item) { int itemId = item.getItemId(); if (itemId == R.id.action_cell_weather_prefs) { Context context = itemView.getContext(); Intent intent = new Intent(context, CellWeatherActivity.class); intent.putExtra(CellWeatherActivity.EXTRA_CELL_ID, mHomeItem.mId); intent.putExtra(CellWeatherActivity.EXTRA_CELL_TYPE, mHomeItem.mDisplayType); context.startActivity(intent); return true; } return false; } @Override public void onConfigurationOptionUpdated(long cellId, String key, String value) { if (cellId == mHomeItem.mId) { updateConfiguration(); } } @Override public void onConfigurationOptionDeleted(long cellId, String key) { if (cellId == mHomeItem.mId) { updateConfiguration(); } } @Override public void onClick(View v) { if (v == mOverflow) { onOverflowClicked(v); } else { String woeid = mConfigurationHelper.getProperty( mHomeItem.mId, WeatherFragment.PREFERENCE_WEATHER_WOEID, null); onBackgroundClicked(woeid); } } private void onOverflowClicked(View v) { PopupMenu popupMenu = new PopupMenu(v.getContext(), v); MenuInflater inflater = popupMenu.getMenuInflater(); inflater.inflate(R.menu.home_item_weather, popupMenu.getMenu()); popupMenu.setOnMenuItemClickListener(this); popupMenu.show(); } public void onBackgroundClicked(String woeid) { if (mOnWeatherCellClickListener != null) { mOnWeatherCellClickListener.onWeatherCellClicked(woeid); } else { Context context = itemView.getContext(); Intent intent = new Intent(context, WeatherActivity.class); String timezone = mConfigurationHelper.getProperty( mHomeItem.mId, WeatherFragment.PREFERENCE_WEATHER_TIMEZONE, null); String defaultUnit = mPreferenceHelper.getDefaultWeatherTemperatureUnit(); String unit = mConfigurationHelper.getProperty( mHomeItem.mId, WeatherFragment.PREFERENCE_WEATHER_UNIT, defaultUnit); if (timezone == null) timezone = TimeZone.getDefault().getID(); intent.putExtra(WeatherActivity.EXTRA_WOEID, woeid); intent.putExtra(WeatherActivity.EXTRA_UNIT, unit); intent.putExtra(WeatherActivity.EXTRA_TIME_ZONE, timezone); context.startActivity(intent); } } void setupTitle(TextView textView, WeatherData weatherData, long cellId) { PreferenceHelper preferenceHelper = mPreferenceHelper; String defaultTitleType = preferenceHelper.getDefaultWeatherTitleType(); String titleType = mConfigurationHelper.getProperty(cellId, WeatherFragment.PREFERENCE_WEATHER_TITLE_TYPE, defaultTitleType); if ("condition".equals(titleType)) { String title = mWeatherUtils.formatConditionCode(weatherData.nowConditionCode); textView.setText(title); } else { textView.setText(weatherData.location); } } public interface OnWeatherCellClickListener { void onWeatherCellClicked(String woeid); } static class BackgroundLoader implements PaintJob.BitmapSource { final Context mContext; final String mWoeid; final int mWidth; final int mHeight; final boolean mIsDay; final int mConditionCode; final BitmapUtils mBitmapUtils; WeatherUtils mWeatherUtils; BackgroundLoader(Context context, WeatherUtils weatherUtils, String woeid, int w, int h, int conditionCode, boolean isDay, BitmapUtils bitmapUtils) { mContext = context; mWeatherUtils = weatherUtils; mWoeid = woeid; mWidth = w; mHeight = h; mConditionCode = conditionCode; mIsDay = isDay; mBitmapUtils = bitmapUtils; } @Override public Bitmap loadBitmapAsync() { File[] files = mWeatherUtils.getCityPhotos(mContext, mWoeid); Bitmap bitmap; if (files != null) { int idx = 0; File file = files[idx]; bitmap = mBitmapUtils.decodeSampledBitmapFromFile(file, mWidth, mHeight); return bitmap; } int resId = ImageDownloadHelper.getFallbackDrawableForConditionCode( mIsDay, mConditionCode); return BitmapFactory.decodeResource(mContext.getResources(), resId); } } }