Skip to content

Commit

Permalink
First
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenBrough committed Jun 15, 2016
0 parents commit 9213067
Show file tree
Hide file tree
Showing 82 changed files with 1,878 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
/.idea
1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
58 changes: 58 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
apply plugin: 'com.android.application'
apply plugin: 'android-apt'

android {
compileSdkVersion 23
buildToolsVersion "23.0.2"

defaultConfig {
applicationId "com.blotcoo.provocraftcodechallenge"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}

sourceSets {
main {
// Manually add resource dirs so we can organize them a bit better
res.srcDirs = [
'src/main/res',
'src/main/res/layout/home',
'src/main/res/layout/detail',
]
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:recyclerview-v7:23.4.0'
compile 'com.android.support:cardview-v7:23.4.0'

// Networking
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'

// View binding
compile 'com.jakewharton:butterknife:8.1.0'
apt 'com.jakewharton:butterknife-compiler:8.1.0'

// Reactive
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.5'
compile 'com.jakewharton.rxbinding:rxbinding:0.2.0'

// Image handling
compile 'com.squareup.picasso:picasso:2.5.2'
}
17 changes: 17 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Users\Stephen\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.blotcoo.provocraftcodechallenge;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
23 changes: 23 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blotcoo.provocraftcodechallenge">

<uses-permission android:name="android.permission.INTERNET"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:name=".App"
android:theme="@style/AppTheme">
<activity android:name=".home.HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
19 changes: 19 additions & 0 deletions app/src/main/java/com/blotcoo/provocraftcodechallenge/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.blotcoo.provocraftcodechallenge;

import android.app.Application;
import android.content.Context;

public class App extends Application {

private static Context mContext;

@Override
public void onCreate() {
super.onCreate();
mContext = this;
}

public static Context getContext() {
return mContext;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.blotcoo.provocraftcodechallenge.details;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.blotcoo.provocraftcodechallenge.App;
import com.blotcoo.provocraftcodechallenge.R;
import com.blotcoo.provocraftcodechallenge.util.network.models.Channel;

import java.util.Arrays;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

public class DetailsFragment extends Fragment {

public Channel c;

// Lists of our string resources
List<String> cloudy;
List<String> sunny;
List<String> rainy;
List<String> snowy;

// Bind all the views
@BindView(R.id.temperature)
TextView temperature;
@BindView(R.id.conditionText)
TextView conditionsText;
@BindView(R.id.conditionsIcon)
ImageView conditionsIcon;
@BindView(R.id.forecast)
LinearLayout forecast;
@BindView(R.id.location)
TextView location;
@BindView(R.id.country)
TextView country;
@BindView(R.id.chill)
TextView chill;
@BindView(R.id.direction)
TextView direction;
@BindView(R.id.humidity)
TextView humidity;
@BindView(R.id.pressure)
TextView pressure;
@BindView(R.id.rising)
TextView rising;
@BindView(R.id.visibility)
TextView visibility;
@BindView(R.id.sunrise)
TextView sunrise;
@BindView(R.id.sunset)
TextView sunset;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.details_fragment, container, false);
ButterKnife.bind(this, v);

cloudy = Arrays.asList(App.getContext().getResources().getStringArray(R.array.cloudy));
sunny = Arrays.asList(App.getContext().getResources().getStringArray(R.array.sunny));
rainy = Arrays.asList(App.getContext().getResources().getStringArray(R.array.rainy));
snowy = Arrays.asList(App.getContext().getResources().getStringArray(R.array.snowy));

location.setText(c.location.city + ", " + c.location.region);
country.setText(c.location.country);
temperature.setText(c.item.condition.temp + "\u00B0" + c.units.temperature);
conditionsText.setText(c.item.condition.text);

chill.setText(c.wind.chill);
direction.setText(c.wind.direction);
humidity.setText(c.atmosphere.humidity);
pressure.setText(c.atmosphere.pressure);
rising.setText(c.atmosphere.rising);
visibility.setText(c.atmosphere.visibility);
sunrise.setText(c.astronomy.sunrise);
sunset.setText(c.astronomy.sunset);
conditionsIcon.setImageResource(getConditionIcon(c.item.condition.code));

// Setup forecast
for (int i = 0; i < 7; i++) {
View day = LayoutInflater.from(getActivity()).inflate(R.layout.forecast, forecast, false);
((TextView) day.findViewById(R.id.date)).setText(c.item.forecast.get(i).day);
((ImageView) day.findViewById(R.id.icon)).setImageResource(getConditionIcon(c.item.forecast.get(i).code));
((TextView) day.findViewById(R.id.description)).setText(c.item.forecast.get(i).text);
((TextView) day.findViewById(R.id.high)).setText(c.item.forecast.get(i).high + "\u00B0" + c.units.temperature);
((TextView) day.findViewById(R.id.low)).setText(c.item.forecast.get(i).low + "\u00B0" + c.units.temperature);

forecast.addView(day);
}

return v;
}

private int getConditionIcon(String code) {
if (cloudy.contains(c.item.condition.code))
return R.drawable.ic_cloudy;
else if (sunny.contains(c.item.condition.code))
return R.drawable.ic_sunny;
else if (rainy.contains(c.item.condition.code))
return R.drawable.ic_rainy;
else if (snowy.contains(c.item.condition.code))
return R.drawable.ic_snowy;
else return R.drawable.ic_sunny;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.blotcoo.provocraftcodechallenge.home;

import android.support.v4.app.Fragment;

/**
* This fragment is wild and free! A fragment without
* the oppressive rule of configuration change! It will save
* us all in our save state!
*
* Seriously, this holds our presenter and other state so it doesn't get crushed
* when you turn the phone. And other configuration changes. Makes it easier to
* keep complex objects around instead of using the save instance state Bundle
*/
public class FragmentSansFrontieres extends Fragment {
public static String TAG = "FragmentSansFrontieres";
public HomeContract.Presenter presenter;

public FragmentSansFrontieres() {
setRetainInstance(true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.blotcoo.provocraftcodechallenge.home;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;

import com.blotcoo.provocraftcodechallenge.R;
import com.blotcoo.provocraftcodechallenge.details.DetailsFragment;
import com.blotcoo.provocraftcodechallenge.util.network.ApiImpl;
import com.blotcoo.provocraftcodechallenge.util.network.models.Channel;

public class HomeActivity extends AppCompatActivity implements HomeContract.View{
private static final String TAG = "HomeActivity";

HomeContract.Presenter presenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_activity);

// Check if Fragment Sans Frontieres is already added, if not, get one configured and saved
if (getSupportFragmentManager().findFragmentByTag(FragmentSansFrontieres.TAG) == null) {
FragmentSansFrontieres frag = new FragmentSansFrontieres();
frag.presenter = new HomePresenterImpl(new ApiImpl());
getSupportFragmentManager().beginTransaction().add(frag, FragmentSansFrontieres.TAG).commit();
getSupportFragmentManager().executePendingTransactions();
}

// If the activity is completely fresh, load up the home fragment
if (null == savedInstanceState) {
getSupportFragmentManager().beginTransaction().replace(R.id.content, new HomeFragment()).commit();
}
}

@Override
public void showForecastDetails(Channel channel) {
// Hide keyboard
View v = getCurrentFocus();
if (v != null) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}

DetailsFragment frag = new DetailsFragment();
frag.c = channel;
getSupportFragmentManager().beginTransaction()
.add(R.id.content, frag)
.addToBackStack(null)
.commit();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.blotcoo.provocraftcodechallenge.home;

import com.blotcoo.provocraftcodechallenge.util.network.models.Channel;
import com.blotcoo.provocraftcodechallenge.util.network.models.WeatherApiBaseModel;

import retrofit2.Callback;

public class HomeContract {
interface View {
/**
* Shows a page with more details on the forecast
*/
void showForecastDetails(Channel channel);
}

interface Presenter {

/**
* Calls up the Yahoo Weather API using a Forecast YQL query
* @param searchQuery Location to search for
* @return A callback containing the query results
*/
void searchWeatherForecast(String searchQuery, Callback<WeatherApiBaseModel> cb);
}
}
Loading

0 comments on commit 9213067

Please sign in to comment.