mirror of
https://github.com/sismics/docs.git
synced 2024-11-25 23:27:57 +01:00
commit
bf8e0827e2
@ -60,7 +60,6 @@ or download the sources from GitHub.
|
||||
|
||||
From the `docs-parent` directory:
|
||||
|
||||
mvn -Pinit validate -N
|
||||
mvn clean -DskipTests install
|
||||
|
||||
#### Run a stand-alone version
|
||||
|
@ -12,10 +12,7 @@
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugAndroidTestSources</task>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
@ -28,7 +25,7 @@
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
@ -50,6 +47,13 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
@ -64,65 +68,58 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/apk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/incremental" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/debug" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/22.2.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.1.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.1.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.1.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.shamanland/fab/0.0.6/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/it.sephiroth.android.library.easing/android-easing/1.0.3/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/it.sephiroth.android.library.imagezoom/imagezoom/1.0.5/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtimfe-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/libs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/ndk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/source" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="fab-0.0.6" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-23.1.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-easing-1.0.3" level="project" />
|
||||
<orderEntry type="library" exported="" name="imagezoom-1.0.5" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-v4-22.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="recyclerview-v7-22.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-query.0.26.8" level="project" />
|
||||
<orderEntry type="library" exported="" name="tokenautocomplete-1.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-22.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="appcompat-v7-22.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-async-http-1.4.6" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-async-http-1.4.9" level="project" />
|
||||
<orderEntry type="library" exported="" name="picasso-2.5.2" level="project" />
|
||||
<orderEntry type="library" exported="" name="eventbus-2.4.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="recyclerview-v7-23.1.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="okhttp-urlconnection-3.0.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-v4-23.1.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="fab-0.0.6" level="project" />
|
||||
<orderEntry type="library" exported="" name="appcompat-v7-23.1.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="httpclient-4.3.6" level="project" />
|
||||
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="picasso2-okhttp3-downloader-1.0.2" level="project" />
|
||||
<orderEntry type="library" exported="" name="tokenautocomplete-1.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="okhttp-3.0.1" level="project" />
|
||||
</component>
|
||||
</module>
|
@ -3,7 +3,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.0.0-alpha3'
|
||||
classpath 'com.android.tools.build:gradle:2.0.0-alpha7'
|
||||
}
|
||||
}
|
||||
apply plugin: 'com.android.application'
|
||||
@ -13,12 +13,12 @@ repositories {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion '23.0.2'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 22
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
@ -50,10 +50,14 @@ android {
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: '*.jar')
|
||||
compile 'com.android.support:appcompat-v7:22.+'
|
||||
compile 'com.android.support:recyclerview-v7:22.+'
|
||||
compile 'com.loopj.android:android-async-http:1.4.6'
|
||||
compile 'com.android.support:appcompat-v7:23.1.1'
|
||||
compile 'com.android.support:recyclerview-v7:23.1.1'
|
||||
compile 'com.loopj.android:android-async-http:1.4.9'
|
||||
compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'
|
||||
compile 'de.greenrobot:eventbus:2.4.1'
|
||||
compile 'com.shamanland:fab:0.0.6'
|
||||
compile 'com.squareup.picasso:picasso:2.5.2'
|
||||
compile 'com.squareup.okhttp3:okhttp:3.0.1'
|
||||
compile "com.squareup.okhttp3:okhttp-urlconnection:3.0.1"
|
||||
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'
|
||||
}
|
||||
|
Binary file not shown.
@ -2,7 +2,6 @@ package com.sismics.docs;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.androidquery.callback.BitmapAjaxCallback;
|
||||
import com.sismics.docs.model.application.ApplicationContext;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
|
||||
@ -24,10 +23,4 @@ public class MainApplication extends Application {
|
||||
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
BitmapAjaxCallback.clearCache();
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import com.sismics.docs.adapter.LanguageAdapter;
|
||||
import com.sismics.docs.adapter.TagAutoCompleteAdapter;
|
||||
import com.sismics.docs.event.DocumentAddEvent;
|
||||
import com.sismics.docs.event.DocumentEditEvent;
|
||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.listener.HttpCallback;
|
||||
import com.sismics.docs.resource.DocumentResource;
|
||||
import com.sismics.docs.ui.form.Validator;
|
||||
import com.sismics.docs.ui.form.validator.Required;
|
||||
@ -25,7 +25,6 @@ import com.sismics.docs.ui.view.DatePickerView;
|
||||
import com.sismics.docs.ui.view.TagsCompleteTextView;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -174,9 +173,9 @@ public class DocumentEditActivity extends AppCompatActivity {
|
||||
});
|
||||
|
||||
// Server callback
|
||||
JsonHttpResponseHandler callback = new JsonHttpResponseHandler() {
|
||||
HttpCallback callback = new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
public void onSuccess(JSONObject response) {
|
||||
// Build a fake document JSON to update the UI
|
||||
final JSONObject outputDoc = new JSONObject();
|
||||
try {
|
||||
@ -211,7 +210,7 @@ public class DocumentEditActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
||||
public void onFailure(JSONObject json, Exception e) {
|
||||
Toast.makeText(DocumentEditActivity.this, R.string.error_editing_document, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,9 @@ import com.sismics.docs.event.DocumentEditEvent;
|
||||
import com.sismics.docs.event.DocumentFullscreenEvent;
|
||||
import com.sismics.docs.event.FileAddEvent;
|
||||
import com.sismics.docs.event.FileDeleteEvent;
|
||||
import com.sismics.docs.fragment.DocExportPdfFragment;
|
||||
import com.sismics.docs.fragment.DocShareFragment;
|
||||
import com.sismics.docs.listener.HttpCallback;
|
||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.model.application.ApplicationContext;
|
||||
import com.sismics.docs.resource.CommentResource;
|
||||
@ -54,7 +56,6 @@ import com.sismics.docs.service.FileUploadService;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
import com.sismics.docs.util.TagUtil;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -63,6 +64,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import cz.msebera.android.httpclient.Header;
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
@ -244,6 +246,16 @@ public class DocumentViewActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
|
||||
// Action export PDF
|
||||
button = (Button) findViewById(R.id.actionExportPdf);
|
||||
button.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
DialogFragment dialog = DocExportPdfFragment.newInstance(DocumentViewActivity.this.document.optString("id"));
|
||||
dialog.show(getSupportFragmentManager(), "DocExportPdfFragment");
|
||||
}
|
||||
});
|
||||
|
||||
// Action share
|
||||
button = (Button) findViewById(R.id.actionSharing);
|
||||
button.setOnClickListener(new View.OnClickListener() {
|
||||
@ -476,14 +488,14 @@ public class DocumentViewActivity extends AppCompatActivity {
|
||||
|
||||
// Actual delete server call
|
||||
final String documentId = document.optString("id");
|
||||
DocumentResource.delete(DocumentViewActivity.this, documentId, new JsonHttpResponseHandler() {
|
||||
DocumentResource.delete(DocumentViewActivity.this, documentId, new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
public void onSuccess(JSONObject response) {
|
||||
EventBus.getDefault().post(new DocumentDeleteEvent(documentId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
||||
public void onFailure(JSONObject json, Exception e) {
|
||||
Toast.makeText(DocumentViewActivity.this, R.string.document_delete_failure, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@ -635,9 +647,9 @@ public class DocumentViewActivity extends AppCompatActivity {
|
||||
// Silently get the document to know if it is writable by the current user
|
||||
// If this call fails or is slow and the document is read-only,
|
||||
// write actions will be allowed and will fail
|
||||
DocumentResource.get(this, document.optString("id"), new JsonHttpResponseHandler() {
|
||||
DocumentResource.get(this, document.optString("id"), new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
public void onSuccess(JSONObject response) {
|
||||
document = response;
|
||||
boolean writable = document.optBoolean("writable");
|
||||
|
||||
@ -720,7 +732,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
JSONArray comments = response.optJSONArray("comments");
|
||||
commentListAdapter = new CommentListAdapter(comments);
|
||||
commentListAdapter = new CommentListAdapter(DocumentViewActivity.this, comments);
|
||||
listView.setAdapter(commentListAdapter);
|
||||
listView.setVisibility(View.VISIBLE);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
@ -10,8 +10,8 @@ import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.androidquery.AQuery;
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.listener.CallbackListener;
|
||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
||||
@ -22,9 +22,10 @@ import com.sismics.docs.ui.form.validator.Required;
|
||||
import com.sismics.docs.util.DialogUtil;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import cz.msebera.android.httpclient.Header;
|
||||
|
||||
/**
|
||||
* Login activity.
|
||||
*
|
||||
@ -43,18 +44,16 @@ public class LoginActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.login_activity);
|
||||
|
||||
AQuery aq = new AQuery(this);
|
||||
aq.id(R.id.loginExplain)
|
||||
.text(Html.fromHtml(getString(R.string.login_explain)))
|
||||
.getTextView()
|
||||
.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
TextView loginExplainTextView = (TextView) findViewById(R.id.loginExplain);
|
||||
loginExplainTextView.setText(Html.fromHtml(getString(R.string.login_explain)));
|
||||
loginExplainTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
final EditText txtServer = aq.id(R.id.txtServer).getEditText();
|
||||
final EditText txtUsername = aq.id(R.id.txtUsername).getEditText();
|
||||
final EditText txtPassword = aq.id(R.id.txtPassword).getEditText();
|
||||
final Button btnConnect = aq.id(R.id.btnConnect).getButton();
|
||||
loginForm = aq.id(R.id.loginForm).getView();
|
||||
progressBar = aq.id(R.id.progressBar).getView();
|
||||
final EditText txtServer = (EditText) findViewById(R.id.txtServer);
|
||||
final EditText txtUsername = (EditText) findViewById(R.id.txtUsername);
|
||||
final EditText txtPassword = (EditText) findViewById(R.id.txtPassword);
|
||||
final Button btnConnect = (Button) findViewById(R.id.btnConnect);
|
||||
loginForm = findViewById(R.id.loginForm);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
|
||||
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
|
||||
|
||||
|
@ -18,7 +18,6 @@ import android.widget.ListView;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.androidquery.util.AQUtility;
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.adapter.TagListAdapter;
|
||||
import com.sismics.docs.event.AdvancedSearchEvent;
|
||||
@ -31,9 +30,9 @@ import com.sismics.docs.resource.TagResource;
|
||||
import com.sismics.docs.resource.UserResource;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import cz.msebera.android.httpclient.Header;
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
@ -274,10 +273,6 @@ public class MainActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
if(isTaskRoot()) {
|
||||
int cacheSizeMb = PreferenceUtil.getIntegerPreference(this, PreferenceUtil.PREF_CACHE_SIZE, 10);
|
||||
AQUtility.cleanCacheAsync(this, cacheSizeMb * 1000000, cacheSizeMb * 1000000);
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package com.sismics.docs.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -10,9 +9,8 @@ import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.androidquery.AQuery;
|
||||
import com.androidquery.callback.BitmapAjaxCallback;
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.util.OkHttpUtil;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
@ -27,22 +25,23 @@ import java.util.List;
|
||||
* @author bgamard.
|
||||
*/
|
||||
public class CommentListAdapter extends BaseAdapter {
|
||||
/**
|
||||
* AQuery.
|
||||
*/
|
||||
private AQuery aq;
|
||||
|
||||
/**
|
||||
* Tags.
|
||||
*/
|
||||
private List<JSONObject> commentList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Context.
|
||||
*/
|
||||
private Context context;
|
||||
|
||||
/**
|
||||
* Comment list adapter.
|
||||
*
|
||||
* @param commentsArray Comments
|
||||
*/
|
||||
public CommentListAdapter(JSONArray commentsArray) {
|
||||
public CommentListAdapter(Context context, JSONArray commentsArray) {
|
||||
this.context = context;
|
||||
for (int i = 0; i < commentsArray.length(); i++) {
|
||||
commentList.add(commentsArray.optJSONObject(i));
|
||||
}
|
||||
@ -70,12 +69,6 @@ public class CommentListAdapter extends BaseAdapter {
|
||||
view = vi.inflate(R.layout.comment_list_item, parent, false);
|
||||
}
|
||||
|
||||
if (aq == null) {
|
||||
aq = new AQuery(view);
|
||||
} else {
|
||||
aq.recycle(view);
|
||||
}
|
||||
|
||||
// Fill the view
|
||||
JSONObject comment = getItem(position);
|
||||
TextView creatorTextView = (TextView) view.findViewById(R.id.creatorTextView);
|
||||
@ -88,14 +81,9 @@ public class CommentListAdapter extends BaseAdapter {
|
||||
|
||||
// Gravatar image
|
||||
String gravatarUrl = "http://www.gravatar.com/avatar/" + comment.optString("creator_gravatar") + "?s=128d=identicon";
|
||||
if (aq.shouldDelay(position, view, parent, gravatarUrl)) {
|
||||
aq.id(gravatarImageView).image((Bitmap) null);
|
||||
} else {
|
||||
aq.id(gravatarImageView).image(new BitmapAjaxCallback()
|
||||
.url(gravatarUrl)
|
||||
.animation(AQuery.FADE_IN_NETWORK)
|
||||
);
|
||||
}
|
||||
OkHttpUtil.picasso(context)
|
||||
.load(gravatarUrl)
|
||||
.into(gravatarImageView);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
@ -7,10 +7,11 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.androidquery.AQuery;
|
||||
import com.androidquery.callback.BitmapAjaxCallback;
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.util.OkHttpUtil;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
import com.squareup.picasso.Callback;
|
||||
import com.squareup.picasso.MemoryPolicy;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
@ -30,11 +31,6 @@ public class FilePagerAdapter extends PagerAdapter {
|
||||
*/
|
||||
private List<JSONObject> files;
|
||||
|
||||
/**
|
||||
* AQuery.
|
||||
*/
|
||||
private AQuery aq;
|
||||
|
||||
/**
|
||||
* Context.
|
||||
*/
|
||||
@ -58,7 +54,6 @@ public class FilePagerAdapter extends PagerAdapter {
|
||||
}
|
||||
this.context = context;
|
||||
this.authToken = PreferenceUtil.getAuthToken(context);
|
||||
aq = new AQuery(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,15 +61,20 @@ public class FilePagerAdapter extends PagerAdapter {
|
||||
View view = LayoutInflater.from(container.getContext()).inflate(R.layout.file_viewpager_item, container, false);
|
||||
|
||||
ImageViewTouch fileImageView = (ImageViewTouch) view.findViewById(R.id.fileImageView);
|
||||
ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.fileProgressBar);
|
||||
final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.fileProgressBar);
|
||||
JSONObject file = files.get(position);
|
||||
String fileUrl = PreferenceUtil.getServerUrl(context) + "/api/file/" + file.optString("id") + "/data?size=web";
|
||||
aq.id(fileImageView)
|
||||
.image(new BitmapAjaxCallback()
|
||||
.url(fileUrl)
|
||||
.progress(progressBar)
|
||||
.animation(AQuery.FADE_IN_NETWORK)
|
||||
.cookie("auth_token", authToken));
|
||||
|
||||
// Load image
|
||||
OkHttpUtil.picasso(context)
|
||||
.load(fileUrl)
|
||||
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE) // Don't memory cache the images
|
||||
.into(fileImageView, new Callback.EmptyCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
fileImageView.setDisplayType(ImageViewTouchBase.DisplayType.FIT_TO_SCREEN);
|
||||
|
||||
@ -109,7 +109,7 @@ public class FilePagerAdapter extends PagerAdapter {
|
||||
* @return Object
|
||||
*/
|
||||
public JSONObject getObjectAt(int position) {
|
||||
if (files == null) {
|
||||
if (files == null || position < 0 || position >= files.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
package com.sismics.docs.fragment;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import com.sismics.docs.R;
|
||||
|
||||
/**
|
||||
* Export PDF dialog fragment.
|
||||
*
|
||||
* @author bgamard.
|
||||
*/
|
||||
public class DocExportPdfFragment extends DialogFragment {
|
||||
/**
|
||||
* Export PDF dialog fragment.
|
||||
*
|
||||
* @param id Document ID
|
||||
*/
|
||||
public static DocExportPdfFragment newInstance(String id) {
|
||||
DocExportPdfFragment fragment = new DocExportPdfFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString("id", id);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
|
||||
// Setup the view
|
||||
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||
View view = inflater.inflate(R.layout.document_export_pdf_dialog, null);
|
||||
|
||||
// Build the dialog
|
||||
builder.setView(view)
|
||||
.setPositiveButton(R.string.download, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
getDialog().cancel();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
getDialog().cancel();
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
}
|
@ -21,13 +21,12 @@ import com.sismics.docs.event.DocumentAddEvent;
|
||||
import com.sismics.docs.event.DocumentDeleteEvent;
|
||||
import com.sismics.docs.event.DocumentEditEvent;
|
||||
import com.sismics.docs.event.SearchEvent;
|
||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.listener.HttpCallback;
|
||||
import com.sismics.docs.listener.RecyclerItemClickListener;
|
||||
import com.sismics.docs.resource.DocumentResource;
|
||||
import com.sismics.docs.ui.view.DividerItemDecoration;
|
||||
import com.sismics.docs.ui.view.EmptyRecyclerView;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
@ -218,16 +217,16 @@ public class DocListFragment extends Fragment {
|
||||
|
||||
recyclerView.setEmptyView(progressBar);
|
||||
|
||||
DocumentResource.list(getActivity(), reset ? 0 : adapter.getItemCount(), query, new JsonHttpResponseHandler() {
|
||||
DocumentResource.list(getActivity(), reset ? 0 : adapter.getItemCount(), query, new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
public void onSuccess(JSONObject response) {
|
||||
adapter.addDocuments(response.optJSONArray("documents"));
|
||||
documentsEmptyView.setText(R.string.no_documents);
|
||||
recyclerView.setEmptyView(documentsEmptyView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
||||
public void onFailure(JSONObject response, Exception e) {
|
||||
documentsEmptyView.setText(R.string.error_loading_documents);
|
||||
recyclerView.setEmptyView(documentsEmptyView);
|
||||
|
||||
|
@ -21,15 +21,16 @@ import com.sismics.docs.R;
|
||||
import com.sismics.docs.adapter.ShareListAdapter;
|
||||
import com.sismics.docs.event.ShareDeleteEvent;
|
||||
import com.sismics.docs.event.ShareSendEvent;
|
||||
import com.sismics.docs.listener.HttpCallback;
|
||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.resource.DocumentResource;
|
||||
import com.sismics.docs.resource.ShareResource;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import cz.msebera.android.httpclient.Header;
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
@ -44,7 +45,8 @@ public class DocShareFragment extends DialogFragment {
|
||||
private JSONObject document;
|
||||
|
||||
/**
|
||||
* Document sharing dialog fragment
|
||||
* Document sharing dialog fragment.
|
||||
*
|
||||
* @param id Document ID
|
||||
*/
|
||||
public static DocShareFragment newInstance(String id) {
|
||||
@ -121,9 +123,9 @@ public class DocShareFragment extends DialogFragment {
|
||||
final ProgressBar shareProgressBar = (ProgressBar) view.findViewById(R.id.shareProgressBar);
|
||||
|
||||
shareListView.setEmptyView(shareProgressBar);
|
||||
DocumentResource.get(getActivity(), getArguments().getString("id"), new JsonHttpResponseHandler() {
|
||||
DocumentResource.get(getActivity(), getArguments().getString("id"), new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
public void onSuccess(JSONObject response) {
|
||||
document = response;
|
||||
JSONArray acls = response.optJSONArray("acls");
|
||||
shareProgressBar.setVisibility(View.GONE);
|
||||
@ -132,7 +134,7 @@ public class DocShareFragment extends DialogFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
||||
public void onFailure(JSONObject json, Exception e) {
|
||||
getDialog().cancel();
|
||||
Toast.makeText(getActivity(), R.string.error_loading_shares, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ import android.preference.PreferenceManager;
|
||||
import android.provider.SearchRecentSuggestions;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.androidquery.util.AQUtility;
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.provider.RecentSuggestionsProvider;
|
||||
import com.sismics.docs.util.ApplicationUtil;
|
||||
import com.sismics.docs.util.OkHttpUtil;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
|
||||
/**
|
||||
@ -52,7 +52,7 @@ public class SettingsFragment extends PreferenceFragment implements SharedPrefer
|
||||
clearCachePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
AQUtility.cleanCacheAsync(getActivity());
|
||||
OkHttpUtil.clearCache(getActivity());
|
||||
Toast.makeText(getActivity(), R.string.pref_clear_cache_success, Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
package com.sismics.docs.listener;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* An HTTP callback.
|
||||
*
|
||||
* @author bgamard.
|
||||
*/
|
||||
public class HttpCallback {
|
||||
public void onSuccess(JSONObject json) {
|
||||
// Implement me
|
||||
}
|
||||
|
||||
public void onFailure(JSONObject json, Exception e) {
|
||||
// Implement me
|
||||
}
|
||||
|
||||
public void onFinish() {
|
||||
// Implement me
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an OkHttp Callback from a HttpCallback.
|
||||
*
|
||||
* @param httpCallback HttpCallback
|
||||
* @return OkHttp Callback
|
||||
*/
|
||||
public static Callback buildOkHttpCallback(final HttpCallback httpCallback) {
|
||||
return new Callback() {
|
||||
@Override
|
||||
public void onResponse(final Call call, final Response response) throws IOException {
|
||||
final String body = response.body().string();
|
||||
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (response.isSuccessful()) {
|
||||
try {
|
||||
httpCallback.onSuccess(new JSONObject(body));
|
||||
} catch (Exception e) {
|
||||
httpCallback.onFailure(null, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
httpCallback.onFailure(new JSONObject(body), null);
|
||||
} catch (Exception e) {
|
||||
httpCallback.onFailure(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
httpCallback.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Call call, final IOException e) {
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
httpCallback.onFailure(null, e);
|
||||
httpCallback.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -22,19 +22,20 @@ import android.util.Log;
|
||||
|
||||
import com.loopj.android.http.TextHttpResponseHandler;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
import cz.msebera.android.httpclient.Header;
|
||||
import cz.msebera.android.httpclient.HttpStatus;
|
||||
|
||||
/**
|
||||
* Used to intercept and handle the responses from requests made using {@link com.loopj.android.http.AsyncHttpClient}, with
|
||||
* automatic parsing into a {@link JSONObject} or {@link JSONArray}. <p> </p> This class is
|
||||
* designed to be passed to get, post, put and delete requests with the {@link #onSuccess(int,
|
||||
* org.apache.http.Header[], org.json.JSONArray)} or {@link #onSuccess(int,
|
||||
* org.apache.http.Header[], org.json.JSONObject)} methods anonymously overridden. <p> </p>
|
||||
* cz.msebera.android.httpclient.Header[], org.json.JSONArray)} or {@link #onSuccess(int,
|
||||
* cz.msebera.android.httpclient.Header[], org.json.JSONObject)} methods anonymously overridden. <p> </p>
|
||||
* Additionally, you can override the other event methods from the parent class.
|
||||
*/
|
||||
public class JsonHttpResponseHandler extends TextHttpResponseHandler {
|
||||
|
@ -8,9 +8,10 @@ import com.sismics.docs.listener.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.resource.UserResource;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import cz.msebera.android.httpclient.Header;
|
||||
|
||||
/**
|
||||
* Global context of the application.
|
||||
*
|
||||
|
@ -3,14 +3,11 @@ package com.sismics.docs.resource;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import com.androidquery.callback.AbstractAjaxCallback;
|
||||
import com.loopj.android.http.AsyncHttpClient;
|
||||
import com.loopj.android.http.PersistentCookieStore;
|
||||
import com.sismics.docs.util.ApplicationUtil;
|
||||
import com.sismics.docs.util.PreferenceUtil;
|
||||
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyManagementException;
|
||||
@ -26,13 +23,14 @@ import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
* Base class for API access.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class BaseResource {
|
||||
|
||||
/**
|
||||
* User-Agent to use.
|
||||
*/
|
||||
@ -44,7 +42,7 @@ public class BaseResource {
|
||||
protected static String ACCEPT_LANGUAGE = null;
|
||||
|
||||
/**
|
||||
* HTTP client.
|
||||
* Async HTTP client.
|
||||
*/
|
||||
protected static AsyncHttpClient client = new AsyncHttpClient();
|
||||
|
||||
@ -54,10 +52,11 @@ public class BaseResource {
|
||||
try {
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
trustStore.load(null, null);
|
||||
|
||||
// Async HTTP Client uses another HTTP libary
|
||||
MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
|
||||
sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
client.setSSLSocketFactory(sf);
|
||||
AbstractAjaxCallback.setSSF(sf);
|
||||
} catch (Exception e) {
|
||||
// NOP
|
||||
}
|
||||
@ -84,12 +83,12 @@ public class BaseResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Socket factory to allow self-signed certificates.
|
||||
* Socket factory to allow self-signed certificates for Async HTTP Client.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public static class MySSLSocketFactory extends SSLSocketFactory {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
public static class MySSLSocketFactory extends cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory {
|
||||
SSLContext sslContext = SSLContext.getInstance(SSLSocketFactory.TLS);
|
||||
|
||||
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
|
||||
super(truststore);
|
||||
@ -106,7 +105,7 @@ public class BaseResource {
|
||||
}
|
||||
};
|
||||
|
||||
sslContext.init(null, new TrustManager[] { tm }, null);
|
||||
sslContext.init(null, new TrustManager[]{tm}, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,11 +2,15 @@ package com.sismics.docs.resource;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.loopj.android.http.RequestParams;
|
||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.listener.HttpCallback;
|
||||
import com.sismics.docs.util.OkHttpUtil;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
|
||||
/**
|
||||
* Access to /document API.
|
||||
*
|
||||
@ -19,18 +23,23 @@ public class DocumentResource extends BaseResource {
|
||||
* @param context Context
|
||||
* @param offset Offset
|
||||
* @param query Search query
|
||||
* @param responseHandler Callback
|
||||
* @param callback Callback
|
||||
*/
|
||||
public static void list(Context context, int offset, String query, JsonHttpResponseHandler responseHandler) {
|
||||
init(context);
|
||||
|
||||
RequestParams params = new RequestParams();
|
||||
params.put("limit", 20);
|
||||
params.put("offset", offset);
|
||||
params.put("sort_column", 3);
|
||||
params.put("asc", false);
|
||||
params.put("search", query);
|
||||
client.get(getApiUrl(context) + "/document/list", params, responseHandler);
|
||||
public static void list(Context context, int offset, String query, HttpCallback callback) {
|
||||
Request request = new Request.Builder()
|
||||
.url(HttpUrl.parse(getApiUrl(context) + "/document/list")
|
||||
.newBuilder()
|
||||
.addQueryParameter("limit", "20")
|
||||
.addQueryParameter("offset", Integer.toString(offset))
|
||||
.addQueryParameter("sort_column", "3")
|
||||
.addQueryParameter("asc", "false")
|
||||
.addQueryParameter("search", query)
|
||||
.build())
|
||||
.get()
|
||||
.build();
|
||||
OkHttpUtil.buildClient(context)
|
||||
.newCall(request)
|
||||
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,12 +47,16 @@ public class DocumentResource extends BaseResource {
|
||||
*
|
||||
* @param context Context
|
||||
* @param id ID
|
||||
* @param responseHandler Callback
|
||||
* @param callback Callback
|
||||
*/
|
||||
public static void get(Context context, String id, JsonHttpResponseHandler responseHandler) {
|
||||
init(context);
|
||||
|
||||
client.get(getApiUrl(context) + "/document/" + id, responseHandler);
|
||||
public static void get(Context context, String id, HttpCallback callback) {
|
||||
Request request = new Request.Builder()
|
||||
.url(HttpUrl.parse(getApiUrl(context) + "/document/" + id))
|
||||
.get()
|
||||
.build();
|
||||
OkHttpUtil.buildClient(context)
|
||||
.newCall(request)
|
||||
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,12 +64,16 @@ public class DocumentResource extends BaseResource {
|
||||
*
|
||||
* @param context Context
|
||||
* @param id ID
|
||||
* @param responseHandler Callback
|
||||
* @param callback Callback
|
||||
*/
|
||||
public static void delete(Context context, String id, JsonHttpResponseHandler responseHandler) {
|
||||
init(context);
|
||||
|
||||
client.delete(getApiUrl(context) + "/document/" + id, responseHandler);
|
||||
public static void delete(Context context, String id, HttpCallback callback) {
|
||||
Request request = new Request.Builder()
|
||||
.url(HttpUrl.parse(getApiUrl(context) + "/document/" + id))
|
||||
.delete()
|
||||
.build();
|
||||
OkHttpUtil.buildClient(context)
|
||||
.newCall(request)
|
||||
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,19 +85,27 @@ public class DocumentResource extends BaseResource {
|
||||
* @param tagIdList Tags ID list
|
||||
* @param language Language
|
||||
* @param createDate Create date
|
||||
* @param responseHandler Callback
|
||||
* @param callback Callback
|
||||
*/
|
||||
public static void add(Context context, String title, String description,
|
||||
Set<String> tagIdList, String language, long createDate, JsonHttpResponseHandler responseHandler) {
|
||||
init(context);
|
||||
Set<String> tagIdList, String language, long createDate, HttpCallback callback) {
|
||||
FormBody.Builder formBuilder = new FormBody.Builder()
|
||||
.add("title", title)
|
||||
.add("description", description)
|
||||
.add("language", language)
|
||||
.add("create_date", Long.toString(createDate));
|
||||
String[] tagIdArray = tagIdList.toArray(new String[tagIdList.size()]);
|
||||
for (int i = 0; i < tagIdArray.length; i++) {
|
||||
formBuilder.add("tags", tagIdArray[i]);
|
||||
}
|
||||
|
||||
RequestParams params = new RequestParams();
|
||||
params.put("title", title);
|
||||
params.put("description", description);
|
||||
params.put("tags", tagIdList);
|
||||
params.put("language", language);
|
||||
params.put("create_date", createDate);
|
||||
client.put(getApiUrl(context) + "/document", params, responseHandler);
|
||||
Request request = new Request.Builder()
|
||||
.url(HttpUrl.parse(getApiUrl(context) + "/document"))
|
||||
.put(formBuilder.build())
|
||||
.build();
|
||||
OkHttpUtil.buildClient(context)
|
||||
.newCall(request)
|
||||
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,19 +118,27 @@ public class DocumentResource extends BaseResource {
|
||||
* @param tagIdList Tags ID list
|
||||
* @param language Language
|
||||
* @param createDate Create date
|
||||
* @param responseHandler Callback
|
||||
* @param callback Callback
|
||||
*/
|
||||
public static void edit(Context context, String id, String title, String description,
|
||||
Set<String> tagIdList, String language, long createDate, JsonHttpResponseHandler responseHandler) {
|
||||
init(context);
|
||||
Set<String> tagIdList, String language, long createDate, HttpCallback callback) {
|
||||
FormBody.Builder formBuilder = new FormBody.Builder()
|
||||
.add("title", title)
|
||||
.add("description", description)
|
||||
.add("language", language)
|
||||
.add("create_date", Long.toString(createDate));
|
||||
String[] tagIdArray = tagIdList.toArray(new String[tagIdList.size()]);
|
||||
for (int i = 0; i < tagIdArray.length; i++) {
|
||||
formBuilder.add("tags", tagIdArray[i]);
|
||||
}
|
||||
|
||||
RequestParams params = new RequestParams();
|
||||
params.put("title", title);
|
||||
params.put("description", description);
|
||||
params.put("tags", tagIdList);
|
||||
params.put("language", language);
|
||||
params.put("create_date", createDate);
|
||||
client.post(getApiUrl(context) + "/document/" + id, params, responseHandler);
|
||||
Request request = new Request.Builder()
|
||||
.url(HttpUrl.parse(getApiUrl(context) + "/document/" + id))
|
||||
.post(formBuilder.build())
|
||||
.build();
|
||||
OkHttpUtil.buildClient(context)
|
||||
.newCall(request)
|
||||
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,229 @@
|
||||
package com.sismics.docs.resource.cookie;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.CookieStore;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* A persistent cookie store which implements the Apache HttpClient CookieStore interface.
|
||||
* Cookies are stored and will persist on the user's device between application sessions since they
|
||||
* are serialized and stored in SharedPreferences.
|
||||
*/
|
||||
public class PersistentCookieStore implements CookieStore {
|
||||
|
||||
private static final String LOG_TAG = "PersistentCookieStore";
|
||||
private static final String COOKIE_PREFS = "CookiePrefsFileOkHttp";
|
||||
private static final String COOKIE_NAME_PREFIX = "cookie_okhttp_";
|
||||
|
||||
private final HashMap<String, ConcurrentHashMap<String, HttpCookie>> cookies;
|
||||
private final SharedPreferences cookiePrefs;
|
||||
|
||||
/**
|
||||
* Construct a persistent cookie store.
|
||||
*
|
||||
* @param context Context to attach cookie store to
|
||||
*/
|
||||
public PersistentCookieStore(Context context) {
|
||||
cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, 0);
|
||||
cookies = new HashMap<>();
|
||||
|
||||
// Load any previously stored cookies into the store
|
||||
Map<String, ?> prefsMap = cookiePrefs.getAll();
|
||||
for (Map.Entry<String, ?> entry : prefsMap.entrySet()) {
|
||||
if (entry.getValue() != null && !((String) entry.getValue()).startsWith(COOKIE_NAME_PREFIX)) {
|
||||
String[] cookieNames = TextUtils.split((String) entry.getValue(), ",");
|
||||
for (String name : cookieNames) {
|
||||
String encodedCookie = cookiePrefs.getString(COOKIE_NAME_PREFIX + name, null);
|
||||
if (encodedCookie != null) {
|
||||
HttpCookie decodedCookie = decodeCookie(encodedCookie);
|
||||
if (decodedCookie != null) {
|
||||
if (!cookies.containsKey(entry.getKey()))
|
||||
cookies.put(entry.getKey(), new ConcurrentHashMap<String, HttpCookie>());
|
||||
cookies.get(entry.getKey()).put(name, decodedCookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(URI uri, HttpCookie cookie) {
|
||||
String name = getCookieToken(uri, cookie);
|
||||
|
||||
// Save cookie into local store, or remove if expired
|
||||
if (!cookie.hasExpired()) {
|
||||
if (!cookies.containsKey(uri.getHost()))
|
||||
cookies.put(uri.getHost(), new ConcurrentHashMap<String, HttpCookie>());
|
||||
cookies.get(uri.getHost()).put(name, cookie);
|
||||
} else {
|
||||
if (cookies.containsKey(uri.toString()))
|
||||
cookies.get(uri.getHost()).remove(name);
|
||||
}
|
||||
|
||||
// Save cookie into persistent store
|
||||
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
|
||||
prefsWriter.putString(uri.getHost(), TextUtils.join(",", cookies.get(uri.getHost()).keySet()));
|
||||
prefsWriter.putString(COOKIE_NAME_PREFIX + name, encodeCookie(new SerializableHttpCookie(cookie)));
|
||||
prefsWriter.apply();
|
||||
}
|
||||
|
||||
protected String getCookieToken(URI uri, HttpCookie cookie) {
|
||||
return cookie.getName() + cookie.getDomain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HttpCookie> get(URI uri) {
|
||||
ArrayList<HttpCookie> ret = new ArrayList<>();
|
||||
if (cookies.containsKey(uri.getHost()))
|
||||
ret.addAll(cookies.get(uri.getHost()).values());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll() {
|
||||
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
|
||||
prefsWriter.clear();
|
||||
prefsWriter.apply();
|
||||
cookies.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean remove(URI uri, HttpCookie cookie) {
|
||||
String name = getCookieToken(uri, cookie);
|
||||
|
||||
if (cookies.containsKey(uri.getHost()) && cookies.get(uri.getHost()).containsKey(name)) {
|
||||
cookies.get(uri.getHost()).remove(name);
|
||||
|
||||
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
|
||||
if (cookiePrefs.contains(COOKIE_NAME_PREFIX + name)) {
|
||||
prefsWriter.remove(COOKIE_NAME_PREFIX + name);
|
||||
}
|
||||
prefsWriter.putString(uri.getHost(), TextUtils.join(",", cookies.get(uri.getHost()).keySet()));
|
||||
prefsWriter.apply();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HttpCookie> getCookies() {
|
||||
ArrayList<HttpCookie> ret = new ArrayList<>();
|
||||
for (String key : cookies.keySet())
|
||||
ret.addAll(cookies.get(key).values());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<URI> getURIs() {
|
||||
ArrayList<URI> ret = new ArrayList<>();
|
||||
for (String key : cookies.keySet())
|
||||
try {
|
||||
ret.add(new URI(key));
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes Cookie object into String
|
||||
*
|
||||
* @param cookie cookie to be encoded, can be null
|
||||
* @return cookie encoded as String
|
||||
*/
|
||||
protected String encodeCookie(SerializableHttpCookie cookie) {
|
||||
if (cookie == null)
|
||||
return null;
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
try {
|
||||
ObjectOutputStream outputStream = new ObjectOutputStream(os);
|
||||
outputStream.writeObject(cookie);
|
||||
} catch (IOException e) {
|
||||
Log.d(LOG_TAG, "IOException in encodeCookie", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return byteArrayToHexString(os.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cookie decoded from cookie string
|
||||
*
|
||||
* @param cookieString string of cookie as returned from http request
|
||||
* @return decoded cookie or null if exception occured
|
||||
*/
|
||||
protected HttpCookie decodeCookie(String cookieString) {
|
||||
byte[] bytes = hexStringToByteArray(cookieString);
|
||||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
|
||||
HttpCookie cookie = null;
|
||||
try {
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
|
||||
cookie = ((SerializableHttpCookie) objectInputStream.readObject()).getCookie();
|
||||
} catch (IOException e) {
|
||||
Log.d(LOG_TAG, "IOException in decodeCookie", e);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.d(LOG_TAG, "ClassNotFoundException in decodeCookie", e);
|
||||
}
|
||||
|
||||
return cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using some super basic byte array <-> hex conversions so we don't have to rely on any
|
||||
* large Base64 libraries. Can be overridden if you like!
|
||||
*
|
||||
* @param bytes byte array to be converted
|
||||
* @return string containing hex values
|
||||
*/
|
||||
protected String byteArrayToHexString(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||||
for (byte element : bytes) {
|
||||
int v = element & 0xff;
|
||||
if (v < 16) {
|
||||
sb.append('0');
|
||||
}
|
||||
sb.append(Integer.toHexString(v));
|
||||
}
|
||||
return sb.toString().toUpperCase(Locale.US);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts hex values from strings to byte arra
|
||||
*
|
||||
* @param hexString string of hex-encoded values
|
||||
* @return decoded byte array
|
||||
*/
|
||||
protected byte[] hexStringToByteArray(String hexString) {
|
||||
int len = hexString.length();
|
||||
byte[] data = new byte[len / 2];
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.sismics.docs.resource.cookie;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.HttpCookie;
|
||||
|
||||
public class SerializableHttpCookie implements Serializable {
|
||||
private static final long serialVersionUID = 6374381323722046732L;
|
||||
|
||||
private transient final HttpCookie cookie;
|
||||
private transient HttpCookie clientCookie;
|
||||
|
||||
public SerializableHttpCookie(HttpCookie cookie) {
|
||||
this.cookie = cookie;
|
||||
}
|
||||
|
||||
public HttpCookie getCookie() {
|
||||
HttpCookie bestCookie = cookie;
|
||||
if (clientCookie != null) {
|
||||
bestCookie = clientCookie;
|
||||
}
|
||||
return bestCookie;
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.writeObject(cookie.getName());
|
||||
out.writeObject(cookie.getValue());
|
||||
out.writeObject(cookie.getComment());
|
||||
out.writeObject(cookie.getCommentURL());
|
||||
out.writeObject(cookie.getDomain());
|
||||
out.writeLong(cookie.getMaxAge());
|
||||
out.writeObject(cookie.getPath());
|
||||
out.writeObject(cookie.getPortlist());
|
||||
out.writeInt(cookie.getVersion());
|
||||
out.writeBoolean(cookie.getSecure());
|
||||
out.writeBoolean(cookie.getDiscard());
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
String name = (String) in.readObject();
|
||||
String value = (String) in.readObject();
|
||||
clientCookie = new HttpCookie(name, value);
|
||||
clientCookie.setComment((String) in.readObject());
|
||||
clientCookie.setCommentURL((String) in.readObject());
|
||||
clientCookie.setDomain((String) in.readObject());
|
||||
clientCookie.setMaxAge(in.readLong());
|
||||
clientCookie.setPath((String) in.readObject());
|
||||
clientCookie.setPortlist((String) in.readObject());
|
||||
clientCookie.setVersion(in.readInt());
|
||||
clientCookie.setSecure(in.readBoolean());
|
||||
clientCookie.setDiscard(in.readBoolean());
|
||||
}
|
||||
}
|
@ -15,12 +15,12 @@ import com.sismics.docs.event.FileAddEvent;
|
||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.resource.FileResource;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import cz.msebera.android.httpclient.Header;
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,191 @@
|
||||
package com.sismics.docs.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jakewharton.picasso.OkHttp3Downloader;
|
||||
import com.sismics.docs.resource.cookie.PersistentCookieStore;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.Cache;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.JavaNetCookieJar;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* Utilities for OkHttp.
|
||||
*
|
||||
* @author bgamard.
|
||||
*/
|
||||
public class OkHttpUtil {
|
||||
/**
|
||||
* OkHttp singleton client.
|
||||
*/
|
||||
private static OkHttpClient okHttpClient = new OkHttpClient();
|
||||
|
||||
/**
|
||||
* Singleton cache.
|
||||
*/
|
||||
private static Cache cache = null;
|
||||
|
||||
/**
|
||||
* User-Agent to use.
|
||||
*/
|
||||
protected static String userAgent = null;
|
||||
|
||||
/**
|
||||
* Accept-Language header.
|
||||
*/
|
||||
protected static String acceptLanguage = null;
|
||||
|
||||
static {
|
||||
// OkHttp configuration
|
||||
try {
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
final TrustManager[] trustAllCerts = new TrustManager[] {
|
||||
new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Install the all-trusting trust manager
|
||||
final SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||
final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||
|
||||
// Configure OkHttpClient
|
||||
okHttpClient = okHttpClient.newBuilder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.writeTimeout(30, TimeUnit.SECONDS)
|
||||
.sslSocketFactory(sslSocketFactory)
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
// NOP
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Picasso object with base config.
|
||||
*
|
||||
* @param context Context
|
||||
* @return Picasso object
|
||||
*/
|
||||
public static Picasso picasso(Context context) {
|
||||
OkHttpClient okHttpClient = buildClient(context)
|
||||
.newBuilder()
|
||||
.addInterceptor(new Interceptor() {
|
||||
@Override
|
||||
public Response intercept(Interceptor.Chain chain) throws IOException { // Override cache configuration
|
||||
final Request original = chain.request();
|
||||
final Request.Builder requestBuilder = original.newBuilder()
|
||||
.header("Cache-Control", "max-age=" + (3600 * 24 * 365))
|
||||
.method(original.method(), original.body());
|
||||
return chain.proceed(requestBuilder.build());
|
||||
}
|
||||
})
|
||||
.cache(getCache(context))
|
||||
.build();
|
||||
|
||||
Picasso picasso = new Picasso.Builder(context)
|
||||
.downloader(new OkHttp3Downloader(okHttpClient))
|
||||
.build();
|
||||
picasso.setIndicatorsEnabled(false); // Debug stuff
|
||||
return picasso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and eventually build the singleton cache.
|
||||
*
|
||||
* @param context Context
|
||||
* @return Cache
|
||||
*/
|
||||
private static Cache getCache(Context context) {
|
||||
if (cache == null) {
|
||||
cache = new Cache(context.getCacheDir(),
|
||||
PreferenceUtil.getIntegerPreference(context, PreferenceUtil.PREF_CACHE_SIZE, 0) * 1000000);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the HTTP cache.
|
||||
*
|
||||
* @param context Context
|
||||
*/
|
||||
public static void clearCache(Context context) {
|
||||
Cache cache = getCache(context);
|
||||
try {
|
||||
cache.evictAll();
|
||||
} catch (IOException e) {
|
||||
Log.e("OKHttpUtil", "Error clearing cache", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an OkHttpClient.
|
||||
*
|
||||
* @param context Context
|
||||
* @return OkHttpClient
|
||||
*/
|
||||
public static OkHttpClient buildClient(final Context context) {
|
||||
// One-time header computation
|
||||
if (userAgent == null) {
|
||||
userAgent = "Sismics Docs Android " + ApplicationUtil.getVersionName(context) + "/Android " + Build.VERSION.RELEASE + "/" + Build.MODEL;
|
||||
}
|
||||
|
||||
if (acceptLanguage == null) {
|
||||
Locale locale = Locale.getDefault();
|
||||
acceptLanguage = locale.getLanguage() + "_" + locale.getCountry();
|
||||
}
|
||||
|
||||
// Cookie handling
|
||||
PersistentCookieStore cookieStore = new PersistentCookieStore(context);
|
||||
CookieManager cookieManager = new CookieManager(cookieStore, CookiePolicy.ACCEPT_ALL);
|
||||
cookieStore.add(URI.create(PreferenceUtil.getServerUrl(context)),
|
||||
new HttpCookie("auth_token", PreferenceUtil.getAuthToken(context))); // TODO Remove me when async http is ditched
|
||||
|
||||
// Runtime configuration
|
||||
return okHttpClient.newBuilder()
|
||||
.cookieJar(new JavaNetCookieJar(cookieManager))
|
||||
.addNetworkInterceptor(new Interceptor() {
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request originalRequest = chain.request();
|
||||
return chain.proceed(originalRequest.newBuilder()
|
||||
.header("User-Agent", userAgent)
|
||||
.header("Accept-Language", acceptLanguage)
|
||||
// TODO necessary?? .method(originalRequest.method(), originalRequest.body())
|
||||
.build());
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
@ -7,11 +7,12 @@ import android.preference.PreferenceManager;
|
||||
|
||||
import com.loopj.android.http.PersistentCookieStore;
|
||||
|
||||
import org.apache.http.cookie.Cookie;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cz.msebera.android.httpclient.cookie.Cookie;
|
||||
|
||||
/**
|
||||
* Utility class on preferences.
|
||||
*
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 353 B |
Binary file not shown.
After Width: | Height: | Size: 461 B |
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="12dp">
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Export metadata"
|
||||
android:id="@+id/checkBox" />
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Export comments"
|
||||
android:id="@+id/checkBox2" />
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Fit image to page"
|
||||
android:id="@+id/checkBox3" />
|
||||
|
||||
<SeekBar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/seekBar" />
|
||||
</LinearLayout>
|
@ -207,6 +207,17 @@
|
||||
android:orientation="horizontal"
|
||||
style="?android:buttonBarStyle">
|
||||
|
||||
<Button
|
||||
android:id="@+id/actionExportPdf"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableTop="@drawable/ic_description_grey600_24dp"
|
||||
style="?android:buttonBarButtonStyle"
|
||||
android:text="@string/export_pdf"
|
||||
android:textColor="@color/button_material_dark"
|
||||
android:textAllCaps="false"
|
||||
android:layout_margin="8dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/actionSharing"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -9,7 +9,7 @@
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="15dip"
|
||||
android:id="@+id/fileProgressBar"
|
||||
android:indeterminate="false"
|
||||
android:indeterminate="true"
|
||||
android:layout_centerInParent="true"/>
|
||||
|
||||
<it.sephiroth.android.library.imagezoom.ImageViewTouch
|
||||
|
@ -117,6 +117,8 @@
|
||||
<string name="comment_delete">Delete comment</string>
|
||||
<string name="deleting_comment">Deleting comment</string>
|
||||
<string name="error_deleting_comment">Error deleting comment</string>
|
||||
<string name="export_pdf">Export PDF</string>
|
||||
<string name="download">Download</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
@ -1,6 +1,6 @@
|
||||
#Mon Nov 23 20:12:30 CET 2015
|
||||
#Sat Jan 16 19:15:13 CET 2016
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
|
||||
|
@ -113,11 +113,6 @@
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.levigo.jbig2</groupId>
|
||||
<artifactId>levigo-jbig2-imageio</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>fr.opensagres.xdocreport</groupId>
|
||||
<artifactId>org.odftoolkit.odfdom.converter.pdf</artifactId>
|
||||
@ -128,15 +123,25 @@
|
||||
<artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- OCR dependencies -->
|
||||
<dependency>
|
||||
<groupId>jna</groupId>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ImageIO plugins -->
|
||||
<dependency>
|
||||
<groupId>jai</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<groupId>com.levigo.jbig2</groupId>
|
||||
<artifactId>levigo-jbig2-imageio</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-jpeg</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.jai-imageio</groupId>
|
||||
<artifactId>jai-imageio-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
|
@ -38,9 +38,9 @@ import javax.imageio.stream.ImageOutputStream;
|
||||
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;
|
||||
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
|
||||
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi;
|
||||
import com.github.jaiimageio.impl.plugins.tiff.TIFFImageReaderSpi;
|
||||
import com.github.jaiimageio.impl.plugins.tiff.TIFFImageWriterSpi;
|
||||
import com.github.jaiimageio.plugins.tiff.TIFFImageWriteParam;
|
||||
|
||||
public class ImageIOHelper {
|
||||
|
||||
@ -51,26 +51,26 @@ public class ImageIOHelper {
|
||||
* Gets pixel data of an
|
||||
* <code>IIOImage</code> object.
|
||||
*
|
||||
* @param image an
|
||||
* @param oimage an
|
||||
* <code>IIOImage</code> object
|
||||
* @return a byte buffer of pixel data
|
||||
* @throws Exception
|
||||
*/
|
||||
public static ByteBuffer getImageByteBuffer(IIOImage image) throws IOException {
|
||||
//Set up the writeParam
|
||||
TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.US);
|
||||
tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
|
||||
|
||||
//Get tif writer and set output to file
|
||||
public static ByteBuffer getImageByteBuffer(BufferedImage oimage) throws IOException {
|
||||
// Get tif writer and set output to file
|
||||
ImageWriter writer = new TIFFImageWriterSpi().createWriterInstance();
|
||||
|
||||
//Get the stream metadata
|
||||
IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(tiffWriteParam);
|
||||
// Set up the writeParam
|
||||
// We are using the old JAI ImageIO plugin, because for some reason, OCR don't work with TwelveMonkeys' plugin
|
||||
ImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.US);
|
||||
tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
|
||||
|
||||
// Get the stream metadata
|
||||
IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(tiffWriteParam);
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ImageOutputStream ios = ImageIO.createImageOutputStream(outputStream);
|
||||
writer.setOutput(ios);
|
||||
writer.write(streamMetadata, new IIOImage(image.getRenderedImage(), null, null), tiffWriteParam);
|
||||
writer.write(streamMetadata, new IIOImage(oimage, null, null), tiffWriteParam);
|
||||
writer.dispose();
|
||||
|
||||
// Read the writed image
|
||||
|
@ -17,7 +17,6 @@ package com.sismics.tess4j;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
@ -25,8 +24,6 @@ import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.imageio.IIOImage;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
/**
|
||||
@ -169,9 +166,8 @@ public class Tesseract {
|
||||
* @throws TesseractException
|
||||
*/
|
||||
public String doOCR(BufferedImage bi, Rectangle rect) throws TesseractException {
|
||||
IIOImage oimage = new IIOImage(bi, null, null);
|
||||
List<IIOImage> imageList = new ArrayList<IIOImage>();
|
||||
imageList.add(oimage);
|
||||
List<BufferedImage> imageList = new ArrayList<BufferedImage>();
|
||||
imageList.add(bi);
|
||||
return doOCR(imageList, rect);
|
||||
}
|
||||
|
||||
@ -179,23 +175,22 @@ public class Tesseract {
|
||||
* Performs OCR operation.
|
||||
*
|
||||
* @param imageList a list of
|
||||
* <code>IIOImage</code> objects
|
||||
* <code>BufferedImage</code> objects
|
||||
* @param rect the bounding rectangle defines the region of the image to be
|
||||
* recognized. A rectangle of zero dimension or
|
||||
* <code>null</code> indicates the whole image.
|
||||
* @return the recognized text
|
||||
* @throws TesseractException
|
||||
*/
|
||||
public String doOCR(List<IIOImage> imageList, Rectangle rect) throws TesseractException {
|
||||
public String doOCR(List<BufferedImage> imageList, Rectangle rect) throws TesseractException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
pageNum = 0;
|
||||
|
||||
for (IIOImage oimage : imageList) {
|
||||
for (BufferedImage oimage : imageList) {
|
||||
pageNum++;
|
||||
try {
|
||||
ByteBuffer buf = ImageIOHelper.getImageByteBuffer(oimage);
|
||||
RenderedImage ri = oimage.getRenderedImage();
|
||||
String pageText = doOCR(ri.getWidth(), ri.getHeight(), buf, rect, ri.getColorModel().getPixelSize());
|
||||
String pageText = doOCR(oimage.getWidth(), oimage.getHeight(), buf, rect, oimage.getColorModel().getPixelSize());
|
||||
sb.append(pageText);
|
||||
} catch (IOException ioe) {
|
||||
//skip the problematic image
|
||||
|
Binary file not shown.
Binary file not shown.
@ -35,8 +35,11 @@
|
||||
<joda-time.joda-time.version>2.9.1</joda-time.joda-time.version>
|
||||
<org.hibernate.hibernate.version>4.1.0.Final</org.hibernate.hibernate.version>
|
||||
<javax.servlet.javax.servlet-api.version>3.1.0</javax.servlet.javax.servlet-api.version>
|
||||
<com.levigo.jbig2.levigo-jbig2-imageio.version>1.6.3</com.levigo.jbig2.levigo-jbig2-imageio.version>
|
||||
<fr.opensagres.xdocreport.version>1.0.5</fr.opensagres.xdocreport.version>
|
||||
<net.java.dev.jna.jna.version>4.2.1</net.java.dev.jna.jna.version>
|
||||
<com.twelvemonkeys.imageio.version>3.2.1</com.twelvemonkeys.imageio.version>
|
||||
<com.levigo.jbig2.levigo-jbig2-imageio.version>1.6.5</com.levigo.jbig2.levigo-jbig2-imageio.version>
|
||||
<com.github.jai-imageio.jai-imageio-core.version>1.3.1</com.github.jai-imageio.jai-imageio-core.version>
|
||||
|
||||
<org.eclipse.jetty.jetty-server.version>9.2.13.v20150730</org.eclipse.jetty.jetty-server.version>
|
||||
<org.eclipse.jetty.jetty-webapp.version>9.2.13.v20150730</org.eclipse.jetty.jetty-webapp.version>
|
||||
@ -69,15 +72,8 @@
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>jbig2.googlecode</id>
|
||||
<name>JBIG2 ImageIO-Plugin repository at googlecode.com</name>
|
||||
<url>http://jbig2-imageio.googlecode.com/svn/maven-repository</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@ -380,79 +376,39 @@
|
||||
<version>${fr.opensagres.xdocreport.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Used to read JBIG2 images. See https://github.com/sismics/docs/issues/38 -->
|
||||
<dependency> <!-- Servlet listener to register SPI ImageIO plugins -->
|
||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||
<artifactId>servlet</artifactId>
|
||||
<version>${com.twelvemonkeys.imageio.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JNA for Tesseract -->
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>${net.java.dev.jna.jna.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- ImageIO plugins -->
|
||||
<dependency> <!-- Permissive JPEG plugin -->
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-jpeg</artifactId>
|
||||
<version>${com.twelvemonkeys.imageio.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency><!-- Only JBIG2 -->
|
||||
<groupId>com.levigo.jbig2</groupId>
|
||||
<artifactId>levigo-jbig2-imageio</artifactId>
|
||||
<version>${com.levigo.jbig2.levigo-jbig2-imageio.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- OCR dependencies -->
|
||||
<dependency>
|
||||
<groupId>jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jai</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>1.0</version>
|
||||
<dependency><!-- Essentially TIFF (for OCR) -->
|
||||
<groupId>com.github.jai-imageio</groupId>
|
||||
<artifactId>jai-imageio-core</artifactId>
|
||||
<version>${com.github.jai-imageio.jai-imageio-core.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>init</id>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<executions>
|
||||
|
||||
<execution>
|
||||
<id>install-jna</id>
|
||||
<phase>validate</phase>
|
||||
<configuration>
|
||||
<file>${project.basedir}/lib/jna.jar</file>
|
||||
<repositoryLayout>default</repositoryLayout>
|
||||
<groupId>jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
<generatePom>true</generatePom>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>install-file</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>install-jai-imageio</id>
|
||||
<phase>validate</phase>
|
||||
<configuration>
|
||||
<file>${project.basedir}/lib/jai_imageio.jar</file>
|
||||
<repositoryLayout>default</repositoryLayout>
|
||||
<groupId>jai</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
<generatePom>true</generatePom>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>install-file</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
@ -84,6 +84,11 @@
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||
<artifactId>servlet</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>com.sismics.docs</groupId>
|
||||
|
@ -7,6 +7,12 @@
|
||||
metadata-complete="true">
|
||||
<display-name>Docs</display-name>
|
||||
|
||||
<!-- Proper loader/unloader of ImageIO plugins -->
|
||||
<listener>
|
||||
<display-name>ImageIO service provider loader/unloader</display-name>
|
||||
<listener-class>com.twelvemonkeys.servlet.image.IIOProviderContextListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!-- This filter is used to process a couple things in the request context -->
|
||||
<filter>
|
||||
<filter-name>requestContextFilter</filter-name>
|
||||
|
@ -3,7 +3,7 @@
|
||||
/**
|
||||
* Share controller.
|
||||
*/
|
||||
angular.module('share').controller('Share', function($scope, $state, $stateParams, Restangular) {
|
||||
angular.module('share').controller('Share', function($scope, $state, $stateParams, Restangular, $modal) {
|
||||
// Load document
|
||||
Restangular.one('document', $stateParams.documentId).get({ share: $stateParams.shareId })
|
||||
.then(function (data) {
|
||||
@ -33,4 +33,16 @@ angular.module('share').controller('Share', function($scope, $state, $stateParam
|
||||
$scope.openFile = function (file) {
|
||||
$state.go('share.file', { documentId: $stateParams.documentId, shareId: $stateParams.shareId, fileId: file.id })
|
||||
};
|
||||
|
||||
/**
|
||||
* Export the current document to PDF.
|
||||
*/
|
||||
$scope.exportPdf = function() {
|
||||
$modal.open({
|
||||
templateUrl: 'partial/share/share.pdf.html',
|
||||
controller: 'ShareModalPdf'
|
||||
});
|
||||
|
||||
return false;
|
||||
};
|
||||
});
|
@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Document modal PDF controller.
|
||||
*/
|
||||
angular.module('share').controller('ShareModalPdf', function ($scope, $window, $stateParams, $modalInstance) {
|
||||
$scope.export = {
|
||||
metadata: false,
|
||||
comments: false,
|
||||
fitimagetopage: true,
|
||||
margin: 10
|
||||
};
|
||||
|
||||
// Export to PDF
|
||||
$scope.exportPdf = function() {
|
||||
$window.open('../api/document/' + $stateParams.documentId
|
||||
+ '/pdf?metadata=' + $scope.export.metadata
|
||||
+ '&comments=' + $scope.export.comments
|
||||
+ '&fitimagetopage=' + $scope.export.fitimagetopage
|
||||
+ '&margin=' + $scope.export.margin
|
||||
+ '&share=' + $stateParams.shareId);
|
||||
|
||||
$modalInstance.close();
|
||||
};
|
||||
|
||||
// Close the modal
|
||||
$scope.close = function () {
|
||||
$modalInstance.close();
|
||||
}
|
||||
});
|
@ -1,11 +1,32 @@
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<div class="text-right">
|
||||
<div class="btn-group dropdown" dropdown>
|
||||
<button class="btn btn-default" dropdown-toggle>
|
||||
<span class="glyphicon glyphicon-export"></span>
|
||||
Export
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a ng-href="../api/file/zip?id={{ document.id }}&share={{ $stateParams.shareId }}" title="Download all files">
|
||||
<span class="glyphicon glyphicon glyphicon-compressed"></span>
|
||||
Download files
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a ng-click="exportPdf()" title="Export document to PDF" class="pointer">
|
||||
<span class="glyphicon glyphicon glyphicon-save-file"></span>
|
||||
Export to PDF
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
{{ document.title }} <small>{{ document.create_date | date: 'yyyy-MM-dd' }}</small>
|
||||
<a ng-href="../api/file/zip?id={{ document.id }}&share={{ $stateParams.shareId }}" class="btn btn-default" title="Download all files">
|
||||
<span class="glyphicon glyphicon-download-alt"></span>
|
||||
</a>
|
||||
</h1>
|
||||
<ul class="list-inline">
|
||||
<li ng-repeat="tag in document.tags"><span class="label label-info" ng-style="{ 'background': tag.color }">{{ tag.name }}</span></li>
|
||||
|
45
docs-web/src/main/webapp/src/partial/share/share.pdf.html
Normal file
45
docs-web/src/main/webapp/src/partial/share/share.pdf.html
Normal file
@ -0,0 +1,45 @@
|
||||
<div class="modal-header">
|
||||
<h3>Export to PDF</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="export.metadata" /> Export metadata
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="export.comments" /> Export comments
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="export.fitimagetopage" /> Fit image to page
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label for="inputMargin" class="col-sm-2 control-label">Margin</label>
|
||||
<div class="input-group col-sm-5">
|
||||
<input type="number" class="form-control" id="inputMargin" ng-model="export.margin" min="0" max="100" step="1">
|
||||
<div class="input-group-addon">mm</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button ng-click="exportPdf()" class="btn btn-primary">
|
||||
<span class="glyphicon glyphicon-save-file"></span> Export
|
||||
</button>
|
||||
<button ng-click="close()" class="btn btn-default">Cancel</button>
|
||||
</div>
|
@ -34,6 +34,7 @@
|
||||
<script src="app/share/app.js" type="text/javascript"></script>
|
||||
<script src="app/share/controller/Main.js" type="text/javascript"></script>
|
||||
<script src="app/share/controller/Share.js" type="text/javascript"></script>
|
||||
<script src="app/share/controller/ShareModalPdf.js" type="text/javascript"></script>
|
||||
<script src="app/share/controller/FileView.js" type="text/javascript"></script>
|
||||
<script src="app/share/controller/FileModalView.js" type="text/javascript"></script>
|
||||
<script src="app/share/filter/Newline.js" type="text/javascript"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user