mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 14:07:55 +01:00
Android: document details
This commit is contained in:
parent
2ce5749226
commit
8c5c54125f
@ -98,7 +98,9 @@
|
||||
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="recyclerview-v7-21.0.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-easing-1.0.3" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-21.0.2" level="project" />
|
||||
<orderEntry type="library" exported="" name="imagezoom-1.0.5" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-v4-21.0.2" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-query.0.26.8" level="project" />
|
||||
<orderEntry type="library" exported="" name="appcompat-v7-21.0.2" level="project" />
|
||||
|
@ -3,7 +3,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:0.14.2'
|
||||
classpath 'com.android.tools.build:gradle:0.14.4'
|
||||
}
|
||||
}
|
||||
apply plugin: 'com.android.application'
|
||||
@ -14,7 +14,7 @@ repositories {
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1"
|
||||
buildToolsVersion "21.1.1"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
@ -27,12 +27,6 @@ android {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
runProguard false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -40,4 +34,5 @@ dependencies {
|
||||
compile 'com.android.support:appcompat-v7:21.0.2'
|
||||
compile 'com.android.support:recyclerview-v7:21.0.0'
|
||||
compile 'com.loopj.android:android-async-http:1.4.6'
|
||||
compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'
|
||||
}
|
||||
|
@ -28,6 +28,11 @@
|
||||
android:logo="@drawable/ic_launcher"
|
||||
android:launchMode="singleTop">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.DocumentActivity"
|
||||
android:label=""
|
||||
android:logo="@drawable/ic_launcher">
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
@ -20,6 +20,16 @@ public class MainApplication extends Application {
|
||||
JSONObject json = PreferenceUtil.getCachedJson(getApplicationContext(), PreferenceUtil.PREF_CACHED_USER_INFO_JSON);
|
||||
ApplicationContext.getInstance().setUserInfo(getApplicationContext(), json);
|
||||
|
||||
// TODO Fullscreen preview
|
||||
// TODO Downloading
|
||||
// TODO Sharing
|
||||
// TODO Shared status
|
||||
// TODO Tags on document
|
||||
// TODO Error feedback
|
||||
// TODO Infinite scrolling on documents
|
||||
// TODO Searching
|
||||
// TODO Printing
|
||||
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,121 @@
|
||||
package com.sismics.docs.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.loopj.android.http.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.adapter.FilePagerAdapter;
|
||||
import com.sismics.docs.model.application.ApplicationContext;
|
||||
import com.sismics.docs.resource.FileResource;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Document activity.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class DocumentActivity extends ActionBarActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle args) {
|
||||
super.onCreate(args);
|
||||
|
||||
// Check if logged in
|
||||
if (!ApplicationContext.getInstance().isLoggedIn()) {
|
||||
startActivity(new Intent(this, LoginActivity.class));
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle activity context
|
||||
if (getIntent() == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse input document
|
||||
String documentJson = getIntent().getStringExtra("document");
|
||||
if (documentJson == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject document;
|
||||
try {
|
||||
document = new JSONObject(documentJson);
|
||||
} catch (JSONException e) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup the activity
|
||||
setContentView(R.layout.document_activity);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
}
|
||||
|
||||
// Grab the document
|
||||
refreshDocument(document);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the displayed document.
|
||||
*
|
||||
* @param document Document in JSON format
|
||||
*/
|
||||
private void refreshDocument(JSONObject document) {
|
||||
String id = document.optString("id");
|
||||
String title = document.optString("title");
|
||||
String date = DateFormat.getDateFormat(this).format(new Date(document.optLong("create_date")));
|
||||
String description = document.optString("description");
|
||||
|
||||
// Fill the layout
|
||||
setTitle(title);
|
||||
TextView createdDateTextView = (TextView) findViewById(R.id.createdDateTextView);
|
||||
createdDateTextView.setText(date);
|
||||
TextView languageTextView = (TextView) findViewById(R.id.languageTextView);
|
||||
languageTextView.setText(document.optString("language"));
|
||||
TextView descriptionTextView = (TextView) findViewById(R.id.descriptionTextView);
|
||||
if (description == null || description.isEmpty()) {
|
||||
descriptionTextView.setVisibility(View.GONE);
|
||||
} else {
|
||||
descriptionTextView.setText(description);
|
||||
}
|
||||
|
||||
// Grab the attached files
|
||||
FileResource.list(this, id, new JsonHttpResponseHandler() {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
ViewPager fileViewPager = (ViewPager) findViewById(R.id.fileViewPager);
|
||||
fileViewPager.setOffscreenPageLimit(1);
|
||||
fileViewPager.setAdapter(new FilePagerAdapter(DocumentActivity.this, response.optJSONArray("files")));
|
||||
findViewById(R.id.progressBar).setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
@ -88,7 +88,21 @@ public class DocListAdapter extends RecyclerView.Adapter<DocListAdapter.ViewHold
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the displayed documents
|
||||
* Return an item at a given position.
|
||||
*
|
||||
* @param position Item position
|
||||
* @return Item
|
||||
*/
|
||||
public JSONObject getItemAt(int position) {
|
||||
if (documents == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return documents.optJSONObject(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the displayed documents.
|
||||
* @param documents Documents
|
||||
*/
|
||||
public void setDocuments(JSONArray documents) {
|
||||
|
@ -0,0 +1,92 @@
|
||||
package com.sismics.docs.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.view.LayoutInflater;
|
||||
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.PreferenceUtil;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import it.sephiroth.android.library.imagezoom.ImageViewTouch;
|
||||
import it.sephiroth.android.library.imagezoom.ImageViewTouchBase;
|
||||
|
||||
/**
|
||||
* @author bgamard.
|
||||
*/
|
||||
public class FilePagerAdapter extends PagerAdapter {
|
||||
/**
|
||||
* Files list.
|
||||
*/
|
||||
private JSONArray files;
|
||||
|
||||
/**
|
||||
* AQuery.
|
||||
*/
|
||||
private AQuery aq;
|
||||
|
||||
/**
|
||||
* Context.
|
||||
*/
|
||||
private Context context;
|
||||
|
||||
/**
|
||||
* Auth token used to download files.
|
||||
*/
|
||||
private String authToken;
|
||||
|
||||
public FilePagerAdapter(Context context, JSONArray files) {
|
||||
this.files = files;
|
||||
this.context = context;
|
||||
this.authToken = PreferenceUtil.getAuthToken(context);
|
||||
aq = new AQuery(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiateItem(ViewGroup container, int position) {
|
||||
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);
|
||||
JSONObject file = files.optJSONObject(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));
|
||||
|
||||
fileImageView.setDisplayType(ImageViewTouchBase.DisplayType.FIT_TO_SCREEN);
|
||||
|
||||
container.addView(view, 0);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
container.removeView((View) object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (files == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return files.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(View view, Object object) {
|
||||
return view == object;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.sismics.docs.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
@ -7,11 +8,11 @@ import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.loopj.android.http.JsonHttpResponseHandler;
|
||||
import com.sismics.docs.DividerItemDecoration;
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.activity.DocumentActivity;
|
||||
import com.sismics.docs.adapter.DocListAdapter;
|
||||
import com.sismics.docs.listener.RecyclerItemClickListener;
|
||||
import com.sismics.docs.resource.DocumentResource;
|
||||
@ -30,8 +31,8 @@ public class DocListFragment extends Fragment {
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
// Initialize the view
|
||||
View view = inflater.inflate(R.layout.doc_list_fragment, container, false);
|
||||
|
||||
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.docList);
|
||||
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLongClickable(true);
|
||||
|
||||
@ -46,7 +47,12 @@ public class DocListFragment extends Fragment {
|
||||
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(View view, int position) {
|
||||
Toast.makeText(getActivity(), position + " clicked", Toast.LENGTH_SHORT).show();
|
||||
JSONObject document = adapter.getItemAt(position);
|
||||
if (document != null) {
|
||||
Intent intent = new Intent(getActivity(), DocumentActivity.class);
|
||||
intent.putExtra("document", document.toString());
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@ -64,6 +70,10 @@ public class DocListFragment extends Fragment {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
adapter.setDocuments(response.optJSONArray("documents"));
|
||||
|
||||
if (getView() != null) {
|
||||
getView().findViewById(R.id.progressBar).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import com.loopj.android.http.RequestParams;
|
||||
* @author bgamard
|
||||
*/
|
||||
public class DocumentResource extends BaseResource {
|
||||
|
||||
/**
|
||||
* GET /document/list.
|
||||
*
|
||||
|
@ -0,0 +1,25 @@
|
||||
package com.sismics.docs.resource;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.loopj.android.http.JsonHttpResponseHandler;
|
||||
|
||||
/**
|
||||
* Access to /file API.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class FileResource extends BaseResource {
|
||||
/**
|
||||
* GET /file/list.
|
||||
*
|
||||
* @param context Context
|
||||
* @param documentId Document ID
|
||||
* @param responseHandler Callback
|
||||
*/
|
||||
public static void list(Context context, String documentId, JsonHttpResponseHandler responseHandler) {
|
||||
init(context);
|
||||
|
||||
client.get(getApiUrl(context) + "/file/list?id=" + documentId, responseHandler);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.sismics.docs.ui.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import it.sephiroth.android.library.imagezoom.ImageViewTouch;
|
||||
|
||||
/**
|
||||
* ViewPager for files.
|
||||
*
|
||||
* @author bgamard.
|
||||
*/
|
||||
public class FileViewPager extends ViewPager {
|
||||
|
||||
public FileViewPager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FileViewPager(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
|
||||
if (v instanceof ImageViewTouch) {
|
||||
return ((ImageViewTouch) v).canScroll(dx);
|
||||
} else {
|
||||
return super.canScroll(v, checkV, dx, x, y);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/docList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="vertical">
|
||||
|
||||
</android.support.v7.widget.RecyclerView>
|
||||
</android.support.v7.widget.RecyclerView>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true" />
|
||||
|
||||
</RelativeLayout>
|
88
docs-android/app/src/main/res/layout/document_activity.xml
Normal file
88
docs-android/app/src/main/res/layout/document_activity.xml
Normal file
@ -0,0 +1,88 @@
|
||||
<?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">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:background="#eee"
|
||||
android:elevation="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/createdDateLabel"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:text="@string/created_date"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/createdDateTextView"
|
||||
android:layout_toRightOf="@id/createdDateLabel"
|
||||
android:layout_toEndOf="@id/createdDateLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:text="01/12/2014"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/languageLabel"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/createdDateLabel"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:text="@string/language"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/languageTextView"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_toRightOf="@id/languageLabel"
|
||||
android:layout_toEndOf="@id/languageLabel"
|
||||
android:layout_below="@id/createdDateTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:text="fr"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/descriptionTextView"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_below="@id/languageLabel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:text="Lorem ipsum dolor sit amen lorem ipsum dolor sit amen lorem ipsum dolor sit amen lorem ipsum dolor sit amen lorem ipsum dolor sit amen."/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<com.sismics.docs.ui.view.FileViewPager
|
||||
android:id="@+id/fileViewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
22
docs-android/app/src/main/res/layout/file_viewpager_item.xml
Normal file
22
docs-android/app/src/main/res/layout/file_viewpager_item.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
style="?android:progressBarStyleHorizontal"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="15dip"
|
||||
android:id="@+id/fileProgressBar"
|
||||
android:indeterminate="false"
|
||||
android:layout_centerInParent="true" />
|
||||
|
||||
<it.sephiroth.android.library.imagezoom.ImageViewTouch
|
||||
android:id="@+id/fileImageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="matrix"
|
||||
android:src="@drawable/ic_launcher" />
|
||||
|
||||
</RelativeLayout>
|
@ -18,6 +18,8 @@
|
||||
<string name="invalid_url_title">Invalid URL</string>
|
||||
<string name="invalid_url">Please check the server URL and try again</string>
|
||||
<string name="crash_toast_text">A crash occurred, a report has been sent to resolve this problem</string>
|
||||
<string name="created_date">Created date</string>
|
||||
<string name="language">Language</string>
|
||||
|
||||
<!-- Validation -->
|
||||
<string name="validate_error_email">Invalid email</string>
|
||||
|
Loading…
Reference in New Issue
Block a user