├── settings.gradle
├── tests
└── api
│ ├── .gitignore
│ ├── test_all.sh
│ ├── test_all_auto.sh
│ ├── auth_token.js
│ ├── package.json
│ ├── types.js
│ ├── tag.js
│ ├── post.js
│ └── api.js
├── markdown
├── .gitignore
├── package.json
├── webpack.config.js
├── README.md
└── markdown-converter.js
├── .gitattributes
├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values-ar
│ │ │ │ └── strings.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── drawable-xxhdpi
│ │ │ │ └── appbar_shadow.9.png
│ │ │ ├── values-w480dp
│ │ │ │ ├── integers.xml
│ │ │ │ └── styles.xml
│ │ │ ├── values-w720dp
│ │ │ │ └── integers.xml
│ │ │ ├── values-w960dp
│ │ │ │ └── integers.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ ├── activity_login.xml
│ │ │ │ ├── fragment_post_view.xml
│ │ │ │ ├── fragment_web_view.xml
│ │ │ │ ├── fragment_web_view_nested_scroll.xml
│ │ │ │ ├── fragment_ghost_auth.xml
│ │ │ │ ├── post_list_footer.xml
│ │ │ │ ├── dialog_image_insert.xml
│ │ │ │ ├── open_source_libs_list_item.xml
│ │ │ │ ├── activity_open_source_libs.xml
│ │ │ │ ├── fragment_post_edit.xml
│ │ │ │ ├── fragment_ghost_v0_error.xml
│ │ │ │ └── format_toolbar.xml
│ │ │ ├── drawable
│ │ │ │ ├── format_italic.xml
│ │ │ │ ├── about_rate.xml
│ │ │ │ ├── about_community.xml
│ │ │ │ ├── status_draft.xml
│ │ │ │ ├── image_placeholder.xml
│ │ │ │ ├── format_image.xml
│ │ │ │ ├── about_open_source_libs.xml
│ │ │ │ ├── about_version.xml
│ │ │ │ ├── new_draft.xml
│ │ │ │ ├── status_scheduled.xml
│ │ │ │ ├── format_link.xml
│ │ │ │ ├── format_bold.xml
│ │ │ │ ├── about_translate.xml
│ │ │ │ ├── about_report_bug.xml
│ │ │ │ ├── share.xml
│ │ │ │ ├── status_published.xml
│ │ │ │ ├── settings.xml
│ │ │ │ ├── ic_launcher_foreground.xml
│ │ │ │ └── ghost_sad_face.xml
│ │ │ ├── menu
│ │ │ │ ├── post_edit.xml
│ │ │ │ ├── insert_image.xml
│ │ │ │ ├── post_list.xml
│ │ │ │ └── post_view.xml
│ │ │ ├── xml
│ │ │ │ └── network_security_config.xml
│ │ │ ├── values
│ │ │ │ ├── integers.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── themes.xml
│ │ │ │ └── dimens.xml
│ │ │ ├── values-ro
│ │ │ │ └── strings.xml
│ │ │ ├── anim-v21
│ │ │ │ └── lift_up.xml
│ │ │ ├── values-ml
│ │ │ │ └── strings.xml
│ │ │ ├── values-ru
│ │ │ │ └── strings.xml
│ │ │ └── values-vi
│ │ │ │ └── strings.xml
│ │ ├── assets
│ │ │ └── fonts
│ │ │ │ ├── OpenSans-Bold.ttf
│ │ │ │ ├── OpenSans-Italic.ttf
│ │ │ │ ├── OpenSans-CondBold.ttf
│ │ │ │ ├── OpenSans-Regular.ttf
│ │ │ │ └── OpenSans-BoldItalic.ttf
│ │ └── java
│ │ │ └── me
│ │ │ └── vickychijwani
│ │ │ └── spectre
│ │ │ ├── event
│ │ │ ├── LoadTagsEvent.java
│ │ │ ├── CredentialsExpiredEvent.java
│ │ │ ├── ForceCancelRefreshEvent.java
│ │ │ ├── CreatePostEvent.java
│ │ │ ├── PostDeletedEvent.java
│ │ │ ├── LoginDoneEvent.java
│ │ │ ├── FileUploadedEvent.java
│ │ │ ├── RefreshDataEvent.java
│ │ │ ├── PostSavedEvent.java
│ │ │ ├── DeletePostEvent.java
│ │ │ ├── PostSyncedEvent.java
│ │ │ ├── UserLoadedEvent.java
│ │ │ ├── ApiCallEvent.java
│ │ │ ├── LoginErrorEvent.java
│ │ │ ├── PostCreatedEvent.java
│ │ │ ├── PostReplacedEvent.java
│ │ │ ├── GhostVersionLoadedEvent.java
│ │ │ ├── TagsLoadedEvent.java
│ │ │ ├── ApiErrorEvent.java
│ │ │ ├── BlogSettingsLoadedEvent.java
│ │ │ ├── FileUploadErrorEvent.java
│ │ │ ├── LogoutStatusEvent.java
│ │ │ ├── DataRefreshedEvent.java
│ │ │ ├── LogoutEvent.java
│ │ │ ├── PostConflictFoundEvent.java
│ │ │ ├── SavePostEvent.java
│ │ │ ├── LoadPostsEvent.java
│ │ │ ├── LoadUserEvent.java
│ │ │ ├── PostsLoadedEvent.java
│ │ │ ├── SyncPostsEvent.java
│ │ │ ├── LoadBlogSettingsEvent.java
│ │ │ ├── LoadGhostVersionEvent.java
│ │ │ ├── BusProvider.java
│ │ │ └── FileUploadEvent.java
│ │ │ ├── network
│ │ │ ├── ApiProviderFactory.java
│ │ │ ├── ApiProvider.java
│ │ │ ├── HttpClientFactory.java
│ │ │ ├── entity
│ │ │ │ ├── TagStub.java
│ │ │ │ ├── ApiErrorList.java
│ │ │ │ ├── UserList.java
│ │ │ │ ├── SettingsList.java
│ │ │ │ ├── ApiError.java
│ │ │ │ ├── PostList.kt
│ │ │ │ ├── RefreshReqBody.java
│ │ │ │ ├── PostStubList.java
│ │ │ │ ├── PostStub.java
│ │ │ │ ├── RevokeReqBody.java
│ │ │ │ ├── ConfigurationList.java
│ │ │ │ └── AuthReqBody.java
│ │ │ ├── RealmExclusionStrategy.java
│ │ │ ├── AnnotationExclusionStrategy.java
│ │ │ ├── ApiFailure.java
│ │ │ ├── DateDeserializer.java
│ │ │ ├── StringConverterFactory.java
│ │ │ ├── JSONObjectConverterFactory.java
│ │ │ ├── PostTypeAdapterFactory.java
│ │ │ ├── ProductionHttpClientFactory.java
│ │ │ └── ConfigurationListDeserializer.java
│ │ │ ├── util
│ │ │ ├── functions
│ │ │ │ ├── Action0.java
│ │ │ │ ├── Action1.java
│ │ │ │ ├── Func1.java
│ │ │ │ ├── Action2.java
│ │ │ │ └── Action3.java
│ │ │ ├── log
│ │ │ │ ├── DebugLogger.java
│ │ │ │ ├── JvmLogger.java
│ │ │ │ ├── ReleaseLogger.java
│ │ │ │ ├── Logger.java
│ │ │ │ └── Log.java
│ │ │ ├── DeviceUtils.java
│ │ │ ├── Listenable.java
│ │ │ ├── DateTimeUtils.java
│ │ │ └── EditTextSelectionState.java
│ │ │ ├── model
│ │ │ ├── DBConfiguration.java
│ │ │ ├── BlogMetadataModule.java
│ │ │ ├── GsonExclude.java
│ │ │ ├── entity
│ │ │ │ ├── Role.java
│ │ │ │ ├── ConfigurationParam.java
│ │ │ │ ├── Setting.java
│ │ │ │ ├── ETag.java
│ │ │ │ ├── PendingAction.java
│ │ │ │ └── User.java
│ │ │ ├── BlogDataModule.java
│ │ │ └── BlogDBMigration.java
│ │ │ ├── error
│ │ │ ├── PostConflictFoundException.java
│ │ │ ├── UserEditsLostException.java
│ │ │ ├── UncaughtRxException.java
│ │ │ ├── UrlNotFoundException.java
│ │ │ ├── LoginFailedException.java
│ │ │ ├── SyncException.java
│ │ │ ├── FileUploadFailedException.java
│ │ │ └── TokenRevocationFailedException.java
│ │ │ ├── auth
│ │ │ ├── PasswordAuth.java
│ │ │ ├── BlogUrlValidator.java
│ │ │ ├── ProductionApiProviderFactory.java
│ │ │ ├── CredentialSource.java
│ │ │ ├── CredentialSink.java
│ │ │ ├── ProductionApiProvider.java
│ │ │ ├── GhostAuth.java
│ │ │ └── AuthStore.java
│ │ │ ├── view
│ │ │ ├── FormatOptionClickListener.java
│ │ │ ├── BundleKeys.java
│ │ │ ├── widget
│ │ │ │ └── SpaceItemDecoration.java
│ │ │ ├── fragments
│ │ │ │ └── GhostV0ErrorFragment.java
│ │ │ ├── AboutActivity.java
│ │ │ ├── image
│ │ │ │ └── BorderedCircleTransformation.java
│ │ │ └── Observables.java
│ │ │ └── pref
│ │ │ ├── BaseKey.java
│ │ │ ├── AppState.java
│ │ │ ├── UserPrefs.java
│ │ │ └── Prefs.java
│ ├── debug
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── me
│ │ │ └── vickychijwani
│ │ │ └── spectre
│ │ │ └── testing
│ │ │ ├── EventBusRule.kt
│ │ │ ├── JvmLoggingRule.kt
│ │ │ ├── UrlMatches.kt
│ │ │ ├── RxSchedulersRule.kt
│ │ │ └── Helpers.kt
│ ├── androidTest
│ │ └── java
│ │ │ └── me
│ │ │ └── vickychijwani
│ │ │ └── spectre
│ │ │ └── testing
│ │ │ ├── BaseIdlingResource.kt
│ │ │ ├── ViewNotVisibleIdlingResource.kt
│ │ │ ├── ViewDoesntMatchTextIdlingResource.kt
│ │ │ ├── OkHttpIdlingResourceRule.kt
│ │ │ ├── EndToEndTestUtils.kt
│ │ │ ├── ActivityStateIdlingResource.kt
│ │ │ ├── ClearPreferencesRule.kt
│ │ │ ├── RecyclerViewMatcher.kt
│ │ │ ├── OkHttpIdlingResource.kt
│ │ │ └── LoginRobot.kt
│ └── sharedTest
│ │ └── java
│ │ └── me
│ │ └── vickychijwani
│ │ └── spectre
│ │ └── testing
│ │ ├── DeleteDefaultPostsRule.kt
│ │ └── GhostApiTestUtils.kt
├── lint.xml
└── proguard-rules.pro
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── ISSUE_TEMPLATE.md
├── CONTRIBUTING.md
├── gradle.properties
├── LICENSE
├── .circleci
└── config.yml
└── gradlew.bat
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/tests/api/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 |
--------------------------------------------------------------------------------
/markdown/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /build
3 |
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | app/src/main/assets/markdown-converter.js binary
2 |
3 |
--------------------------------------------------------------------------------
/tests/api/test_all.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | jasmine-node . --growl
3 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /crashlytics.properties
3 | /fabric.properties
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ar/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/api/test_all_auto.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | jasmine-node . --growl --autotest --watch . --color
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea
4 | *.iml
5 | **/*.iml
6 | .DS_Store
7 | /build
8 | /captures/
9 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/OpenSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/assets/fonts/OpenSans-Bold.ttf
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/OpenSans-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/assets/fonts/OpenSans-Italic.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | FILL THESE DETAILS FIRST:
2 |
3 | - Ghost version: X.Y.Z
4 | - App version: X.Y.Z
5 |
6 | ----
7 |
8 | DESCRIBE YOUR ISSUE HERE
9 |
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/OpenSans-CondBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/assets/fonts/OpenSans-CondBold.ttf
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/OpenSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/assets/fonts/OpenSans-Regular.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/assets/fonts/OpenSans-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/assets/fonts/OpenSans-BoldItalic.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LoadTagsEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class LoadTagsEvent {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/appbar_shadow.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/drawable-xxhdpi/appbar_shadow.9.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TryGhost/Ghost-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/CredentialsExpiredEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class CredentialsExpiredEvent {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/ForceCancelRefreshEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class ForceCancelRefreshEvent {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w480dp/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 2
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w720dp/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 3
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w960dp/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/debug/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ghost (Dev)
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/CreatePostEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class CreatePostEvent {
4 |
5 | public CreatePostEvent() {}
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/app/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/ApiProviderFactory.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network;
2 |
3 | public interface ApiProviderFactory {
4 |
5 | ApiProvider create(String blogUrl);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/tests/api/auth_token.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash-node');
2 |
3 | module.exports = {};
4 |
5 | module.exports.schema = {
6 | access_token: String,
7 | expires_in: Number,
8 | token_type: 'Bearer',
9 | };
10 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/util/functions/Action0.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.util.functions;
2 |
3 | /**
4 | * A zero-argument action.
5 | */
6 | public interface Action0 {
7 |
8 | void call();
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/util/functions/Action1.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.util.functions;
2 |
3 | /**
4 | * A one-argument action.
5 | */
6 | public interface Action1 {
7 |
8 | void call(T t);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/util/functions/Func1.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.util.functions;
2 |
3 | /**
4 | * A function with one argument.
5 | */
6 | public interface Func1 {
7 |
8 | R call(T t);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/util/functions/Action2.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.util.functions;
2 |
3 | /**
4 | * A two-argument action.
5 | */
6 | public interface Action2 {
7 |
8 | void call(T1 t1, T2 t2);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/util/functions/Action3.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.util.functions;
2 |
3 | /**
4 | * A three-argument action.
5 | */
6 | public interface Action3 {
7 |
8 | void call(T1 t1, T2 t2, T3 t3);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/ApiProvider.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network;
2 |
3 | import retrofit2.Retrofit;
4 |
5 | public interface ApiProvider {
6 |
7 | Retrofit getRetrofit();
8 |
9 | GhostApiService getGhostApi();
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Feb 11 23:30:42 IST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/PostDeletedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class PostDeletedEvent {
4 |
5 | public final String postId;
6 |
7 | public PostDeletedEvent(String postId) {
8 | this.postId = postId;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LoginDoneEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class LoginDoneEvent {
4 |
5 | public final String blogUrl;
6 |
7 | public LoginDoneEvent(String blogUrl) {
8 | this.blogUrl = blogUrl;
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/model/DBConfiguration.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.model;
2 |
3 | public abstract class DBConfiguration {
4 |
5 | public static final int METADATA_DB_SCHEMA_VERSION = 4;
6 |
7 | public static final int DATA_DB_SCHEMA_VERSION = 4;
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "quill-ghost-api-tests",
3 | "scripts": {
4 | "test": "echo \"Error: no test specified\" && exit 1"
5 | },
6 | "dependencies": {
7 | "frisby": "^0.8.5",
8 | "lodash-node": "^3.10.0",
9 | "request-json": "^0.5.3",
10 | "x-ray": "^2.0.2"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/FileUploadedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class FileUploadedEvent {
4 |
5 | public final String relativeUrl;
6 |
7 | public FileUploadedEvent(String relativeUrl) {
8 | this.relativeUrl = relativeUrl;
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/error/PostConflictFoundException.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.error;
2 |
3 | public class PostConflictFoundException extends RuntimeException {
4 |
5 | public PostConflictFoundException() {
6 | super("POST CONFLICT FOUND: see logs for details");
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/RefreshDataEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class RefreshDataEvent {
4 |
5 | public final boolean loadCachedData;
6 |
7 | public RefreshDataEvent(boolean loadCachedData) {
8 | this.loadCachedData = loadCachedData;
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/error/UserEditsLostException.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.error;
2 |
3 | public final class UserEditsLostException extends RuntimeException {
4 |
5 | public UserEditsLostException() {
6 | super("USER EDITS WERE OVERWRITTEN! SEE STACK TO TRACE THE ROOT CAUSE.");
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/PostSavedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.model.entity.Post;
4 |
5 | public class PostSavedEvent {
6 |
7 | public final Post post;
8 |
9 | public PostSavedEvent(Post post) {
10 | this.post = post;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/DeletePostEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.model.entity.Post;
4 |
5 | public class DeletePostEvent {
6 |
7 | public final Post post;
8 |
9 | public DeletePostEvent(Post post) {
10 | this.post = post;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/PostSyncedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.model.entity.Post;
4 |
5 | public class PostSyncedEvent {
6 |
7 | public final Post post;
8 |
9 | public PostSyncedEvent(Post post) {
10 | this.post = post;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/UserLoadedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.model.entity.User;
4 |
5 | public class UserLoadedEvent {
6 |
7 | public final User user;
8 |
9 | public UserLoadedEvent(User user) {
10 | this.user = user;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/HttpClientFactory.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network;
2 |
3 | import android.support.annotation.Nullable;
4 |
5 | import java.io.File;
6 |
7 | import okhttp3.OkHttpClient;
8 |
9 | public interface HttpClientFactory {
10 |
11 | OkHttpClient create(@Nullable File cacheDir);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/ApiCallEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public interface ApiCallEvent {
4 |
5 | /**
6 | * Indicate to the receiver that a network call will fail (network errors, site down) and
7 | * therefore should NOT be attempted
8 | */
9 | void loadCachedData();
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LoginErrorEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import android.support.annotation.Nullable;
4 |
5 | public class LoginErrorEvent {
6 |
7 | public final String blogUrl;
8 |
9 | public LoginErrorEvent(@Nullable String blogUrl) {
10 | this.blogUrl = blogUrl;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/PostCreatedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.model.entity.Post;
4 |
5 | public class PostCreatedEvent {
6 |
7 | public final Post newPost;
8 |
9 | public PostCreatedEvent(Post newPost) {
10 | this.newPost = newPost;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/PostReplacedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.model.entity.Post;
4 |
5 | public class PostReplacedEvent {
6 |
7 | public final Post newPost;
8 |
9 | public PostReplacedEvent(Post newPost) {
10 | this.newPost = newPost;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/auth/PasswordAuth.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.auth;
2 |
3 | public final class PasswordAuth {
4 |
5 | public static class Params {
6 |
7 | public final String blogUrl;
8 |
9 | public Params(String blogUrl) {
10 | this.blogUrl = blogUrl;
11 | }
12 |
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/error/UncaughtRxException.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.error;
2 |
3 | public class UncaughtRxException extends RuntimeException {
4 |
5 | /**
6 | * @param cause - the original cause of this exception
7 | */
8 | public UncaughtRxException(Throwable cause) {
9 | super(cause);
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/view/FormatOptionClickListener.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.view;
2 |
3 | import android.view.View;
4 |
5 | public interface FormatOptionClickListener {
6 | void onFormatBoldClicked(View v);
7 | void onFormatItalicClicked(View v);
8 | void onFormatLinkClicked(View v);
9 | void onFormatImageClicked(View v);
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/error/UrlNotFoundException.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.error;
2 |
3 | public class UrlNotFoundException extends RuntimeException {
4 |
5 | /**
6 | * @param url - the URL that could not be found
7 | */
8 | public UrlNotFoundException(String url) {
9 | super("URL RETURNED 404: " + url);
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/GhostVersionLoadedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | public class GhostVersionLoadedEvent {
6 |
7 | public final String version;
8 |
9 | public GhostVersionLoadedEvent(@NonNull String version) {
10 | this.version = version;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/TagsLoadedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import java.util.List;
4 |
5 | import me.vickychijwani.spectre.model.entity.Tag;
6 |
7 | public class TagsLoadedEvent {
8 |
9 | public final List tags;
10 |
11 | public TagsLoadedEvent(List tags) {
12 | this.tags = tags;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/model/BlogMetadataModule.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.model;
2 |
3 | import io.realm.annotations.RealmModule;
4 | import me.vickychijwani.spectre.model.entity.BlogMetadata;
5 |
6 | // set of classes included in the schema for blog metadata Realm
7 |
8 | @RealmModule(classes = {
9 | BlogMetadata.class
10 | })
11 | public class BlogMetadataModule {}
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/format_italic.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_post_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/post_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/ApiErrorEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import me.vickychijwani.spectre.network.ApiFailure;
6 |
7 | public class ApiErrorEvent {
8 |
9 | public final ApiFailure apiFailure;
10 |
11 | public ApiErrorEvent(@NonNull ApiFailure apiFailure) {
12 | this.apiFailure = apiFailure;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/BlogSettingsLoadedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import java.util.List;
4 |
5 | import me.vickychijwani.spectre.model.entity.Setting;
6 |
7 | public class BlogSettingsLoadedEvent {
8 |
9 | public final List settings;
10 |
11 | public BlogSettingsLoadedEvent(List settings) {
12 | this.settings = settings;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/FileUploadErrorEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.network.ApiFailure;
4 |
5 | @SuppressWarnings({"WeakerAccess", "unused"})
6 | public class FileUploadErrorEvent {
7 |
8 | public final ApiFailure apiFailure;
9 |
10 | public FileUploadErrorEvent(ApiFailure apiFailure) {
11 | this.apiFailure = apiFailure;
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LogoutStatusEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class LogoutStatusEvent {
4 |
5 | public final boolean succeeded;
6 | public final boolean hasPendingActions;
7 |
8 | public LogoutStatusEvent(boolean succeeded, boolean hasPendingActions) {
9 | this.succeeded = succeeded;
10 | this.hasPendingActions = hasPendingActions;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/tests/api/types.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | StringOrNull: function (val) { return expect(val).toBeTypeOrNull(String); },
3 | NumberOrNull: function (val) { return expect(val).toBeTypeOrNull(Number); },
4 | DateString: function (val) { return expect(val).toMatch(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$/); },
5 | DateStringOrNull: function (val) { return expect(val).toMatchOrBeNull(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$/); },
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/DataRefreshedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import android.support.annotation.Nullable;
4 |
5 | import me.vickychijwani.spectre.network.ApiFailure;
6 |
7 | public class DataRefreshedEvent {
8 |
9 | public final ApiFailure apiFailure;
10 |
11 | public DataRefreshedEvent(@Nullable ApiFailure apiFailure) {
12 | this.apiFailure = apiFailure;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/about_rate.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/model/GsonExclude.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.model;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | // credits: http://stackoverflow.com/a/27986860/504611
9 | @Retention(RetentionPolicy.RUNTIME)
10 | @Target(ElementType.FIELD)
11 | public @interface GsonExclude {
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/entity/TagStub.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network.entity;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import me.vickychijwani.spectre.model.entity.Tag;
6 |
7 | @SuppressWarnings({"WeakerAccess", "unused"})
8 | public class TagStub {
9 |
10 | public final String name;
11 |
12 | public TagStub(@NonNull Tag tag) {
13 | this.name = tag.getName();
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LogoutEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | public class LogoutEvent {
6 |
7 | @NonNull public final String blogUrl;
8 | public final boolean forceLogout;
9 |
10 | public LogoutEvent(@NonNull String blogUrl, boolean forceLogout) {
11 | this.blogUrl = blogUrl;
12 | this.forceLogout = forceLogout;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/tests/api/tag.js:
--------------------------------------------------------------------------------
1 | var types = require('./types');
2 |
3 | module.exports = {};
4 |
5 | module.exports.schema = {
6 | uuid: String,
7 | name: String,
8 |
9 | slug: String,
10 | description: types.StringOrNull,
11 | image: types.StringOrNull,
12 | hidden: Boolean,
13 |
14 | meta_title: types.StringOrNull,
15 | meta_description: types.StringOrNull,
16 |
17 | created_at: types.DateString,
18 | updated_at: types.DateString,
19 | };
20 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ### Reporting bugs
2 |
3 | **Please follow these guidelines when creating a new issue:**
4 |
5 | - Take some time to check for related issues before you create a new one.
6 | - Describe your issue in as much detail as possible.
7 | - Always include these details in bug reports: app version, Android version, device name. **Reports without these details may be ignored.**
8 |
9 | **[VIEW OR CREATE ISSUES HERE](https://github.com/TryGhost/Ghost-Android/issues)**
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/about_community.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/status_draft.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/image_placeholder.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w480dp/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 769
5 | 770
6 | 200
7 | 1
8 |
9 |
10 | 300
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/PostConflictFoundEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.model.entity.Post;
4 |
5 | public final class PostConflictFoundEvent {
6 |
7 | public final Post localPost;
8 | public final Post serverPost;
9 |
10 | public PostConflictFoundEvent(Post localPost, Post serverPost) {
11 | this.localPost = localPost;
12 | this.serverPost = serverPost;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/format_image.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/SavePostEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import me.vickychijwani.spectre.model.entity.Post;
4 |
5 | public class SavePostEvent {
6 |
7 | public final Post post;
8 | public final boolean isAutoSave; // was this post saved automatically or explicitly?
9 |
10 | public SavePostEvent(Post post, boolean isAutoSave) {
11 | this.post = post;
12 | this.isAutoSave = isAutoSave;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/about_open_source_libs.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/util/log/DebugLogger.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.util.log;
2 |
3 | final class DebugLogger extends Logger {
4 |
5 | @Override
6 | public void log(int priority, String tag, String message) {
7 | android.util.Log.println(priority, tag, message);
8 | }
9 |
10 | @Override
11 | public void exception(Throwable error) {
12 | android.util.Log.e("Exception", android.util.Log.getStackTraceString(error));
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LoadPostsEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class LoadPostsEvent implements ApiCallEvent {
4 |
5 | public final boolean forceNetworkCall;
6 | public boolean loadCachedData = false;
7 |
8 | public LoadPostsEvent(boolean forceNetworkCall) {
9 | this.forceNetworkCall = forceNetworkCall;
10 | }
11 |
12 | @Override
13 | public void loadCachedData() {
14 | loadCachedData = true;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LoadUserEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class LoadUserEvent implements ApiCallEvent {
4 |
5 | public final boolean forceNetworkCall;
6 | public boolean loadCachedData = false;
7 |
8 | public LoadUserEvent(boolean forceNetworkCall) {
9 | this.forceNetworkCall = forceNetworkCall;
10 | }
11 |
12 | @Override
13 | public void loadCachedData() {
14 | loadCachedData = true;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/PostsLoadedEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import java.util.List;
4 |
5 | import me.vickychijwani.spectre.model.entity.Post;
6 |
7 | public class PostsLoadedEvent {
8 |
9 | public final List posts;
10 | public final int postsFetchLimit;
11 |
12 | public PostsLoadedEvent(List posts, int postsFetchLimit) {
13 | this.posts = posts;
14 | this.postsFetchLimit = postsFetchLimit;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/SyncPostsEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class SyncPostsEvent implements ApiCallEvent {
4 |
5 | public final boolean forceNetworkCall;
6 | public boolean loadCachedData = false;
7 |
8 | public SyncPostsEvent(boolean forceNetworkCall) {
9 | this.forceNetworkCall = forceNetworkCall;
10 | }
11 |
12 | @Override
13 | public void loadCachedData() {
14 | loadCachedData = true;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/entity/ApiErrorList.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network.entity;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 |
6 | @SuppressWarnings("unused")
7 | public class ApiErrorList {
8 |
9 | public List errors;
10 |
11 | public static ApiErrorList from(ApiError... errors) {
12 | ApiErrorList errorList = new ApiErrorList();
13 | errorList.errors = Arrays.asList(errors);
14 | return errorList;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/util/log/JvmLogger.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.util.log;
2 |
3 | /**
4 | * Use this for code running on a JVM instead of on Android (e.g., unit tests).
5 | */
6 | final class JvmLogger extends Logger {
7 |
8 | @Override
9 | public void log(int priority, String tag, String message) {
10 | System.out.println(message);
11 | }
12 |
13 | @Override
14 | public void exception(Throwable error) {
15 | error.printStackTrace();
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LoadBlogSettingsEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class LoadBlogSettingsEvent implements ApiCallEvent {
4 |
5 | public final boolean forceNetworkCall;
6 | public boolean loadCachedData = false;
7 |
8 | public LoadBlogSettingsEvent(boolean forceNetworkCall) {
9 | this.forceNetworkCall = forceNetworkCall;
10 | }
11 |
12 | @Override
13 | public void loadCachedData() {
14 | loadCachedData = true;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/LoadGhostVersionEvent.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | public class LoadGhostVersionEvent implements ApiCallEvent {
4 |
5 | public final boolean forceNetworkCall;
6 | public boolean loadCachedData = false;
7 |
8 | public LoadGhostVersionEvent(boolean forceNetworkCall) {
9 | this.forceNetworkCall = forceNetworkCall;
10 | }
11 |
12 | @Override
13 | public void loadCachedData() {
14 | loadCachedData = true;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/view/BundleKeys.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.view;
2 |
3 | public final class BundleKeys {
4 |
5 | public static final String POST = "key:post";
6 | public static final String START_EDITING = "key:start_editing";
7 | public static final String URL = "key:url";
8 | public static final String POST_EDITED = "key:post_edited";
9 |
10 | public static final String LOCAL_POST = "key:local_post";
11 | public static final String SERVER_POST = "key:server_post";
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/about_version.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/new_draft.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/status_scheduled.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/markdown/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ghost-android-markdown",
3 | "description": "Builds the Markdown-to-HTML converter used by Ghost Android",
4 | "repository": {
5 | "type": "git",
6 | "url": "git@github.com:TryGhost/Ghost-Android.git"
7 | },
8 | "scripts": {
9 | "build": "./node_modules/.bin/webpack --optimize-minimize"
10 | },
11 | "devDependencies": {
12 | "markdown-it": "8.4.1",
13 | "markdown-it-footnote": "3.0.1",
14 | "markdown-it-lazy-headers": "0.1.3",
15 | "markdown-it-mark": "2.0.0",
16 | "webpack": "^3.3.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/util/DeviceUtils.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.util;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.support.annotation.NonNull;
6 |
7 | public class DeviceUtils {
8 |
9 | public static int getScreenWidth(@NonNull Context context) {
10 | return context.getResources().getDisplayMetrics().widthPixels;
11 | }
12 |
13 | public static float dpToPx(final float dp) {
14 | return dp * Resources.getSystem().getDisplayMetrics().density;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_web_view.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/event/BusProvider.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.event;
2 |
3 | import android.support.annotation.RestrictTo;
4 |
5 | import com.squareup.otto.Bus;
6 | import com.squareup.otto.ThreadEnforcer;
7 |
8 | public class BusProvider {
9 |
10 | private static Bus sBus = new Bus();
11 |
12 | private BusProvider() {}
13 |
14 | @RestrictTo(RestrictTo.Scope.TESTS)
15 | public static void setupForTesting() {
16 | sBus = new Bus(ThreadEnforcer.ANY);
17 | }
18 |
19 | public static Bus getBus() { return sBus; }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_web_view_nested_scroll.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/entity/UserList.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network.entity;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 |
6 | import me.vickychijwani.spectre.model.entity.User;
7 |
8 | // dummy wrapper class needed for Retrofit
9 | @SuppressWarnings("unused")
10 | public class UserList {
11 |
12 | public List users;
13 |
14 | public static UserList from(User... users) {
15 | UserList userList = new UserList();
16 | userList.users = Arrays.asList(users);
17 | return userList;
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/format_link.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/entity/SettingsList.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network.entity;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 |
6 | import me.vickychijwani.spectre.model.entity.Setting;
7 |
8 | @SuppressWarnings("unused")
9 | public class SettingsList {
10 |
11 | public List settings;
12 |
13 | public static SettingsList from(Setting... settings) {
14 | SettingsList settingsList = new SettingsList();
15 | settingsList.settings = Arrays.asList(settings);
16 | return settingsList;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/RealmExclusionStrategy.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network;
2 |
3 | import com.google.gson.ExclusionStrategy;
4 | import com.google.gson.FieldAttributes;
5 |
6 | import io.realm.RealmObject;
7 |
8 | class RealmExclusionStrategy implements ExclusionStrategy {
9 |
10 | @Override
11 | public boolean shouldSkipField(FieldAttributes f) {
12 | return f.getDeclaringClass().equals(RealmObject.class);
13 | }
14 |
15 | @Override
16 | public boolean shouldSkipClass(Class> clazz) {
17 | return false;
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/entity/ApiError.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network.entity;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | @SuppressWarnings("unused")
6 | public class ApiError {
7 |
8 | public String message; // meant for humans
9 |
10 | // unfortunately there is a bug in the field name on the API side, it is "errorType" rather than
11 | // "error_type", hence the custom @SerializedName
12 | @SerializedName("errorType")
13 | public String errorType; // meant for machines: "UnauthorizedError", etc.
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/network/entity/PostList.kt:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.network.entity
2 |
3 | import me.vickychijwani.spectre.model.entity.Post
4 |
5 | // dummy wrapper class needed for Retrofit
6 | class PostList(var posts: MutableList) {
7 |
8 | operator fun contains(id: String): Boolean {
9 | for (post in posts) {
10 | if (id == post.id) {
11 | return true
12 | }
13 | }
14 | return false
15 | }
16 |
17 | fun remove(idx: Int): Post {
18 | return posts.removeAt(idx)
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/format_bold.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/pref/BaseKey.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.pref;
2 |
3 | abstract class BaseKey {
4 |
5 | private final String mStr;
6 | private final Class mType;
7 | private final Object mDefaultValue;
8 |
9 | /* package */ BaseKey(String str, Class type, T defaultValue) {
10 | mStr = str;
11 | mType = type;
12 | mDefaultValue = defaultValue;
13 | }
14 |
15 | public Object getDefaultValue() { return mDefaultValue; }
16 | public Class getType() { return mType; }
17 | public String toString() { return mStr; }
18 |
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/error/LoginFailedException.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.error;
2 |
3 | public final class LoginFailedException extends RuntimeException {
4 |
5 | /**
6 | * @param throwable - the cause of this login failure
7 | */
8 | public LoginFailedException(Throwable throwable) {
9 | super("LOGIN FAILED: see previous exception for details", throwable);
10 | }
11 |
12 | /**
13 | * @param message a custom String message
14 | */
15 | public LoginFailedException(String message) {
16 | super("LOGIN FAILED: " + message);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/me/vickychijwani/spectre/error/SyncException.java:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.error;
2 |
3 | public final class SyncException extends RuntimeException {
4 |
5 | /**
6 | * @param throwable - the cause of this exception
7 | */
8 | public SyncException(String message, Throwable throwable) {
9 | super("SYNC EXCEPTION: " + message + ", see previous exception for details", throwable);
10 | }
11 |
12 | /**
13 | * @param message a custom String message
14 | */
15 | public SyncException(String message) {
16 | super("SYNC EXCEPTION: " + message);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/test/java/me/vickychijwani/spectre/testing/EventBusRule.kt:
--------------------------------------------------------------------------------
1 | package me.vickychijwani.spectre.testing
2 |
3 | import me.vickychijwani.spectre.event.BusProvider
4 | import org.junit.rules.TestRule
5 | import org.junit.runner.Description
6 | import org.junit.runners.model.Statement
7 |
8 | class EventBusRule : TestRule {
9 |
10 | override fun apply(base: Statement, description: Description): Statement {
11 | return object : Statement() {
12 | override fun evaluate() {
13 | BusProvider.setupForTesting()
14 | base.evaluate()
15 | }
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/markdown/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 |
3 | module.exports = {
4 | entry: './markdown-converter.js',
5 | // the generated converter will be usable as MarkdownConverter.render("**Markdown** _string_")
6 | // when included in a