45 |
46 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'android-apt'
3 | apply plugin: 'me.tatarka.retrolambda'
4 |
5 | android {
6 | compileSdkVersion 24
7 | buildToolsVersion "24.0.1"
8 |
9 | defaultConfig {
10 | applicationId "com.pddstudio.orlyandroid"
11 | minSdkVersion 16
12 | targetSdkVersion 24
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | compileOptions {
23 | sourceCompatibility JavaVersion.VERSION_1_8
24 | targetCompatibility JavaVersion.VERSION_1_8
25 | }
26 | lintOptions {
27 | abortOnError false
28 | }
29 | }
30 |
31 | apt {
32 | arguments {
33 | androidManifestFile variant.outputs[0]?.processResources?.manifestFile
34 | // if you have multiple outputs (when using splits), you may want to have other index than 0
35 |
36 | // you should set your package name here if you are using different application IDs
37 | // resourcePackageName "your.package.name"
38 |
39 | // You can set optional annotation processing options here, like these commented options:
40 | // logLevel 'INFO'
41 | // logFile '/var/log/aa.log'
42 | }
43 | }
44 |
45 | dependencies {
46 | compile fileTree(include: ['*.jar'], dir: 'libs')
47 | testCompile 'junit:junit:4.12'
48 |
49 | compile 'com.android.support:appcompat-v7:24.1.1'
50 | compile 'com.android.support:cardview-v7:24.1.1'
51 | compile 'com.android.support:recyclerview-v7:24.1.1'
52 | compile 'com.android.support:design:24.1.1'
53 |
54 | apt "org.androidannotations:androidannotations:4.0.0"
55 | compile 'org.androidannotations:androidannotations-api:4.0.0'
56 |
57 | compile 'com.squareup.okhttp3:okhttp:3.4.1'
58 | compile 'com.squareup.picasso:picasso:2.5.2'
59 |
60 | compile 'com.afollestad.material-dialogs:core:0.9.0.1'
61 | compile 'com.afollestad.material-dialogs:commons:0.9.0.1'
62 |
63 | compile 'com.github.drozdzynski:Steppers:5a7b08a7fc'
64 | //compile 'com.github.PDDStudio:Steppers:0.0.2'
65 |
66 | compile('com.mikepenz:aboutlibraries:5.7.2@aar') {
67 | transitive = true
68 | }
69 |
70 | compile project(':o-rly-generator')
71 | }
72 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/o-rly-generator/src/main/java/com/pddstudio/orly/book/generator/BookGenerator.java:
--------------------------------------------------------------------------------
1 | package com.pddstudio.orly.book.generator;
2 |
3 | import android.util.Log;
4 |
5 | import com.pddstudio.orly.book.generator.enums.CoverColor;
6 | import com.pddstudio.orly.book.generator.enums.CoverImage;
7 | import com.pddstudio.orly.book.generator.enums.GuideTextPosition;
8 |
9 | /**
10 | * Created by pddstudio on 15/08/16.
11 | */
12 | public final class BookGenerator {
13 |
14 | private static final String TAG = BookGenerator.class.getSimpleName();
15 |
16 | private final Book book;
17 |
18 | private BookGenerator() {
19 | this.book = new Book();
20 | }
21 |
22 | public static BookGenerator createBook() {
23 | return new BookGenerator();
24 | }
25 |
26 | public BookGenerator withTitle(String title) {
27 | if (title == null || title.isEmpty() || title.replaceAll(" ", "").isEmpty()) {
28 | Log.e(TAG, "A title is required to generate a book cover. Make sure this value is set!");
29 | title = "Title";
30 | }
31 | book.setTitle(title);
32 | return this;
33 | }
34 |
35 | public BookGenerator withTopText(String topText) {
36 | if (topText == null || topText.isEmpty() || topText.replaceAll(" ", "").isEmpty()) {
37 | Log.e(TAG, "A top text is required to generate a book cover. Make sure this value is set!");
38 | topText = "Top Text";
39 | }
40 | book.setTopText(topText);
41 | return this;
42 | }
43 |
44 | public BookGenerator withAuthor(String author) {
45 | if (author == null || author.isEmpty() || author.replaceAll(" ", "").isEmpty()) {
46 | Log.e(TAG, "Author is required to generate a book cover. Make sure this value is set!");
47 | author = "Author";
48 | }
49 | book.setAuthor(author);
50 | return this;
51 | }
52 |
53 | public BookGenerator withGuideText(String guideText) {
54 | if (guideText == null) {
55 | guideText = "";
56 | }
57 | book.setGuideText(guideText);
58 | return this;
59 | }
60 |
61 | public BookGenerator withGuideTextPosition(GuideTextPosition guideTextPosition) {
62 | if (guideTextPosition == null) {
63 | guideTextPosition = GuideTextPosition.DEFAULT;
64 | }
65 | book.setGuideTextPosition(guideTextPosition);
66 | return this;
67 | }
68 |
69 | public BookGenerator withCoverColor(CoverColor coverColor) {
70 | if (coverColor == null) {
71 | Log.e(TAG, "Cover color can't be null! Setting default value.");
72 | coverColor = CoverColor.DEFAULT;
73 | }
74 | book.setCoverColor(coverColor);
75 | return this;
76 | }
77 |
78 | public BookGenerator withCoverImage(CoverImage coverImage) {
79 | if (coverImage == null) {
80 | Log.e(TAG, "Cover image can't be null! Setting default value.");
81 | coverImage = CoverImage.DEFAULT;
82 | }
83 | book.setCoverImage(coverImage);
84 | return this;
85 | }
86 |
87 | public Book generate() {
88 | book.invalidate();
89 | return book;
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/o-rly-generator/src/main/java/com/pddstudio/orly/book/generator/Book.java:
--------------------------------------------------------------------------------
1 | package com.pddstudio.orly.book.generator;
2 |
3 | import com.pddstudio.orly.book.generator.enums.CoverColor;
4 | import com.pddstudio.orly.book.generator.enums.CoverImage;
5 | import com.pddstudio.orly.book.generator.enums.GuideTextPosition;
6 | import com.pddstudio.orly.book.generator.utils.BookUtils;
7 |
8 | /**
9 | * Created by pddstudio on 15/08/16.
10 | */
11 | public class Book {
12 |
13 | private String title;
14 | private String topText;
15 | private String author;
16 | private String guideText;
17 | private CoverColor coverColor;
18 | private CoverImage coverImage;
19 | private GuideTextPosition guideTextPosition;
20 |
21 | protected Book() {
22 |
23 | }
24 |
25 | public String getTitle() {
26 | return title;
27 | }
28 |
29 | protected void setTitle(String title) {
30 | this.title = title;
31 | }
32 |
33 | public String getTopText() {
34 | return topText;
35 | }
36 |
37 | protected void setTopText(String topText) {
38 | this.topText = topText;
39 | }
40 |
41 | public String getAuthor() {
42 | return author;
43 | }
44 |
45 | protected void setAuthor(String author) {
46 | this.author = author;
47 | }
48 |
49 | public String getGuideText() {
50 | return guideText;
51 | }
52 |
53 | protected void setGuideText(String guideText) {
54 | this.guideText = guideText;
55 | }
56 |
57 | public CoverColor getCoverColor() {
58 | return coverColor;
59 | }
60 |
61 | protected void setCoverColor(CoverColor coverColor) {
62 | this.coverColor = coverColor;
63 | }
64 |
65 | public CoverImage getCoverImage() {
66 | return coverImage;
67 | }
68 |
69 | protected void setCoverImage(CoverImage coverImage) {
70 | this.coverImage = coverImage;
71 | }
72 |
73 | public GuideTextPosition getGuideTextPosition() {
74 | return guideTextPosition;
75 | }
76 |
77 | protected void setGuideTextPosition(GuideTextPosition guideTextPosition) {
78 | this.guideTextPosition = guideTextPosition;
79 | }
80 |
81 | public String getGeneratedUrl() {
82 | invalidate();
83 | return BookUtils.buildCoverUrl(this);
84 | }
85 |
86 | protected void invalidate() {
87 | title = validateString(title);
88 | topText = validateString(topText);
89 | author = validateString(author);
90 | if (guideText == null) {
91 | guideText = "";
92 | }
93 | if (coverColor == null) {
94 | coverColor = CoverColor.DEFAULT;
95 | }
96 | if (coverImage == null) {
97 | coverImage = CoverImage.DEFAULT;
98 | }
99 | if (guideTextPosition == null) {
100 | guideTextPosition = GuideTextPosition.DEFAULT;
101 | }
102 | }
103 |
104 | private String validateString(String s) {
105 | if (BookUtils.isNullOrEmpty(s)) {
106 | s = "???";
107 | }
108 | return s;
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## O RLY Book Cover Generator
2 |
3 | [](https://travis-ci.org/PDDStudio/O-Rly-Android)
4 | [](https://www.apache.org/licenses/LICENSE-2.0.html)
5 |
6 |
7 | *Now on Android brought to you by [PDDStudio](https://github.com/PDDStudio)*
8 |
9 | ***Insult your co-workers with snarky O RLY parody book covers!***
10 |
11 | 
12 |
13 | O-Rly-Android is a simple app which allows you to create O RLY parody covers on your Android phone.
14 |
15 |
16 | ##Disclaimer:
17 |
18 | I only created the Android-App for the [O RLY Cover Generator](https://dev.to/rly) and do not hold any special permission, except the agreement to bring this awesome site to Android.
19 |
20 |
21 | The site is hosted by [@ThePracticalDev](https://twitter.com/ThePracticalDev) and the original tool was created by [@AModelEngineer](https://twitter.com/AModelEngineer).
22 |
23 | ##Functions:
24 |
25 | - Create O Rly Book Covers with the same functions as on the Website
26 | - Share created Books immediately without saving them on your device
27 | - Save created Books to your device's storage to view and/or use them again
28 | - Android 6.0 Ready
29 |
30 | ##Notice
31 | There are a few known edge cases that do not generate.
32 |
33 | Some characters and long words won't work, etc. If you want to report an issue, feel free to do this in the [Issue Section](https://github.com/PDDStudio/O-Rly-Android/issues)
34 |
35 | ##Google Play
36 |
37 | ###Note:
38 | The App is currently *not* listed in the PlayStore, this will change in the next few days after collecting some Feedback.
39 |
40 | In meanwhile please download the APK from the [Release Section](https://github.com/PDDStudio/O-Rly-Android/releases)
41 |
42 |
43 |
44 |
45 | ##Contact
46 |
47 | Feel free to contact or follow me.
48 |
49 | - [Google+ Profile](https://plus.google.com/+PatrickJung42)
50 | - [GitHub Account](https://github.com/PDDStudio)
51 | - [Send me an E-Mail](mailto:patrick.pddstudio@gmail.com)
52 |
53 | ##License
54 | Copyright 2016 Patrick J
55 |
56 | Licensed under the Apache License, Version 2.0 (the "License");
57 | you may not use this file except in compliance with the License.
58 | You may obtain a copy of the License at
59 |
60 | http://www.apache.org/licenses/LICENSE-2.0
61 |
62 | Unless required by applicable law or agreed to in writing, software
63 | distributed under the License is distributed on an "AS IS" BASIS,
64 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65 | See the License for the specific language governing permissions and
66 | limitations under the License.
--------------------------------------------------------------------------------
/app/src/main/java/com/pddstudio/orlyandroid/ResultActivity.java:
--------------------------------------------------------------------------------
1 | package com.pddstudio.orlyandroid;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageManager;
5 | import android.support.annotation.NonNull;
6 | import android.support.design.widget.Snackbar;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.View;
10 | import android.widget.ImageView;
11 |
12 | import com.pddstudio.orlyandroid.utils.StorageManager;
13 | import com.squareup.picasso.Picasso;
14 |
15 | import org.androidannotations.annotations.AfterViews;
16 | import org.androidannotations.annotations.Bean;
17 | import org.androidannotations.annotations.EActivity;
18 | import org.androidannotations.annotations.Extra;
19 | import org.androidannotations.annotations.InstanceState;
20 | import org.androidannotations.annotations.OptionsItem;
21 | import org.androidannotations.annotations.OptionsMenu;
22 | import org.androidannotations.annotations.ViewById;
23 |
24 | import java.io.File;
25 |
26 | @EActivity(R.layout.activity_result)
27 | @OptionsMenu(R.menu.menu_result)
28 | public class ResultActivity extends AppCompatActivity implements View.OnClickListener {
29 |
30 | public static void open(Context context, File image) {
31 | ResultActivity_.intent(context).imageFile(image).start();
32 | }
33 |
34 | @ViewById(R.id.toolbar)
35 | Toolbar toolbar;
36 |
37 | @ViewById(R.id.image)
38 | ImageView imageView;
39 |
40 | @InstanceState
41 | @Extra
42 | File imageFile;
43 |
44 | @Bean
45 | StorageManager storageManager;
46 |
47 | @AfterViews
48 | void prepareActivity() {
49 | toolbar.setTitle(R.string.result_activity_title);
50 | toolbar.setNavigationIcon(R.drawable.ic_close_24dp);
51 | toolbar.setNavigationOnClickListener(this);
52 | setSupportActionBar(toolbar);
53 | Picasso.with(this).load(imageFile).into(imageView);
54 | }
55 |
56 | @Override
57 | @OptionsItem(android.R.id.home)
58 | public void onBackPressed() {
59 | //delete temporary stuff
60 | storageManager.recycle();
61 | super.onBackPressed();
62 | }
63 |
64 | @Override
65 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
66 | if (requestCode == StorageManager.STORAGE_REQUEST_CODE) {
67 | if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
68 | onSaveImage();
69 | } else {
70 | showPermissionDeniedSnackBar();
71 | }
72 | }
73 | }
74 |
75 | @OptionsItem(R.id.menu_save_image)
76 | void onSaveImage() {
77 | if (storageManager.canAccessStorage()) {
78 | boolean result = storageManager.saveImageToStorage();
79 | showSnackBarForResult(result);
80 | } else {
81 | storageManager.requestStoragePermission(this);
82 | }
83 | }
84 |
85 | @OptionsItem(R.id.menu_share_image)
86 | void onShareImage() {
87 | storageManager.shareCachedImage(this);
88 | }
89 |
90 | @OptionsItem(R.id.menu_delete_image)
91 | void onDeleteImage() {
92 | //TODO: Add a dialog for confirming deletion
93 | onBackPressed();
94 | }
95 |
96 | private void showSnackBarForResult(boolean result) {
97 | if (result) {
98 | Snackbar.make(imageView,
99 | String.format(getString(R.string.snack_bar_save_success), storageManager.getDestFile().getAbsolutePath()),
100 | Snackbar.LENGTH_LONG).setAction(android.R.string.ok, new View.OnClickListener() {
101 | @Override
102 | public void onClick(View view) {
103 |
104 | }
105 | }).show();
106 | } else {
107 | Snackbar.make(imageView, R.string.snack_bar_save_fail, Snackbar.LENGTH_LONG).setAction(android.R.string.ok, new View.OnClickListener() {
108 | @Override
109 | public void onClick(View view) {
110 |
111 | }
112 | }).show();
113 | }
114 |
115 | }
116 |
117 | private void showPermissionDeniedSnackBar() {
118 | Snackbar.make(imageView, R.string.snack_bar_permission_required, Snackbar.LENGTH_LONG).setAction(android.R.string.ok, new View.OnClickListener() {
119 | @Override
120 | public void onClick(View view) {
121 |
122 | }
123 | }).show();
124 | }
125 |
126 | @Override
127 | public void onClick(View view) {
128 | onBackPressed();
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/app/src/main/res/values/library_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | excilys
6 | http://androidannotations.org/
7 | AndroidAnnotations
8 | AndroidAnnotations is an Open Source framework that speeds up Android development. It takes
9 | care of the plumbing, and lets you concentrate on what\'s really important. By simplifying your code, it facilitates its maintenance.
10 | 4.0.0
11 | https://github.com/excilys/androidannotations/
12 | apache_2_0
13 | true
14 | https://github.com/excilys/androidannotations/
15 |
16 |
17 | streamsupport
18 | https://github.com/streamsupport/streamsupport
19 | StreamSupport
20 | streamsupport is a backport of the Java 8 java.util.function (functional interfaces) and
21 | java.util.stream (streams) API for users of Java 6 or 7 supplemented with selected additions from java.util.concurrent which didn\'t exist back in Java 6.
22 | 1.5.1
23 | https://github.com/streamsupport/streamsupport
24 | gpl_2
25 | true
26 | https://github.com/streamsupport/streamsupport
27 |
28 |
29 | orfjackal
30 | https://github.com/orfjackal/retrolambda
31 | Retrolambda
32 | Just as there was Retroweaver et al. for running Java 5 code with generics on Java 1.4, Retrolambda lets you run Java 8 code with lambda expressions, method references and try-with-resources statements on Java 7, 6 or 5. It does this by transforming your Java 8 compiled bytecode so that it can run on an older Java runtime. After the transformation they are just a bunch of normal .class files, without any additional runtime dependencies.
33 | 3.2.5
34 | https://github.com/orfjackal/retrolambda
35 | apache_2_0
36 | true
37 | https://github.com/orfjackal/retrolambda
38 |
39 |
40 | drozdzynski
41 | https://github.com/drozdzynski/Steppers
42 | Steppers
43 | A Material Design inspired Stepper Library.
44 | 0.3.3
45 | https://github.com/drozdzynski/Steppers
46 | apache_2_0
47 | true
48 | https://github.com/drozdzynski/Steppers
49 |
--------------------------------------------------------------------------------
/o-rly-generator/src/main/java/com/pddstudio/orly/book/generator/utils/BookUtils.java:
--------------------------------------------------------------------------------
1 | package com.pddstudio.orly.book.generator.utils;
2 |
3 | import android.content.Context;
4 | import android.content.res.AssetManager;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.util.Log;
8 |
9 | import com.pddstudio.orly.book.generator.Book;
10 | import com.pddstudio.orly.book.generator.enums.CoverImage;
11 |
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.util.LinkedList;
15 | import java.util.List;
16 | import java.util.Random;
17 |
18 | import java8.util.J8Arrays;
19 |
20 | /**
21 | * Created by pddstudio on 15/08/16.
22 | */
23 | public class BookUtils {
24 |
25 | private static final String BASE_URL = "https://orly-appstore.herokuapp" + "" +
26 | ".com/generate?title=%1$s&top_text=%2$s&author=%3$s&image_code=%4$s&theme=%5$s&guide_text=%6$s&guide_text_placement=%7$s";
27 |
28 | public static T getRandomItem(T... values) {
29 | return values[new Random().nextInt(values.length)];
30 | }
31 |
32 | public static boolean isNullOrEmpty(String s) {
33 | return (s == null || s.isEmpty() || s.replaceAll(" ", "").isEmpty());
34 | }
35 |
36 | public static String encodeString(String text) {
37 | Log.d("BookUtils", "Normal text: " + text);
38 | String encodedText = text.replaceAll("%", "%25")
39 | .replaceAll(" ", "%20")
40 | .replaceAll("#", "%23")
41 | .replaceAll("$", "%24")
42 | .replaceAll("&", "%26")
43 | .replaceAll("'", "%27")
44 | .replaceAll("\\+", "%2B")
45 | .replaceAll(",", "%2C")
46 | .replaceAll("/", "%2F")
47 | .replaceAll(":", "%3A")
48 | .replaceAll(";", "%3B")
49 | .replaceAll("=", "%3D")
50 | .replaceAll("\\?", "%3F")
51 | .replaceAll("@", "%40")
52 | .replaceAll("\\[", "%5B")
53 | .replaceAll("\\\\", "%5C")
54 | .replaceAll("\\]", "%5C")
55 | .replaceAll("^", "%5D")
56 | .replaceAll("_", "%5E")
57 | .replaceAll("`", "%60")
58 | .replaceAll("\\{", "%7B")
59 | .replaceAll("\\|", "%7C")
60 | .replaceAll("\\}", "%7D");
61 |
62 | Log.d("BookUtils", "Encoded text: " + encodedText);
63 | //TODO: This temporary workaround needs to be fixed.
64 | return encodedText.substring(3, encodedText.length() - 3);
65 | }
66 |
67 | public static String buildCoverUrl(Book book) {
68 | String imageCode = book.getCoverImage().getImageCode() + "";
69 | String coverTheme = book.getCoverColor().getColorCode() + "";
70 | String coverUrl = String.format(BASE_URL,
71 | encodeString(book.getTitle()),
72 | encodeString(book.getTopText()),
73 | encodeString(book.getAuthor()),
74 | imageCode,
75 | coverTheme,
76 | encodeString(book.getGuideText()),
77 | book.getGuideTextPosition().getPositionName());
78 | Log.d("BookUtils", "Generated Url: " + coverUrl);
79 | return coverUrl;
80 | }
81 |
82 | public static List getImageResources(Context context) {
83 | AssetManager assetManager = context.getAssets();
84 | List images = new LinkedList<>();
85 | J8Arrays.stream(CoverImage.values()).forEach(coverImage -> {
86 | try {
87 | InputStream inputStream = assetManager.open("images/" + coverImage.getImageCode() + ".png");
88 | Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
89 | images.add(bitmap);
90 | inputStream.close();
91 | } catch (IOException io) {
92 | io.printStackTrace();
93 | }
94 | });
95 | return images;
96 | }
97 |
98 | public static Bitmap getImageResource(Context context, int imageCode) {
99 | AssetManager assetManager = context.getAssets();
100 | CoverImage coverImg = J8Arrays.stream(CoverImage.values()).filter(coverImage -> coverImage.getImageCode() == imageCode).findAny().orElse(null);
101 | if (coverImg == null) {
102 | return null;
103 | }
104 | Bitmap bitmap = null;
105 | try {
106 | InputStream inputStream = assetManager.open("images/" + coverImg.getImageCode() + ".png");
107 | bitmap = BitmapFactory.decodeStream(inputStream);
108 | inputStream.close();
109 | } catch (IOException io) {
110 | io.printStackTrace();
111 | }
112 | return bitmap;
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | O-Rly-Android
3 | Generated Book Cover
4 | About
5 | Share via…
6 |
7 | Title
8 | Specify the Title of the Book
9 | Top Text
10 | Specify the top Text of the Book
11 | Sub Title
12 | Specify the sub Title of the Book (optional)
13 | Author
14 | Specify the Author of the Book
15 | Color
16 | Specify the Color of the Book
17 | Image
18 | Specify the Image of the Book
19 |
20 | Book Title:
21 | Book Sub Title:
22 | Book Top Text:
23 | Book Author:
24 | Select Cover Color
25 | Select Cover Image
26 | Open
27 |
28 | Pick A Cover Color
29 | Pick A Cover Image
30 | Cancel Book Cover Generation?
31 | This will reset all data.\nAre you sure you want to proceed?
32 | No Internet Connection Available
33 | Please make sure you have an active internet connection in order to proceed.
34 | Generating Book Cover
35 | It should be ready soon! Hang tight…
36 |
37 | Reset Content
38 | View on GitHub
39 | About
40 | Settings
41 |
42 | Save
43 | Share
44 | Delete
45 |
46 | Continue
47 | Generate
48 | Reset
49 |
50 | Image successfully saved to:\n%s
51 | Unable to save Image. If this issue persists please file an issue on GitHub.
52 | Storage Permission is required to save images!
53 |
54 | true
55 | false
56 |
57 | O-Rly Book Cover Generator
59 | Now on Android by PDDStudio
60 | Feel free to contact or follow me:
61 | - Google+
62 | - GitHub
63 | - E-Mail
64 |
65 | Disclaimer:
66 | I only created the Android-App for the O RLY Cover Generator and do not hold any special permission, except the agreement to bring this awesome site to Android.
67 | The site is hosted by @ThePracticalDev and the original tool was created by @AModelEngineer.
68 | Insult your co-workers with snarky O RLY parody book covers!
69 | PS. There are a few known edge cases that do not generate. Some characters and long words won\'t work, etc. If you want to report an issue, feel free to do this in the GitHub Repository.]]>
70 |
71 |
72 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/com/pddstudio/orlyandroid/utils/StorageManager.java:
--------------------------------------------------------------------------------
1 | package com.pddstudio.orlyandroid.utils;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.pm.PackageManager;
8 | import android.net.Uri;
9 | import android.os.Build;
10 | import android.os.Environment;
11 | import android.support.v4.app.ActivityCompat;
12 | import android.support.v4.content.ContextCompat;
13 | import android.support.v4.content.FileProvider;
14 |
15 | import com.pddstudio.orly.book.generator.Book;
16 | import com.pddstudio.orlyandroid.R;
17 |
18 | import org.androidannotations.annotations.EBean;
19 | import org.androidannotations.annotations.RootContext;
20 |
21 | import java.io.File;
22 | import java.io.FileInputStream;
23 | import java.io.FileOutputStream;
24 | import java.io.IOException;
25 | import java.io.InputStream;
26 | import java.io.OutputStream;
27 |
28 | import java8.util.J8Arrays;
29 | import okhttp3.OkHttpClient;
30 | import okhttp3.Request;
31 | import okhttp3.Response;
32 | import okio.BufferedSink;
33 | import okio.Okio;
34 |
35 | /**
36 | * Created by pddstudio on 15/08/16.
37 | */
38 | @EBean(scope = EBean.Scope.Singleton)
39 | public class StorageManager {
40 |
41 | public static final int STORAGE_REQUEST_CODE = 42;
42 | private static final String STORAGE_FOLDER_NAME = "ORly-Android-Covers";
43 |
44 | @RootContext
45 | Context context;
46 |
47 | private OkHttpClient okHttpClient = new OkHttpClient();
48 |
49 | private Book tmpBook;
50 | private File tmpFile;
51 | private File destFile;
52 |
53 | private String generateName(Book book) {
54 | return book.getTitle() + "_" + book.getAuthor() + "_" + System.currentTimeMillis() + ".png";
55 | }
56 |
57 | public File saveBook(Book book) {
58 | try {
59 |
60 | Request request = new Request.Builder().url(book.getGeneratedUrl()).build();
61 | Response response = okHttpClient.newCall(request).execute();
62 |
63 | if (!response.isSuccessful()) {
64 | throw new IOException("Something went wrong!\n" + response);
65 | }
66 |
67 | String bookName = generateName(book);
68 | tmpBook = book;
69 | tmpFile = new File(context.getCacheDir(), bookName);
70 | BufferedSink bufferedSink = Okio.buffer(Okio.sink(tmpFile));
71 | bufferedSink.writeAll(response.body().source());
72 | bufferedSink.close();
73 |
74 | if (tmpFile.exists()) {
75 | return tmpFile;
76 | } else {
77 | throw new IOException("Unable to find file: " + tmpFile.getAbsolutePath());
78 | }
79 |
80 | } catch (IOException io) {
81 | io.printStackTrace();
82 | recycle();
83 | return null;
84 | }
85 | }
86 |
87 | public Book getTmpBook() {
88 | return tmpBook;
89 | }
90 |
91 | public File getTmpFile() {
92 | return tmpFile;
93 | }
94 |
95 | public File getDestFile() {
96 | return destFile;
97 | }
98 |
99 | public void recycle() {
100 | if (tmpFile.exists()) {
101 | tmpFile.delete();
102 | }
103 | destFile = null;
104 | tmpBook = null;
105 | tmpFile = null;
106 | }
107 |
108 | public void shareCachedImage(Context context) {
109 | if (tmpFile != null && tmpFile.exists()) {
110 | Uri imageUri = FileProvider.getUriForFile(context, "com.pddstudio.orlyandroid.fileprovider", tmpFile);
111 | if (imageUri != null) {
112 | Intent shareIntent = new Intent();
113 | shareIntent.setAction(Intent.ACTION_SEND);
114 | shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
115 | shareIntent.setDataAndType(imageUri, context.getContentResolver().getType(imageUri));
116 | shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
117 | context.startActivity(Intent.createChooser(shareIntent, context.getString(R.string.share_image_text)));
118 | }
119 | }
120 | }
121 |
122 | public boolean canAccessStorage() {
123 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
124 | return true;
125 | }
126 | return ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
127 | }
128 |
129 | public void requestStoragePermission(Activity activity) {
130 | ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_REQUEST_CODE);
131 | }
132 |
133 | private boolean checkIfDirectoryExistsAndCreateIfNot() {
134 | if (canAccessStorage()) {
135 | String directory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + STORAGE_FOLDER_NAME;
136 | File storageDir = new File(directory);
137 | if (!storageDir.exists()) {
138 | storageDir.mkdirs();
139 | }
140 | return storageDir.exists() && storageDir.isDirectory();
141 | } else {
142 | return false;
143 | }
144 | }
145 |
146 | private File getStorageDir() {
147 | String directory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + STORAGE_FOLDER_NAME;
148 | return new File(directory);
149 | }
150 |
151 | public boolean saveImageToStorage() {
152 | if (!checkIfDirectoryExistsAndCreateIfNot()) {
153 | return false;
154 | } else {
155 | destFile = new File(getStorageDir(), tmpFile.getName());
156 | copyFile(tmpFile, destFile);
157 | return destFile.exists();
158 | }
159 | }
160 |
161 | private void copyFile(File source, File dest) {
162 | try {
163 | InputStream inputStream = new FileInputStream(source);
164 | OutputStream outputStream = new FileOutputStream(dest);
165 | byte[] buffer = new byte[1024];
166 | int reader;
167 | while ((reader = inputStream.read(buffer)) > 0) {
168 | outputStream.write(buffer, 0, reader);
169 | }
170 | inputStream.close();
171 | outputStream.close();
172 | } catch (IOException io) {
173 | io.printStackTrace();
174 | }
175 | }
176 |
177 | public void cleanCacheDir() {
178 | File cache = context.getCacheDir();
179 | J8Arrays.stream(cache.listFiles()).filter(File::isFile).forEach(file -> {
180 | if (file.getName().endsWith(".png")) {
181 | file.delete();
182 | }
183 | });
184 | }
185 |
186 | }
187 |
--------------------------------------------------------------------------------
/app/src/main/java/com/pddstudio/orlyandroid/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.pddstudio.orlyandroid;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.support.annotation.ColorInt;
6 | import android.support.annotation.NonNull;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.inputmethod.InputMethodManager;
12 | import android.widget.EditText;
13 |
14 | import com.afollestad.materialdialogs.MaterialDialog;
15 | import com.afollestad.materialdialogs.color.ColorChooserDialog;
16 | import com.pddstudio.orly.book.generator.enums.CoverColor;
17 | import com.pddstudio.orlyandroid.enums.Type;
18 | import com.pddstudio.orlyandroid.enums.UrlType;
19 | import com.pddstudio.orlyandroid.fragments.ColorPickerFragment;
20 | import com.pddstudio.orlyandroid.fragments.CoverImagePickerFragment;
21 | import com.pddstudio.orlyandroid.fragments.SingleTextFragment;
22 | import com.pddstudio.orlyandroid.utils.BuilderUtil;
23 | import com.pddstudio.orlyandroid.utils.GenerationUtils;
24 | import com.pddstudio.orlyandroid.utils.NetworkUtils;
25 | import com.pddstudio.orlyandroid.utils.StorageManager;
26 |
27 | import org.androidannotations.annotations.AfterInject;
28 | import org.androidannotations.annotations.AfterViews;
29 | import org.androidannotations.annotations.Background;
30 | import org.androidannotations.annotations.Bean;
31 | import org.androidannotations.annotations.EActivity;
32 | import org.androidannotations.annotations.OptionsItem;
33 | import org.androidannotations.annotations.OptionsMenu;
34 | import org.androidannotations.annotations.UiThread;
35 | import org.androidannotations.annotations.ViewById;
36 |
37 | import java.io.File;
38 | import java.util.ArrayList;
39 | import java.util.List;
40 |
41 | import me.drozdzynski.library.steppers.OnCancelAction;
42 | import me.drozdzynski.library.steppers.OnFinishAction;
43 | import me.drozdzynski.library.steppers.SteppersItem;
44 | import me.drozdzynski.library.steppers.SteppersView;
45 |
46 | @EActivity(R.layout.activity_main)
47 | @OptionsMenu(R.menu.menu_main)
48 | public class MainActivity extends AppCompatActivity implements OnFinishAction, OnCancelAction, ColorChooserDialog.ColorCallback, ColorPickerFragment.Callback {
49 |
50 | @Bean
51 | GenerationUtils generationUtils;
52 |
53 | @Bean
54 | BuilderUtil builderUtil;
55 |
56 | @Bean
57 | StorageManager storageManager;
58 |
59 | @Bean
60 | NetworkUtils networkUtils;
61 |
62 | @ViewById(R.id.toolbar)
63 | Toolbar toolbar;
64 |
65 | @ViewById(R.id.steppers_view)
66 | SteppersView steppersView;
67 |
68 | SteppersView.Config steppersViewConfig;
69 | MaterialDialog loadingDialog;
70 |
71 | @AfterInject
72 | void prepareApplication() {
73 | storageManager.cleanCacheDir();
74 | }
75 |
76 | @AfterViews
77 | void prepareLayout() {
78 | setSupportActionBar(toolbar);
79 | steppersViewConfig = new SteppersView.Config();
80 | steppersViewConfig.setOnFinishAction(this);
81 | steppersViewConfig.setOnCancelAction(this);
82 | steppersViewConfig.setFragmentManager(getSupportFragmentManager());
83 | steppersView.setConfig(steppersViewConfig);
84 | steppersView.setItems(prepareSteps());
85 | steppersView.build();
86 | }
87 |
88 | private List prepareSteps() {
89 | List items = new ArrayList<>();
90 | //Title item
91 | SteppersItem titleItem = new SteppersItem();
92 | titleItem.setLabel(getString(R.string.step_title_title));
93 | titleItem.setSubLabel(getString(R.string.step_title_summary));
94 | titleItem.setFragment(SingleTextFragment.create(this, R.string.fragment_title_text, Type.TITLE));
95 | items.add(titleItem);
96 | //SubTitle item
97 | SteppersItem subTitleItem = new SteppersItem();
98 | subTitleItem.setLabel(getString(R.string.step_guide_text_title));
99 | subTitleItem.setSubLabel(getString(R.string.step_guide_text_summary));
100 | subTitleItem.setFragment(SingleTextFragment.create(this, R.string.fragment_sub_title_text, Type.GUIDE));
101 | items.add(subTitleItem);
102 | //Top Title item
103 | SteppersItem topTitleItem = new SteppersItem();
104 | topTitleItem.setLabel(getString(R.string.step_top_title_title));
105 | topTitleItem.setSubLabel(getString(R.string.step_top_title_summary));
106 | topTitleItem.setFragment(SingleTextFragment.create(this, R.string.fragment_top_text, Type.TOP_TITLE));
107 | items.add(topTitleItem);
108 | //Author item
109 | SteppersItem authorItem = new SteppersItem();
110 | authorItem.setLabel(getString(R.string.step_author_title));
111 | authorItem.setSubLabel(getString(R.string.step_author_summary));
112 | authorItem.setFragment(SingleTextFragment.create(this, R.string.fragment_author_text, Type.AUTHOR));
113 | items.add(authorItem);
114 | //Color item
115 | SteppersItem colorItem = new SteppersItem();
116 | colorItem.setLabel(getString(R.string.step_color_title));
117 | colorItem.setSubLabel(getString(R.string.step_color_summary));
118 | colorItem.setFragment(ColorPickerFragment.create());
119 | items.add(colorItem);
120 | //Image item
121 | SteppersItem imageItem = new SteppersItem();
122 | imageItem.setLabel(getString(R.string.step_image_title));
123 | imageItem.setSubLabel(getString(R.string.step_image_summary));
124 | imageItem.setFragment(CoverImagePickerFragment.create());
125 | items.add(imageItem);
126 |
127 | return items;
128 | }
129 |
130 | private void restartActivity() {
131 | MainActivity_.intent(this).start();
132 | this.finish();
133 | }
134 |
135 | private void showNotConnectedDialog() {
136 | new MaterialDialog.Builder(this).title(R.string.dialog_no_connection_title)
137 | .content(R.string.dialog_no_connection_content)
138 | .positiveText(android.R.string.ok)
139 | .show();
140 | }
141 |
142 | @Override
143 | public void onFinish() {
144 | if (networkUtils.isConnectionAvailable()) {
145 | loadingDialog = new MaterialDialog.Builder(this).title(R.string.dialog_generate_image_title)
146 | .content(R.string.dialog_generate_image_content)
147 | .progress(true, -1)
148 | .cancelable(false)
149 | .canceledOnTouchOutside(false)
150 | .autoDismiss(false)
151 | .show();
152 | downloadImage();
153 | } else {
154 | showNotConnectedDialog();
155 | }
156 |
157 | }
158 |
159 | @UiThread
160 | void onImageDownloaded(File downloadedFile) {
161 |
162 | if (loadingDialog != null && loadingDialog.isShowing()) {
163 | loadingDialog.dismiss();
164 | }
165 |
166 | if (downloadedFile != null && downloadedFile.exists()) {
167 | ResultActivity.open(this, downloadedFile);
168 | builderUtil.clean();
169 | } else {
170 | //TODO: handle case if saving failed!
171 | }
172 | }
173 |
174 | @Background
175 | void downloadImage() {
176 | File downloadedFile = storageManager.saveBook(builderUtil.build());
177 | onImageDownloaded(downloadedFile);
178 | }
179 |
180 | @Override
181 | @OptionsItem(R.id.menu_reset_content)
182 | public void onCancel() {
183 | new MaterialDialog.Builder(this).title(R.string.dialog_cancel_title)
184 | .content(R.string.dialog_cancel_content)
185 | .positiveText(android.R.string.yes)
186 | .negativeText(android.R.string.no)
187 | .onPositive((dialog, which) -> restartActivity())
188 | .show();
189 | }
190 |
191 | @OptionsItem(R.id.menu_github)
192 | void openGithubPage() {
193 | networkUtils.openUrl(this, UrlType.GITHUB);
194 | }
195 |
196 | @OptionsItem(R.id.menu_about)
197 | void openAboutPage() {
198 | AboutActivity.open(this);
199 | }
200 |
201 | @OptionsItem(R.id.menu_settings)
202 | void openSettingsPage() {
203 | //TODO: Add settings
204 | }
205 |
206 | @Override
207 | public void onColorSelection(@NonNull ColorChooserDialog dialog, @ColorInt int selectedColor) {
208 | String strColor = String.format("#%06X", 0xFFFFFF & selectedColor);
209 | builderUtil.setCoverColor(CoverColor.getForHex(strColor));
210 | }
211 |
212 | @Override
213 | public void onColorDialogClicked(int[] colors) {
214 | new ColorChooserDialog.Builder(this, R.string.dialog_pick_color_title).customColors(colors, null)
215 | .allowUserColorInput(false)
216 | .allowUserColorInputAlpha(false)
217 | .show();
218 | }
219 |
220 | @Override
221 | public boolean dispatchTouchEvent(MotionEvent event) {
222 | if (event.getAction() == MotionEvent.ACTION_DOWN) {
223 | View view = getCurrentFocus();
224 | if (view instanceof EditText) {
225 | Rect outRect = new Rect();
226 | view.getGlobalVisibleRect(outRect);
227 | if (!outRect.contains((int) event.getRawX(), (int) event.getRawY())) {
228 | view.clearFocus();
229 | InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
230 | imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
231 | }
232 | }
233 | }
234 | return super.dispatchTouchEvent(event);
235 | }
236 |
237 | }
238 |
--------------------------------------------------------------------------------