@ -1,147 +0,0 @@
|
|||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'com.neenbedankt.android-apt'
|
|
||||||
apply plugin: 'me.tatarka.retrolambda'
|
|
||||||
apply plugin: 'jacoco'
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 25
|
|
||||||
buildToolsVersion "25.0.2"
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId "org.isoron.uhabits"
|
|
||||||
minSdkVersion 19
|
|
||||||
targetSdkVersion 25
|
|
||||||
|
|
||||||
buildConfigField "Integer", "databaseVersion", "19"
|
|
||||||
buildConfigField "String", "databaseFilename", "\"uhabits.db\""
|
|
||||||
buildConfigField "int", "roboSdk", (System.getenv("ROBO_SDK")?: "25")
|
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
|
||||||
testInstrumentationRunnerArgument "size", "medium"
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled true
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
|
||||||
}
|
|
||||||
debug {
|
|
||||||
testCoverageEnabled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lintOptions {
|
|
||||||
checkReleaseBuilds false
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
targetCompatibility 1.8
|
|
||||||
sourceCompatibility 1.8
|
|
||||||
}
|
|
||||||
|
|
||||||
testOptions {
|
|
||||||
unitTests.all {
|
|
||||||
testLogging {
|
|
||||||
events "passed", "skipped", "failed", "standardOut", "standardError"
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
showStandardStreams = true
|
|
||||||
}
|
|
||||||
jacoco {
|
|
||||||
includeNoLocationClasses = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
|
|
||||||
androidTestApt 'com.google.dagger:dagger-compiler:2.11-rc2'
|
|
||||||
|
|
||||||
androidTestCompile 'com.android.support:support-annotations:25.3.1'
|
|
||||||
androidTestCompile 'com.android.support.test:rules:0.5'
|
|
||||||
androidTestCompile 'com.android.support.test:runner:0.5'
|
|
||||||
androidTestCompile 'com.google.auto.factory:auto-factory:1.0-beta3'
|
|
||||||
androidTestCompile "com.google.dexmaker:dexmaker:1.2"
|
|
||||||
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
|
|
||||||
androidTestCompile 'org.mockito:mockito-core:1.10.19'
|
|
||||||
androidTestCompile 'com.google.guava:guava:20.0'
|
|
||||||
|
|
||||||
apt 'com.google.dagger:dagger-compiler:2.11-rc2'
|
|
||||||
apt 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
|
|
||||||
|
|
||||||
compile 'com.android.support:appcompat-v7:25.3.1'
|
|
||||||
compile 'com.android.support:design:25.3.1'
|
|
||||||
compile 'com.android.support:preference-v14:25.3.1'
|
|
||||||
compile 'com.android.support:support-v4:25.3.1'
|
|
||||||
compile 'com.getpebble:pebblekit:3.0.0'
|
|
||||||
compile 'com.github.paolorotolo:appintro:3.4.0'
|
|
||||||
compile 'com.google.auto.factory:auto-factory:1.0-beta3'
|
|
||||||
compile 'com.google.dagger:dagger:2.11-rc2'
|
|
||||||
compile 'com.jakewharton:butterknife:8.6.1-SNAPSHOT'
|
|
||||||
compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
|
|
||||||
compile 'com.opencsv:opencsv:3.9'
|
|
||||||
compile 'org.apmem.tools:layouts:1.10'
|
|
||||||
compile 'org.jetbrains:annotations-java5:15.0'
|
|
||||||
compile 'com.google.code.gson:gson:2.7'
|
|
||||||
compile 'com.google.code.findbugs:jsr305:3.0.2'
|
|
||||||
compile 'com.google.guava:guava:20.0'
|
|
||||||
|
|
||||||
provided 'javax.annotation:jsr250-api:1.0'
|
|
||||||
|
|
||||||
compile ('io.socket:socket.io-client:+') {
|
|
||||||
exclude group: 'org.json', module: 'json'
|
|
||||||
}
|
|
||||||
|
|
||||||
testApt 'com.google.dagger:dagger-compiler:2.11-rc2'
|
|
||||||
testApt 'com.google.guava:guava:20.0'
|
|
||||||
|
|
||||||
testCompile 'junit:junit:5.0-SNAPSHOT'
|
|
||||||
testCompile 'org.hamcrest:hamcrest-library:1.4-atlassian-1'
|
|
||||||
testCompile 'org.mockito:mockito-core:2.8.9'
|
|
||||||
testCompile 'org.json:json:20160810'
|
|
||||||
testCompile 'org.robolectric:robolectric:3.4-rc2'
|
|
||||||
}
|
|
||||||
|
|
||||||
retrolambda {
|
|
||||||
defaultMethods true
|
|
||||||
}
|
|
||||||
|
|
||||||
jacoco {
|
|
||||||
toolVersion = "0.7.6.201602180812"
|
|
||||||
}
|
|
||||||
|
|
||||||
task coverageReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) {
|
|
||||||
|
|
||||||
jacocoClasspath = configurations['androidJacocoAnt']
|
|
||||||
|
|
||||||
reports {
|
|
||||||
html.enabled = true
|
|
||||||
xml.enabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
def excludes = [
|
|
||||||
'**/R.class',
|
|
||||||
'**/R$*.class',
|
|
||||||
'**/BuildConfig.*',
|
|
||||||
'**/Manifest*',
|
|
||||||
'**/*Test*.*',
|
|
||||||
'**/*$Lambda$*',
|
|
||||||
'**/*$ViewBinder*',
|
|
||||||
'**/*MembersInjector*',
|
|
||||||
'**/*_Provide*',
|
|
||||||
'**/*Module_*',
|
|
||||||
'**/com/android/**/*',
|
|
||||||
'android/**/*',
|
|
||||||
'**/*Dagger*',
|
|
||||||
'**/*_Factory*'
|
|
||||||
]
|
|
||||||
|
|
||||||
def srcDir = "${project.projectDir}/src/main/java"
|
|
||||||
def classDir = "${buildDir}/intermediates/classes/debug"
|
|
||||||
def jvmExecData = "${buildDir}/jacoco/testDebugUnitTest.exec"
|
|
||||||
def connectedExecData = "${buildDir}/outputs/code-coverage/connected/coverage.ec"
|
|
||||||
|
|
||||||
sourceDirectories = files(srcDir)
|
|
||||||
classDirectories = files(fileTree(dir: classDir, excludes: excludes))
|
|
||||||
executionData = files(jvmExecData, connectedExecData)
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.utils;
|
|
||||||
|
|
||||||
import android.appwidget.*;
|
|
||||||
import android.content.*;
|
|
||||||
import android.os.*;
|
|
||||||
import android.support.annotation.*;
|
|
||||||
import android.widget.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.widgets.*;
|
|
||||||
|
|
||||||
import static android.appwidget.AppWidgetManager.*;
|
|
||||||
import static org.isoron.uhabits.utils.InterfaceUtils.*;
|
|
||||||
|
|
||||||
public abstract class WidgetUtils
|
|
||||||
{
|
|
||||||
@NonNull
|
|
||||||
public static WidgetDimensions getDimensionsFromOptions(
|
|
||||||
@NonNull Context ctx, @NonNull Bundle options)
|
|
||||||
{
|
|
||||||
int maxWidth =
|
|
||||||
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_WIDTH));
|
|
||||||
int maxHeight =
|
|
||||||
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_HEIGHT));
|
|
||||||
int minWidth =
|
|
||||||
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_WIDTH));
|
|
||||||
int minHeight =
|
|
||||||
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_HEIGHT));
|
|
||||||
|
|
||||||
return new WidgetDimensions(minWidth, maxHeight, maxWidth, minHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void updateAppWidget(@NonNull AppWidgetManager manager,
|
|
||||||
@NonNull BaseWidget widget)
|
|
||||||
{
|
|
||||||
RemoteViews landscape = widget.getLandscapeRemoteViews();
|
|
||||||
RemoteViews portrait = widget.getPortraitRemoteViews();
|
|
||||||
RemoteViews views = new RemoteViews(landscape, portrait);
|
|
||||||
manager.updateAppWidget(widget.getId(), views);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,199 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities;
|
|
||||||
|
|
||||||
import android.content.*;
|
|
||||||
import android.os.*;
|
|
||||||
import android.support.v4.app.*;
|
|
||||||
import android.support.v7.app.*;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
|
||||||
import android.view.*;
|
|
||||||
import android.widget.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
|
||||||
import org.isoron.uhabits.activities.common.dialogs.*;
|
|
||||||
import org.junit.*;
|
|
||||||
import org.junit.runner.*;
|
|
||||||
import org.robolectric.*;
|
|
||||||
import org.robolectric.annotation.*;
|
|
||||||
import org.robolectric.shadows.*;
|
|
||||||
|
|
||||||
import static org.hamcrest.core.IsEqual.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
import static org.robolectric.Robolectric.*;
|
|
||||||
import static org.robolectric.Shadows.*;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
|
||||||
@Config(sdk = BuildConfig.roboSdk, constants = BuildConfig.class)
|
|
||||||
public class BaseActivityTest
|
|
||||||
{
|
|
||||||
private static boolean hasCrashed = false;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void activityResultTest()
|
|
||||||
{
|
|
||||||
ScreenActivity activity = spy(setupActivity(ScreenActivity.class));
|
|
||||||
activity.onActivityResult(0, 0, null);
|
|
||||||
verify(activity.screen).onResult(0, 0, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void componentTest()
|
|
||||||
{
|
|
||||||
EmptyActivity activity = setupActivity(EmptyActivity.class);
|
|
||||||
ActivityComponent component = activity.getComponent();
|
|
||||||
assertThat(component.getActivity(), equalTo(activity));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void dialogFragmentTest()
|
|
||||||
{
|
|
||||||
EmptyActivity activity = setupActivity(EmptyActivity.class);
|
|
||||||
FragmentManager manager = activity.getSupportFragmentManager();
|
|
||||||
ColorPickerDialog d = new ColorPickerDialogFactory(activity).create(0);
|
|
||||||
|
|
||||||
activity.showDialog(d, "picker");
|
|
||||||
assertTrue(d.getDialog().isShowing());
|
|
||||||
assertThat(d, equalTo(manager.findFragmentByTag("picker")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void dialogTest()
|
|
||||||
{
|
|
||||||
EmptyActivity activity = setupActivity(EmptyActivity.class);
|
|
||||||
AlertDialog dialog =
|
|
||||||
new AlertDialog.Builder(activity).setTitle("Hello world").create();
|
|
||||||
|
|
||||||
activity.showDialog(dialog);
|
|
||||||
assertTrue(dialog.isShowing());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void restartTest() throws Exception
|
|
||||||
{
|
|
||||||
EmptyActivity activity = setupActivity(EmptyActivity.class);
|
|
||||||
|
|
||||||
activity.restartWithFade(EmptyActivity.class);
|
|
||||||
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
|
|
||||||
|
|
||||||
Intent nextStartedActivity = shadowOf(activity).getNextStartedActivity();
|
|
||||||
assertNotNull(nextStartedActivity);
|
|
||||||
|
|
||||||
assertTrue(activity.isFinishing());
|
|
||||||
assertThat(shadowOf(nextStartedActivity).getIntentClass(),
|
|
||||||
equalTo(EmptyActivity.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void exceptionHandlerTest() throws InterruptedException
|
|
||||||
{
|
|
||||||
assertFalse(hasCrashed);
|
|
||||||
|
|
||||||
Thread crashThread = new Thread()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
Looper.prepare();
|
|
||||||
CrashActivity activity = setupActivity(CrashActivity.class);
|
|
||||||
activity.crash();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
crashThread.start();
|
|
||||||
crashThread.join();
|
|
||||||
assertTrue(hasCrashed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void menuTest()
|
|
||||||
{
|
|
||||||
MenuActivity activity = setupActivity(MenuActivity.class);
|
|
||||||
verify(activity.baseMenu).onCreate(eq(activity.getMenuInflater()),
|
|
||||||
any());
|
|
||||||
|
|
||||||
Menu menu = activity.toolbar.getMenu();
|
|
||||||
MenuItem item = menu.getItem(0);
|
|
||||||
activity.onMenuItemSelected(0, item);
|
|
||||||
verify(activity.baseMenu).onItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CrashActivity extends BaseActivity
|
|
||||||
{
|
|
||||||
public void crash()
|
|
||||||
{
|
|
||||||
throw new RuntimeException("crash!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Thread.UncaughtExceptionHandler getExceptionHandler()
|
|
||||||
{
|
|
||||||
return (t, e) -> hasCrashed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class EmptyActivity extends BaseActivity
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MenuActivity extends BaseActivity
|
|
||||||
{
|
|
||||||
public BaseMenu baseMenu;
|
|
||||||
|
|
||||||
public Toolbar toolbar;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
toolbar = new Toolbar(this);
|
|
||||||
LinearLayout layout = new LinearLayout(this);
|
|
||||||
layout.addView(toolbar);
|
|
||||||
setContentView(layout);
|
|
||||||
setSupportActionBar(toolbar);
|
|
||||||
|
|
||||||
baseMenu = spy(new BaseMenu(this)
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
protected int getMenuResourceId()
|
|
||||||
{
|
|
||||||
return R.menu.list_habits;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setBaseMenu(baseMenu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ScreenActivity extends BaseActivity
|
|
||||||
{
|
|
||||||
private BaseScreen screen;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
screen = spy(new BaseScreen(this));
|
|
||||||
setScreen(screen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities;
|
|
||||||
|
|
||||||
import android.content.*;
|
|
||||||
import android.support.annotation.*;
|
|
||||||
import android.support.v7.view.ActionMode;
|
|
||||||
import android.support.v7.widget.*;
|
|
||||||
import android.view.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
|
||||||
import org.junit.*;
|
|
||||||
import org.junit.runner.*;
|
|
||||||
import org.robolectric.*;
|
|
||||||
import org.robolectric.annotation.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static android.view.View.*;
|
|
||||||
import static junit.framework.Assert.assertNotNull;
|
|
||||||
import static org.hamcrest.core.IsEqual.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.mockito.Matchers.any;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
import static org.robolectric.Robolectric.*;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
|
||||||
@Config(sdk = BuildConfig.roboSdk, constants = BuildConfig.class)
|
|
||||||
public class BaseScreenTest
|
|
||||||
{
|
|
||||||
@Test
|
|
||||||
public void selectionMenuTest()
|
|
||||||
{
|
|
||||||
BaseSelectionMenu selectionMenu = spy(new BaseSelectionMenu()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
protected int getResourceId()
|
|
||||||
{
|
|
||||||
return R.menu.list_habits_selection;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ActionModeActivity activity = setupActivity(ActionModeActivity.class);
|
|
||||||
BaseScreen screen = new BaseScreen(activity);
|
|
||||||
screen.setSelectionMenu(selectionMenu);
|
|
||||||
activity.setScreen(screen);
|
|
||||||
|
|
||||||
screen.startSelection();
|
|
||||||
assertNotNull(activity.callback);
|
|
||||||
verify(selectionMenu).onCreate(any(), any(), any());
|
|
||||||
verify(selectionMenu).onPrepare(any());
|
|
||||||
|
|
||||||
ActionMode mode = mock(ActionMode.class);
|
|
||||||
MenuItem item = mock(MenuItem.class);
|
|
||||||
|
|
||||||
activity.callback.onActionItemClicked(mode, item);
|
|
||||||
verify(selectionMenu).onItemClicked(item);
|
|
||||||
|
|
||||||
activity.callback.onDestroyActionMode(mode);
|
|
||||||
verify(selectionMenu).onFinish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void showMessageTest()
|
|
||||||
{
|
|
||||||
EmptyActivity activity = setupActivity(EmptyActivity.class);
|
|
||||||
ConcreteRootView rootView = new ConcreteRootView(activity);
|
|
||||||
View decor = activity.getWindow().getDecorView();
|
|
||||||
BaseScreen screen = new BaseScreen(activity);
|
|
||||||
screen.setRootView(rootView);
|
|
||||||
activity.setScreen(screen);
|
|
||||||
|
|
||||||
ArrayList<View> matches = new ArrayList<>();
|
|
||||||
|
|
||||||
screen.showMessage(R.string.checkmark);
|
|
||||||
decor.findViewsWithText(matches, "Checkmark", FIND_VIEWS_WITH_TEXT);
|
|
||||||
assertThat(matches.size(), equalTo(1));
|
|
||||||
assertTrue(matches.get(0).isShown());
|
|
||||||
|
|
||||||
screen.showMessage(R.string.frequency);
|
|
||||||
decor.findViewsWithText(matches, "Frequency", FIND_VIEWS_WITH_TEXT);
|
|
||||||
assertThat(matches.size(), equalTo(1));
|
|
||||||
assertTrue(matches.get(0).isShown());
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ActionModeActivity extends BaseActivity
|
|
||||||
{
|
|
||||||
private ActionMode.Callback callback;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public ActionMode startSupportActionMode(
|
|
||||||
@NonNull ActionMode.Callback callback)
|
|
||||||
{
|
|
||||||
this.callback = callback;
|
|
||||||
return super.startSupportActionMode(this.callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ConcreteRootView extends BaseRootView
|
|
||||||
{
|
|
||||||
private final Toolbar toolbar;
|
|
||||||
|
|
||||||
public ConcreteRootView(@NonNull Context context)
|
|
||||||
{
|
|
||||||
super(context);
|
|
||||||
toolbar = new Toolbar(context);
|
|
||||||
addView(toolbar);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public Toolbar getToolbar()
|
|
||||||
{
|
|
||||||
return toolbar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class EmptyActivity extends BaseActivity
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
|
||||||
import org.isoron.uhabits.activities.*;
|
|
||||||
import org.isoron.uhabits.activities.habits.list.model.*;
|
|
||||||
import org.isoron.uhabits.commands.*;
|
|
||||||
import org.isoron.uhabits.models.*;
|
|
||||||
import org.isoron.uhabits.preferences.*;
|
|
||||||
import org.isoron.uhabits.tasks.*;
|
|
||||||
import org.isoron.uhabits.utils.*;
|
|
||||||
import org.isoron.uhabits.widgets.*;
|
|
||||||
import org.junit.*;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
public class ListHabitsControllerTest extends BaseUnitTest
|
|
||||||
{
|
|
||||||
|
|
||||||
private ListHabitsController controller;
|
|
||||||
|
|
||||||
private ImportDataTaskFactory importTaskFactory;
|
|
||||||
|
|
||||||
private BaseSystem system;
|
|
||||||
|
|
||||||
private CommandRunner commandRunner;
|
|
||||||
|
|
||||||
private HabitCardListAdapter adapter;
|
|
||||||
|
|
||||||
private ListHabitsScreen screen;
|
|
||||||
|
|
||||||
private Preferences prefs;
|
|
||||||
|
|
||||||
private ReminderScheduler reminderScheduler;
|
|
||||||
|
|
||||||
private SingleThreadTaskRunner taskRunner;
|
|
||||||
|
|
||||||
private WidgetUpdater widgetUpdater;
|
|
||||||
|
|
||||||
private ExportCSVTaskFactory exportCSVFactory;
|
|
||||||
|
|
||||||
private ExportDBTaskFactory exportDBFactory;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp()
|
|
||||||
{
|
|
||||||
super.setUp();
|
|
||||||
|
|
||||||
habitList = mock(HabitList.class);
|
|
||||||
system = mock(BaseSystem.class);
|
|
||||||
commandRunner = mock(CommandRunner.class);
|
|
||||||
adapter = mock(HabitCardListAdapter.class);
|
|
||||||
screen = mock(ListHabitsScreen.class);
|
|
||||||
prefs = mock(Preferences.class);
|
|
||||||
reminderScheduler = mock(ReminderScheduler.class);
|
|
||||||
taskRunner = new SingleThreadTaskRunner();
|
|
||||||
widgetUpdater = mock(WidgetUpdater.class);
|
|
||||||
importTaskFactory = mock(ImportDataTaskFactory.class);
|
|
||||||
exportCSVFactory = mock(ExportCSVTaskFactory.class);
|
|
||||||
exportDBFactory = mock(ExportDBTaskFactory.class);
|
|
||||||
|
|
||||||
controller =
|
|
||||||
spy(new ListHabitsController(system, commandRunner, habitList,
|
|
||||||
adapter, screen, prefs, reminderScheduler, taskRunner,
|
|
||||||
widgetUpdater, importTaskFactory, exportCSVFactory, exportDBFactory));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnHabitClick()
|
|
||||||
{
|
|
||||||
Habit h = mock(Habit.class);
|
|
||||||
controller.onHabitClick(h);
|
|
||||||
verify(screen).showHabitScreen(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnHabitReorder()
|
|
||||||
{
|
|
||||||
Habit from = mock(Habit.class);
|
|
||||||
Habit to = mock(Habit.class);
|
|
||||||
controller.onHabitReorder(from, to);
|
|
||||||
verify(habitList).reorder(from, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onInvalidToggle()
|
|
||||||
{
|
|
||||||
controller.onInvalidToggle();
|
|
||||||
verify(screen).showMessage(R.string.long_press_to_toggle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onStartup_notFirstLaunch()
|
|
||||||
{
|
|
||||||
when(prefs.isFirstRun()).thenReturn(false);
|
|
||||||
controller.onStartup();
|
|
||||||
verify(prefs).incrementLaunchCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onStartup_firstLaunch()
|
|
||||||
{
|
|
||||||
long today = DateUtils.getStartOfToday();
|
|
||||||
|
|
||||||
when(prefs.isFirstRun()).thenReturn(true);
|
|
||||||
controller.onStartup();
|
|
||||||
verify(prefs).setFirstRun(false);
|
|
||||||
verify(prefs).updateLastHint(-1, today);
|
|
||||||
verify(screen).showIntroScreen();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.show;
|
|
||||||
|
|
||||||
import android.view.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
|
||||||
import org.isoron.uhabits.models.*;
|
|
||||||
import org.isoron.uhabits.tasks.*;
|
|
||||||
import org.junit.*;
|
|
||||||
|
|
||||||
import static org.mockito.Matchers.any;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
public class ShowHabitsMenuTest extends BaseUnitTest
|
|
||||||
{
|
|
||||||
private ShowHabitActivity activity;
|
|
||||||
|
|
||||||
private ShowHabitScreen screen;
|
|
||||||
|
|
||||||
private ShowHabitsMenu menu;
|
|
||||||
|
|
||||||
private Habit habit;
|
|
||||||
|
|
||||||
private ExportCSVTaskFactory exportCSVFactory;
|
|
||||||
|
|
||||||
private TaskRunner taskRunner;
|
|
||||||
|
|
||||||
private ExportCSVTask task;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp()
|
|
||||||
{
|
|
||||||
super.setUp();
|
|
||||||
activity = mock(ShowHabitActivity.class);
|
|
||||||
screen = mock(ShowHabitScreen.class);
|
|
||||||
habit = mock(Habit.class);
|
|
||||||
exportCSVFactory = mock(ExportCSVTaskFactory.class);
|
|
||||||
taskRunner = mock(TaskRunner.class);
|
|
||||||
menu = new ShowHabitsMenu(activity, screen, habit, exportCSVFactory,
|
|
||||||
taskRunner);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnDownloadHabit()
|
|
||||||
{
|
|
||||||
onItemSelected(R.id.export);
|
|
||||||
verify(taskRunner).execute(any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnEditHabit()
|
|
||||||
{
|
|
||||||
onItemSelected(R.id.action_edit_habit);
|
|
||||||
verify(screen).showEditHabitDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onItemSelected(int actionId)
|
|
||||||
{
|
|
||||||
MenuItem item = mock(MenuItem.class);
|
|
||||||
when(item.getItemId()).thenReturn(actionId);
|
|
||||||
menu.onItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +1,22 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven { url 'https://maven.google.com' }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.3.2'
|
classpath 'com.android.tools.build:gradle:3.0.0-alpha2'
|
||||||
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
||||||
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.6.4'
|
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.6.4'
|
||||||
classpath 'me.tatarka:gradle-retrolambda:3.2.5'
|
|
||||||
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
||||||
|
classpath 'org.jacoco:org.jacoco.core:+'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven { url 'https://maven.google.com' }
|
||||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#Fri Mar 17 21:42:38 EDT 2017
|
#Wed May 24 19:36:48 EDT 2017
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip
|
distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-4.0-20170417000025+0000-all.zip
|
||||||
|
@ -1 +1 @@
|
|||||||
include ':app'
|
include ':uhabits-android', ':uhabits-core'
|
||||||
|
@ -0,0 +1,145 @@
|
|||||||
|
apply plugin: 'idea'
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'jacoco'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 25
|
||||||
|
buildToolsVersion "25.0.2"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "org.isoron.uhabits"
|
||||||
|
minSdkVersion 19
|
||||||
|
targetSdkVersion 25
|
||||||
|
|
||||||
|
buildConfigField "Integer", "databaseVersion", "19"
|
||||||
|
buildConfigField "String", "databaseFilename", "\"uhabits.db\""
|
||||||
|
buildConfigField "int", "roboSdk", (System.getenv("ROBO_SDK") ?: "25")
|
||||||
|
|
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
testCoverageEnabled true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
checkReleaseBuilds false
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
testOptions {
|
||||||
|
unitTests.all {
|
||||||
|
testLogging {
|
||||||
|
events "passed", "skipped", "failed", "standardOut", "standardError"
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
showStandardStreams = true
|
||||||
|
}
|
||||||
|
jacoco {
|
||||||
|
includeNoLocationClasses = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(":uhabits-core")
|
||||||
|
implementation 'com.android.support:appcompat-v7:25.3.1'
|
||||||
|
implementation 'com.android.support:design:25.3.1'
|
||||||
|
implementation 'com.android.support:preference-v14:25.3.1'
|
||||||
|
implementation 'com.android.support:support-v4:25.3.1'
|
||||||
|
implementation 'com.getpebble:pebblekit:3.0.0'
|
||||||
|
implementation 'com.github.paolorotolo:appintro:3.4.0'
|
||||||
|
implementation 'com.google.dagger:dagger:2.9'
|
||||||
|
implementation 'com.jakewharton:butterknife:8.6.1-SNAPSHOT'
|
||||||
|
implementation 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
|
||||||
|
implementation 'org.apmem.tools:layouts:1.10'
|
||||||
|
implementation 'org.jetbrains:annotations-java5:15.0'
|
||||||
|
implementation 'com.google.code.gson:gson:2.7'
|
||||||
|
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
|
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||||
|
compileOnly 'com.google.auto.factory:auto-factory:1.0-beta3'
|
||||||
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.9'
|
||||||
|
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
|
||||||
|
annotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3'
|
||||||
|
|
||||||
|
androidTestImplementation project(":uhabits-core")
|
||||||
|
androidTestImplementation 'com.android.support:support-annotations:25.3.1'
|
||||||
|
androidTestImplementation 'com.android.support.test:rules:0.5'
|
||||||
|
androidTestImplementation 'com.android.support.test:runner:0.5'
|
||||||
|
androidTestImplementation 'com.google.guava:guava:20.0'
|
||||||
|
androidTestCompileOnly 'com.google.auto.factory:auto-factory:1.0-beta3'
|
||||||
|
androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:2.9'
|
||||||
|
androidTestAnnotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3'
|
||||||
|
androidTestAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
|
||||||
|
|
||||||
|
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.9'
|
||||||
|
testAnnotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3'
|
||||||
|
testAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
|
||||||
|
|
||||||
|
testCompile 'com.google.dagger:dagger:2.9'
|
||||||
|
testCompile "org.mockito:mockito-core:2.8.9"
|
||||||
|
testCompile "org.mockito:mockito-inline:2.8.9"
|
||||||
|
androidTestCompile 'com.google.dagger:dagger:2.9'
|
||||||
|
androidTestCompile "org.mockito:mockito-android:2.8.9"
|
||||||
|
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
|
||||||
|
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
|
||||||
|
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
|
||||||
|
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.2'
|
||||||
|
androidTestCompile 'com.linkedin.testbutler:test-butler-library:1.3.1'
|
||||||
|
|
||||||
|
implementation('com.opencsv:opencsv:3.9') {
|
||||||
|
exclude group: 'commons-logging', module: 'commons-logging'
|
||||||
|
}
|
||||||
|
implementation('io.socket:socket.io-client:+') {
|
||||||
|
exclude group: 'org.json', module: 'json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
task coverageReport(type: JacocoReport) {
|
||||||
|
|
||||||
|
jacocoClasspath = configurations['androidJacocoAnt']
|
||||||
|
|
||||||
|
reports {
|
||||||
|
html.enabled = true
|
||||||
|
xml.enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
def excludes = [
|
||||||
|
'**/R.class',
|
||||||
|
'**/R$*.class',
|
||||||
|
'**/BuildConfig.*',
|
||||||
|
'**/Manifest*',
|
||||||
|
'**/*Test*.*',
|
||||||
|
'**/*$Lambda$*',
|
||||||
|
'**/*$ViewBinder*',
|
||||||
|
'**/*MembersInjector*',
|
||||||
|
'**/*_Provide*',
|
||||||
|
'**/*Module_*',
|
||||||
|
'**/com/android/**/*',
|
||||||
|
'**/*Dagger*',
|
||||||
|
'**/*_Factory*'
|
||||||
|
]
|
||||||
|
|
||||||
|
def androidSrc = "${project.projectDir}/src/main/java"
|
||||||
|
def androidClasses = "${buildDir}/intermediates/classes/debug"
|
||||||
|
def jvmExecData = "${buildDir}/jacoco/testDebugUnitTest.exec"
|
||||||
|
def connectedExecData = "${buildDir}/outputs/code-coverage/connected/coverage.ec"
|
||||||
|
|
||||||
|
sourceDirectories = files(androidSrc)
|
||||||
|
classDirectories = files(fileTree(dir: androidClasses, excludes: excludes))
|
||||||
|
executionData = files(jvmExecData, connectedExecData)
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
~
|
||||||
|
~ This file is part of Loop Habit Tracker.
|
||||||
|
~
|
||||||
|
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by the
|
||||||
|
~ Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
~ option) any later version.
|
||||||
|
~
|
||||||
|
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
~ more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License along
|
||||||
|
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<manifest
|
||||||
|
package="org.isoron.uhabits"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<instrumentation>
|
||||||
|
<meta-data android:name="notPackage" android:value="net.bytebuddy"/>
|
||||||
|
</instrumentation>
|
||||||
|
</manifest>
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 582 B After Width: | Height: | Size: 582 B |
Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 541 B |
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 577 B After Width: | Height: | Size: 577 B |
Before Width: | Height: | Size: 543 B After Width: | Height: | Size: 543 B |
Before Width: | Height: | Size: 583 B After Width: | Height: | Size: 583 B |